15 Min. Lesezeit

Lernziele

Am Ende dieses Moduls werden Sie in der Lage sein:

  • Eine GitHub-Actions-Workflow zu erstellen, der ein Container erstellt, es an das IONOS-Container-Registrierungspush und es auf jeden Push an `main` auf Managed Kubernetes bereitstellt
  • Eine äquivalente GitLab-CI-Pipeline mit IONOS-spezifischen Build-, Push- und Deploy-Phasen zu konfigurieren
  • Terraform in CI/CD mit `plan` bei Pull-Requests und `apply` bei Merge auszuführen, wobei `IONOS_TOKEN` und andere Geheimnisse sicher verwaltet werden
  • Bereitstellungsstrategien und Rollback mit `kubectl rollout` und Terraform-Statuswiederherstellung zu implementieren
  • Wiederverwendbare Terraform-Module aus der TaskBoard-Infrastruktur zu extrahieren, um eine Team-Modulbibliothek zu erstellen

Einheit 3.3: CI/CD-Pipelines für IONOS

Einführung

Sie haben TaskBoard containerisiert, dessen Images in das IONOS Container Registry hochgeladen und es manuell auf Managed Kubernetes bereitgestellt. Das Ausführen von docker push und kubectl apply von Ihrem Laptop aus skaliert nicht auf ein Team und überlebt nicht den Moment, in dem Sie vergessen, welcher Image-Tag in der Produktion ist. In dieser Einheit verbinden Sie die gesamte Schleife so, dass ein git push der einzige manuelle Schritt ist. Ein Commit löst einen Build aus, das Image landet im Container Registry mit dem git-SHA-Tag und das neue Tag wird auf die Cluster ausgerollt.

Sie werden auch die Infrastruktur unter die gleiche Disziplin bringen. Terraform plan wird bei jedem Pull-Request ausgeführt, damit die Überprüfer den Diff sehen, bevor sich etwas ändert, und apply wird nur nach dem Merge ausgeführt. Zwei IONOS-Einschränkungen prägen jede Pipeline, die Sie hier schreiben: die API ist asynchron, sodass die Bereitstellungen auf die Bereitschaft warten müssen, anstatt sie anzunehmen, und die Container-Registrierungsauthentifizierung ist tokenbasiert mit Docker-Anmeldung, ohne RBAC und ohne teambezogene Repositorys, sodass die Anmeldedaten in CI-Geheimnissen gespeichert werden.

1. Pipeline-Design für IONOS

Eine IONOS-Pipeline teilt sich in zwei verschiedene Flüsse auf, die keine Aufgabe gemeinsam haben sollten. Änderungen an der Anwendung folgen build -> test -> push image -> deploy to Kubernetes. Änderungen an der Infrastruktur folgen plan -> apply. Eine Mischung beider bedeutet, dass ein Tippfehler in einem Kubernetes-Manifest eine dringende Infrastrukturkorrektur blockieren kann und eine langsame terraform apply jeden Anwendungs-Deploy verzögert.

Der Anwendungsfluss endet mit kubectl apply oder, genauer gesagt, einer kontrollierten Image-Tag-Aktualisierung gegen eine bestehende Bereitstellung. Der Infrastrukturfluss endet mit terraform apply gegen Ihre IONOS-Ressourcen. Beide Flüsse authentifizieren sich bei IONOS, verwenden jedoch unterschiedliche Anmeldeinformationen: Der Anwendungsfluss benötigt ein Container-Registrierungstoken und ein kubeconfig, während der Infrastrukturfluss ein IONOS_TOKEN-Bearer-Token für den Cloud-API benötigt.

1.1 Tagging von Bildern mit dem Git-SHA

Niemals :latest bereitstellen. Ein mutabler Tag macht Rollbacks mehrdeutig und bricht den Link zwischen einem laufenden Pod und dem Commit, der es produziert hat. Jedes Bild mit dem unveränderlichen Git-SHA taggen, damit die laufende Revision immer nachvollziehbar ist.

# Derive an immutable tag from the commit
REGISTRY="taskboard.cr.de-fra.ionos.com"
SHA=$(git rev-parse --short HEAD)
IMAGE="${REGISTRY}/taskboard-api:${SHA}"

