Ga naar inhoud

Uitwerking

CI Week 3 - Blue-Green Deploy Week 3 - Switch Blue-Green Slot

In week 3 heb ik een Blue-Green deployment opgezet voor de applicatie uit week 1 en 2, met Google Artifact Registry als container registry in plaats van Docker Hub. Daarnaast heb ik een CI/CD pipeline ingericht met GitHub Actions.


Blue-Green strategie

Bij een Blue-Green deployment draaien twee versies van de applicatie tegelijk in Kubernetes. Een Kubernetes Service stuurt al het verkeer naar één versie (de actieve slot). Overschakelen gaat zonder downtime door simpelweg de selector in de Service aan te passen.
SlotBranchDocker image tagStatus
BluemainblueProductie - ontvangt live verkeer
GreendevelopmentgreenTest - draait parallel, ontvangt geen verkeer

Hoe de pipeline werkt

  • Push naar main: CI workflow bouwt het :blue image en deployed naar deployment-blue
  • Push naar development: CI workflow bouwt het :green image en deployed naar deployment-green

Beide deployments draaien tegelijkertijd. Dit maakt het mogelijk om nieuwe functionaliteiten te ontwikkelen op development, te testen in de green slot, en daarna te switchen via de switch-slot workflow.

Switchen tussen slots

De switch-slot workflow is een handmatige workflow (workflow_dispatch) die via GitHub Actions gestart wordt. Bij het starten kies ik blue of green, waarna de Service selector wordt aangepast met:

kubectl patch service public-cloud-concepts \
  -p '{"spec":{"selector":{"slot":"<blue|green>"}}}'

De pipeline gebruikt kubectl apply zodat de Service ook aangemaakt wordt als die nog niet bestaat. Na de switch verifieert de pipeline de actieve slot en toont de draaiende pods.


Stap 1: Kubernetes Cluster aanmaken

Als basis gebruik ik de Week 2-omgeving: een GKE cluster, opnieuw opgezet als week3-cluster. Standaard cluster, 2 nodes, e2-medium (2 vCPU, 4 GB RAM), europe-west4-a.

gcloud container clusters get-credentials week3-cluster \
  --region europe-west4-a \
  --project project-5b8c5498-4fe2-42b9-bc3

gcloud connect cluster commando

GKE cluster nodes actief


Stap 2: Service Account aanmaken

Een Service Account voor GitHub Actions om met GCP te communiceren:

Het formulier voor het aanmaken van een service account

Service account aanmaken

Naam: Github Pipeline Account. Rollen:

  • Artifact Registry Reader
  • Artifact Registry Writer
  • Kubernetes Engine Developer

Rollen toegewezen aan het service account

Service account principals overzicht


Stap 3: JSON Key aanmaken

Bij het aanmaken van de key verschijnt een foutmelding:

Foutmelding: service account key creation is disabled

Een Organization Policy (iam.disableServiceAccountKeyCreation) blokkeert dit.

Organization Policy overzicht

Organization Policy geblokkeerd

Opgelost via Cloud Shell:

gcloud organizations list

Lijst van organizations

gcloud organizations add-iam-policy-binding 774668784967 \
  --member="user:stentijhuis861@gmail.com" \
  --role="roles/orgpolicy.policyAdmin"

IAM policy binding toevoegen

gcloud resource-manager org-policies disable-enforce iam.disableServiceAccountKeyCreation \
  --project=project-5b8c5498-4fe2-42b9-bc3

Policy succesvol uitgeschakeld op projectniveau

JSON key downloaden

JSON key opgeslagen

Service account keys overzicht


Stap 4: GitHub Secrets instellen

De JSON key en projectgegevens als repository secrets via Settings > Secrets and variables > Actions:

GitHub Secrets gedeeltelijk ingesteld

GitHub Secrets volledig ingesteld (GCP_PROJECT_ID, GCP_SA_KEY, GKE_CLUSTER, GKE_ZONE)


Stap 5: Artifact Registry

Artifact Registry repository aangemaakt: public-cloud-concepts, Docker-formaat, europe-west4. Container Scanning API ingeschakeld voor kwetsbaarheidsscans.

Artifact Registry aanmaken

Lege Artifact Registry na aanmaken

