Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Der Aufbau eines zuverlässigen Prozesses für Continuous Integration und Continuous Delivery (CI/CD) für eine Microservices-Architektur kann herausfordernd sein. Jedes Team muss Dienste schnell und zuverlässig freigeben, ohne andere Teams zu stören oder die Anwendung als Ganzes zu destabilisieren.
In diesem Artikel wird ein Beispiel für eine CI/CD-Pipeline für die Bereitstellung von Microservices in Azure Kubernetes Service (AKS) beschrieben. Jedes Team und jedes Projekt ist anders, daher sollten Sie diesen Artikel nicht als feststehende Sammlung unverrückbarer Regeln verstehen. Verwenden Sie es stattdessen als Ausgangspunkt für das Entwerfen Ihres eigenen CI/CD-Prozesses.
Die folgende Liste fasst die Ziele einer CI/CD-Pipeline für Kubernetes gehostete Microservices zusammen:
- Teams können ihre Dienste unabhängig voneinander entwickeln und bereitstellen.
- Codeänderungen, die den CI-Prozess erfolgreich durchlaufen, werden automatisch in eine produktionsähnliche Umgebung bereitgestellt.
- Jede Phase der Pipeline stellt Qualitätsprüfungen sicher.
- Eine neue Version eines Diensts kann parallel zur vorherigen Version bereitgestellt werden.
Weitere Informationen finden Sie unter CI/CD für Microservices-Architekturen.
Annahmen
In diesem Beispiel sind einige Annahmen über das Entwicklungsteam und die Codebasis aufgeführt:
- Für das Coderepository wird der Monorepo-Ansatz genutzt, und die Ordner sind nach Microservice organisiert.
- Die Branchstrategie des Teams basiert auf der trunkbasierten Entwicklung.
- Das Team verwendet Releasebranches zur Verwaltung von Releases. Für jeden Microservice werden separate Releases erstellt.
- Der CI/CD-Prozess verwendet Azure Pipelines zum Erstellen, Testen und Bereitstellen der Microservices in AKS.
- Die Containerimages für alle Microservices werden in einer einzigen, freigegebenen Azure Container Registry Instanz mit einem separaten Repository für jeden Microservice gespeichert. Verwenden Sie Azure Container Registry ABAC-Repositoryberechtigungen, um jede Pipelineidentität auf das jeweils eigene Repository zu beschränken, oder verwenden Sie separate Containerregistrierungen, wenn stärkere Vertrauensgrenzen erforderlich sind.
- Das Team verwendet Helm-Charts, um die Microservices zu verpacken.
- Es wird ein Pushbereitstellungsmodell verwendet, bei dem Azure Pipelines und zugehörigen Agents Bereitstellungen ausführen, indem eine direkte Verbindung mit dem AKS-Cluster hergestellt wird.
Diese Annahmen bestimmen viele der spezifischen Details der CI/CD-Pipeline. Sie können jedoch den hier beschriebenen grundlegenden Ansatz für andere Prozesse, Tools und Dienste wie GitHub Actions, Jenkins oder Docker Hub anpassen.
Alternatives
Wenn Sie eine CI/CD-Strategie mit AKS auswählen, sollten Sie die folgenden gängigen Alternativen in Betracht ziehen:
Anstatt Helm als Paketverwaltungs- und Bereitstellungstool zu verwenden, können Sie Kustomize verwenden, ein Kubernetes-systemeigenes Konfigurationsverwaltungstool, mit dem eine vorlagenfreie Möglichkeit zum Anpassen und Parametrisieren der Anwendungskonfiguration eingeführt wird.
Anstatt Azure DevOps für Git-Repositorys und -Pipelines zu verwenden, können Sie GitHub Repositorys für private und öffentliche Git-Repositorys und GitHub Actions für CI/CD-Pipelines verwenden.
GitHub Actions bietet Integrationen mit AKS durch Workflowvorlagen und unterstützt OpenID Connect (OIDC) für eine sichere Authentifizierung ohne Secrets bei Azure.
Anstatt ein Pushbereitstellungsmodell zu verwenden, sollten Sie die Kubernetes-Konfiguration im großen Maßstab mithilfe eines GitOps -Bereitstellungsmodells (Pull-Bereitstellungsmodell) verwalten. Ein In-Cluster Kubernetes-Operator wie Flux oder Argo CD synchronisiert den Clusterzustand basierend auf der Konfiguration, die in einem Git-Repository gespeichert ist. GitOps beseitigt die Notwendigkeit, dass Pipelines direkten Clusterzugriff haben, die Angriffsfläche reduzieren und Selbstheilungs- und Drifterkennungsfunktionen bieten.
Tip
Berücksichtigen Sie bei der Bewertung von Push-basierten gegenüber Pull-basierten (GitOps-)Bereitstellungsmodellen Ihre Workloadanforderungen. Pushbasierte Bereitstellungen bieten deterministische Updates und direkte Pipelinesteuerung, die für sichere Bereitstellungsmethoden geeignet ist. Pull-basierte Bereitstellungen (GitOps) bieten Konsistenz, Auditierbarkeit und Self-Healing, was sie ideal für Umgebungen macht, in denen Cluster mit einem gewünschten Zustand ohne direkten Pipeline-zu-Cluster-Zugriff in Einklang gebracht werden müssen.
Validierungsbuilds
Angenommen, ein Entwickler arbeitet an einem Microservice namens Delivery Service. Bei der Entwicklung eines neuen Features checkt der Entwickler den Code in einem Feature-Branch ein. In der Regel werden Feature-Branches gemäß der Benennungskonvention feature/* benannt.
Das Diagramm zeigt zwei horizontale Git-Verzweigungslinien und eine Buildpipeline darunter. Oben befindet sich der Hauptzweig, der als horizontale Linie dargestellt wird. Der Branch „feature/8150“ weicht von „main“ ab. Auf diesem Branch befinden sich drei Punkte, die zusammen als „Commits“ bezeichnet werden. Von jedem der drei Commits zeigt ein Pfeil nach unten auf ein Feld am unteren Rand des Diagramms. Das Feld ist mit „Build pipeline“ beschriftet und enthält den Pipelinenamen ci-delivery-validation. Alle drei gestrichelten Pfeile laufen auf dieses einzelne Feld der Build-Pipeline zusammen und zeigen damit an, dass jeder Commit im Branch feature/8150 eine Ausführung der ci-delivery-validation-Pipeline auslöst.
Die Builddefinitionsdatei enthält einen Trigger, der nach dem Branchnamen und dem Quellpfad filtert:
trigger:
batch: true
branches:
include:
# for new release to production: release flow strategy
- release/delivery/v*
- refs/release/delivery/v*
- main
- feature/delivery/*
- topic/delivery/*
paths:
include:
- /src/shipping/delivery/
Wenn Sie diesen Ansatz verwenden, hat jedes Team seine eigene Build-Pipeline. Nur der Code, der in den Ordner /src/shipping/delivery eingecheckt wird, löst einen Build von Delivery Service aus. Das Pushen von Commits auf einen Branch, der mit dem Filter übereinstimmt, löst einen CI-Build aus. An diesem Punkt des Workflows führt der CI-Build eine Codeüberprüfung mit minimalem Umfang durch:
- Erstellen des Codes.
- Ausführen von Komponententests.
Das Ziel besteht darin, die Buildzeiten kurz zu halten, damit der Entwickler schnell Feedback erhält. Wenn das Feature bereit ist, in den main-Branch gemergt zu werden, öffnet der Entwickler eine PR. Durch diesen Vorgang wird ein weiterer CI-Build ausgelöst, bei dem einige zusätzliche Überprüfungen durchgeführt werden:
- Erstellen des Codes.
- Ausführen von Komponententests.
- Führen Sie statische Anwendungssicherheitstests (SAST) im Quellcode aus.
- Erstelle das ausführbare Container-Image.
- Schwachstellen-Scans für das Image durchführen.
Das Diagramm zeigt zwei horizontale Git-Verzweigungslinien und eine Buildpipeline darunter. Oben befindet sich der Hauptzweig, der als horizontale Linie dargestellt wird. Darunter verläuft der Branch feature/8150 parallel dazu und weist drei Punkte auf, die Commits darstellen. Am rechten Ende des feature/8150-Branchs verbindet ein gestrichelter Pfeil sich mit einem Punkt auf dem Haupt-Branch. Dieser Punkt ist mit einem weiteren, mit „PR“ beschrifteten Punkt gekennzeichnet, was darauf hinweist, dass ein Pull Request gegen main geöffnet wurde. Vom PR-Punkt auf der Hauptverzweigung zeigt ein gestrichelter Pfeil nach unten auf eine boxbeschriftete Buildpipeline, die den Pipelinenamen ci-delivery-full enthält. Diese Zeile veranschaulicht, dass das Öffnen eines Pull Requests vom Feature-Branch zu main die ci-delivery-full-Pipeline auslöst, die die erweiterte Menge an CI-Prüfungen ausführt.
Hinweis
In Azure Repos, einem der Dienste in Azure DevOps, können Sie Richtlinien definieren, um Branches zu schützen. Die Richtlinie kann z. B. einen erfolgreichen CI-Build und eine Abmeldung von einem Genehmigenden erfordern, bevor eine Zusammenführung in den Hauptvorgang erfolgt.
Vollständiger CI/CD-Build
Wenn das Team bereit ist, eine neue Version des Zustellungsdiensts bereitzustellen, erstellt der Release-Manager eine Verzweigung aus der Hauptzweigung, wobei dieses Benennungsmuster verwendet wird: release/<microservice name>/<semver> Beispiel: release/delivery/v1.0.2
Durch das Erstellen dieser Verzweigung wird ein vollständiger CI-Build ausgelöst, der alle vorherigen Schritte und die folgenden Schritte ausführt:
- Übertragen Sie das Container-Image in die Container Registry. Das Image wird mit der Versionsnummer aus dem Branch-Namen getaggt.
- Ausführen von
helm packagezum Verpacken des Helm-Charts für den Dienst Das Chart ist außerdem mit einer Versionsnummer gekennzeichnet. - Übertragen des Helm-Pakets an die Containerregistrierung per Push.
Wenn dieser Build erfolgreich ist, löst er einen Bereitstellungsprozess (CD) mithilfe einer Azure Pipelines Releasepipeline aus. Diese Pipeline enthält die folgenden Schritte:
- Bereitstellen des Helm-Charts in einer QA-Umgebung.
- Eine genehmigende Person meldet sich ab, bevor das Paket für die Produktion bereitgestellt wird. Weitere Informationen finden Sie unter Steuerung von Releasebereitstellungen durch Genehmigungen.
- Versehen Sie das Docker-Image für den Produktions-Namespace in der Container Registry mit einem neuen Tag. Wenn das aktuelle Tag beispielsweise
myrepo.azurecr.io/delivery:v1.0.2ist, lautet das Produktionstagmyrepo.azurecr.io/prod/delivery:v1.0.2. - Stellen Sie das Helm-Chart in der Produktionsumgebung bereit.
Auch in einem Monorepo können Sie diese Aufgaben auf einzelne Microservices beschränken, damit Teams unabhängig bereitstellen können. Der Prozess umfasst einige manuelle Schritte: das Genehmigen von PRs, das Erstellen von Release-Branches und das Genehmigen von Deployments in den Produktionscluster. Workloadteams können diese Schritte automatisieren, wenn sie möchten.
Isolation von Umgebungen
Sie stellen Dienste in mehreren Umgebungen bereit, einschließlich Umgebungen für Entwicklung, Rauchtests, Integrationstests, Auslastungstests und Produktion. Für diese Umgebungen ist ein gewisses Maß an Isolation erforderlich. In Kubernetes können Sie zwischen physischer Isolation und logischer Isolation wählen. Physische Isolierung wird in separaten Clustern bereitgestellt. Die logische Isolierung verwendet Namespaces und Richtlinien.
Unsere Empfehlung besteht darin, einen dedizierten Produktionscluster zusammen mit einem separaten Cluster für Ihre Entwicklungs-/Testumgebungen zu erstellen. Verwenden Sie die logische Isolation, um Umgebungen im Entwicklungs-/Testcluster zu trennen. Im Entwicklungs-/Testcluster bereitgestellte Dienste sollten niemals Zugriff auf Datenspeicher haben, in denen sich Geschäftsdaten befinden.
Führen Sie die folgenden Schritte aus, um die Isolation innerhalb eines Clusters zu erzwingen:
-
Namespaces: Verwenden Sie Kubernetes-Namespaces, um Umgebungen logisch voneinander zu trennen (zum Beispiel
dev,staging,qa). - Netzwerkrichtlinien: Wenden Sie Kubernetes-Netzwerkrichtlinien an, um die Pod-zu-Pod-Kommunikation über Namespaces hinweg zu verweigern.
- Ressourcenkontingente: Wenden Sie Ressourcenkontingente pro Namespace an, um Probleme mit lauten Nachbarn in freigegebenen Clustern zu verhindern.
- Microsoft Entra ID Integration: Kombinieren Sie Microsoft Entra ID Authentifizierung mit Kubernetes RBAC und Microsoft Entra ID, um zu steuern, welche Microsoft Entra Benutzer und Gruppen auf jeden Namespace zugreifen können.
Authentifizierung und Autorisierung
Verwenden Sie nach Möglichkeit sowohl für die Pipelines, die Ihre Microservices bereitstellen, als auch für die Workloads, die diese Pipelines bereitstellen, eine secretlose Authentifizierung:
- Workload-Identitätsverbund für Pipelines: Verwenden Sie für Azure Pipelines eine Dienstverbindung für den Workload-Identitätsverbund, um sich bei Azure zu authentifizieren, ohne langlebige Geheimnisse des Dienstprinzipals zu speichern. Konfigurieren Sie OIDC für GitHub Actions, um dieselbe Authentifizierung ohne Geheimnisse zu erreichen.
- Microsoft Entra Workload ID für bereitgestellte Workloads: Konfigurieren Sie die Mikroservices, die Ihre Pipeline bereitstellt, um Microsoft Entra Workload ID zu verwenden, anstatt Anmeldeinformationen über Manifeste, Helmwerte oder Kubernetes-Schlüssel einzugeben. Die Workload-ID verknüpft Kubernetes-Dienstkonten mit Microsoft Entra ID, sodass pods sich bei Azure Diensten (z. B. Azure Key Vault, Containerregistrierung oder Azure SQL) authentifizieren können, ohne dass die Pipeline geheime Schlüssel verwaltet.
Geheimnisverwaltung
Nie geheime Schlüssel (Verbindungszeichenfolgen, API-Schlüssel, Datenbank-Kennwörter) direkt in Quellcode, Dockerfiles, Helm-Wertedateien oder Pipelinedefinitionen einbetten. Stattdessen:
- Speichern Sie geheime Schlüssel im Key Vault.
- Verwenden Sie den Key Vault Provider for Secrets Store CSI Driver, um Geheimnisse direkt in Pods als Volumes oder Umgebungsvariablen einzubinden. Dieser Ansatz hält Geheimnisse aus Kubernetes-
SecretObjekten heraus, die standardmäßig Base64-kodiert und nicht verschlüsselt sind. - Verwenden Sie für Pipelinegeheimnisse Key Vault-Integration mit Azure Pipelines oder GitHub Actions-Geheimnisse.
- Aktivieren Sie Schutz vor vorläufigem und endgültigem Löschen im Key Vault, um das versehentliche oder böswillige Löschen von Geheimnissen zu verhindern.
Important
Vermeiden Sie das Speichern langlebiger Anmeldeinformationen (geheime Clientschlüssel, Zertifikate oder Kennwörter) in Pipelinevariablen, Umgebungsvariablen oder Kubernetes-Schlüsseln. Verwenden Sie stattdessen verwaltete Identitäten und föderierte Anmeldeinformationen, um den Aufwand für die Rotation von Anmeldeinformationen und die Angriffsfläche zu verringern.
Erstellungsprozess
Verpacken Sie nach Möglichkeit Ihren Buildprozess in einem Docker-Container. Mit dieser Konfiguration können Sie Codeartefakte mithilfe von Docker erstellen, ohne eine Buildumgebung auf jedem Buildcomputer zu konfigurieren. Ein containerisierter Buildprozess vereinfacht das Skalieren der CI-Pipeline durch Hinzufügen neuer Build-Agents. Außerdem kann jeder Entwickler im Team den Code erstellen, indem er den Buildcontainer ausführt.
Mithilfe von Multistage-Builds in Docker können Sie die Buildumgebung und das Laufzeitimage in einer einzelnen Dockerfile-Datei definieren. Beispielsweise erstellt die folgende Dockerfile-Datei eine .NET 10-Anwendung:
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src/Fabrikam.Workflow.Service
COPY Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.csproj
COPY Fabrikam.Workflow.Service/. .
RUN dotnet build Fabrikam.Workflow.Service.csproj -c Release -o /app/build --no-restore
FROM build AS testrunner
WORKDIR /src/tests
COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj
COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]
FROM build AS publish
RUN dotnet publish Fabrikam.Workflow.Service.csproj -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Fabrikam.Workflow.Service.dll"]
Dieses Dockerfile definiert mehrere Buildphasen. Beachten Sie, dass die Stufe namens base das .NET 10 ASP.NET-Laufzeitimage verwendet, während die Stufe namens build das vollständige .NET 10 SDK verwendet. In der build Phase wird das .NET Projekt erstellt. Der endgültige Laufzeitcontainer wird jedoch aus base erstellt, das nur die Runtime enthält und erheblich kleiner als das vollständige SDK-Image ist.
Important
Ab .NET 8 enthalten offizielle Linux-basierte .NET-Container-Images einen Nicht-Root-Benutzer namens app. Die USER app Anweisung in der Dockerfile-Datei führt den Container als dieser nicht privilegierte Benutzer aus, und zwar nach dem Prinzip der geringsten Rechte. ASP.NET Core-Containerimages haben auch ihren Standard-Lauschport von 80 auf 8080 geändert.
Erstellen eines Test Runners
Eine weitere bewährte Methode ist das Ausführen von Komponententests im Container. Der folgende Code zeigt beispielsweise einen Teil einer Dockerfile-Datei, die einen Testläufer erstellt:
FROM build AS testrunner
WORKDIR /src/tests
COPY Fabrikam.Workflow.Service.Tests/*.csproj .
RUN dotnet restore Fabrikam.Workflow.Service.Tests.csproj
COPY Fabrikam.Workflow.Service.Tests/. .
ENTRYPOINT ["dotnet", "test", "--logger:trx"]
Ein Entwickler kann diese Dockerfile-Datei verwenden, um die Tests lokal auszuführen:
docker build . -t delivery-test:1 --target=testrunner
docker run delivery-test:1
Die CI-Pipeline sollte die Tests ebenfalls im Rahmen des Build-Verifizierungsschritts ausführen.
Diese Datei verwendet den Docker-Befehl ENTRYPOINT , nicht den Docker-Befehl RUN , um die Tests auszuführen.
- Wenn Sie den Befehl
RUNverwenden, werden die Tests jedes Mal ausgeführt, wenn Sie das Image erstellen. Wenn SieENTRYPOINTverwenden, sind die Tests optional. Sie werden nur ausgeführt, wenn Sie die Phasetestrunnerexplizit ansteuern. - Ein Fehler im Test führt nicht zu einem Fehler beim Docker-Befehl
build. Mit diesem Verhalten können Sie Containerbuildfehler von Testfehlern unterscheiden. - Testergebnisse können auf einem eingebundenen Volume gespeichert werden.
Bewährte Praktiken für Container
Hier sind einige weitere bewährte Methoden, die beim Arbeiten mit Containern berücksichtigt werden sollten:
- Definieren Sie organisationsweite Konventionen für Containertags, Versionsverwaltung und Benennungskonventionen für Ressourcen, die im Cluster bereitgestellt werden (z. B. Pods und Dienste). Die Verwendung dieser Konventionen erleichtert die Diagnose von Bereitstellungsproblemen.
- Während des Entwicklungs- und Testzyklus erstellt der CI/CD-Prozess viele Containerimages. Nur einige dieser Bilder sind Kandidaten für die Veröffentlichung, und nur einige dieser Releasekandidaten werden zur Produktion heraufgestuft. Verfügen Sie über eine klare Versionsverwaltungsstrategie, damit Sie wissen, welche Images zurzeit in der Produktion bereitgestellt werden und bei Bedarf problemlos auf eine frühere Version zurückwechseln können.
- Stellen Sie immer spezifische Containerversionstags bereit, nicht einfach
latest. - Verwenden Sie Namespaces in Container Registry, um Images, die für die Produktion freigegeben sind, von Images zu isolieren, die noch getestet werden. Verschieben Sie ein Image nur dann in den Produktions-Namespace, wenn Sie bereit sind, es in der Produktion einzusetzen. Durch die Kombination dieser Vorgehensweise mit der semantischen Versionsverwaltung von Containerimages kann die Wahrscheinlichkeit reduziert werden, dass versehentlich eine Version bereitgestellt wird, die nicht für die Veröffentlichung genehmigt wurde.
- Befolgen Sie das Prinzip der geringsten Rechte, indem Sie Container als Benutzer ohne besondere Rechte ausführen. Verwenden Sie in Kubernetes Pod Security Standards mit Pod Security admission (das in Kubernetes 1.25 die veralteten Pod Security Policies ersetzt hat), um Einschränkungen durchzusetzen, etwa dass Container nicht als Root ausgeführt werden. Verwenden Sie das
restrictedProfil für Produktionsworkloads. - Verwenden Sie minimale oder distroless Basisimages (z. B. Alpine-basierte Images, Azure Linux-Basisimages oder distroless Images oder chiseled .NET-Images), um die Angriffsfläche Ihrer Container-Images zu reduzieren.
- Konfigurieren Sie für Premium-Registrierungen eine Aufbewahrungsrichtlinie für die Containerregistrierung , um nicht markierte Manifeste zu löschen. Um Tags nach Alter oder Namen zu löschen, planen Sie eine Container Registry-Aufgabe, die acr purge ausführt. Behalten Sie Images bei, auf die sich aktive Bereitstellungen und Rollbackpläne beziehen.
Helm-Charts
Erwägen Sie, das Tool Helm für das Entwickeln und Implementieren von Diensten zu nutzen. Die folgenden Helm-Funktionen unterstützen eine CI/CD-Pipeline:
- Ein einzelner Microservice wird häufig durch mehrere Kubernetes-Objekte definiert. Helm ermöglicht es, diese Objekte in ein einzelnes Helm-Diagramm zu packen.
- Sie können ein Diagramm mithilfe eines einzigen Helmbefehls anstelle einer Reihe von Kubectl-Befehlen bereitstellen.
- Charts enthalten eine explizite Versionsangabe. Verwenden Sie Helm, um eine Version zu veröffentlichen, Releases anzuzeigen und das Rollback zu einer früheren Version auszuführen. Helm verwendet die semantische Versionsverwaltung zum Nachverfolgen von Updates und Überarbeitungen.
- Helm-Charts verwenden Vorlagen, um Informationen wie Labels und Selektoren nicht über viele Dateien hinweg zu duplizieren.
- Helm kann Abhängigkeiten zwischen Charts verwalten.
- Sie können Charts in einem Helm-Repository, z. B. in einer Container Registry, speichern und in die Build-Pipeline integrieren.
Weitere Informationen finden Sie unter Verwenden der Container Registry als Helm-Repository für Ihre Anwendungs-Charts.
Ein einzelner Microservice erfordert möglicherweise mehrere Kubernetes-Konfigurationsdateien. Um einen Dienst zu aktualisieren, müssen Sie möglicherweise alle diese Dateien bearbeiten, um Selektoren, Bezeichnungen und Bildtags zu aktualisieren. Helm behandelt diese Dateien als einzelnes Paket, das als Diagramm bezeichnet wird, und erleichtert das Aktualisieren der YAML-Dateien mithilfe von Variablen. Helm verwendet eine Vorlagensprache (basierend auf Go-Vorlagen), mit der Sie parametrisierte YAML-Konfigurationsdateien schreiben können.
Dies ist beispielsweise ein Teil einer YAML-Datei, die eine Bereitstellung definiert:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "package.fullname" . | replace "." "" }}
labels:
app.kubernetes.io/name: {{ include "package.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
annotations:
kubernetes.io/change-cause: {{ .Values.reason }}
...
spec:
template:
spec:
containers:
- name: &package-container_name fabrikam-package
image: {{ .Values.dockerregistry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: LOG_LEVEL
value: {{ .Values.log.level }}
Sie können sehen, dass der Name der Bereitstellung, die Labels und die Containerspezifikation alle Vorlagenparameter verwenden, die Sie bei der Bereitstellung angeben. Beispielsweise in der Befehlszeile:
helm install <release-name> oci://<registry>/<repository>/<package-chart-name> --version <desiredVersion> \
--set image.tag=0.1.0 \
--set image.repository=package \
--set dockerregistry=$ACR_SERVER \
--namespace backend
Obwohl eine CI/CD-Pipeline ein Diagramm direkt in Kubernetes installieren kann, erstellen Sie ein Diagrammarchiv (TGZ-Datei), und verschieben Sie das Diagramm an ein Helm-Repository wie container Registry. Weitere Informationen finden Sie unter Packen und Bereitstellen von Helmdiagrammen (HelmDeploy-Aufgabe).
Revisions
Helm-Charts haben immer eine Versionsnummer, die dem Schema der semantischen Versionierung folgen muss. Ein Diagramm kann außerdem ein appVersion enthalten. Dieses Feld ist optional und muss nicht mit der Diagrammversion verknüpft sein. Einige Teams möchten Anwendungen möglicherweise separat von Updates für die Diagramme versionsieren. Ein einfacherer Ansatz besteht darin, eine Versionsnummer zu verwenden. Daher gibt es eine Beziehung zwischen Diagrammversion und Anwendungsversion. Auf diese Weise können Sie ein Chart pro Release speichern und das gewünschte Release komfortabel bereitstellen:
helm install <package-chart-name> --version <desiredVersion>
Eine weitere bewährte Methode besteht im Angeben einer Anmerkung für den Änderungsgrund in der Bereitstellungsvorlage:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "delivery.fullname" . | replace "." "" }}
labels:
...
annotations:
kubernetes.io/change-cause: {{ .Values.reason }}
Mit dieser Anmerkung können Sie das Änderungsursachenfeld für jede Überarbeitung mithilfe des kubectl rollout history Befehls anzeigen. Im vorherigen Beispiel wird die Änderungsursache als Helm-Diagrammparameter bereitgestellt.
kubectl rollout history deployments/delivery-v010 -n backend
deployment.apps/delivery-v010
REVISION CHANGE-CAUSE
1 Initial deployment
Sie können aber auch den Befehl helm list verwenden, um den Revisionsverlauf anzuzeigen:
helm list -n backend
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
delivery-v0.1.0 backend 1 2024-04-07 00:25:30.000000 +0000 UTC deployed delivery-v0.1.0 v0.1.0
Azure Pipelines
Azure Pipelines, ein Dienst in Azure DevOps, verfügt über zwei Pipelinetypen: Buildpipelines und Releasepipelines. Die Build-Pipeline führt den CI-Prozess aus und erstellt Build-Artefakte. Für eine Microservicearchitektur in Kubernetes sind diese Artefakte die Containerimages und Helm-Charts, die jeden Microservice definieren. Die Releasepipeline führt den CD-Prozess aus, der einen Microservice in einem Cluster bereitstellt.
Aufbauend auf dem weiter oben in diesem Artikel beschriebenen CI-Flow, kann eine Buildpipeline aus den folgenden Aufgaben bestehen:
- Erstellen Sie den Testausführungscontainer mithilfe der
Docker-Aufgabe. - Führen Sie die Tests aus, indem Sie mithilfe der
Docker-Aufgabedocker runfür den Testausführungscontainer aufrufen. - Veröffentlichen Sie die Testergebnisse mithilfe der
PublishTestResultsAufgabe. Weitere Informationen finden Sie unter Erstellen eines Bilds. - Führen Sie SAST im Quellcode aus.
- Erstellen Sie den Laufzeitcontainer mithilfe von lokalem
docker buildund derDockerAufgabe oder mithilfe von Builds der Container Registry und derAzureCLIAufgabe. Generieren Sie eine Software-Stückliste (SBOM) für das Image, z. B. mithilfe des Microsoft SBOM-Tools, und veröffentlichen Sie diese als Pipeline-Artefakt, das dem Image-Digest zugeordnet ist, oder fügen Sie diese dem Image in der Container Registry hinzu. - Führen Sie die Sicherheitsrisikoüberprüfung des Containerimages aus (z. B. mithilfe von Microsoft Defender für Container oder einem Tool ohne Microsoft wie Trivy), um bekannte Sicherheitsrisiken zu erkennen, bevor das Image veröffentlicht wird.
- Übertragen Sie das Containerimage mithilfe der Aufgabe
DockeroderAzureCLIan Container Registry (oder eine andere Containerregistrierung). - Signieren Sie das übertragene Image anhand des unveränderlichen Digests, um seine Integrität und Authentizität sicherzustellen. Befolgen Sie für Azure Pipelines die Anleitung zum Signieren mit Notation.
- Packen Sie das Helmdiagramm mithilfe der
HelmDeployAufgabe. - Übertragen Sie das Helm-Paket mithilfe der Aufgabe
HelmDeployan Container Registry (oder ein anderes Helm-Repository).
Die Ausgabe der CI-Pipeline ist ein produktionsbereites Containerimage und ein aktualisiertes Helm-Chart für den Microservice. An diesem Punkt kann die Releasepipeline übernehmen. Für jeden Microservice gibt es eine einzigartige Releasepipeline. Die Release-Pipeline wurde so konfiguriert, dass die Quelle des Triggers auf die CI-Pipeline festgelegt wurde, die das Artefakt veröffentlicht hat. Mit dieser Pipeline können Sie jeden Microservice unabhängig bereitstellen. Die Releasepipeline führt die folgenden Schritte aus:
- Stellen Sie das Helm-Diagramm für Entwicklungs-/QA/Staging-Umgebungen bereit. Sie können den
helm upgradeBefehl mit der--installKennzeichnung verwenden, um die erste Installation und nachfolgende Upgrades zu unterstützen. - Warten auf einen Genehmiger, der die Bereitstellung genehmigt oder ablehnt.
- Taggen Sie das Container-Image für die Veröffentlichung neu.
- Übertragen Sie das Releasetag per Push in die Containerregistrierung.
- Stellen Sie das Helm-Chart im Produktionscluster bereit. Verwenden Sie Ratify mit Azure Policy, um Bildsignaturen während der Zulassung zu überprüfen, und konfigurieren Sie separat eine Richtlinie für zulässige Bilder, um Bilder auf vertrauenswürdige Registrierungen einzuschränken.
Hinweis
Um AKS das Abrufen von Images aus der Containerregistrierung ohne separate Image-Pullschlüssel zu ermöglichen, verwenden Sie die AKS-to-Container-Registry-Integration für eine Registrierung, die registrierungsweite RBAC verwendet. Für eine ABAC-fähige Registrierung wird diese Integration nicht unterstützt. Weisen Sie stattdessen der vom kubelet verwalteten Identität des Clusters die Rolle Container Registry Repository Reader zu.
Weitere Informationen zum Erstellen einer Releasepipeline finden Sie unter Release pipelines, draft releases, and release options (Releasepipelines, Entwurfsreleases und Releaseoptionen).
Im folgenden Diagramm ist der in diesem Artikel beschriebene End-to-End-CI/CD--Prozess dargestellt:
Alternative zu GitHub Actions
Wenn Ihr Team GitHub für die Quellcodeverwaltung verwendet, stellt GitHub Actions eine entsprechende CI/CD-Plattform bereit. Berücksichtigen Sie zusätzlich zu den zuvor erwähnten Startworkflows und der OIDC-Authentifizierung diese GitHub spezifischen Funktionen, wenn Sie auf AKS abzielen:
- Umgebungen und Schutzregeln. Wenn Ihr GitHub-Plan und die Sichtbarkeit des Repositorys dies unterstützen, verwenden Sie GitHub-Umgebungen mit erforderlichen Reviewern, Wartezeiten und Deployment-Branches, um Freigabegates zu implementieren.
- Containerüberprüfung. Verwenden Sie GitHub Actions Marketplace-Aktionen für Trivy, Microsoft Defender for DevOps oder ähnliche Tools zum Scannen von Containerimages direkt in Ihrem Workflow.
Observierbarkeit und Systemüberwachung
Implementieren Sie Observability über die gesamte CI/CD-Pipeline und die Laufzeitumgebung hinweg:
- Pipelineüberwachung. Verfolgen Sie Build-Dauern, Testerfolgsraten, die Häufigkeit von Bereitstellungen und Fehlerraten. Azure DevOps bietet integrierte Analysen. GitHub Actions können nicht Microsoft Dashboards verwenden.
- Laufzeitüberwachung. Verwenden Sie Azure Monitor verwalteten Dienst für Prometheus und Azure Managed Grafana, um AKS-Clusterintegritäts- und Workloadmetriken zu überwachen.
- Anwendungstelemetrie. Instrumentieren Sie Ihre Microservices mit Azure Monitor Application Insights für verteilte Ablaufverfolgung, Anforderungsprotokollierung und Abhängigkeitsnachverfolgung.
- Alarmierung. Konfigurieren Sie Warnungen für Bereitstellungsfehler, Pod-Neustarts, hohe Fehlerraten und Ressourcensättigung, um eine schnelle Reaktion auf Vorfälle zu ermöglichen.
Abstimmung mit dem Well-Architected Framework
Berücksichtigen Sie beim Entwerfen Ihrer CI/CD-Pipeline für Microservices auf Kubernetes die Säulen des Azure Well-Architected Frameworks:
| Säule | Considerations |
|---|---|
| Reliability | Automatisierte Rollbackstrategien, Health-Probes bei Bereitstellungen, Blue-Green- oder Canary-Release-Strategien, Pod-Disruption-Budgets. |
| Security | Geheime Authentifizierung (Workload-ID, OIDC), Imagesignierung, Lieferkettensicherheit, RBAC mit geringsten Rechten, Netzwerkrichtlinien. |
| Kostenoptimierung | Die richtige Dimensionierung von Build-Agenten, die Verwendung ephemerer selbstgehosteter Runner, die Implementierung von Image-Aufbewahrungsrichtlinien für Container-Registrierungen und die ausschließliche Verwendung von Spot-Knotenpools für unterbrechungstolerante Nicht-Produktions-Workloads. |
| Operative Exzellenz | GitOps für deklarative Bereitstellungen, Infrastruktur als Code, Pipeline as Code (YAML), Observierbarkeit und Runbook-Automatisierung. |
| Performance-Effizienz | Parallele Pipeline-Stufen, Build-Caching (Docker-Layer-Caching, Dependency-Caching), horizontale Pod-Autoskalierung. |
Beitragende
Microsoft verwaltet diesen Artikel. Die folgenden Mitwirkenden haben diesen Artikel geschrieben.
Hauptautor:
- Ray Kao | Principal Solutions Engineer
Um nicht öffentliche LinkedIn-Profile zu sehen, melden Sie sich bei LinkedIn an.
Nächste Schritte
- Eine Git-Branching-Strategie einführen
- Was ist Azure Pipelines?
- Releasepipelines, Entwurfsversionen und Releaseoptionen
- Bereitstellungssteuerung mithilfe von Genehmigungen
- Einführung in Azure Container Registry
- Microsoft Entra Workload ID mit AKS
- Azure Key Vault-Anbieter für Secrets Store CSI Driver
- DevSecOps in AKS