docker build -t "${IMAGE}" ./api
docker push "${IMAGE}"

Der Registrierungs-Hostname folgt dem Muster {registry-name}.cr.{location-with-dash}.ionos.com, beispielsweise tue1608es.cr.es-vit.ionos.com. Der Hostname wird erst zugewiesen, nachdem das Registrierungs-System den Zustand "Running" erreicht hat und ist bis dahin leer, sodass eine Pipeline, die ein frisches Registrierungs-System bereitstellt, den Hostnamen aus der Terraform-Ausgabe lesen muss, anstatt ihn hart zu codieren.

1.2 Trennung der Anwendungs- und Infrastruktur-Repositorys

Halten Sie Terraform in einem Infrastruktur-Repository und Kubernetes-Manifeste sowie Anwendungscode in einem Anwendungs-Repository. Das Infrastruktur-Repository wird auf Merge angewendet; das Anwendungs-Repository wird auf Push erstellt und bereitgestellt. Diese Trennung hält den Radius einer schlechten Änderung klein und ermöglicht es Ihnen, verschiedenen Teams unterschiedlichen Zugriff zu gewähren.

taskboard-app/          # build, push, kubectl deploy
  api/Dockerfile
  k8s/deployment.yaml
  .github/workflows/deploy.yml
taskboard-infra/        # terraform plan/apply
  main.tf
  modules/
  .github/workflows/terraform.yml

2. GitHub Actions für IONOS

Ein GitHub Actions-Workflow für den Anwendungsfluss hat drei logische Stufen in einem einzigen Job: Build und Test, Docker-Anmeldung und Push, dann Bereitstellung in Managed Kubernetes. Die IONOS-spezifischen Teile sind die Registrierungsanmeldung (tokenbasiert) und die kubeconfig-Abruf.

2.1 Speichern von IONOS-Geheimnissen

Token gehören niemals in das Repository. Speichern Sie das Container-Registrierungstoken und die kubeconfig als Repository- oder Umgebungsgeheimnisse. Das Container-Registrierungstoken-Passwort wird nur einmal bei der Erstellung angezeigt, daher erfassen Sie es sofort und speichern es in CI. Ein Registrierungstoken kann permanent oder temporär mit einem expiryDate sein, und bei Ablauf des Tokens wird es gelöscht, anstatt deaktiviert, was bedeutet, dass ein abgelaufenes Token in CI den Docker-Anmeldevorgang sofort fehlschlägt, anstatt stillschweigend zu verschlechtern.

Geheimnisname Inhalt Verwendet von
CR_USERNAME Container-Registrierungstoken-Name docker login
CR_PASSWORD Container-Registrierungstoken-Passwort (wird nur einmal angezeigt) docker login
KUBECONFIG base64-kodierte kubeconfig aus Terraform-Ausgabe kubectl
IONOS_TOKEN Cloud-API-Bearer-Token Terraform / ionosctl

2.2 Der Bereitstellungs-Workflow

# .github/workflows/deploy.yml
name: deploy-taskboard
on:
  push:
    branches: [main]

env:
  REGISTRY: taskboard.cr.de-fra.ionos.com
  IMAGE_NAME: taskboard-api

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set image tag
        run: echo "TAG=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"

      - name: Run tests
        run: |
          cd api
          pip install -r requirements.txt
          pytest

      - name: Log in to IONOS Container Registry
        run: echo "${{ secrets.CR_PASSWORD }}" | docker login "$REGISTRY" \
             -u "${{ secrets.CR_USERNAME }}" --password-stdin

      - name: Build and push image
        run: |
          docker build -t "$REGISTRY/$IMAGE_NAME:$TAG" ./api
          docker push "$REGISTRY/$IMAGE_NAME:$TAG"

      - name: Configure kubectl
        run: |
          mkdir -p "$HOME/.kube"
          echo "${{ secrets.KUBECONFIG }}" | base64 -d > "$HOME/.kube/config"

      - name: Deploy to Managed Kubernetes
        run: |
          kubectl set image deployment/taskboard-api \
            api="$REGISTRY/$IMAGE_NAME:$TAG"
          kubectl rollout status deployment/taskboard-api --timeout=180s

