Exécuter et mettre à l'échelle des exécuteurs GitHub auto-hébergés sur des pools de nœuds de calcul Cloud Run

Ce tutoriel vous explique comment utiliser des runners GitHub auto-hébergés sur des pools de nœuds de calcul pour exécuter les workflows définis dans votre dépôt GitHub et comment mettre à l'échelle votre pool de nœuds de calcul avec Cloud Run External Metrics Autoscaling (CREMA).

À propos des exécuteurs GitHub auto-hébergés

Dans un workflow GitHub Actions, les runners sont les machines qui exécutent les tâches. Par exemple, un runner peut cloner votre dépôt localement, installer un logiciel de test, puis exécuter des commandes qui évaluent votre code.

Vous pouvez utiliser des exécuteurs auto-hébergés pour exécuter des actions GitHub sur des instances de pool de nœuds de calcul Cloud Run. Ce tutoriel explique comment mettre automatiquement à l'échelle un pool de runners en fonction du nombre de tâches en cours d'exécution et non planifiées.

Objectifs

Au cours de ce tutoriel, vous allez :

Coûts

Dans ce document, vous utilisez les composants facturables de Google Cloudsuivants :

Vous pouvez obtenir une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.

Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai sans frais.

Avant de commencer

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. Enable the Cloud Run, Secret Manager, Parameter Manager, Artifact Registry, and Cloud Build APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  7. Installez et initialisez la gcloud CLI.
  8. Mettez à jour les composants :
    gcloud components update
  9. Définissez les variables de configuration suivantes pour CREMA, utilisées dans ce tutoriel :
    PROJECT_ID=PROJECT_ID
    CREMA_SERVICE_ACCOUNT_NAME=crema-service-account@$PROJECT_ID.iam.gserviceaccount.com
    CREMA_REPO_NAME=crema
    AR_REGION=us-central1
    Remplacez PROJECT_ID par l'ID de votre projet Google Cloud .
  10. Les frais de votre service de scaling Cloud Run dépendent de la fréquence à laquelle vous déclenchez le scaling. Pour en savoir plus, estimez les coûts avec le simulateur de coût.
  11. Rôles requis

    Pour obtenir les autorisations nécessaires pour suivre le tutoriel, demandez à votre administrateur de vous accorder les rôles IAM suivants sur votre projet :

    Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

    Vous pouvez également obtenir les autorisations requises via des rôles personnalisés ou d'autres rôles prédéfinis.

    Vous devez disposer de l'autorisation de modifier les paramètres d'un dépôt GitHub pour configurer les runners auto-hébergés. Le dépôt peut appartenir à un utilisateur ou à une organisation.

    GitHub recommande d'utiliser des exécuteurs auto-hébergés uniquement avec des dépôts privés.

    Créer un compte de service personnalisé

    Ce tutoriel utilise un compte de service personnalisé avec les autorisations minimales requises pour utiliser les ressources provisionnées. Pour configurer le compte de service, procédez comme suit :

    gcloud iam service-accounts create crema-service-account \
      --display-name="CREMA Service Account"
    

Ajouter des exécuteurs GitHub auto-hébergés

Pour ajouter des runners GitHub auto-hébergés, suivez les instructions de la section Ajouter des runners auto-hébergés de la documentation GitHub.

Identifier le dépôt GitHub

Dans ce tutoriel, la variable GITHUB_REPO représente le nom du dépôt. Il s'agit de la partie du nom qui se trouve après le nom de domaine pour les dépôts d'utilisateurs personnels et les dépôts d'organisation. Exemple :

  • Si l'URL de votre domaine est https://github.com/myuser/myrepo, le GITHUB_REPO est myuser/myrepo.
  • Si l'URL de votre domaine est https://github.com/mycompany/ourrepo, le GITHUB_REPO est mycompany/ourrepo.

Créer un jeton d'accès