Container Scanning API ingeschakeld

Artifact Registry met het gepushte green image


IAM-configuratie

Er zijn twee identiteiten betrokken:

GitHub Pipeline Account - wordt door GitHub Actions gebruikt om images te pushen naar Artifact Registry en kubectl-opdrachten te sturen naar GKE.

Compute Engine default service account - wordt door de GKE-nodes gebruikt om images te pullen bij het starten van pods. Zonder Artifact Registry Reader op dit account krijg je een ImagePullBackOff fout, ook als het pipeline account wel de juiste rechten heeft.

IAM-rechten van het GitHub pipeline service account

IAM-rechten van het Compute Engine default service account


Resultaat

GitHub Actions workflow: Build, push & deploy geslaagd

GitHub Actions workflow volledig groen

Website draaiend in het cluster

GKE observability overzicht

Beide deployments parallel testen

Beide deployments draaien tegelijkertijd. De Service bepaalt via de selector welke slot verkeer ontvangt. Switchen kan op twee manieren: via de commandline of via een GitHub Actions workflow.

Optie 1: Commandline (kubectl)

kubectl patch past direct de selector in de Service aan. Kubernetes stuurt verkeer meteen door naar de nieuwe pods, zonder herstart of downtime.

# Naar green switchen
kubectl patch service public-cloud-concepts \
  -p '{"spec":{"selector":{"slot":"green"}}}'

# Terug naar blue
kubectl patch service public-cloud-concepts \
  -p '{"spec":{"selector":{"slot":"blue"}}}'

Controleer daarna welke slot actief is:

kubectl get service public-cloud-concepts \
  -o jsonpath='Actieve slot: {.spec.selector.slot}{"\n"}'
kubectl patch is de aanbevolen manier voor blue-green switching in Kubernetes. Het is atomisch: de selector-update is één API-call en Kubernetes zorgt dat verkeer direct naar de nieuwe pods gaat. De pipeline gebruikt kubectl apply (idempotent: maakt de Service ook aan als die nog niet bestaat), maar voor handmatig switchen is patch sneller en directer.

Optie 2: GitHub Actions workflow (GUI)

Voor wie niet via de commandline wil switchen, is er de switch-slot workflow: een handmatige workflow (workflow_dispatch) die je vanuit de GitHub Actions UI kunt starten. Je kiest blue of green, en de pipeline doet de rest.

Blue-Green slot switch via GitHub Actions workflow UI

De workflow toont na de switch de actieve slot en de draaiende pods:

Actieve slot: blue
NAME                                READY   STATUS    RESTARTS   AGE
deployment-blue-78c48bc59-m7xqm     1/1     Running   0          7m48s
deployment-green-7fbf59cf77-q2nxj   1/1     Running   0          7m32s

Je hebt dus zowel een commandline-optie als een kleine GUI; beide leiden tot hetzelfde resultaat.

De website met actieve blue slot - blauwe balk bovenaan

De website met actieve green slot - groene balk bovenaan

Service handmatig aangemaakt na switch

Overzicht van de draaiende pods met slot-labels


Cluster verbinden en status controleren

Verbinden met het cluster

Kubeconfig instellen voor kubectl-toegang:

gcloud container clusters get-credentials week3-cluster \
  --region europe-west4-a \
  --project <GCP_PROJECT_ID>

Extern IP-adres ophalen

Het externe IP ophalen via de LoadBalancer Service:

kubectl get service public-cloud-concepts

Uitvoer:

NAME                    TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)        AGE
public-cloud-concepts   LoadBalancer   10.X.X.X       <EXTERNAL-IP>    80:XXXXX/TCP   Xm

Het EXTERNAL-IP-veld is het publieke IP-adres waarop de applicatie bereikbaar is via poort 80. Dit adres wordt toegewezen door de Google Cloud load balancer.

Actieve slot controleren

Welke slot momenteel verkeer ontvangt:

kubectl get service public-cloud-concepts \
  -o jsonpath='{.spec.selector.slot}'

Dit geeft blue of green terug.

Overzicht van draaiende deployments

Alle deployments en hun status:

