- Authors

- Name
- Phillip Pham
- @ddppham
TL;DR
GitHub Actions automatisiert den kompletten Weg vom Git-Push bis zum Kubernetes-Deployment. Du definierst Workflows als YAML, baust Container-Images, pushst sie in eine Registry und rollst per kubectl oder Kustomize aus. Mit Environments und Approval Gates sicherst du Production-Deployments ab.
CI/CD für Kubernetes mit GitHub Actions
Manuelles kubectl apply auf dem Laptop ist keine Deployment-Strategie. GitHub Actions bietet eine native CI/CD-Lösung, die direkt im Repository lebt und ohne externen CI-Server auskommt.
Ein minimaler Workflow, der bei jedem Push auf main auslöst:
# .github/workflows/deploy.yaml
name: Deploy to Kubernetes
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
run: docker build -t ghcr.io/${{ github.repository }}:${{ github.sha }} .
- name: Push to GHCR
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker push ghcr.io/${{ github.repository }}:${{ github.sha }}
Workflow-Struktur verstehen
GitHub Actions Workflows bestehen aus Events (Trigger), Jobs (parallele Einheiten) und Steps (sequentielle Schritte). Für Kubernetes-Deployments brauchst du typischerweise zwei Jobs: Build und Deploy.
| Komponente | Aufgabe | Beispiel |
|---|---|---|
| Event | Workflow auslösen | push, pull_request, workflow_dispatch |
| Job | Isolierte Ausführungseinheit | build, deploy-staging, deploy-prod |
| Step | Einzelner Schritt im Job | docker build, kubectl apply |
| Secret | Verschlüsselte Variable | Kubeconfig, Registry-Credentials |
kubectl in GitHub Actions nutzen
Für den Cluster-Zugriff brauchst du eine kubeconfig als GitHub Secret. Speichere sie base64-kodiert:
# Kubeconfig base64-kodieren und als GitHub Secret speichern
cat ~/.kube/config | base64 -w 0
# Diesen Wert als Secret KUBECONFIG_BASE64 im Repository hinterlegen
Im Workflow decodierst du die kubeconfig und nutzt kubectl:
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBECONFIG_BASE64 }}" | base64 -d > $HOME/.kube/config
chmod 600 $HOME/.kube/config
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/myapp \
myapp=ghcr.io/${{ github.repository }}:${{ github.sha }} \
-n production
kubectl rollout status deployment/myapp -n production --timeout=120s
Kustomize für Deployments
Hartcodierte Image-Tags in Manifesten sind fragil. Kustomize löst das elegant — es ist seit v1.14 in kubectl eingebaut.
Projektstruktur:
k8s/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── overlays/
├── staging/
│ └── kustomization.yaml
└── production/
└── kustomization.yaml
Der Workflow-Step für Kustomize-Deployments:
- name: Deploy with Kustomize
run: |
cd k8s/overlays/production
kustomize edit set image myapp=ghcr.io/${{ github.repository }}:${{ github.sha }}
kubectl apply -k .
kubectl rollout status deployment/myapp -n production --timeout=180s
Das überschreibt nur den Image-Tag im Overlay, ohne die Base-Manifeste anzufassen.
Environments und Approval Gates
GitHub Environments ermöglichen manuelle Freigaben vor Production-Deployments. Konfiguriere sie unter Settings > Environments im Repository.
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- name: Deploy to Staging
run: kubectl apply -k k8s/overlays/staging
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://myapp.example.com
steps:
- uses: actions/checkout@v4
- name: Deploy to Production
run: kubectl apply -k k8s/overlays/production
Im Environment production aktivierst du Required reviewers. Der Workflow pausiert dann vor dem Production-Deploy und wartet auf manuelle Freigabe. Das ist besonders für regulierte Umgebungen wichtig.
Secrets richtig verwalten
Speichere sensible Daten ausschließlich als GitHub Secrets oder nutze einen externen Secret-Manager:
- name: Deploy with Helm
env:
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
run: |
helm upgrade --install myapp ./chart \
--set database.password=$DB_PASSWORD \
--set image.tag=${{ github.sha }} \
-n production
Wichtig: Verwende für Production einen dedizierten Service Account mit minimalen RBAC-Rechten. Ein kubeconfig mit cluster-admin-Zugriff in GitHub Secrets ist ein Sicherheitsrisiko.
# Service Account für CI/CD erstellen
apiVersion: v1
kind: ServiceAccount
metadata:
name: github-deployer
namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer-role
namespace: production
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "patch", "update"]
- apiGroups: [""]
resources: ["services", "configmaps"]
verbs: ["get", "list", "create", "update", "patch"]
Vollständiger Production-Workflow
Hier ein kompletter Workflow mit Build, Test, Staging und Production:
name: Production Pipeline
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: go test ./... -v
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- run: |
echo "${{ secrets.KUBECONFIG_BASE64 }}" | base64 -d > $HOME/.kube/config
cd k8s/overlays/staging
kustomize edit set image app=ghcr.io/${{ github.repository }}:${{ github.sha }}
kubectl apply -k .
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- run: |
echo "${{ secrets.KUBECONFIG_PROD }}" | base64 -d > $HOME/.kube/config
cd k8s/overlays/production
kustomize edit set image app=ghcr.io/${{ github.repository }}:${{ github.sha }}
kubectl apply -k .
kubectl rollout status deployment/myapp -n production --timeout=300s
FAQ
Wie rollback ich ein fehlgeschlagenes Deployment?
Nutze kubectl rollout undo deployment/myapp -n production als manuellen Fallback. Besser: Baue einen automatischen Rollback-Step ein, der bei fehlgeschlagenem rollout status die vorherige Version wiederherstellt.
Kann ich GitHub Actions auch für Multi-Cluster-Deployments nutzen?
Ja. Definiere pro Cluster ein eigenes Environment mit separater kubeconfig. Der Workflow deployt sequentiell oder parallel in mehrere Cluster. Matrix-Strategien eignen sich gut dafür.
Wie schütze ich Production vor versehentlichen Deployments?
Aktiviere Required reviewers im Production-Environment, nutze Branch-Protection-Rules auf main und beschränke das Environment auf bestimmte Branches. So kann nur geprüfter Code in Production landen.
Was kostet GitHub Actions für CI/CD?
Public Repositories haben unlimitierte Minuten. Private Repos bekommen 2.000 Minuten pro Monat im Free-Plan. Ein typischer Build-und-Deploy-Workflow braucht 2-5 Minuten.
Nächster Schritt: Ergänze deinen Workflow um automatisierte Smoke-Tests nach dem Deployment. Ein einfacher curl-Check auf den Health-Endpoint reicht oft schon, um kaputte Deployments sofort zu erkennen.
Kubernetes-Expertise gesucht?
Managed Services, Beratung, Training oder Security – wir unterstützen deutsche Unternehmen bei allen Kubernetes-Themen.
Kubernetes-Beratung gesucht?
Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
ArgoCD ApplicationSets: Multi-App Deployment Patterns
ArgoCD ApplicationSets automatisieren Multi-App und Multi-Cluster Deployments mit Generatoren. Praxis-Patterns für Git, Cluster und Matrix.
Documentation as Code für Kubernetes-Plattformen
Kubernetes-Plattform-Dokumentation als Code verwalten mit MkDocs, automatisch generierten Docs aus CRDs und Helm Charts sowie ADRs in Git.
GitOps Repository-Struktur: Best Practices
Die richtige Repository-Struktur entscheidet über den Erfolg von GitOps. Mono-Repo vs. Multi-Repo, Verzeichnisaufbau und Environment-Promotion praxisnah erklärt.
Kustomize vs Helm: Kubernetes-Konfiguration im Vergleich
Kustomize und Helm lösen dasselbe Problem unterschiedlich. Dieser Vergleich zeigt beide Tools am selben Deployment und hilft bei der Entscheidung für dein Projekt.
Kubernetes Testing: Unit-, Integrations- und E2E-Tests
Kubernetes Testing mit der Test-Pyramide: Unit-, Integrations- und E2E-Tests mit Testcontainers, Kind und CI/CD-Pipeline-Integration einrichten.