Déployer dbt sur Cloud Run Jobs implique plusieurs services GCP qui doivent être configurés dans le bon ordre : comptes de service, liaisons IAM, Artifact Registry, la tâche elle-même et un scheduler. Faire cela manuellement via la console est sujet aux erreurs et non reproductible. Un script de déploiement capture chaque étape sous forme de code.
Le script ci-dessous déploie une configuration dbt Cloud Run Jobs complète depuis zéro. Exécutez-le une fois pour la configuration initiale, puis faites évoluer les composants individuels selon vos besoins. Les gardes || true sur les commandes create rendent le script idempotent — sûr à réexécuter sans échouer sur les ressources qui existent déjà.
Le script complet
#!/bin/bashset -e
export PROJECT_ID=your-project-idexport REGION=us-central1export SA_NAME=dbt-runnerexport SA_EMAIL=$SA_NAME@$PROJECT_ID.iam.gserviceaccount.comexport IMAGE=$REGION-docker.pkg.dev/$PROJECT_ID/dbt-images/dbt-runner:v1.0.0
# --- Service Account ---gcloud iam service-accounts create $SA_NAME \ --display-name="dbt Cloud Run Runner" \ --description="Service account for dbt Cloud Run Jobs" \ --project=$PROJECT_ID || true
# --- IAM Bindings ---# BigQuery permissions for dbt executiongcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$SA_EMAIL" \ --role="roles/bigquery.dataEditor"
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$SA_EMAIL" \ --role="roles/bigquery.jobUser"
# --- Artifact Registry ---gcloud artifacts repositories create dbt-images \ --repository-format=docker \ --location=$REGION \ --project=$PROJECT_ID || true
# --- Build and Push Image ---gcloud builds submit \ --tag $IMAGE \ --project=$PROJECT_ID
# --- Cloud Run Job ---gcloud run jobs create dbt-daily \ --image=$IMAGE \ --region=$REGION \ --service-account=$SA_EMAIL \ --memory=2Gi \ --cpu=2 \ --max-retries=2 \ --task-timeout=3600 \ --set-env-vars="GCP_PROJECT=$PROJECT_ID,DBT_DATASET=analytics,BQ_LOCATION=US" \ --project=$PROJECT_ID
# --- Scheduler Service Account ---gcloud iam service-accounts create dbt-scheduler \ --display-name="dbt Scheduler Invoker" \ --project=$PROJECT_ID || true
gcloud run jobs add-iam-policy-binding dbt-daily \ --region=$REGION \ --member="serviceAccount:dbt-scheduler@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/run.invoker" \ --project=$PROJECT_ID
# --- Cloud Scheduler ---gcloud scheduler jobs create http dbt-daily-schedule \ --location=$REGION \ --schedule="0 6 * * *" \ --uri="https://$REGION-run.googleapis.com/apis/run.googleapis.com/v1/namespaces/$PROJECT_ID/jobs/dbt-daily:run" \ --http-method=POST \ --oauth-service-account-email=dbt-scheduler@$PROJECT_ID.iam.gserviceaccount.com \ --project=$PROJECT_ID
echo "Deployment complete. Test with:"echo "gcloud run jobs execute dbt-daily --region=$REGION --wait"Pourquoi deux comptes de service
Le script crée deux comptes de service distincts avec des objectifs différents :
dbt-runner est l’identité sous laquelle votre code dbt s’exécute. Il obtient bigquery.dataEditor et bigquery.jobUser — les permissions minimales nécessaires pour créer des tables et exécuter des requêtes. C’est le compte de service attaché au Cloud Run Job. Lorsque dbt se connecte à BigQuery via method: oauth, il s’authentifie sous cette identité via Workload Identity.
dbt-scheduler est l’identité que Cloud Scheduler utilise pour invoquer le Cloud Run Job. Il obtient uniquement roles/run.invoker sur la tâche spécifique — la permission de déclencher l’exécution, rien de plus. Il ne peut pas lire les données BigQuery, ne peut pas modifier les tables, ne peut rien faire d’autre que démarrer la tâche dbt.
Séparer ces comptes suit le principe du moindre privilège. Si le compte de service du scheduler était compromis, l’attaquant pourrait déclencher des exécutions dbt (gênant, mais impact limité). Il ne pourrait pas accéder à votre entrepôt de données. Inversement, le compte dbt-runner peut accéder à BigQuery mais ne peut pas déclencher sa propre exécution — il n’a aucune capacité d’auto-invocation.
Choix de configuration
Mémoire et CPU. Le script définit --memory=2Gi et --cpu=2. L’utilisation de la mémoire de dbt s’échelonne avec la complexité des modèles et le paramètre threads dans profiles.yml. Chaque thread maintient une connexion BigQuery et traite les résultats de requêtes en mémoire. Commencez avec 2 Go et 2 CPU. Si vous voyez des erreurs OOM (out-of-memory) dans Cloud Logging, augmentez la mémoire. Si les exécutions sont plus lentes que prévu, augmentez à la fois les CPU et les threads — plus de threads sans plus de CPU crée juste de la contention.
Timeout de tâche. --task-timeout=3600 donne à dbt une heure. Définissez cela plus haut que votre exécution la plus longue attendue, avec une marge pour la variance. Un projet qui se termine normalement en 15 minutes pourrait prendre 45 minutes lors d’un full refresh ou après une longue période sans traitement incrémental. Le maximum est de 168 heures (7 jours), mais si votre exécution dbt prend aussi longtemps, vous avez de plus gros problèmes.
Nombre max de réessais. --max-retries=2 signifie que Cloud Run réessaie les exécutions échouées deux fois. dbt quitte avec un code non-zéro en cas d’échec, que Cloud Run interprète comme une erreur retriable. Cela gère les échecs BigQuery transitoires (erreurs de quota, brèves interruptions réseau) sans logique de réessai personnalisée. Pour les échecs persistants, les réessais ne font que retarder l’alerte — vous avez toujours besoin de monitoring.
Variables d’environnement. --set-env-vars passe la configuration au conteneur. Le profiles.yml conteneurisé les lit avec env_var(). Modifier les variables d’environnement sur le Cloud Run Job ne nécessite pas de reconstruire l’image — vous pouvez changer de datasets ou de projets avec une commande gcloud run jobs update.
Tester le déploiement
Après avoir exécuté le script, vérifiez avec une exécution manuelle :
gcloud run jobs execute dbt-daily --region=us-central1 --waitL’indicateur --wait bloque votre terminal jusqu’à la fin de la tâche, en diffusant les logs au fur et à mesure. Surveillez :
- Erreurs d’authentification — le compte de service n’a pas les bonnes permissions BigQuery
- Dataset introuvable — le dataset cible n’existe pas et dbt n’a pas
bigquery.dataOwnerpour le créer - OOM killed — le conteneur a dépassé sa limite de mémoire (augmentez
--memory) - Timeout — la tâche a atteint
--task-timeoutavant de se terminer (augmentez le timeout)
Si l’exécution manuelle réussit, déclenchez le scheduler pour vérifier la chaîne complète :
gcloud scheduler jobs run dbt-daily-schedule --location=us-central1Vérifiez ensuite la liste d’exécutions du Cloud Run Job pour confirmer que l’exécution déclenchée par le scheduler s’est terminée.
Faire évoluer le script
Ce script est un point de départ. À mesure que votre déploiement mûrit, envisagez :
- Passer à Terraform pour une gestion d’infrastructure déclarative (le script capture quoi déployer ; Terraform capture ce qui devrait exister)
- Ajouter des déclencheurs Eventarc pour une exécution event-driven en complément du fallback planifié
- Configurer des alertes basées sur les logs pour les échecs de tâches avec
gcloud logging metrics create - Paramétrer davantage le script (nom de tâche, planning, limites de ressources) pour la réutilisation sur plusieurs projets dbt
Le script rend le déploiement initial reproductible et documenté. Chaque commande gcloud est visible, révisable et exécutable — pas d’étapes de wizard console, pas de liaisons IAM non documentées.