Créez un jeton d'accès GitHub pour ajouter et supprimer des runners de manière dynamique en interagissant avec le dépôt sélectionné. Pour créer un jeton d'accès sur GitHub et l'enregistrer dans Secret Manager, procédez comme suit :

  1. Assurez-vous d'être connecté à votre compte GitHub.
  2. Accédez à la page Settings > Developer Settings > Personal Access Tokens > Tokens (classic) (Paramètres > Paramètres du développeur > Jetons d'accès personnels > Jetons (classiques)) de GitHub.
  3. Cliquez sur Générer un nouveau jeton, puis sélectionnez Générer un nouveau jeton (classique).
  4. Pour le champ d'application du jeton, cochez la case repo.
  5. Cliquez sur Generate token (Générer un jeton).
  6. Copiez le jeton généré.

Pour en savoir plus sur les jetons d'accès, consultez la section Exigences d'authentification dans la documentation GitHub.

Créer un secret pour votre jeton d'accès à l'aide de Secret Manager

Prenez le jeton secret que vous avez créé à l'étape précédente et stockez-le dans Secret Manager. Pour définir les autorisations d'accès, procédez comme suit :

  1. Créez le secret dans Secret Manager :

    echo -n "GITHUB_TOKEN" | gcloud secrets create github_runner_token --data-file=-
    

    Remplacez GITHUB_TOKEN par la valeur que vous avez copiée à partir de GitHub.

  2. Accordez au roles/secretmanager.secretAccessor de votre compte de service personnalisé l'accès au secret que vous venez de créer :

    gcloud secrets add-iam-policy-binding github_runner_token \
      --member "serviceAccount:$CREMA_SERVICE_ACCOUNT_NAME" \
      --role "roles/secretmanager.secretAccessor"
    

Déployer un pool de nœuds de calcul

Créez un pool de nœuds de calcul Cloud Run pour traiter les actions GitHub. Ce pool utilisera une image basée sur l'image actions/runner créée par GitHub. Pour déployer un pool de nœuds de calcul :

  1. Clonez l'exemple de dépôt sur votre ordinateur local pour récupérer l'exemple de code à utiliser :

    git clone https://github.com/GoogleCloudPlatform/cloud-run-samples
    
  2. Accédez au répertoire contenant l'exemple de code Cloud Run :

    cd cloud-run-samples/github-runner/worker-pool-container
    
  3. Déployez le pool de nœuds de calcul :

    gcloud beta run worker-pools deploy WORKER_POOL_NAME \
      --region us-central1 \
      --source . \
      --instances 1 \
      --set-env-vars GITHUB_REPO=GITHUB_REPO \
      --set-secrets GITHUB_TOKEN=github_runner_token:latest \
      --service-account $CREMA_SERVICE_ACCOUNT_NAME \
      --memory 2Gi \
      --cpu 4
    

    Remplacez les éléments suivants :

    • WORKER_POOL_NAME : nom du pool de nœuds de calcul
    • WORKER_POOL_LOCATION : région du pool de nœuds de calcul
    • GITHUB_REPO : nom du dépôt GitHub

    Si vous utilisez des déploiements de source Cloud Run pour la première fois dans ce projet, Cloud Run vous invite à créer un dépôt Artifact Registry par défaut.

Comprendre l'exemple de code

Le pool de nœuds de calcul est configuré avec un fichier Dockerfile basé sur l'image actions/runner créée par GitHub :

FROM ghcr.io/actions/actions-runner:2.330.0

# Add scripts with right permissions.
USER root
# hadolint ignore=DL3045
COPY start.sh start.sh
RUN chmod +x start.sh

# Add start entrypoint with right permissions.
USER runner
ENTRYPOINT ["./start.sh"]

Ce script d'assistance s'exécute au démarrage du conteneur. Il s'enregistre dans le dépôt configuré en tant qu'instance éphémère à l'aide d'un jeton que vous créez.

# Configure the current runner instance with URL, token and name.
mkdir /home/docker/actions-runner && cd /home/docker/actions-runner
echo "GitHub Repo: ${GITHUB_REPO_URL} for ${RUNNER_PREFIX}-${RUNNER_SUFFIX}"
./config.sh --unattended --url ${GITHUB_REPO_URL} --pat ${GH_TOKEN} --name ${RUNNER_NAME}

# Function to cleanup and remove runner from Github.
cleanup() {
   echo "Removing runner..."
   ./config.sh remove --unattended --pat ${GH_TOKEN}
}

# Trap signals.
trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM

# Run the runner.
./run.sh & wait $!

Utiliser le pool de nœuds de calcul pour accepter les jobs des actions GitHub

Votre instance de pool de nœuds de calcul est prête à accepter les jobs des actions GitHub.

Si votre dépôt ne comporte pas encore d'actions GitHub, suivez les instructions du guide de démarrage rapide pour créer votre premier workflow.

Si votre dépôt comporte des actions GitHub, vérifiez que vous avez terminé la configuration de votre exécuteur auto-hébergé en appelant une action GitHub sur votre dépôt.

Si votre action GitHub n'utilise pas d'exécuteurs auto-hébergés, modifiez le job de votre action GitHub en remplaçant la valeur runs-on par self-hosted.

Une fois que vous avez configuré une action pour utiliser les runners auto-hébergés, exécutez-la.

Vérifiez que l'action s'est bien déroulée dans l'interface GitHub.

Déployer le service CREMA de l'autoscaler

Vous avez déployé un nœud de calcul dans votre pool d'origine, ce qui permet de traiter une action à la fois. En fonction de votre utilisation de l'intégration continue (CI), vous devrez peut-être mettre à l'échelle votre pool pour gérer un afflux de tâches à effectuer.

Une fois que vous avez déployé le pool de nœuds de calcul avec un runner GitHub actif, configurez l'autoscaler CREMA pour provisionner des instances de nœud de calcul en fonction de l'état des jobs dans la file d'attente des actions.

Cette implémentation écoute un événement workflow_job. Lorsque vous créez un job de workflow, il augmente la taille du pool de nœuds de calcul, puis la réduit une fois le job terminé. Il ne mettra pas à l'échelle le pool au-delà du nombre maximal d'instances que vous configurez et le mettra à zéro une fois que tous les jobs en cours d'exécution seront terminés.

Vous pouvez adapter CREMA en fonction de vos charges de travail.

Configurer l'autoscaler

Ce tutoriel utilise le gestionnaire de paramètres pour stocker le fichier de configuration YAML pour CREMA.

  1. Créez un paramètre dans le Gestionnaire de paramètres pour stocker les versions de paramètres pour CREMA :

    PARAMETER_ID=crema-config
    PARAMETER_REGION=global
    gcloud parametermanager parameters create $PARAMETER_ID --location=$PARAMETER_REGION --parameter-format=YAML
    
  2. Créez un fichier YAML, my-crema-config.yaml, dans le répertoire parent pour définir la configuration de l'autoscaler :

    apiVersion: crema/v1
    kind: CremaConfig
    metadata:
      name: gh-demo
    spec:
      pollingInterval: 10
      triggerAuthentications:
        - metadata:
            name: github-trigger-auth
          spec:
            gcpSecretManager:
              secrets:
                - parameter: personalAccessToken
                  id: github_runner_token
                  version: latest
      scaledObjects:
        - spec:
            scaleTargetRef:
              name: projects/PROJECT_ID/locations/us-central1/workerpools/WORKER_POOL_NAME
            triggers:
              - type: github-runner
                name: GITHUB_RUNNER
                metadata:
                  owner: REPOSITORY_OWNER
                  runnerScope: repo
                  repos: REPOSITORY_NAME
                  targetWorkflowQueueLength: 1
                authenticationRef:
                  name: github-trigger-auth
            advanced:
              horizontalPodAutoscalerConfig:
                behavior:
                  scaleDown:
                    stabilizationWindowSeconds: 10
                    policies:
                      - type: Pods
                        value: 100
                        periodSeconds: 10
                  scaleUp:
                    stabilizationWindowSeconds: 10
                    policies:
                      - type: Pods
                        value: 2
                        periodSeconds: 10
    
    

    Remplacez les éléments suivants :

    • PROJECT_ID : ID du projet Google Cloud
    • WORKER_POOL_NAME : nom du pool de nœuds de calcul que vous avez déployé
    • GITHUB_RUNNER : nom du GitHub Runner que vous avez configuré.
    • REPOSITORY_OWNER : propriétaire du dépôt GitHub
    • REPOSITORY_NAME : nom du dépôt GitHub
  3. Importez votre fichier YAML local en tant que nouvelle version de paramètre :

    LOCAL_YAML_CONFIG_FILE=my-crema-config.yaml
    PARAMETER_VERSION=1
    
    gcloud parametermanager parameters versions create $PARAMETER_VERSION \
      --location=$PARAMETER_REGION \
      --parameter=$PARAMETER_ID \
      --payload-data-from-file=$LOCAL_YAML_CONFIG_FILE
    

Accorder des autorisations supplémentaires à votre compte de service personnalisé

Pour mettre à l'échelle le pool de nœuds de calcul que vous avez spécifié dans votre configuration YAML, accordez les autorisations suivantes au compte de service personnalisé :

  1. Accordez à votre compte de service CREMA l'autorisation de lire les paramètres dans Parameter Manager :

    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:$CREMA_SERVICE_ACCOUNT_NAME" \
      --role="roles/parametermanager.parameterViewer"
    
  2. Attribuez le rôle roles/run.developer à votre compte de service CREMA sur le pool de nœuds de calcul :

    WORKER_POOL_NAME=WORKER_POOL_NAME
    WORKER_POOL_REGION=us-central1
    gcloud beta run worker-pools add-iam-policy-binding $WORKER_POOL_NAME \
      --region=$WORKER_POOL_REGION \
      --member="serviceAccount:$CREMA_SERVICE_ACCOUNT_NAME" \
      --role="roles/run.developer"
    

    Remplacez WORKER_POOL_NAME par le nom du pool de nœuds de calcul.

  3. Autorisez votre compte de service CREMA à écrire des métriques :

     gcloud projects add-iam-policy-binding $PROJECT_ID \
       --member="serviceAccount:$CREMA_SERVICE_ACCOUNT_NAME" \
       --role="roles/monitoring.metricWriter"
    
  4. Attribuez le rôle d'utilisateur de compte de service à votre compte de service CREMA :

    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:$CREMA_SERVICE_ACCOUNT_NAME" \
      --role="roles/iam.serviceAccountUser"
    

Déployer le service pour faire évoluer vos charges de travail

Pour déployer le service afin de mettre à l'échelle votre pool de nœuds de calcul, exécutez la commande suivante avec une image de conteneur prédéfinie :

SERVICE_NAME=my-crema-service
SERVICE_REGION=us-central1

CREMA_CONFIG_PARAM_VERSION=projects/$PROJECT_ID/locations/$PARAMETER_REGION/parameters/$PARAMETER_ID/versions/$PARAMETER_VERSION
IMAGE=us-central1-docker.pkg.dev/cloud-run-oss-images/crema-v1/autoscaler:1.0

gcloud beta run deploy $SERVICE_NAME \
  --image=${IMAGE} \
  --region=${SERVICE_REGION} \
  --service-account="${CREMA_SERVICE_ACCOUNT_NAME}" \
  --no-allow-unauthenticated \
  --no-cpu-throttling \
  --base-image=us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/java21 \
  --labels=created-by=crema \
  --set-env-vars="CREMA_CONFIG=${CREMA_CONFIG_PARAM_VERSION},OUTPUT_SCALER_METRICS=True"

Créer une valeur secrète de webhook

Pour créer une valeur secrète permettant d'accéder au webhook GitHub, procédez comme suit :

  1. Créez un secret Secret Manager pour gérer l'accès à votre webhook GitHub.

    echo -n "WEBHOOK_SECRET" | gcloud secrets create github_webhook_secret --data-file=-
    

    Remplacez WEBHOOK_SECRET par une valeur de chaîne arbitraire.

  2. Accordez l'accès au secret au compte de service de l'autoscaler :

    gcloud secrets add-iam-policy-binding github_webhook_secret \
      --member "serviceAccount:$CREMA_SERVICE_ACCOUNT_NAME" \
      --role "roles/secretmanager.secretAccessor"
    

Créer un webhook GitHub

Pour créer le webhook GitHub, procédez comme suit :

  1. Assurez-vous d'être connecté à votre compte GitHub.
  2. Accédez à votre dépôt GitHub.
  3. Cliquez sur Paramètres.
  4. Sous Code et automatisation, cliquez sur Webhooks.
  5. Cliquez sur Add webhook (Ajouter un Webhook).
  6. Saisissez ce qui suit :

    1. Dans URL de charge utile, saisissez l'URL du service CREMA Cloud Run que vous avez déployé, my-crema-service.
    2. Pour Type de contenu, sélectionnez application/json.
    3. Dans le champ Secret, saisissez la valeur WEBHOOK_SECRET que vous avez créée précédemment.
    4. Pour Vérification SSL, sélectionnez Activer la vérification SSL.
    5. Dans Quels événements souhaitez-vous déclencher ce webhook ?, sélectionnez Me laisser sélectionner des événements individuels.
    6. Dans la sélection d'événements, sélectionnez Jobs de workflow. Désélectionnez toute autre option.
    7. Cliquez sur Add webhook (Ajouter un Webhook).

Tester votre service CREMA

Pour vérifier que votre service d'autoscaling fonctionne correctement, consultez l'onglet Journaux du service Cloud Run.

Vous devriez voir les journaux suivants dans les journaux de votre service chaque fois que les métriques sont actualisées :

Chaque message de journal est associé au composant qui l'a émis.

[INFO] [METRIC-PROVIDER] Starting metric collection cycle
[INFO] [METRIC-PROVIDER] Successfully fetched scaled object metrics ...
[INFO] [METRIC-PROVIDER] Sending scale request ...
[INFO] [SCALER] Received ScaleRequest ...
[INFO] [SCALER] Current instances ...
[INFO] [SCALER] Recommended instances ...

Effectuer un nettoyage

Pour éviter des frais supplémentaires sur votre compte Google Cloud , supprimez toutes les ressources que vous avez déployées avec ce tutoriel.

Supprimer le projet

Si vous avez créé un projet pour ce tutoriel, supprimez-le. Si vous avez utilisé un projet existant et que vous devez le conserver sans les modifications que vous avez apportées dans ce tutoriel, supprimez les ressources que vous avez créées pour ce tutoriel.

Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé pour ce tutoriel.

Pour supprimer le projet :

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Supprimer les ressources du tutoriel

  1. Supprimez le service Cloud Run que vous avez déployé dans ce tutoriel. Les services Cloud Run n'entraînent pas de coûts tant qu'ils ne reçoivent pas de requêtes.

    Pour supprimer votre service Cloud Run, exécutez la commande suivante :

    gcloud run services delete SERVICE-NAME

    Remplacez SERVICE-NAME par le nom du service.

    Vous pouvez également supprimer des services Cloud Run à partir de la consoleGoogle Cloud .

  2. Supprimez la configuration régionale par défaut gcloud que vous avez ajoutée lors de la configuration du tutoriel :

     gcloud config unset run/region
    
  3. Supprimez la configuration du projet :

     gcloud config unset project
    
  4. Supprimez les autres ressources Google Cloud créées dans ce tutoriel :

Étapes suivantes