kubectl set image aktualisiert nur das Bildfeld im bestehenden Deployment, was einen rollierenden Update auslöst, ohne das gesamte Manifest erneut anzuwenden. Der kubectl rollout status-Schritt blockiert, bis die Bereitstellung abgeschlossen ist oder der Timeout ausgelöst wird, was die richtige Methode ist, um einen fehlgeschlagenen Bereitstellungsprozess als fehlgeschlagenen Pipeline-Prozess zu kennzeichnen. Die kubeconfig selbst stammt aus dem Managed Kubernetes-Cluster: Sie können sie aus den Cluster-Einstellungen herunterladen oder in einer automatisierten Pipeline aus der Terraform-Ausgabe (in Einheit 3.2 behandelt) lesen und den base64-kodierten Wert als das KUBECONFIG-Geheimnis speichern.

3. GitLab CI für IONOS

GitLab CI drückt den gleichen Ablauf als separate Stadien in .gitlab-ci.yml aus. Die IONOS-spezifischen Details sind identisch: Token-basiertes Docker-Login zum Registry und ein Kubeconfig für den Cluster. GitLab bietet einen Docker-in-Docker-Service für das Erstellen von Bildern innerhalb der Pipeline.

3.1 Pipeline-Stadien

# .gitlab-ci.yml
stages: [test, build, deploy]

variables:
  REGISTRY: taskboard.cr.de-fra.ionos.com
  IMAGE_NAME: taskboard-api

test:
  stage: test
  image: python:3.12
  script:
    - cd api && pip install -r requirements.txt && pytest

build:
  stage: build
  image: docker:24
  services: [docker:24-dind]
  script:
    - export TAG=$CI_COMMIT_SHORT_SHA
    - echo "$CR_PASSWORD" | docker login "$REGISTRY" -u "$CR_USERNAME" --password-stdin
    - docker build -t "$REGISTRY/$IMAGE_NAME:$TAG" ./api
    - docker push "$REGISTRY/$IMAGE_NAME:$TAG"

deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - echo "$KUBECONFIG_B64" | base64 -d > /tmp/kubeconfig
    - export KUBECONFIG=/tmp/kubeconfig
    - kubectl set image deployment/taskboard-api api="$REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA"
    - kubectl rollout status deployment/taskboard-api --timeout=180s
  only: [main]

Speichern Sie CR_USERNAME, CR_PASSWORD und KUBECONFIG_B64 als maskierte, geschützte CI/CD-Variablen in den GitLab-Projekt-Einstellungen. Geschützte Variablen werden nur Pipelines zugänglich gemacht, die auf geschützten Zweigen ausgeführt werden, was die Produktions-Anmeldeinformationen aus den Feature-Branch-Pipelines heraus hält. CI_COMMIT_SHORT_SHA ist das GitLab-Äquivalent zum Git-SHA-Tag, das die gleiche unveränderliche-Tag-Garantie wie das GitHub-Actions-Beispiel bietet.

4. Terraform in CI/CD

Infrastrukturänderungen verdienen eine Überprüfung, bevor sie die IONOS-Ressourcen beeinflussen, da terraform apply abrechnungsfähige Ressourcen erstellt und zerstören kann. Das Standardmuster führt terraform plan bei jedem Pull-Request aus und veröffentlicht den Plan als PR-Kommentar, dann führt es terraform apply nur nach dem Merge zu main aus. Dies gibt den Reviewern die genaue Differenz und verhindert, dass unüberprüfte Änderungen angewendet werden.

4.1 Plan auf PR, Anwenden bei Merge

# .github/workflows/terraform.yml
name: terraform
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

env:
  IONOS_TOKEN: ${{ secrets.IONOS_TOKEN }}

jobs:
  plan:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform plan -no-color -out=tfplan
      - run: terraform show -no-color tfplan > plan.txt
      - uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const plan = fs.readFileSync('plan.txt', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '```\n' + plan.slice(0, 60000) + '\n```'
            });

  apply:
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
      - run: terraform apply -auto-approve

Der IONOS-Terraform-Anbieter authentifiziert sich über die IONOS_TOKEN-Umgebungsvariable, sodass das Übergeben des Bearer-Tokens als Umgebungsvariable alles ist, was der Anbieter-Block benötigt. Der Anbieter pollt interne asynchrone IONOS-Operationen, sodass terraform apply-Blöcke, bis jede Ressource ihren bereiten Zustand erreicht, bevor sie zum nächsten Schritt übergeht. Dies bedeutet, dass die Pipeline keine eigenen Bereitschaftsschleifen für Terraform-verwaltete Ressourcen benötigt.

