Manuelle Bereitstellungen sind nicht fehleranfällig. Darüber hinaus bestehen sie aus einer Reihe sich wiederholender und komplexer Aufgaben. Die Entwicklungsteams haben Angst vor der Komplexität der Bereitstellung einer neuen Version einer Anwendung und den damit verbundenen Kopfschmerzen. Manchmal erfordert die Bereitstellung einer Anwendung fortgeschrittene Plattformkenntnisse. Das Debuggen von Bereitstellungsproblemen ist ein langwieriger Prozess.
FluxCD hilft Ihnen, den Aufwand für manuelle und sich wiederholende Aufgaben zu reduzieren. Außerdem werden Bereitstellungsfehler und menschliche Interaktionen minimiert. Es bietet Tools zum Verfolgen und Aktualisieren des Status Ihrer Bereitstellungen mithilfe deklarativer Dateien und vereinfacht so den Bereitstellungs- und Debugging-Prozess für Ihre Entwicklungsteams.
In diesem Artikel wird die Automatisierung Ihrer Bereitstellungsprozesse untersucht, um sie mithilfe von FluxCD , Flagger und Grafana in kontinuierliche Bereitstellungsprozesse umzuwandeln.
Lesen Sie den ersten Artikel, um mehr über die kontinuierliche Bereitstellung einer Anwendung zu erfahren:
CI/CD Hands-On: Ein einfacher, aber funktionaler Continuous-Integration-Workflow [Teil 1] .
GitHub-Beispiel: https://github.com/joan-mido-qa/continious-deployment-example
Verwenden Sie KinD und Terraform , um den Kubernetes-Cluster einzurichten. Erstellen Sie zunächst den Cluster und exportieren Sie die Kubernetes-Konfiguration, um den Kubernetes-Anbieter festzulegen:
$ kind create cluster --name develop $ kind export kubeconfig --name develop --kubeconfig kubeconfig
Erstellen Sie ein neues GitHub-Repository und ein Entwickler-Token mit Repository-Berechtigungen. Terrafom benötigt es zum Einrichten von FluxCD. Initialisieren Sie Terraform und übernehmen Sie die Änderungen:
$ terraform init $ terraform apply -var="github_owner=owner_name" -var="github_repository=repo_name" # Introduce your GitHub token
Sobald Terraform den Installationsprozess abgeschlossen hat, sollte FluxCD in Ihrem KinD-Cluster und ein neuer Ordner namens Cluster in Ihrem Repository ausgeführt werden.
Unter der Haube installiert Terraform MetalLB und konfiguriert den IP-Bereich. Mehr über die MetalLB-Konfiguration können Sie im ersten Teil des Artikels lesen:
resource "helm_release" "metallb" { name = "metallb" repository = "https://metallb.github.io/metallb" chart = "metallb" } data "docker_network" "kind" { name = "kind" } resource "kubectl_manifest" "kind-address-pool" { yaml_body = yamlencode({ "apiVersion" : "metallb.io/v1beta1", "kind" : "IPAddressPool", "metadata" : { "name" : "kind-address-pool" }, "spec" : { "addresses" : [replace(tolist(data.docker_network.kind.ipam_config)[0].subnet, ".0.0/16", ".255.0/24")] } }) depends_on = [helm_release.metallb] } resource "kubectl_manifest" "kind-advertisement" { yaml_body = <<YAML apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: kind-advertisement YAML depends_on = [helm_release.metallb] }
Anschließend wird FLuxCD Helm Chart installiert und das GitHub-Repository für die Verwendung von FluxCD konfiguriert:
resource "helm_release" "flux" { repository = "https://fluxcd-community.github.io/helm-charts" chart = "flux2" name = "flux2" namespace = "flux-system" create_namespace = true version = "2.9.2" } resource "tls_private_key" "flux" { depends_on = [helm_release.flux] algorithm = "ECDSA" ecdsa_curve = "P256" } resource "github_repository_deploy_key" "flux" { depends_on = [tls_private_key.flux] title = "Flux" repository = var.github_repository key = tls_private_key.flux.public_key_openssh read_only = "false" } resource "flux_bootstrap_git" "this" { depends_on = [github_repository_deploy_key.flux] path = "clusters/develop" }
Vorschläge für Pre-Commit-Hooks:
FluxCD ist ein GitOps-Tool, um einen Kubernetes-Cluster mit den neuesten Quellcodeverwaltungsänderungen (wie Git-Repositorys) zu halten. Flux automatisiert die Bereitstellung von neuem Code.
Sobald Flux im Cluster ausgeführt wird, sehen wir uns an, wie es funktioniert. Wir werden ingress-nginx als Ingress-Provider bereitstellen. Flux erzwingt nicht die Projektordnerstruktur. Sie können es nach Ihren Wünschen konfigurieren oder Ihrem bevorzugten Standard folgen.
Erstellen Sie einen Ordner mit dem Namen „ base“ in einem Ordner mit dem Namen „infrastructure“ . Der Basisordner enthält die grundlegende Infrastrukturkonfiguration für alle Ihre Cluster. Erstellen Sie als Nächstes einen Ordner mit dem Namen ingress-nginx . Verwenden Sie den Namespace-Namen als Ordnernamen.
--- apiVersion: v1 kind: Namespace metadata: name: ingress-ngnix --- apiVersion: source.toolkit.fluxcd.io/v1beta1 kind: HelmRepository metadata: name: ingress-nginx spec: interval: 2h url: https://kubernetes.github.io/ingress-nginx --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: ingress-nginx spec: interval: 15m chart: spec: chart: ingress-nginx version: 4.7.1 sourceRef: kind: HelmRepository name: ingress-nginx interval: 15m --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: ingress-ngnix resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
Verwenden Sie mehrere Dateien, um Ihre Objekte zu definieren: helmrelease.yaml , helmrepository.yaml , namespace.yaml , kustomization.yaml usw.
Die Kustomisierung liest und verarbeitet die Ressourcen, um sie anzuwenden. Zu guter Letzt müssen Sie ein Kustomization-Objekt erstellen, um Ihre Clusterkonfiguration zu synchronisieren. Erstellen Sie eine YAML-Datei mit dem Namen „infrastructure.yaml“ im Ordner „cluster/cluster_name“ :
--- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: infra-base namespace: flux-system spec: interval: 1h retryInterval: 1m timeout: 5m sourceRef: kind: GitRepository name: flux-system path: ./infrastructure/base prune: true wait: true
Nachdem Sie Ihre Änderungen festgeschrieben und in Ihr Repository übertragen haben, gleicht Flux den Clusterstatus ab, um das ingress-nginx-Helm-Chart zu installieren.
Flagger ist ein Kubernetes-Betreiber, der Ihre Anwendung schrittweise mithilfe von Blue/Green-Bereitstellungen, Canary-Release oder A/B-Tests bereitstellt.
Sie können den Basisordner verwenden, um Ihren Stack in allen Ihren Clustern zu installieren, oder einen anderen Ordner verwenden, um Ihre Installation je nach Cluster anzupassen. Beispielsweise möchten wir Flagger nur im Entwicklungscluster installieren.
Erstellen Sie einen neuen Ordner mit Ihrem Clusternamen im Infrastrukturordner . Erstellen Sie dann eine Datei mit dem Namen i nfrastructure.yaml in Ihrem Cluster/Clustername :
--- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: infra-cluster-name namespace: flux-system spec: dependsOn: - name: infra-base interval: 1h retryInterval: 1m timeout: 5m sourceRef: kind: GitRepository name: flux-system path: ./infrastructure/cluster_name prune: true
FluxCD synchronisiert den Clusterstatus nach Anwendung der Infra-Base-Kustomisierung. Installieren Sie Flagger und erstellen Sie die folgende YAML-Datei im Ordner „infrastructure/cluster_name/flagger-system“ :
--- apiVersion: v1 kind: Namespace metadata: name: flagger-system --- apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: HelmRepository metadata: name: flagger spec: interval: 1h url: https://flagger.app --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: flagger spec: interval: 1h install: crds: CreateReplace upgrade: crds: CreateReplace chart: spec: chart: flagger version: 1.xx interval: 6h sourceRef: kind: HelmRepository name: flagger --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: flagger-loadtester spec: interval: 1h chart: spec: chart: loadtester version: 0.xx interval: 6h sourceRef: kind: HelmRepository name: flagger --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: flagger-system resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
Um die Pipeline für die kontinuierliche Bereitstellung der Podinfo- Anwendung zu erstellen, erstellen Sie die Installations-YAML-Datei im Verzeichnis apps/cluster_name/podinfo *:*
--- apiVersion: v1 kind: Namespace metadata: name: podinfo --- apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: HelmRepository metadata: name: podinfo spec: interval: 5m url: https://stefanprodan.github.io/podinfo --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: podinfo spec: releaseName: podinfo chart: spec: chart: podinfo version: 6.5.0 sourceRef: kind: HelmRepository name: podinfo interval: 50m install: remediation: retries: 3 values: ingress: enabled: true className: nginx hpa: enabled: true --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
Sie können das Python-Skript „update hosts“ verwenden, um die Hosts Ihrer lokalen Umgebung zu aktualisieren, wie im ersten Teil des Artikels erläutert.
Erstellen Sie dann die Kustomization-Datei im Ordner „cluster/cluster_name“, um Ihre Apps zu synchronisieren:
--- apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: apps namespace: flux-system spec: interval: 10m0s dependsOn: - name: infra-cluster-name sourceRef: kind: GitRepository name: flux-system path: ./apps/cluster_name prune: true wait: true timeout: 5m0s
Als Nächstes können wir FluxCD so konfigurieren, dass die Podinfo-Image-Helm-Chart-Version automatisch aktualisiert wird. Um die automatische Bildaktualisierung zu konfigurieren, müssen wir ein Bild-Repository erstellen, um nach neuen Bild-Tags zu suchen, eine Bildaktualisierungsrichtlinie, um das zu aktualisierende Versionsmuster zu definieren, und eine automatische Bildaktualisierung, um das Repository so zu konfigurieren, dass die Änderung übertragen wird.
--- apiVersion: image.toolkit.fluxcd.io/v1beta2 kind: ImageRepository metadata: name: podinfo-chart spec: image: ghcr.io/stefanprodan/charts/podinfo interval: 5m --- apiVersion: image.toolkit.fluxcd.io/v1beta2 kind: ImagePolicy metadata: name: podinfo-chart spec: imageRepositoryRef: name: podinfo-chart policy: semver: range: 6.xx --- apiVersion: image.toolkit.fluxcd.io/v1beta1 kind: ImageUpdateAutomation metadata: name: podinfo-chart spec: interval: 30m sourceRef: kind: GitRepository name: flux-system namespace: flux-system git: checkout: ref: branch: main commit: author: email: [email protected] name: fluxcdbot messageTemplate: 'chore(develop): update podinfo chart to {{range .Updated.Images}}{{println .}}{{end}}' push: branch: main update: path: ./apps/cluster_name/podinfo strategy: Setters --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: [...] - imagepolicy.yaml - imagerepository.yaml - imageautoupdate.yaml
Wenden Sie abschließend die Bildaktualisierungsrichtlinie auf das Bild oder Tag an, das Sie aktualisieren möchten:
apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: podinfo spec: releaseName: podinfo chart: spec: chart: podinfo version: 6.5.0 # {"$imagepolicy": "podinfo:podinfo-chart:tag"} sourceRef: kind: HelmRepository name: podinfo interval: 50m install: remediation: retries: 3
Immer wenn Podinfo Chart eine neue Version im Bereich 6.xx hat, sendet FluxCD einen Commit an das Repository und aktualisiert die aktuelle Version mit der neueren.
Geben Sie eine neue Anwendungsversion für eine kleine Untergruppe von Benutzern frei, um sicherzustellen, dass die Anwendungsfunktionalität, Leistung und Sicherheit den Erwartungen entsprechen. FluxCD aktualisiert automatisch die Chart-Version und stellt sie den Benutzern zur Verfügung. Im Falle eines Fehlers setzt FluxCD die Image-Version automatisch auf die vorherige zurück.
Flagger stellt die neue Anwendungsversion nach und nach einer Untergruppe von Benutzern bereit und überwacht den Anwendungsstatus. Es erstellt eine neue Bereitstellung für die neuen Anwendungsversionen und leitet den eingehenden Datenverkehr schrittweise an die neue Bereitstellung weiter. Es wird die Canary-Bereitstellung nach einer erfolgreichen Analyse der Metriken fördern. Im Falle eines Fehlers löscht Flagger die neue Bereitstellung und stellt den Datenverkehrsfluss zur alten Bereitstellung wieder her. Dieser Prozess gibt vor, Mängel, Probleme und Fehler zu erkennen, bevor die Anwendung allen Benutzern bereitgestellt wird.
Erstellen Sie zunächst eine Metrikvorlage, um Flagger über den Bewerbungsstatus zu informieren. Wir verwenden Prometheus, um die Erfolgsquote der Anfrage zu messen:
--- apiVersion: flagger.app/v1beta1 kind: MetricTemplate metadata: name: podinfo-request-success-rate spec: provider: type: prometheus address: http://loki-stack-prometheus-server.loki-stack:80 query: | 100 - sum( rate( http_requests_total{ app_kubernetes_io_name="podinfo", namespace="{{ namespace }}", status!~"5.*" }[{{ interval }}] ) ) / sum( rate( http_requests_total{ app_kubernetes_io_name="podinfo", namespace="{{ namespace }}", }[{{ interval }}] ) ) * 100 --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: [...] - metrictemplate.yaml
Definieren Sie dann den Canary-Release-Prozess. Wir nutzen Nginx als Anbieter, um den eingehenden Datenverkehr zu gestalten. Flagger bietet mehrere Möglichkeiten und Tools zum Konfigurieren Ihrer Releases.
--- apiVersion: flagger.app/v1beta1 kind: Canary metadata: name: podinfo spec: provider: nginx targetRef: apiVersion: apps/v1 kind: Deployment name: podinfo ingressRef: apiVersion: networking.k8s.io/v1 kind: Ingress name: podinfo autoscalerRef: apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler name: podinfo progressDeadlineSeconds: 60 service: port: 9898 targetPort: 9898 analysis: interval: 10s threshold: 10 maxWeight: 50 stepWeight: 5 metrics: - name: podinfo-request-success-rate thresholdRange: min: 99 interval: 1m webhooks: - name: acceptance-test type: pre-rollout url: http://flagger-loadtester.flagger-system/ timeout: 30s metadata: type: bash cmd: curl -sd 'test' http://podinfo-canary.podinfo:9898/token | grep token - name: load-test url: http://flagger-loadtester.flagger-system/ timeout: 5s metadata: cmd: hey -z 1m -q 10 -c 2 http://podinfo-canary.podinfo:9898/healthz --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: podinfo resources: [...] - canary.yaml
Flagger benötigt die Verweise auf Ihre Bereitstellung, Ihren Ingress und Ihren Pod-Auto-Escaler. Immer wenn Flagger eine neue Version erkennt, skaliert es die Bereitstellung, erstellt einen primären und sekundären Dienst und konfiguriert nginx so, dass der eingehende Datenverkehr an den entsprechenden Dienst gesendet wird. Verwenden Sie die Eigenschaften „maxWeight“ und „stepWeight“, um den maximalen Prozentsatz der Datenverkehrsumleitung und den Prozentsatz der inkrementellen Schritte zu konfigurieren.
Testen Sie Ihre Anwendung mit Flagger-Hooks. Es hat mehrere Haken. Die Akzeptanz-Hooks prüfen die Canary-Bereitstellungsbereitschaft und der Lasttest-Hook generiert konstanten eingehenden Datenverkehr.
Flagger überwacht den Canary-Release-Status anhand der vordefinierten Erfolgsratenmetrik, um über den Fall einer Canary-Bereitstellungsförderung zu entscheiden. Flagger erwartet eine Erfolgsquote der Anfragen von 99 %, um die Canary-Bereitstellung voranzutreiben. Verwenden Sie die Schwellenwerteigenschaft, um eine maximale Anzahl fehlgeschlagener Metrikprüfungen vor dem Rollback zu konfigurieren.
Verwenden Sie den Loki-Stack, um den Status der Clusterressourcen mithilfe von Grafana + Loki + Prometheus zu überwachen. Installieren Sie den Loki-Stack, indem Sie die folgende YAML-Datei im Ordner „infrastructure/cluster_name/loki-stack“ erstellen:
--- apiVersion: v1 kind: Namespace metadata: name: loki-stack --- apiVersion: source.toolkit.fluxcd.io/v1beta1 kind: HelmRepository metadata: name: grafana spec: interval: 2h url: https://grafana.github.io/helm-charts --- apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: name: loki-stack spec: interval: 1h chart: spec: chart: loki-stack version: v2.9.11 sourceRef: kind: HelmRepository name: grafana interval: 1h values: grafana: enabled: true ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx hosts: - grafana.local prometheus: enabled: true nodeExporter: enabled: true --- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: loki-stack resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml
Die Loki-Stack-Installation ermöglicht dem Grafana Ingress den Zugriff auf Grafana, Prometheus zum Sammeln Ihrer Umgebungsmetriken und Node Exporter zum Exportieren Ihrer Knotenmetriken.
Sie können das Python-Skript „Update Hosts“ verwenden, um die Hosts Ihrer lokalen Umgebung zu aktualisieren, wie im ersten Teil des Artikels erläutert
Melden Sie sich mit dem Admin-Benutzernamen und dem Passwort bei Grafana an. Sie können das Administratorkennwort mithilfe der Installationswerte definieren. Standardmäßig erstellt das Diagramm ein Kubernetes-Geheimnis, um ein zufälliges Passwort zu speichern. Beschreiben Sie das Geheimnis, um den Base64-Passwortwert zu erhalten und ihn zu entschlüsseln.
Sie können Ihr Lieblings-Dashboard importieren, indem Sie dessen ID verwenden oder den rohen JSON-Code kopieren:
Im ersten Artikel wurde untersucht, wie eine gut getestete Anwendung bereitgestellt werden kann. In diesem Artikel wird erläutert, wie Sie eine Leistung kontinuierlich bereitstellen und den Status der Bereitstellung überwachen.
FluxCD und Flagger bieten mehrere Funktionen zum kontinuierlichen Testen, Bereitstellen und Überwachen Ihres Anwendungsstatus. In diesem Artikel werden einige davon verwendet, aber wir haben die Webhooks- und Benachrichtigungsfunktionen nicht gesehen. Verwenden Sie die Benachrichtigungsfunktionen, um zu erfahren, wann eine Bereitstellung fehlgeschlagen ist, oder die Web-Hooks-Funktion, um die Bereitstellung in eine neue Umgebung hochzustufen oder Ihre Tests mit neuen Versionen zu starten. Integrieren Sie FluxCD zusammen mit anderen Tools, um Ihre Bereitstellungspipeline zu bereichern.
Vermeiden Sie manuelle Bereitstellungen. Sie sind komplex und nicht fehleranfällig. Ermutigen Sie die Entwicklungsteams, ihre Anwendungen zu warten, um den Bereitstellungsprozess zu vereinfachen. Automatische Bereitstellungen reduzieren die Vorlaufzeit, die Feedbackschleife und die Gesamtkosten. Entwickler können sich auf das Wesentliche konzentrieren.