Aller au contenu principal

Plane sur Google Cloud Run

Plane sur Google Cloud Run

Plane est une plateforme open source de gestion de projets — une alternative à Jira / Linear pour les tickets, les cycles, les modules et les feuilles de route. Ce module déploie Plane sur Cloud Run v2 au-dessus du socle App_CloudRun, qui provisionne et gère l'infrastructure Google Cloud partagée.

Ce guide se concentre sur les services cloud qu'utilise Plane et sur la manière de les explorer et de les exploiter depuis la console Google Cloud et la ligne de commande. Pour les mécanismes communs à toute application Cloud Run — identité du service, entrée et équilibrage de charge, mise à l'échelle et concurrence, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC Service Controls, sauvegardes et cycle de vie du déploiement — reportez-vous au guide du socle App_CloudRun plutôt que de les répéter ici.


1. Vue d'ensemble​

La pile auto-hébergée amont de Plane comporte plusieurs services : web / space / admin (frontends), api (Django/gunicorn), worker + beat (Celery), live (collaboration en temps réel) et un job migrator, plus PostgreSQL, Redis, RabbitMQ et un stockage objet compatible S3. Ce module déploie l'image communautaire tout-en-un publiée par Plane (makeplane/plane-aio-community), qui regroupe tous les sous-services derrière un reverse proxy Caddy interne sur le port 80 via supervisord — un seul service Cloud Run expose donc toute l'application. Le déploiement assemble :