4.2 Remote-Zustand für CI/CD

Lokaler Zustand funktioniert in CI/CD nicht, da jeder Runner mit einem sauberen Checkout beginnt. Verwenden Sie das S3-kompatible IONOS-Object Storage-Backend, damit jeder Pipeline-Lauf denselben Zustand liest und schreibt und der Zustandssperre zwei gleichzeitige Anwendungen davon abhält, ihn zu beschädigen.

terraform {
  backend "s3" {
    bucket                      = "taskboard-tfstate"
    key                         = "infra/terraform.tfstate"
    region                      = "de"
    endpoints = { s3 = "https://s3-eu-central-1.ionoscloud.com" }
    skip_credentials_validation = true
    skip_region_validation      = true
    skip_requesting_account_id  = true
  }
}

Object Storage verwendet eine Zugriffsschlüssel- plus Geheimschlüssel-Authentifizierung, nicht Bearer-Tokens, sodass die Backend-Anmeldeinformationen von IONOS_TOKEN getrennt sind. Stellen Sie sie der Pipeline als AWS_ACCESS_KEY_ID- und AWS_SECRET_ACCESS_KEY-Geheimnisse zur Verfügung, die das S3-Backend automatisch liest.

5. Bereitstellungsstrategien und Rückgängigstellung

Die Standard-Kubernetes-Bereitstellungsstrategie ist RollingUpdate, die Pods inkrementell ersetzt, sodass der Dienst während der Bereitstellung verfügbar bleibt. Für Workloads, die nicht zwei Versionen gleichzeitig ausführen können, verwenden Sie Recreate, die alle alten Pods beendet, bevor neue gestartet werden, was jedoch einen kurzen Ausfall zur Folge hat.

5.1 Konfiguration der Strategie

apiVersion: apps/v1
kind: Deployment
metadata:
  name: taskboard-api
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels: { app: taskboard-api }
  template:
    metadata:
      labels: { app: taskboard-api }
    spec:
      imagePullSecrets:
        - name: cr-pull-secret
      containers:
        - name: api
          image: taskboard.cr.de-fra.ionos.com/taskboard-api:abc1234
          readinessProbe:
            httpGet: { path: /healthz, port: 8080 }
            initialDelaySeconds: 5

maxUnavailable: 0 garantiert, dass während des Rollouts keine Kapazität verloren geht, und die readinessProbe stellt sicher, dass der Datenverkehr nur Pods erreicht, die als gesund gemeldet werden. Der imagePullSecrets-Eintrag verweist auf das Container-Registrierungstoken, da die Cluster Bilder mithilfe desselben tokenbasierten Zugriffsdatensatzes abruft, den Ihre Pipeline verwendet hat, um sie zu übertragen. Canary- und Blue-Green-Veröffentlichungen sind mit parallelen Bereitstellungen und Datenverkehrsumlenkung oder mit einem GitOps-Tool wie ArgoCD erreichbar, das in Einheit 5.3 als Muster behandelt wird und nicht hier.

5.2 Rückgängigstellung

Wenn eine Bereitstellung schiefgeht, können Sie die Anwendung mit kubectl rollout undo zurücksetzen, die die Bereitstellung auf ihre vorherige Revision zurücksetzt, ohne etwas neu zu erstellen.

# Inspect revision history
kubectl rollout history deployment/taskboard-api

# Roll back to the immediately previous revision
kubectl rollout undo deployment/taskboard-api

# Roll back to a specific revision
kubectl rollout undo deployment/taskboard-api --to-revision=4

Da jedes Bild mit seinem Git-SHA-Tag versehen ist, können Sie auch deterministisch mit kubectl set image auf einen bekannten guten Tag verweisen. Für die Infrastruktur bedeutet eine Rückgängigstellung, den fehlerhaften Commit rückgängig zu machen und terraform apply erneut auszuführen, was die Live-Ressourcen wieder mit dem committierten Zustand in Einklang bringt. Wenn der Zustand selbst beschädigt ist, können Sie ihn aus einer versionierten Kopie im Object Storage-Backend wiederherstellen.

