funnelcake-deployment-workflow

Par divinevideo · divine-mobile

Déploie funnelcake (api + relay) sur N'IMPORTE QUEL environnement (production, staging, poc) sur GKE via ArgoCD. À utiliser pour : (1) Déployer de nouveaux commits funnelcake, (2) Builder des images Docker pour GKE (amd64), (3) Exécuter des migrations ClickHouse, (4) Résoudre les erreurs ImagePullBackOff, (5) Synchroniser staging/poc après un déploiement en production. Couvre le workflow complet avec une CHECKLIST PRÉ-VOL pour prévenir les échecs de déploiement courants.

npx skills add https://github.com/divinevideo/divine-mobile --skill funnelcake-deployment-workflow

Flux de travail de déploiement Funnelcake

Problème

Le déploiement de funnelcake nécessite plusieurs étapes coordonnées dans des ENVIRONNEMENTS DIFFÉRENTS, chacun disposant de son propre registre de conteneurs et de sa propre instance ArgoCD. Défaillances courantes :

  • Mise à jour de la kustomization avec des tags d'image qui n'existent pas dans le registre cible
  • Assumer que le push vers main redéploie automatiquement vers staging/poc (ce n'est pas le cas)
  • Ne pas vérifier que les pods ont réellement démarré (vs bloqués en ImagePullBackOff)

Contexte / Conditions d'activation

  • L'utilisateur demande de déployer funnelcake vers n'importe quel environnement
  • De nouveaux commits doivent être déployés
  • Les migrations doivent être exécutées
  • Les pods sont bloqués en ImagePullBackOff ou ErrImagePull
  • Staging/poc est en retard par rapport à la production

CRITIQUE : Architecture multi-environnements

Chaque environnement est ISOLÉ - rien n'est partagé !

Environnement Registre de conteneurs ArgoCD Contexte kubectl
Production us-central1-docker.pkg.dev/dv-platform-prod/containers-production/ Dans le cluster production connectgateway_dv-platform-prod_us-central1_gke-production-membership
Staging us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/ Dans le cluster staging connectgateway_dv-platform-staging_us-central1_gke-staging-membership
POC us-central1-docker.pkg.dev/rich-compiler-479518-d2/containers-poc/ Dans le cluster POC connectgateway_rich-compiler-479518-d2_us-central1_gke-poc-membership

Points clés :

  • Les images du registre production ne sont PAS disponibles pour staging/poc
  • Pousser vers la branche main ne synchronise PAS automatiquement ArgoCD staging/poc
  • L'ArgoCD de chaque environnement doit être synchronisé séparément

LISTE DE VÉRIFICATION PRÉ-VOL (COMMENCEZ PAR LÀ !)

Avant de déployer vers N'IMPORTE QUEL environnement, vérifiez :

1. L'image existe-t-elle dans le registre CIBLE ?

# Vérifier quelles images existent
gcloud artifacts docker images list \
  us-central1-docker.pkg.dev/<PROJECT>/<REPO>/funnelcake-relay \
  --include-tags --limit=5

# Projets/repos par environnement :
# - Production: dv-platform-prod/containers-production
# - Staging: dv-platform-staging/containers-staging
# - POC: rich-compiler-479518-d2/containers-poc

Si l'image n'existe pas → CONSTRUISEZ ET POUSSEZ-LA D'ABORD !

2. Suis-je en train de mettre à jour le bon overlay ?

# Overlay staging :
k8s/applications/funnelcake-relay/overlays/staging/kustomization.yaml

# Overlay POC :
k8s/applications/funnelcake-relay/overlays/poc/kustomization.yaml

# Overlay production :
k8s/applications/funnelcake-relay/overlays/production/kustomization.yaml

3. Qu'est-ce qui est actuellement déployé vs ce qui est dans git ?

# Vérifier l'image déployée
kubectl --context <CONTEXT> get deployment funnelcake-relay -n funnelcake \
  -o jsonpath='{.spec.template.spec.containers[0].image}'

# Vérifier la kustomization git
cat k8s/applications/funnelcake-relay/overlays/<ENV>/kustomization.yaml | grep newTag

Flux de travail de déploiement complet

Étape 1 : Récupérer le code le plus récent

cd /Users/rabble/code/divine/divine-funnelcake
git pull
git log --oneline -3  # Notez le hash du commit (ex. e02d3b1)

Étape 2 : Construire les images pour AMD64 (CRITIQUE)

IMPORTANT : Les builds Mac ciblent arm64 par défaut. GKE exécute amd64. Vous DEVEZ spécifier --platform linux/amd64.

# Construire l'image API
docker buildx build --platform linux/amd64 --target api \
  -t us-central1-docker.pkg.dev/dv-platform-prod/containers-production/funnelcake-api:COMMIT_HASH \
  --push .

# Construire l'image Relay
docker buildx build --platform linux/amd64 --target relay \
  -t us-central1-docker.pkg.dev/dv-platform-prod/containers-production/funnelcake-relay:COMMIT_HASH \
  --push .

Si vous recevez des erreurs d'authentification, exécutez :

gcloud auth configure-docker us-central1-docker.pkg.dev --quiet

Étape 3 : Mettre à jour Kustomize et pousser

cd /Users/rabble/code/divine/divine-iac-coreconfig

# Mettre à jour les tags d'image
sed -i '' 's/newTag: "OLD_HASH"/newTag: "NEW_HASH"/' \
  k8s/applications/funnelcake-api/overlays/production/kustomization.yaml
sed -i '' 's/newTag: "OLD_HASH"/newTag: "NEW_HASH"/' \
  k8s/applications/funnelcake-relay/overlays/production/kustomization.yaml

# Commiter et pousser (gérer les conflits potentiels)
git add k8s/applications/funnelcake-*/overlays/production/kustomization.yaml
git commit -m "deploy(production): funnelcake NEW_HASH - description"
git pull --rebase origin main && git push origin main

Étape 4 : Déclencher la synchronisation ArgoCD

# Rafraîchir pour reprendre les changements git
kubectl patch application funnelcake-api -n argocd --type=merge \
  -p '{"metadata":{"annotations":{"argocd.argoproj.io/refresh":"hard"}}}'
kubectl patch application funnelcake-relay -n argocd --type=merge \
  -p '{"metadata":{"annotations":{"argocd.argoproj.io/refresh":"hard"}}}'

# Attendre, puis déclencher la synchronisation
sleep 3
kubectl patch application funnelcake-api -n argocd --type=merge \
  -p '{"operation":{"sync":{"revision":"HEAD"}}}'
kubectl patch application funnelcake-relay -n argocd --type=merge \
  -p '{"operation":{"sync":{"revision":"HEAD"}}}'

Étape 5 : Attendre le déploiement

kubectl rollout status deploy/funnelcake-api deploy/funnelcake-relay \
  -n funnelcake --timeout=120s

Étape 6 : Vérifier

kubectl get deploy funnelcake-api -n funnelcake \
  -o jsonpath='{.spec.template.spec.containers[0].image}'

Exécuter les migrations

CRITIQUE : Le point d'entrée des migrations a deux modes

Le fichier database/entrypoint.sh détecte le mode de connexion ClickHouse à partir des variables d'environnement :

  • Mode 1 (CLICKHOUSE_URL) : Suppose ClickHouse Cloud — force le port 9440 avec TLS. À utiliser pour la production (ClickHouse Cloud à *.clickhouse.cloud).
  • Mode 2 (CLICKHOUSE_HOST + CLICKHOUSE_PORT) : Host/port direct, pas d'hypothèse TLS. À utiliser pour staging/poc (ClickHouse auto-hébergé sur le port 9000).

Si vous passez CLICKHOUSE_URL pour ClickHouse auto-hébergé, les migrations échoueront avec i/o timeout sur le port 9440 car l'instance auto-hébergée écoute sur le port 9000.

Construire et pousser l'image de migration

cd /Users/rabble/code/divine/divine-funnelcake/database
docker buildx build --platform linux/amd64 \
  -t us-central1-docker.pkg.dev/dv-platform-prod/containers-production/funnelcake-migrate:COMMIT_HASH \
  --push .

Exécuter le job de migration — PRODUCTION (ClickHouse Cloud)

kubectl delete job funnelcake-db-migrate -n funnelcake --ignore-not-found
cat <<'EOF' | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
  name: funnelcake-db-migrate
  namespace: funnelcake
spec:
  ttlSecondsAfterFinished: 600
  backoffLimit: 3
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: migrate
          image: us-central1-docker.pkg.dev/dv-platform-prod/containers-production/funnelcake-migrate:COMMIT_HASH
          args: ["up"]
          env:
            - name: CLICKHOUSE_URL
              valueFrom:
                secretKeyRef:
                  name: funnelcake-clickhouse-credentials
                  key: CLICKHOUSE_URL
            - name: CLICKHOUSE_USER
              valueFrom:
                secretKeyRef:
                  name: funnelcake-clickhouse-credentials
                  key: CLICKHOUSE_USER
            - name: CLICKHOUSE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: funnelcake-clickhouse-credentials
                  key: CLICKHOUSE_PASSWORD
            - name: CLICKHOUSE_DATABASE
              valueFrom:
                secretKeyRef:
                  name: funnelcake-clickhouse-credentials
                  key: CLICKHOUSE_DATABASE
EOF

Exécuter le job de migration — STAGING/POC (ClickHouse auto-hébergé)

# Utiliser CLICKHOUSE_HOST + CLICKHOUSE_PORT à la place de CLICKHOUSE_URL !
kubectl --context <STAGING_CONTEXT> delete job funnelcake-db-migrate -n funnelcake --ignore-not-found
cat <<'EOF' | kubectl --context <STAGING_CONTEXT> apply -f -
apiVersion: batch/v1
kind: Job
metadata:
  name: funnelcake-db-migrate
  namespace: funnelcake
spec:
  ttlSecondsAfterFinished: 600
  backoffLimit: 3
  template:
    spec:
      restartPolicy: OnFailure
      containers:
        - name: migrate
          image: us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/funnelcake-migrate:COMMIT_HASH
          args: ["up"]
          env:
            - name: CLICKHOUSE_HOST
              value: "funnelcake-funnelcake-clickhouse.funnelcake.svc.cluster.local"
            - name: CLICKHOUSE_PORT
              value: "9000"
            - name: CLICKHOUSE_USER
              valueFrom:
                secretKeyRef:
                  name: funnelcake-clickhouse-credentials
                  key: CLICKHOUSE_USER
            - name: CLICKHOUSE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: funnelcake-clickhouse-credentials
                  key: CLICKHOUSE_PASSWORD
            - name: CLICKHOUSE_DATABASE
              valueFrom:
                secretKeyRef:
                  name: funnelcake-clickhouse-credentials
                  key: CLICKHOUSE_DATABASE
EOF

Vérifier les logs de migration

sleep 10 && kubectl logs job/funnelcake-db-migrate -n funnelcake

Gérer l'erreur « Dirty Database »

Si vous voyez error: Dirty database version X, une migration précédente a échoué à mi-chemin :

# Forcer la version pour effacer l'état dirty
kubectl delete job funnelcake-db-migrate -n funnelcake --ignore-not-found
# Créer un job avec args: ["force", "X"] à la place de ["up"]
# Puis exécuter "up" à nouveau

Erreurs courantes et corrections

Erreur : « no match for platform in manifest: not found »

Cause : Image construite pour la mauvaise architecture (arm64 sur Mac, mais GKE a besoin d'amd64) Correction : Reconstruire avec --platform linux/amd64

Erreur : « Unauthenticated request » lors du push

Cause : Docker non authentifié auprès d'Artifact Registry Correction : gcloud auth configure-docker us-central1-docker.pkg.dev --quiet

Erreur : « failed to push... fetch first »

Cause : Le serveur distant a de nouveaux commits Correction : git pull --rebase origin main && git push origin main

Erreur : « Dirty database version X »

Cause : Une migration précédente a échoué à mi-chemin Correction : Exécuter force X pour effacer l'état dirty, puis up à nouveau

Pods bloqués en ImagePullBackOff

Causes :

  1. Mauvaise architecture (vérifier avec kubectl describe pod)
  2. L'image n'existe pas (typo dans le tag)
  3. Problèmes d'authentification (vérifier imagePullSecrets)

Chemins clés

  • Repo funnelcake : /Users/rabble/code/divine/divine-funnelcake
  • Repo IaC : /Users/rabble/code/divine/divine-iac-coreconfig
  • Kustomization API : k8s/applications/funnelcake-api/overlays/production/kustomization.yaml
  • Kustomization Relay : k8s/applications/funnelcake-relay/overlays/production/kustomization.yaml
  • Migrations : /Users/rabble/code/divine/divine-funnelcake/database/migrations/

Déployer vers Staging ou POC

Flux de travail complet pour les environnements hors production

# 1. Vérifier ce qui est en production et que nous voulons déployer
cat k8s/applications/funnelcake-relay/overlays/production/kustomization.yaml | grep newTag
# ex. newTag: "e7e79eb"

# 2. VÉRIFIER si cette image existe dans le registre staging
gcloud artifacts docker images list \
  us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/funnelcake-relay \
  --include-tags --limit=10 | grep e7e79eb

# 3. Si NOT trouvée → CONSTRUIRE ET POUSSER
cd /Users/rabble/code/divine/divine-funnelcake
git checkout e7e79eb

docker build --platform linux/amd64 --target relay \
  -t us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/funnelcake-relay:e7e79eb .
docker push us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/funnelcake-relay:e7e79eb

docker build --platform linux/amd64 --target api \
  -t us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/funnelcake-api:e7e79eb .
docker push us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/funnelcake-api:e7e79eb

# Pour POC, tagguer et pousser vers le registre POC aussi
docker tag ...staging...:e7e79eb ...poc...:e7e79eb
docker push ...poc...:e7e79eb

git checkout main  # Revenir à main

# 4. Mettre à jour la kustomization (seulement APRÈS que les images existent !)
cd /Users/rabble/code/divine/divine-iac-coreconfig
# Éditer les overlays staging/poc avec les nouveaux tags

# 5. Commiter et pousser
git add -A && git commit -m "deploy(staging, poc): funnelcake @ e7e79eb" && git push

# 6. Synchroniser ArgoCD (chaque environnement a le sien !)
kubectl --context connectgateway_dv-platform-staging_us-central1_gke-staging-membership \
  patch application funnelcake-relay -n argocd --type merge \
  -p '{"operation":{"initiatedBy":{"username":"claude"},"sync":{"syncStrategy":{"apply":{"force":false}}}}}'

# 7. VÉRIFIER que les pods sont réellement en cours d'exécution (pas en ImagePullBackOff !)
kubectl --context connectgateway_dv-platform-staging_us-central1_gke-staging-membership \
  get pods -n funnelcake

LISTE DE VÉRIFICATION POST-DÉPLOIEMENT

Toujours exécuter ceci après tout déploiement :

# 1. Vérifier le statut des pods (doit être Running, pas ImagePullBackOff)
kubectl --context <CONTEXT> get pods -n funnelcake

# 2. Vérifier que l'image déployée réelle correspond à celle attendue
kubectl --context <CONTEXT> get deployment funnelcake-relay -n funnelcake \
  -o jsonpath='{.spec.template.spec.containers[0].image}'

# 3. Vérifier que le site fonctionne réellement
curl -s https://relay.staging.dvines.org/ | grep -o "version.*" | head -1

Registre d'images

  • Production : us-central1-docker.pkg.dev/dv-platform-prod/containers-production/
  • Staging : us-central1-docker.pkg.dev/dv-platform-staging/containers-staging/
  • POC : us-central1-docker.pkg.dev/rich-compiler-479518-d2/containers-poc/

Notes

  • Toujours utiliser le hash de commit court (7 caractères) pour les tags d'image
  • Le Dockerfile a un build multi-étapes : --target api ou --target relay
  • L'image de migration est dans database/Dockerfile
  • Les identifiants ClickHouse sont dans le secret funnelcake-clickhouse-credentials
  • ArgoCD a besoin des opérations de REFRESH et de SYNC

Skills similaires