cloud-run-job-cloudsql-setup

Par divinevideo · divine-mobile

Configurez Cloud Run Jobs avec une connexion CloudSQL. À utiliser quand : (1) déploiement de jobs batch de longue durée nécessitant un accès à la base de données, (2) erreurs du type « Cloud SQL Proxy not found » dans le conteneur, (3) « password authentication failed » malgré des identifiants corrects, (4) la création du job échoue avec des erreurs de permission. Couvre la configuration du chemin de socket, les permissions IAM et les erreurs courantes.

npx skills add https://github.com/divinevideo/divine-mobile --skill cloud-run-job-cloudsql-setup

Cloud Run Job avec Configuration CloudSQL

Problème

Configurer Cloud Run Jobs pour se connecter à CloudSQL implique plusieurs étapes non évidentes et des pièges qui causent des erreurs confuses. Les principaux problèmes sont :

  1. Mauvais flags gcloud pour la connexion CloudSQL
  2. Configuration incorrecte du chemin socket
  3. Permissions IAM manquantes
  4. Code applicatif tentant de démarrer le proxy alors que Cloud Run le fournit déjà

Contexte / Conditions de déclenchement

  • Erreur : « unrecognized arguments: --add-cloudsql-instances » (mauvais nom de flag)
  • Erreur : « Cloud SQL Proxy not found » (app tentant de démarrer le proxy dans le conteneur)
  • Erreur : « password authentication failed » (chemin socket mal configuré ou saut de ligne dans le secret)
  • Erreur : « Permission denied on secret » (rôle secretAccessor manquant)
  • Erreur : « does not have permission to access namespaces » (rôle cloudsql.client manquant)

Solution

1. Créer le Job avec les bons flags

gcloud run jobs create my-job \
  --region=us-central1 \
  --image=gcr.io/PROJECT/IMAGE:latest \
  --set-cloudsql-instances=PROJECT:REGION:INSTANCE \  # NOT --add-cloudsql-instances
  --set-env-vars="POSTGRES_SOCKET_PATH=/cloudsql/PROJECT:REGION:INSTANCE,POSTGRES_DATABASE=mydb,POSTGRES_USER=myuser" \
  --set-secrets="POSTGRES_PASSWORD=my-secret:latest"

Point clé : Utiliser --set-cloudsql-instances et NOT --add-cloudsql-instances

2. Configurer le chemin socket dans l'app

Pour Node.js avec la librairie pg :

// Utiliser socketPath pour un socket unix, pas host
if (config.socketPath) {
  pool = new Pool({
    host: config.socketPath,  // par ex., "/cloudsql/project:region:instance"
    database: config.database,
    user: config.user,
    password: config.password,
  });
}

Variable d'environnement : POSTGRES_SOCKET_PATH=/cloudsql/PROJECT:REGION:INSTANCE

3. Accorder les permissions IAM requises

# Accès au secret
gcloud secrets add-iam-policy-binding my-secret \
  --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

# Connexion CloudSQL
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
  --role="roles/cloudsql.client"

4. Ne pas auto-démarrer le Proxy dans le conteneur

Cloud Run fournit automatiquement le socket du proxy CloudSQL. Si votre app a une logique pour démarrer le proxy, l'ignorer quand un chemin socket est configuré :

// Ignorer le démarrage du proxy si socketPath fourni (Cloud Run le gère)
if (!config.socketPath && config.host === "localhost") {
  await ensureCloudSqlProxy();  // Uniquement pour le développement local
}

5. Créer les secrets sans sauts de ligne

# INCORRECT - ajoute un saut de ligne final
gcloud secrets create my-secret --data-file=- <<< "password"

# CORRECT - pas de saut de ligne
echo -n "password" | gcloud secrets create my-secret --data-file=-

Vérification

# Vérifier la config du job
gcloud run jobs describe my-job --region=us-central1

# Exécuter et vérifier les logs
gcloud run jobs execute my-job --region=us-central1
gcloud run jobs logs read my-job --region=us-central1 --limit=50

Exemple : Configuration complète

# 1. Créer les secrets (pas de sauts de ligne !)
echo -n "dbpassword123" | gcloud secrets create db-password --data-file=-

# 2. Accorder les permissions
gcloud secrets add-iam-policy-binding db-password \
  --member="serviceAccount:123456789-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

# 3. Créer le job
gcloud run jobs create my-processor \
  --region=us-central1 \
  --image=gcr.io/my-project/processor:latest \
  --memory=4Gi \
  --cpu=2 \
  --task-timeout=86400s \
  --max-retries=3 \
  --set-cloudsql-instances=my-project:us-central1:my-instance \
  --set-env-vars="POSTGRES_SOCKET_PATH=/cloudsql/my-project:us-central1:my-instance,POSTGRES_DATABASE=mydb,POSTGRES_USER=myuser" \
  --set-secrets="POSTGRES_PASSWORD=db-password:latest"

# 4. Exécuter
gcloud run jobs execute my-processor --region=us-central1

Notes

  • Le timeout maximum d'un Cloud Run Job est 86400s (24 heures)
  • Le format du chemin socket est /cloudsql/PROJECT:REGION:INSTANCE
  • Le socket apparaît comme un socket Unix à ce chemin quand le conteneur démarre
  • Pas besoin du binaire Cloud SQL Proxy dans votre conteneur
  • Le compte de service Cloud Build a besoin de permissions différentes du compte de service compute
  • Piège de réinitialisation du mot de passe PostgreSQL : Lors de la réinitialisation des mots de passe Cloud SQL PostgreSQL, ne PAS utiliser --host='%'. Ce flag est spécifique à MySQL et crée une entrée utilisateur séparée dans PostgreSQL, causant des échecs intermittents d'authentification par mot de passe (certains jobs se connectent, d'autres non, malgré DATABASE_URL identique). Utiliser : gcloud sql users set-password USERNAME --instance=INSTANCE --password=PASSWORD (pas de flag --host)
  • Les changements de mot de passe peuvent prendre une minute pour se propager à travers les sidecars Cloud SQL Auth Proxy. Si l'authentification échoue immédiatement après une réinitialisation, redéployer le job pour forcer une nouvelle connexion proxy

Références

Skills similaires