6. Erstellung einer Terraform-Modulbibliothek

Sobald die Infrastruktur von TaskBoard funktioniert, können die wiederholten Muster in Module extrahiert werden, damit der nächste Dienst nicht von vorne beginnt. Ein Modul gruppiert verwandte Ressourcen hinter Eingabevariablen und gibt Ausgaben aus, wodurch ein umfangreicher Stapel in wenige Zeilen Aufrufercode umgewandelt wird.

6.1 Modulstruktur

# modules/k8s-service/variables.tf
variable "name"        { type = string }
variable "node_count"  { type = number, default = 2 }
variable "k8s_version" { type = string, default = "1.34" }

# modules/k8s-service/main.tf
resource "ionoscloud_k8s_cluster" "this" {
  name        = var.name
  k8s_version = var.k8s_version
}

resource "ionoscloud_k8s_node_pool" "this" {
  name        = "${var.name}-pool"
  k8s_cluster_id = ionoscloud_k8s_cluster.this.id
  node_count  = var.node_count
  # ... cores, ram, availability_zone, etc.
}

# modules/k8s-service/outputs.tf
output "cluster_id" { value = ionoscloud_k8s_cluster.this.id }

Die unterstützten Kubernetes-Versionen sind 1.34, 1.33, 1.32 und 1.31, daher sollte eine bekannte gute Version in der Modulstandardvorgabe festgelegt und den Aufrufern die Möglichkeit gegeben werden, sie zu überschreiben. Node Pools kann Dedicated Core oder vCPU Server-Typen verwenden, und ein Node-Pool hat ein hartes Maximum von 100 Knoten mit einem empfohlenen Maximum von 20, daher sollte node_count anhand dieser Grenzen validiert werden, anstatt einen Tippfehler zuzulassen, der einen überdimensionierten Pool bereitstellt.

6.2 Verwendung des Moduls

module "taskboard" {
  source     = "./modules/k8s-service"
  name       = "taskboard-prod"
  node_count = 3
}

output "taskboard_cluster" {
  value = module.taskboard.cluster_id
}

Versionieren Sie das Modulrepository mit git-Tags und verweisen Sie in source auf ein bestimmtes Tag, damit eine nachgelagerte Änderung des Moduls einen bestehenden Stapel nicht stillschweigend ändert. Auf diese Weise kann ein Team eine funktionierende Bereitstellung in eine wiederverwendbare Bibliothek umwandeln.

API Referenz-Quick-Card

Wichtige Endpunkte, die von CI/CD-Pipelines auf IONOS verwendet werden:

Methode Endpunkt Beschreibung
POST /containerregistries/registries/{id}/tokens Erstellen eines Registrierungstokens für CI
GET /k8s/{clusterId}/kubeconfig Abrufen von kubeconfig für die Bereitstellung
GET /k8s/{clusterId}/nodepools Auflisten von Node Pools für ein Cluster
GET /requests/{requestId}/status Abfragen einer asynchronen Operation, bis DONE
DELETE /containerregistries/registries/{id}/repositories/{name} Löschen eines Repositorys (Name URL-kodiert)

Basis-URL: https://api.ionos.com/cloudapi/v6 Authentifizierung: Authorization: Bearer <token>

Code-Lab

Ziel: Erstellen Sie eine GitHub-Actions-Pipeline, die TaskBoard auf every Push zu Managed Kubernetes erstellt, pushen und bereitstellt.

Voraussetzungen:

  • IONOS Cloud-Konto mit API-Token (main)
  • Ein bestehendes Container-Registry und Managed Kubernetes Cluster (aus den Einheiten 3.1 und 3.2)
  • Ein GitHub-Repository für die TaskBoard-Anwendung
  • IONOS_TOKEN, docker und kubectl lokal installiert

Schritt 1: Erstellen Sie ein Registry-Token für CI

ionosctl container-registry token create \
  --registry-id "$REGISTRY_ID" --name ci-deploy

Erwartete Ausgabe:

TokenId    Name        Status   ExpiryDate
a1b2c3d4   ci-deploy   enabled  -
Password: <shown once - copy it now>