kubectl get deployments
NAME                READY   UP-TO-DATE   AVAILABLE   AGE
deployment-blue     1/1     1            1           Xm
deployment-green    1/1     1            1           Xm

Pods inclusief hun slot-label:

kubectl get pods -l app=public-cloud-concepts --show-labels

Dit is ook zichtbaar in de Google Cloud Console. In de Cloud Shell terminal zijn de kubectl patch-opdrachten en het IP-adres te zien:

GKE cluster details en kubectl-commando’s in Cloud Shell


Argo CD en Flux CD

Wat is Argo CD?

Argo CD is een GitOps-tool die continu het Kubernetes-cluster synchroniseert met wat er in een Git-repository staat. Het idee achter GitOps is dat Git de enige bron van waarheid is: de gewenste staat van het cluster staat in YAML-bestanden in Git. Argo CD bewaakt het cluster en vergelijkt het continu met die bestanden. Als er een verschil is, herstelt Argo CD dat automatisch.

Argo CD heeft een webinterface waar je per applicatie kunt zien of het cluster overeenkomt met Git (Synced) of niet (OutOfSync). Je kunt handmatig synchroniseren of auto-sync aanzetten. Het geeft ook een boomstructuur van alle Kubernetes-resources die bij een applicatie horen, inclusief pods, services en deployments.

Praktisch werkt het zo: je deployt Argo CD in je cluster, je maakt een Application-object aan dat verwijst naar een Git-repository en een pad daarin, en Argo CD houdt dat pad in de gaten. Als je een nieuw image-tag in een YAML-bestand commit, trekt Argo CD die wijziging op en past het cluster aan.

Wat is Flux CD?

Flux CD doet hetzelfde als Argo CD (GitOps, pull-model), maar werkt heel anders van binnen. Flux bestaat uit een stel Kubernetes-controllers die je installeert in het cluster. Er is geen aparte webinterface. Alles wat Flux doet, is terug te zien via kubectl.

Flux heeft losse controllers voor verschillende taken:

  • Source Controller let op Git-repositories, Helm-repositories en OCI-registries en downloadt nieuwe versies.
  • Kustomize Controller past Kustomize-overlays toe op wat de Source Controller ophaalt.
  • Helm Controller installeert of updatet Helm charts op basis van een HelmRelease-object in Git.
  • Notification Controller stuurt berichten naar Slack, Teams of webhooks bij events.

Omdat alles via Kubernetes-objects gaat, is Flux goed te integreren in bestaande GitOps-workflows en makkelijk te beheren via CI/CD-tools die al met kubectl werken.

Vergelijking met GitHub Actions

GitHub ActionsArgo CDFlux CD
ModelPush: pipeline stuurt actief naar het clusterPull: Argo CD haalt wijzigingen op uit GitPull: Flux controllers halen wijzigingen op
TriggerEvent in GitHub (push, PR)Continu polling van Git, of webhookContinu polling, of webhook
Cluster-toegangRunner buiten het cluster heeft directe toegang nodigArgo CD draait in het cluster zelfFlux draait in het cluster zelf
Drift detectieGeen, pipeline runt alleen bij eventsAutomatisch, herstelt zonder triggerAutomatisch, herstelt zonder trigger
UIGeen ingebouwde Kubernetes-UIUitgebreide webinterfaceGeen UI, alles via kubectl
Geschikt voorCI: bouwen, testen, pushen van imagesCD: deployen en bewaken van de staatCD: volledig geautomatiseerde omgevingen

Wanneer gebruik je wat?

GitHub Actions is goed voor het bouwen van images, draaien van tests en pushen naar een registry. Dat is CI. Voor de deployment zelf (CD) zijn Argo CD en Flux CD beter geschikt, omdat ze het cluster continu in sync houden met Git en afwijkingen automatisch herstellen.

In een typische productie-setup combineer je beide: GitHub Actions bouwt het image en schrijft de nieuwe tag terug naar een YAML-bestand in Git. Argo CD of Flux CD detecteert die wijziging en deployt de nieuwe versie naar het cluster.

Argo CD kies je als je een visueel overzicht wil van wat er in het cluster draait en wat de staat is. Flux kies je als je een puur declaratieve aanpak wil zonder extra UI, of als je al werkt met Kustomize of complexe Helm-setups.