FonctionnalitéService Google CloudRemarques
CalculCloud Run v2Conteneur tout-en-un (api + workers + frontends + migrator), 2 vCPU / 4 GiB par défaut
Courtier de messagesRabbitMQ en sidecar dans le podrabbitmq:3.13-management-alpine sur 127.0.0.1:5672 — obligatoire pour Celery
Base de donnéesCloud SQL for PostgreSQL 15PostgreSQL standard, aucune extension requise
Cache / backend de file de tâchesRedisActivé par défaut ; hébergé sur la VM du serveur NFS si aucun hôte externe n'est indiqué
Fichiers partagésFilestore / NFS autogéréNécessaire à la colocalisation de Redis (environnement d'exécution gen2)
Stockage objetCloud StorageUn bucket storage dédié est provisionné — le câblage des téléversements S3 est un TODO documenté
SecretsSecret ManagerSECRET_KEY, LIVE_SERVER_SECRET_KEY et le mot de passe de la base de données gérés automatiquement
EntréeURL Cloud Run / Cloud Load BalancingURL run.app par défaut, équilibreur de charge HTTPS externe et domaine personnalisé facultatifs

Valeurs par défaut judicieuses à connaître d'emblée :

  • PostgreSQL 15 est le moteur imposé. Plane est une application Django ; database_type = "POSTGRES_15" et aucun autre moteur ne fonctionne.
  • RabbitMQ est obligatoire et s'exécute en sidecar dans le pod. Le start.sh de Plane se termine avec un code non nul si AMQP_URL est vide. AMQP (TCP 5672) est un protocole non HTTP que le réseau de service à service de Cloud Run ne peut pas acheminer ; le courtier partage donc le pod sur 127.0.0.1:5672. L'état du courtier est éphémère (la durabilité des files est un TODO documenté).
  • Build personnalisé. Un Dockerfile wrapper minimal ajoute un point d'entrée de la plateforme à l'image AIO ; ce point d'entrée compose les chaînes de connexion DATABASE_URL / REDIS_URL / AMQP_URL attendues par Plane à partir des valeurs distinctes DB_* / REDIS_* / RABBITMQ_* injectées par le socle.
  • application_version vaut stable par défaut. L'image amont n'a pas de tag latest — une entrée latest est automatiquement convertie en stable au moment du build.
  • Démarrage à froid par défaut. cpu_always_allocated = false et min_instance_count = 0 (facturation à la requête, mise à zéro). Les notifications, webhooks et exports Celery sont différés jusqu'à ce que la requête suivante réveille une instance — définissez cpu_always_allocated = true et min_instance_count = 1 pour un traitement en arrière-plan continu.
  • Deux secrets applicatifs sont générés automatiquement dans Secret Manager : le SECRET_KEY Django (50 caractères) et LIVE_SERVER_SECRET_KEY (40 caractères, authentification de la collaboration en temps réel).
  • Un job db-init s'exécute à chaque apply pour créer de façon idempotente la base de données et l'utilisateur Plane ; les migrations de schéma sont exécutées au démarrage par l'étape migrator propre à l'image AIO.
  • Les téléversements de fichiers sont un TODO. Plane a besoin d'un point de terminaison compatible S3 ; le bucket GCS storage existe, mais les clés HMAC d'interopérabilité S3 de GCS ne sont pas encore câblées. Les tickets, projets et cycles fonctionnent sans lui — les pièces jointes et les avatars, non.
  • Les sondes de santé ciblent /health via le proxy Caddy interne sur le port 80.

2. Services Google Cloud et comment les explorer​

Toutes les commandes supposent que PROJECT et REGION sont définis. Les noms des services et des ressources figurent dans les sorties du déploiement.

A. Cloud Run — le service Plane (avec le sidecar RabbitMQ)​

Plane s'exécute comme un service Cloud Run v2 unique. Le conteneur principal est l'image tout-en-un (supervisord exécute migrator → api / frontends / live + worker/beat Celery derrière Caddy sur :80) ; un second conteneur sidecar mq exécute RabbitMQ. Le démarrage du conteneur principal attend la sonde TCP 5672 du sidecar.

  • Console : Cloud Run → sélectionnez le service pour voir les révisions, le trafic, les journaux et les métriques. Le sidecar apparaît dans l'onglet Conteneurs de la révision.
  • CLI :
    gcloud run services list --project "$PROJECT" --region "$REGION"
    gcloud run services describe <service-name> --project "$PROJECT" --region "$REGION"
    gcloud run revisions list --service <service-name> --project "$PROJECT" --region "$REGION"

Consultez App_CloudRun pour la mise à l'échelle, la concurrence, l'environnement d'exécution et la répartition du trafic.

B. Cloud SQL for PostgreSQL 15​

Plane stocke les espaces de travail, projets, tickets, cycles et utilisateurs dans une instance gérée Cloud SQL for PostgreSQL 15. Au premier déploiement, un Job db-init crée la base de données et l'utilisateur de l'application ; l'étape migrator de l'image AIO applique ensuite les migrations Django à chaque démarrage du conteneur. Le point d'entrée de la plateforme se connecte via l'IP privée en TCP avec sslmode=require (le volume de socket Cloud SQL est monté, mais Django/psycopg de Plane utilise le DATABASE_URL composé).

  • Console : SQL → sélectionnez l'instance pour voir les connexions, les sauvegardes, les flags et les métriques.
  • CLI :
    gcloud sql instances list --project "$PROJECT"
    gcloud sql instances describe <instance-name> --project "$PROJECT"
    gcloud sql connect <instance-name> --user=<db-user> --project "$PROJECT"

Le nom de l'instance, la base de données, l'utilisateur et le secret du mot de passe figurent dans les sorties. Consultez App_CloudRun pour le modèle de connexion, les sauvegardes et la rotation du mot de passe.

C. Redis (backend Celery et cache)​

Redis sert de cache à Plane et de stockage des résultats Celery. Lorsqu'aucun redis_host externe n'est configuré, la VM du serveur NFS héberge Redis et son IP est résolue à l'exécution (le point d'entrée substitue l'espace réservé $(NFS_SERVER_IP) avant de composer REDIS_URL).

  • Console : Memorystore → Redis (si vous utilisez une instance gérée) ; Compute Engine → Instances de VM (VM NFS/Redis).
  • CLI :
    redis-cli -h <redis-host> ping
    gcloud run services logs read <service-name> --project "$PROJECT" --region "$REGION" --limit 50 | grep "Composed REDIS_URL"

D. Cloud Storage​

Un bucket storage dédié (gcs-<service-name>-storage) est provisionné pour les téléversements de fichiers de Plane. Le câblage des téléversements est un TODO : Plane exige un point de terminaison compatible S3, et bien que AWS_S3_ENDPOINT_URL pointe vers https://storage.googleapis.com, les clés HMAC d'interopérabilité S3 de GCS ne sont pas provisionnées — fournissez AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY via environment_variables (ou utilisez un bucket S3 externe) pour activer les pièces jointes.

  • Console : Cloud Storage → Buckets.
  • CLI :
    gcloud storage buckets list --project "$PROJECT" --filter="name~plane"
    gcloud storage ls gs://<storage-bucket>/

E. Secret Manager​

Trois secrets sont gérés automatiquement : le SECRET_KEY Django, le LIVE_SERVER_SECRET_KEY (authentification de la collaboration en temps réel) et le mot de passe Cloud SQL. Tous sont injectés à l'exécution ; le texte en clair n'apparaît jamais dans la configuration.

  • Console : Security → Secret Manager.
  • CLI :
    gcloud secrets list --project "$PROJECT" --filter="name~plane"
    gcloud secrets versions access latest --secret=<secret-name> --project "$PROJECT"

Consultez App_CloudRun pour le détail de l'injection et de la rotation.

F. Réseau et entrée​

Le service est joignable par défaut à son URL run.app ; l'URL prévue est injectée en tant que WEB_URL / DOMAIN_NAME / CORS_ALLOWED_ORIGINS afin que les redirections OAuth, CORS et les liens des e-mails fonctionnent d'emblée. Un équilibreur de charge HTTPS externe avec domaine personnalisé, Cloud CDN et Cloud Armor peut être ajouté — dans ce cas, le domaine doit correspondre à ces variables d'URL.

  • Console : Cloud Run (URL du service) ; Network services → Load balancing.
  • CLI :
    gcloud run services describe <service-name> --region "$REGION" --format='value(status.url)'
    gcloud compute addresses list --project "$PROJECT"

Consultez App_CloudRun.

G. Cloud Logging et Monitoring​

Les journaux du conteneur (y compris la sortie supervisord de chaque sous-service intégré et du sidecar mq) sont envoyés vers Cloud Logging ; les métriques Cloud Run et Cloud SQL vers Cloud Monitoring, avec un test de disponibilité facultatif sur /health (désactivé par défaut) et des règles d'alerte facultatives.

  • Console : Logging → Logs Explorer ; Monitoring → Dashboards / Tests de disponibilité.
  • CLI :
    gcloud run services logs read <service-name> --project "$PROJECT" --region "$REGION" --limit 50

3. Comportement de l'application Plane​

  • Configuration de la base de données au premier déploiement. Un Job db-init (postgres:15-alpine) crée de façon idempotente la base de données et l'utilisateur Plane, accorde les privilèges (dont GRANT <user> TO postgres afin que la propriété puisse être définie) et arrête proprement son sidecar Cloud SQL Proxy. Il s'exécute à chaque apply et peut être relancé sans risque.
  • Les migrations s'exécutent au démarrage, pas dans un job d'initialisation. Le supervisord de l'image AIO exécute un programme migrator (manage.py migrate) avant le démarrage de l'api et des frontends. La sonde de démarrage accorde jusqu'à ~5 minutes (délai initial de 30 s + 30 échecs × 10 s) pour un premier démarrage à froid.
  • Les URL de connexion sont composées par le point d'entrée. Le point d'entrée de la plateforme construit DATABASE_URL (TCP sur IP privée, sslmode=require ; loopback avec sslmode=disable sur GKE), REDIS_URL (en résolvant $(NFS_SERVER_IP)) et AMQP_URL (à partir de l'hôte injecté du sidecar), puis exécute le /app/start.sh intégré de Plane. Recherchez les lignes de journal Composed DATABASE_URL / REDIS_URL / AMQP_URL lors du débogage.
  • RabbitMQ est obligatoire. Le start.sh de Plane valide AMQP_URL et se termine s'il est vide. L'état du courtier du sidecar est éphémère — les tâches Celery en file sont perdues lors du recyclage d'une instance (TODO de durcissement documenté).
  • Configuration initiale — God Mode. Ouvrez <web_url>/god-mode/ pour créer l'administrateur de l'instance et configurer celle-ci (le point d'entrée modifie le Caddyfile interne avec une redirection 308 de /god-mode vers /god-mode/, pour contourner un problème de basename de la SPA Remix). Inscrivez-vous ensuite à l'URL racine et créez votre premier espace de travail.
  • Les téléversements de fichiers échouent tant que le stockage S3 n'est pas câblé. Tout le reste (tickets, projets, cycles, modules) fonctionne ; les pièces jointes et les avatars nécessitent de vrais identifiants S3 (voir §2D).
  • Compromis du démarrage à froid. Avec la configuration par défaut cpu_always_allocated = false + min = 0, le travail Celery en arrière-plan (notifications, webhooks, exports) ne s'exécute que lorsqu'une instance est active. Pour les équipes qui dépendent de notifications rapides, passez à cpu_always_allocated = true + min_instance_count = 1.
  • Chemin de santé. Les sondes de démarrage et de vivacité ainsi que le test de disponibilité ciblent /health sur le port 80 (le proxy Caddy interne).
  • Vérification :
    curl -s -o /dev/null -w "%{http_code}\n" "$SERVICE_URL/health"
    gcloud run services logs read <service-name> --region "$REGION" --limit 100 | grep -E "Composed|Starting Plane"

4. Variables de configuration​

Les variables sont regroupées exactement comme elles apparaissent sur la plateforme de déploiement. Seuls les paramètres propres à Plane ou notables pour lui sont listés ; toutes les autres entrées sont héritées d'App_CloudRun avec leur comportement standard.

Groupe 1 — Projet et identité​

VariableValeur par défautDescription
project_id(obligatoire)Projet Google Cloud cible.
regionus-central1Région du service et des ressources régionales.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 2 — Environnement de déploiement​

VariableValeur par défautDescription
tenant_iddemoSuffixe court qui rend les noms de ressources uniques par environnement.
support_users[]Adresses e-mail auxquelles sont accordés l'accès au projet et les alertes de monitoring.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 3 — Identité de l'application​

VariableValeur par défautDescription
application_nameplaneNom de base des ressources. Ne pas modifier après le premier déploiement.
display_namePlane - Project ManagementNom convivial affiché dans la console.
application_versionstableTag de l'image AIO. L'image amont n'a pas de tag latest — latest est converti en stable au moment du build.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 4 — Exécution et mise à l'échelle​

VariableValeur par défautDescription
cpu_limit2000mL'image AIO exécute de nombreux processus (api, workers, frontends, Caddy) ; 2 vCPU au minimum.
memory_limit4Gi4 GiB recommandés — augmentez si le migrator ou le worker manque de mémoire (OOM).
cpu_always_allocatedfalseDémarrage à froid / facturation à la requête. Les notifications, webhooks et exports Celery sont différés jusqu'à la requête suivante ; définissez true (avec min ≥ 1) pour un traitement en arrière-plan continu.
min_instance_count0Mise à zéro. Définissez 1 pour éviter les démarrages à froid et maintenir le flux des tâches en arrière-plan.
max_instance_count3Plafond de coût.
container_port80Le port du proxy Caddy interne — le seul port qu'expose le conteneur AIO.
enable_cloudsql_volumetrueMonte le volume de socket Cloud SQL (le point d'entrée se connecte néanmoins en TCP sur l'IP privée).
execution_environmentgen2Nécessaire pour les montages NFS.
timeout_seconds300Délai d'expiration des requêtes.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 5 — Contrôle d'accès et d'entrée​

VariableValeur par défautDescription
ingress_settingsallAccès public depuis Internet (nécessaire pour accéder à Plane depuis un navigateur).
vpc_egress_settingPRIVATE_RANGES_ONLYSortie vers les plages privées via le connecteur VPC (Cloud SQL, Redis, NFS).

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 6 — Variables d'environnement et secrets​

VariableValeur par défautDescription
environment_variables{}Remplace ou complète l'environnement de Plane. Utilisez-le pour fournir de vrais identifiants S3 (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_S3_BUCKET_NAME, AWS_S3_ENDPOINT_URL) une fois le stockage objet câblé.
secret_environment_variables{}Map variable d'environnement → nom du secret Secret Manager.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupes 7–10 — Sauvegarde, CI/CD, SQL personnalisé, domaine et CDN​

Comportement standard d'App_CloudRun — consultez App_CloudRun. À noter pour Plane : si vous définissez application_domains, le domaine personnalisé devient l'hôte qu'atteignent les utilisateurs, et WEB_URL / CORS_ALLOWED_ORIGINS / DOMAIN_NAME doivent pointer vers lui (surcharge via environment_variables), faute de quoi la connexion et les liens des e-mails ne fonctionnent plus.

Groupe 11 — Stockage et système de fichiers​

VariableValeur par défautDescription
enable_nfstrueNécessaire à la colocalisation de Redis sur la VM du serveur NFS (gen2).
create_cloud_storagetrueProvisionne le bucket storage déclaré par Plane_Common.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 12 — Backend de base de données​

VariableValeur par défautDescription
database_typePOSTGRES_15Plane exige PostgreSQL — ne pas passer à MySQL.
db_nameplane_dbNom de la base de données. Immuable après le premier déploiement.
db_userplane_userUtilisateur de l'application. Immuable après le premier déploiement.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 13 — Jobs et tâches planifiées​

VariableValeur par défautDescription
initialization_jobs[]Laissez vide pour utiliser le job db-init intégré (postgres:15-alpine). Les migrations de schéma sont gérées au démarrage par le migrator propre à l'image AIO.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 14 — Observabilité et santé​

VariableValeur par défautDescription
startup_probeHTTP /health, délai initial de 30 s, 30 échecs × 10 sFenêtre généreuse (~5 min) pour l'étape migrator du premier démarrage.
liveness_probeHTTP /health, délai de 30 s, période de 30 sVivacité vérifiée sur le point de terminaison de santé servi par Caddy.
uptime_check_configdésactivé, chemin /healthTest de disponibilité Cloud Monitoring ; désactivé par défaut.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 21 — Cache Redis​

VariableValeur par défautDescription
enable_redistrueObligatoire — la file de tâches Celery et le cache de Plane dépendent de Redis.
redis_host""Laissez vide pour utiliser le Redis hébergé sur la VM NFS.
redis_port6379Port Redis.

Toutes les autres entrées suivent le comportement standard d'App_CloudRun.

Groupe 22 — VPC Service Controls et journalisation d'audit​

Comportement standard d'App_CloudRun (enable_vpc_sc, vpc_cidr_ranges, vpc_sc_dry_run, enable_audit_logging) — consultez App_CloudRun.


5. Sorties​

Renvoyés à l'issue d'un déploiement réussi — le moyen le plus rapide de localiser et d'explorer les ressources en cours d'exécution.

SortieDescription
service_nameNom du service Cloud Run.
web_urlURL de l'interface web de Plane (le proxy Caddy interne sert web/space/admin/api sur cette URL unique).
api_urlURL de l'API Plane (même URL de service, routée par le proxy interne).
service_locationRégion dans laquelle le service s'exécute.
stage_servicesDétails des services par étape (Cloud Deploy).
load_balancer_ip / load_balancer_urlIP / URL de l'équilibreur de charge HTTPS externe (s'il est activé).
database_instance_nameNom de l'instance Cloud SQL.
database_name / database_userNom / utilisateur de la base de données de l'application.
database_password_secretSecret Secret Manager contenant le mot de passe de la base de données.
database_host / database_portPoint de terminaison de la base de données (sensible) / port.
storage_bucketsBuckets Cloud Storage créés (dont le bucket storage).
network_name / network_exists / regionsRéseau VPC, présence, régions.
container_image / container_registryImage déployée et dépôt Artifact Registry.
monitoring_enabled / monitoring_notification_channels / uptime_check_namesÉtat du monitoring, canaux, tests de disponibilité.
initialization_jobsNoms des jobs de configuration.
deployment_id / tenant_id / resource_prefixIdentifiants de nommage.
project_id / project_numberIdentifiants du projet.
cicd_enabled / github_repository_url / cicd_configurationÉtat et détails du CI/CD.
artifact_registry_repository / cloudbuild_trigger_name / cloudbuild_trigger_idRegistre et déclencheur de build.
vpc_sc_enabled / vpc_sc_perimeter_name / vpc_sc_dry_run_modeÉtat de VPC-SC.
audit_logging_enabled / artifact_registry_cmek_enabledÉtat de la journalisation d'audit et de CMEK.

6. Pièges de configuration et valeurs par défaut judicieuses​

Les validations au moment du plan détectent plusieurs de ces erreurs ; les autres n'apparaissent qu'à l'exécution.

Risque : Critique (perte de données / panne / sécurité) — Élevé (service dégradé) — Moyen (coût ou dégradation partielle) — Faible (mineur).

ParamètreValeur judicieuseRisqueConséquence en cas d'erreur
database_typePOSTGRES_15CritiquePlane est une application Django/PostgreSQL ; MySQL ou NONE cassent le migrator et le démarrage.
db_name / db_userÀ définir une seule foisCritiqueImmuables après le premier déploiement ; les renommer recrée la base/l'utilisateur et détruit toutes les données.
Sidecar RabbitMQLe laisser câbléCritiqueLe start.sh de Plane se termine si AMQP_URL est vide — le courtier est obligatoire et doit se trouver dans le pod (Cloud Run ne peut pas acheminer AMQP entre services).
container_port80CritiqueLe conteneur AIO n'expose que le proxy Caddy interne sur :80 ; tout autre port fait échouer toutes les sondes.
application_versionstable ou un tag réelÉlevéL'image amont n'a pas de tag latest ; le module convertit latest→stable, mais un tag explicite invalide fait échouer le build en 404 (MANIFEST_UNKNOWN).
enable_redistrueÉlevéSans Redis, Celery et le cache n'ont pas de backend ; les workers ne démarrent pas.
enable_nfstrue (lorsque redis_host est vide)ÉlevéLe Redis par défaut réside sur la VM NFS ; désactiver NFS sans redis_host externe laisse Plane sans point de terminaison Redis.
Fenêtre d'échec de startup_probe≥ 30 × 10 sÉlevéLe migrator du premier démarrage peut prendre plusieurs minutes ; une sonde trop stricte tue l'instance en pleine migration.
cpu_always_allocated / min_instance_counttrue / 1 pour les équipes dépendantes des notificationsMoyenAvec le démarrage à froid par défaut, les notifications/webhooks/exports Celery ne s'exécutent que lorsqu'une instance est active.
Stockage objet (AWS_*)De vrais identifiants S3 avant de compter sur les téléversementsMoyenLes téléversements de fichiers (pièces jointes, avatars) échouent tant que des clés HMAC ou un point de terminaison S3 externe ne sont pas fournis — le reste de Plane fonctionne.
application_domains + variables d'environnement d'URLLes garder synchronisésMoyenUn domaine personnalisé qui ne correspond pas à WEB_URL/CORS_ALLOWED_ORIGINS/DOMAIN_NAME casse les redirections de connexion et les liens des e-mails.
memory_limit4GiMoyenL'image AIO exécute de nombreux processus ; un sous-dimensionnement provoque un manque de mémoire (OOM) du migrator ou du worker Celery.
Durabilité de RabbitMQAccepter l'éphémère ou externaliserFaibleL'état du courtier du sidecar est éphémère ; les tâches en file sont perdues lors du recyclage d'une instance.

Pour le comportement du socle évoqué tout au long de ce guide — identité du service, mise à l'échelle et concurrence, entrée et équilibrage de charge, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC-SC, sauvegardes et mise en miroir des images — consultez App_CloudRun. La configuration applicative propre à Plane, partagée avec la variante GKE, est décrite dans Plane_Common.

Need RAD to do something it does not do yet? Request it on the roadmap, or vote on what is already there.