Schritt 2: Speichern Sie Geheimnisse in GitHub

gh secret set CR_USERNAME --body "ci-deploy"
gh secret set CR_PASSWORD --body "<password from step 1>"
gh secret set KUBECONFIG  --body "$(ionosctl k8s kubeconfig get \
  --cluster-id "$CLUSTER_ID" | base64 -w0)"

Erwartete Ausgabe:

✓ Set secret CR_USERNAME
✓ Set secret CR_PASSWORD
✓ Set secret KUBECONFIG

Schritt 3: Fügen Sie die Workflow-Datei hinzu Committen Sie ionosctl aus Abschnitt 2.2 in das Repository. Erwartete Ausgabe:

[main 9f3c1ab] add deploy workflow
 1 file changed, 38 insertions(+)

Schritt 4: Triggerung der Pipeline

git commit --allow-empty -m "trigger deploy"
git push origin main

Erwartete Ausgabe:

To github.com:you/taskboard-app.git
   8d2e1f0..9f3c1ab  main -> main

Schritt 5: Beobachten Sie den Lauf

gh run watch

Erwartete Ausgabe:

✓ build-and-deploy succeeded
  ✓ Build and push image
  ✓ Deploy to Managed Kubernetes

Schritt 6: Überprüfen Sie die Bereitstellung auf dem Cluster

kubectl get deployment taskboard-api -o wide

Erwartete Ausgabe:

NAME            READY   IMAGE
taskboard-api   3/3     taskboard.cr.de-fra.ionos.com/taskboard-api:9f3c1ab

Validierungs-Checkliste:

  • [ ] Bild mit dem git-SHA-Tag existiert im Container-Registry
  • [ ] Bereitstellungs-Bild entspricht dem gepushten Tag
  • [ ] .github/workflows/deploy.yml meldet Erfolg in der Pipeline
  • [ ] Ein zweiter Push produziert einen neuen SHA-Tag und ein sauberes Rolling-Update

Aufräumen:

gh secret delete CR_USERNAME CR_PASSWORD KUBECONFIG
ionosctl container-registry token delete --registry-id "$REGISTRY_ID" --token-id "$TOKEN_ID"

Häufige Fallstricke

Entwicklerfehler, die bei CI/CD auf IONOS vermieden werden sollten:

  1. Festkodierung des Registrierungshostnamens, bevor das Register läuft

    • Problem: Die Pipeline schlägt mit einem Docker-Anmeldefehler und einem DNS-Auflösungsfehler gegen einen leeren Hostnamen fehl.
    • Warum es passiert: Der Registrierungshostname wird erst nachdem das Register den Zustand "Running" erreicht hat, zugewiesen, sodass ein frisch bereitgestelltes Register noch keinen Hostnamen hat.
    • Lösung: Lesen Sie den Hostnamen aus der Terraform-Ausgabe, anstatt ihn fest zu kodieren, und sperren Sie den Push-Vorgang, bis das Register bereit ist:
    output "registry_hostname" { value = ionoscloud_container_registry.this.hostname }
    
  2. Erwarten, dass ein Kubernetes-Lastenausgleichsdienst ein echter externer Load Balancer ist

    • Problem: Die Durchsatzleistung erreicht ein Plateau und die Quelle IP jeder Anfrage wird als interne Cluster-Adresse angezeigt, was die Ratebegrenzung und die Überwachungsprotokolle unterbricht.
    • Warum es passiert: Ein Lastenausgleichsdienst auf Managed Kubernetes stellt keinen externen Lastenausgleich bereit. IONOS reserviert eine statische öffentliche IP und weist sie als sekundäre IP einem Worker-Node zu, und kube-proxy leitet den Datenverkehr an den Pod um, wodurch die Durchsatzleistung auf das öffentliche Limit dieses einzelnen Node begrenzt wird und die Quelle IP verloren geht.
    • Lösung: Setzen Sie externalTrafficPolicy: Local, um die Quelle IP zu erhalten, und platzieren Sie den Dienst vor einem separat bereitgestellten Managed ALB oder verteilen Sie ihn auf mehrere LB-IPs, um die Durchsatzleistung eines einzelnen Node zu überschreiten:
    spec:
      type: LoadBalancer
      externalTrafficPolicy: Local
    
  3. Ausführen von Terraform mit lokalem Zustand in CI/CD

    • Problem: Jeder Pipeline-Lauf beginnt mit einem leeren Zustand, sodass terraform apply versucht, Ressourcen neu zu erstellen, die bereits existieren, und aufgrund von doppelten Namen Fehlermeldung ausgibt.
    • Warum es passiert: CI-Runner überprüfen einen sauberen Arbeitsbereich ohne Zustandsdatei, und es gibt keinen gemeinsamen Hintergrund.
    • Lösung: Konfigurieren Sie den S3-kompatiblen Object Storage-Hintergrund, sodass alle Läufe den Zustand teilen, und liefern Sie Zugriffsschlüssel sowie geheime Schlüssel-Anmeldedaten als Pipeline-Geheimnisse:
    export AWS_ACCESS_KEY_ID="$IONOS_S3_KEY"
    export AWS_SECRET_ACCESS_KEY="$IONOS_S3_SECRET"
    terraform init
    

