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 :
- Mauvais flags gcloud pour la connexion CloudSQL
- Configuration incorrecte du chemin socket
- Permissions IAM manquantes
- 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