Zusammenfassung

Sie können jetzt den gesamten Build-Test-Deploy-Zyklus aus einem einzigen git push steuern. Die Anwendungspipeline erstellt ein Container, kennzeichnet es mit dem git-SHA, meldet sich bei der IONOS Container-Registrierung mit einem tokenbasierten Docker-Login an, pusht das Bild und rollt es mit einem bereitstellungsgeprüften kubectl set image und kubectl rollout status auf Managed Kubernetes aus. Die Infrastruktur-Pipeline hält Terraform ehrlich, indem sie bei Pull-Requests plant und nur bei Merge anwendet, unterstützt durch einen gemeinsamen Zustand in Object Storage. Wenn etwas fehlschlägt, kehren kubectl rollout undo und ein rückgängig gemachter Terraform-Commit Sie in einen bekannten guten Zustand zurück, und Ihre extrahierte Modulbibliothek bedeutet, dass der nächste Dienst diese Muster wiederverwendet, anstatt sie neu zu erfinden.

Wichtige Punkte:

  • Teilen Sie den Anwendungsfluss (build -> test -> push -> deploy) vom Infrastrukturfluss (plan -> apply); teilen Sie nie einen Job zwischen ihnen
  • Kennzeichnen Sie jedes Bild mit dem unveränderlichen git-SHA, verändern Sie es nie :latest, damit die laufende Revision immer nachvollziehbar ist und Rollbacks deterministisch sind
  • Container-Registrierungstoken werden einmal bei der Erstellung angezeigt und werden bei Ablauf gelöscht; speichern Sie sie als CI-Geheimnisse und ziehen Sie Bilder mit denselben tokenbasierten Anmeldeinformationen
  • Führen Sie terraform plan auf PRs und terraform apply auf Merge aus, mit gemeinsamem S3-kompatiblen Zustand in Object Storage und IONOS_TOKEN als Geheimnis
  • Rollen Sie Anwendungen mit kubectl rollout undo und Infrastruktur zurück, indem Sie den Commit rückgängig machen und erneut anwenden

Wichtige Begriffe:

  • Unveränderlicher Tag: Ein Container-Bild-Tag, der aus dem git-SHA abgeleitet wird und nie geändert wird, der jeden laufenden Pod mit dem genauen Commit verknüpft, der ihn erstellt hat.
  • Rolling-Update: Die Standard-Kubernetes-Deploy-Strategie, die Pods inkrementell ersetzt, sodass der Dienst während einer Bereitstellung verfügbar bleibt.
  • Plan auf PR: Das Terraform-CI-Muster, terraform plan auf Pull-Requests auszuführen und den Diff für die Überprüfung vor jedem apply zu posten.
  • Remote-State-Backend: Ein gemeinsamer Terraform-Zustandspeicher (S3-kompatibler Object Storage auf IONOS), der es jedem CI-Lauf ermöglicht, den gleichen Zustand mit Sperren zu lesen und zu schreiben.
  • imagePullSecret: Ein Kubernetes-Geheimnis, das Container-Registrierungstoken-Anmeldeinformationen enthält, sodass der Cluster private Bilder ziehen kann.

Nächste Schritte

Weiterlernen: Einheit 3.4: Wissensprüfung - Container und CI/CD

Verwandte Themen: