Planifier des instances de calcul avec Cloud Scheduler

Ce tutoriel explique comment utiliser Cloud Scheduler et Cloud Functions pour démarrer et arrêter automatiquement des instances Compute Engine selon un calendrier régulier, à l'aide d'étiquettes de ressources.

Objectifs

  • Apprendre à utiliser Cloud Functions pour écrire et déployer un ensemble de fonctions permettant de démarrer et d'arrêter des instances Compute Engine.
  • À l'aide de Cloud Scheduler, créez un ensemble de tâches qui programment les instances avec un libellé de ressource dev, de sorte qu'elles s'exécutent du lundi au vendredi de 9h00 à 17h00 en concordance avec les horaires de bureau habituels.

Coûts

Ce tutoriel utilise les composants facturables suivants de Google Cloud :

  • Cloud Scheduler
  • Cloud Functions
  • Pub/Sub
  • Instance

Obtenez 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 gratuit.

Avant de commencer

  1. Configurez votre environnement pour Cloud Scheduler.

    Configurer votre environnement

  2. Activez les Cloud Functions, Pub/Sub, and Compute Engine API.

    Activer les API

Architecture de l'application

Cette solution comprend les composants Google Cloud suivants :

  1. Instance Compute Engine : une instance Compute Engine que nous souhaitons exécuter selon un calendrier spécifique.
  2. Fonctions Cloud Functions : des fonctions permettant de démarrer et d'arrêter l'instance pour laquelle nous souhaitons définir un calendrier d'exécution.
  3. Messages Pub/Sub : des messages envoyés et reçus pour chaque événement de démarrage ou d'arrêt.
  4. Tâches Cloud Scheduler : des tâches permettant d'appeler les fonctions de démarrage et d'arrêt de l'instance en fonction du calendrier défini.

Diagramme de l'architecture système illustrant Cloud Scheduler programmant une instance Compute Engine via Pub/Sub

Exigences relatives aux emplacements

Certains composants ne sont compatibles qu'avec certaines régions :

  1. Instance Compute Engine : compatibilité avec toutes les régions et zones Compute Engine
  2. Fonctions Cloud Functions : compatibilité avec les régions répertoriées en tant qu'emplacements Cloud Functions
  3. Messages Pub/Sub : compatibilité mondiale, car Pub/Sub est un service mondial
  4. Tâches Cloud Scheduler : compatibilité avec n'importe quel emplacement App Engine actuel

Bonne pratique : Pourquoi pas HTTP au lieu de Pub/Sub ?

Pour simplifier cette architecture, vous pourriez utiliser les déclencheurs HTTP de Cloud Functions au lieu des déclencheurs Pub/Sub.

Diagramme d'architecture système présentant la planification d'une instance Compute Engine par Cloud Scheduler via HTTP

Diagramme d'architecture système montrant que la planification via HTTP permet à n'importe qui de modifier la planification de votre instance Compute Engine

Pour créer une configuration plus sécurisée, nous vous recommandons de privilégier des fonctions Pub/Sub.

Configurer l'instance Compute Engine

Console

  1. Accédez à la page Instances de VM de Cloud Console.
    Accéder à la page "Instances de VM"
  2. Cliquez sur Créer une instance.
  3. Définissez le paramètre Nom sur dev-instance.
  4. Dans le champ Région, sélectionnez us-west1.
  5. Pour Zone, sélectionnez us-west1-b.
  6. Développez la section Gestion, sécurité, disques, mise en réseau et location unique.
  7. Sous "Gestion", cliquez sur Ajouter une étiquette. Saisissez env pour le champ Clé et dev pour Valeur.
  8. Cliquez sur Créer en bas de la page.

gcloud

gcloud compute instances create dev-instance \
    --network default \
    --zone us-west1-b \
    --labels=env=dev

Configurer les fonctions Cloud Functions avec Pub/Sub

Créer et déployer les fonctions

Console

Créez la fonction de démarrage.

  1. Accédez à la page Cloud Functions dans Cloud Console.
    Accéder à la page Cloud Functions
  2. Cliquez sur Créer une fonction.
  3. Définissez le paramètre Nom sur startInstancePubSub.
  4. Laissez le paramètre Mémoire allouée sur sa valeur par défaut.
  5. Pour Déclencheur, sélectionnez Cloud Pub/Sub.
  6. Pour Sujet, sélectionnez Create new topic....
  7. Une boîte de dialogue Nouveau sujet Pub/Sub doit s'afficher.
    1. Dans le champ Nom, saisissez start-instance-event.
    2. Cliquez sur Créer pour créer la fonction et fermer la boîte de dialogue.
  8. Pour Environnement d'exécution, sélectionnez Node.js 8.
  9. Au-dessus du bloc de texte de code, sélectionnez l'onglet index.js.
  10. Remplacez le code de démarrage par le code suivant :

    const Compute = require('@google-cloud/compute');
    const compute = new Compute();
    
    /**
     * Starts Compute Engine instances.
     *
     * Expects a PubSub message with JSON-formatted event data containing the
     * following attributes:
     *  zone - the GCP zone the instances are located in.
     *  label - the label of instances to start.
     *
     * @param {!object} event Cloud Function PubSub message event.
     * @param {!object} callback Cloud Function PubSub callback indicating
     *  completion.
     */
    exports.startInstancePubSub = async (event, context, callback) => {
      try {
        const payload = _validatePayload(
          JSON.parse(Buffer.from(event.data, 'base64').toString())
        );
        const options = {filter: `labels.${payload.label}`};
        const [vms] = await compute.getVMs(options);
        await Promise.all(
          vms.map(async (instance) => {
            if (payload.zone === instance.zone.id) {
              const [operation] = await compute
                .zone(payload.zone)
                .vm(instance.name)
                .start();
    
              // Operation pending
              return operation.promise();
            }
          })
        );
    
        // Operation complete. Instance successfully started.
        const message = `Successfully started instance(s)`;
        console.log(message);
        callback(null, message);
      } catch (err) {
        console.log(err);
        callback(err);
      }
    };
    
    /**
     * Validates that a request payload contains the expected fields.
     *
     * @param {!object} payload the request payload to validate.
     * @return {!object} the payload object.
     */
    const _validatePayload = (payload) => {
      if (!payload.zone) {
        throw new Error(`Attribute 'zone' missing from payload`);
      } else if (!payload.label) {
        throw new Error(`Attribute 'label' missing from payload`);
      }
      return payload;
    };
  11. Au-dessus du bloc de texte de code, sélectionnez l'onglet package.json.

  12. Remplacez le code de démarrage par le code suivant :

    {
      "name": "cloud-functions-schedule-instance",
      "version": "0.1.0",
      "private": true,
      "license": "Apache-2.0",
      "author": "Google Inc.",
      "repository": {
        "type": "git",
        "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
      },
      "engines": {
        "node": ">=8.0.0"
      },
      "scripts": {
        "test": "mocha test/*.test.js --timeout=20000"
      },
      "devDependencies": {
        "mocha": "^7.0.0",
        "proxyquire": "^2.0.0",
        "sinon": "^9.0.0"
      },
      "dependencies": {
        "@google-cloud/compute": "^1.0.0"
      }
    }
    
  13. Pour Fonction à exécuter, saisissez startInstancePubSub.

  14. Cliquez sur Créer.

Créez la fonction d'arrêt.

  1. Vous devez vous trouver sur la page Cloud Functions de Cloud Console.
  2. Cliquez sur Créer une fonction.
  3. Définissez le paramètre Nom sur stopInstancePubSub.
  4. Laissez le paramètre Mémoire allouée sur sa valeur par défaut.
  5. Pour Déclencheur, sélectionnez Cloud Pub/Sub.
  6. Pour Sujet, sélectionnez Create new topic....
  7. Une boîte de dialogue Nouveau sujet Pub/Sub doit s'afficher.
    1. Dans le champ Nom, saisissez stop-instance-event.
    2. Cliquez sur Créer pour créer la fonction et fermer la boîte de dialogue.
  8. Pour Environnement d'exécution, sélectionnez Node.js 8.
  9. Au-dessus du bloc de texte de code, sélectionnez l'onglet index.js.
  10. Remplacez le code de démarrage par le code suivant :

    const Compute = require('@google-cloud/compute');
    const compute = new Compute();
    
    /**
     * Stops Compute Engine instances.
     *
     * Expects a PubSub message with JSON-formatted event data containing the
     * following attributes:
     *  zone - the GCP zone the instances are located in.
     *  label - the label of instances to stop.
     *
     * @param {!object} event Cloud Function PubSub message event.
     * @param {!object} callback Cloud Function PubSub callback indicating completion.
     */
    exports.stopInstancePubSub = async (event, context, callback) => {
      try {
        const payload = _validatePayload(
          JSON.parse(Buffer.from(event.data, 'base64').toString())
        );
        const options = {filter: `labels.${payload.label}`};
        const [vms] = await compute.getVMs(options);
        await Promise.all(
          vms.map(async (instance) => {
            if (payload.zone === instance.zone.id) {
              const [operation] = await compute
                .zone(payload.zone)
                .vm(instance.name)
                .stop();
    
              // Operation pending
              return operation.promise();
            } else {
              return Promise.resolve();
            }
          })
        );
    
        // Operation complete. Instance successfully stopped.
        const message = `Successfully stopped instance(s)`;
        console.log(message);
        callback(null, message);
      } catch (err) {
        console.log(err);
        callback(err);
      }
    };
    
    /**
     * Validates that a request payload contains the expected fields.
     *
     * @param {!object} payload the request payload to validate.
     * @return {!object} the payload object.
     */
    const _validatePayload = (payload) => {
      if (!payload.zone) {
        throw new Error(`Attribute 'zone' missing from payload`);
      } else if (!payload.label) {
        throw new Error(`Attribute 'label' missing from payload`);
      }
      return payload;
    };
  11. Au-dessus du bloc de texte de code, sélectionnez l'onglet package.json.

  12. Remplacez le code de démarrage par le code suivant :

    {
      "name": "cloud-functions-schedule-instance",
      "version": "0.1.0",
      "private": true,
      "license": "Apache-2.0",
      "author": "Google Inc.",
      "repository": {
        "type": "git",
        "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
      },
      "engines": {
        "node": ">=8.0.0"
      },
      "scripts": {
        "test": "mocha test/*.test.js --timeout=20000"
      },
      "devDependencies": {
        "mocha": "^7.0.0",
        "proxyquire": "^2.0.0",
        "sinon": "^9.0.0"
      },
      "dependencies": {
        "@google-cloud/compute": "^1.0.0"
      }
    }
    
  13. Pour Fonction à exécuter, saisissez stopInstancePubSub.

  14. Cliquez sur Créer.

gcloud

Créez les sujets Pub/Sub.

gcloud pubsub topics create start-instance-event
gcloud pubsub topics create stop-instance-event

Obtenir le code

  1. Téléchargez le code.

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    Vous pouvez également télécharger l'exemple en tant que fichier ZIP et l'extraire.

  2. Accédez au répertoire approprié.

    cd nodejs-docs-samples/functions/scheduleinstance/
    

Créez les fonctions de démarrage et d'arrêt.

Vous devez vous trouver dans le répertoire nodejs-docs-samples/functions/scheduleinstance/.

gcloud functions deploy startInstancePubSub \
    --trigger-topic start-instance-event \
    --runtime nodejs8
gcloud functions deploy stopInstancePubSub \
    --trigger-topic stop-instance-event \
    --runtime nodejs8

Vérifier que les fonctions sont opérationnelles (facultatif)

Console

Arrêter l'instance

  1. Accédez à la page Cloud Functions dans Cloud Console.
    Accéder à la page Cloud Functions
  2. Cliquez sur la fonction nommée stopInstancePubSub.
  3. Vous devriez voir un certain nombre d'onglets : Général, Déclencheur, Source et Test. Cliquez sur l'onglet Test.
  4. Pour le paramètre Événement déclencheur, saisissez les informations suivantes :

    {"data":"eyJ6b25lIjoidXMtd2VzdDEtYiIsICJsYWJlbCI6ImVudj1kZXYifQo="}
    

    • Il s'agit simplement de la chaîne encodée en base64 pour {"zone":"us-west1-b", "label":"env=dev"}.

    • Si vous souhaitez encoder votre propre chaîne, vous pouvez utiliser n'importe quel outil d'encodage base64 en ligne.

  5. Cliquez sur le bouton Tester la fonction.

  6. Une fois l'exécution terminée, Successfully stopped instance dev-instance devrait s'afficher sous Sortie. L'arrêt total de l'instance peut prendre jusqu'à 60 secondes.

    • Si au lieu de cela error: 'Error: function failed to load.' s'affiche, attendez 10 secondes environ pour que la fonction termine le déploiement, puis réessayez.

    • Si au lieu de cela error: 'Error: function execution attempt timed out.' s'affiche, passez simplement à l'étape suivante pour déterminer si l'instance prend simplement un certain temps à s'arrêter.

    • Si la fonction s'exécute correctement et que rien ne s'affiche, cela peut indiquer que le délai d'exécution a été dépassé. Passez à l'étape suivante pour vérifier si cela vient du fait que l'instance met beaucoup de temps à s'arrêter.

  7. Accédez à la page Instances de VM de Cloud Console.
    Accéder à la page "Instances de VM"

  8. Vérifiez qu'un carré gris est présent à côté du nom de l'instance nommée dev-instance. Ce carré indique que l'instance s'est arrêtée. L'arrêt total de l'instance peut prendre jusqu'à 30 secondes.

    • Si l'instance ne semble pas s'arrêter, essayez de cliquer sur Actualiser en haut de la page.

Démarrer l'instance

  1. Accédez à la page Cloud Functions dans Cloud Console.
    Accéder à la page Cloud Functions
  2. Cliquez sur la fonction nommée startInstancePubSub.
  3. Vous devriez voir un certain nombre d'onglets : Général, Déclencheur, Source et Test. Cliquez sur l'onglet Test.
  4. Pour le paramètre Événement déclencheur, saisissez les informations suivantes :

    {"data":"eyJ6b25lIjoidXMtd2VzdDEtYiIsICJsYWJlbCI6ImVudj1kZXYifQo="}
    

    • Encore une fois, il s'agit simplement de la chaîne encodée en base64 pour {"zone":"us-west1-b", "label":"env=dev"}.
  5. Cliquez sur le bouton Tester la fonction.

  6. Une fois l'exécution terminée, Successfully started instance dev-instance devrait s'afficher sous Sortie.

  7. Accédez à la page Instances de VM de Cloud Console.
    Accéder à la page "Instances de VM"

  8. Vérifiez qu'une coche verte est présente à côté du nom de l'instance nommée dev-instance. Cette coche indique que l'instance s'est arrêtée. Le démarrage effectif de l'instance peut prendre jusqu'à 30 secondes.

gcloud

Pour arrêter l'instance, procédez comme suit :

  1. Appelez la fonction permettant d'arrêter l'instance.

    gcloud functions call stopInstancePubSub \
        --data '{"data":"eyJ6b25lIjoidXMtd2VzdDEtYiIsICJsYWJlbCI6ImVudj1kZXYifQo="}'
    
    • Il s'agit simplement de la chaîne encodée en base64 pour {"zone":"us-west1-b", "label":"env=dev"}.

    • Si vous voulez encoder votre propre chaîne, vous pouvez utiliser n'importe quel outil d'encodage base64. Voici un exemple d'utilisation avec l'outil de ligne de commande base64 :

      echo '{"zone":"us-west1-b", "label":"env=dev"}' | base64
      
      eyJ6b25lIjoidXMtd2VzdDEtYiIsICJsYWJlbCI6ImVudj1kZXYifQo=
      

    Lorsque la fonction a terminé, le résultat suivant doit s'afficher :

    result: Successfully stopped instance dev-instance
    

    L'arrêt total de l'instance peut prendre jusqu'à 60 secondes.

    • Si au lieu de ce résultat, l'erreur suivante s'affiche :

      error: 'Error: function failed to load.`
      

      Patientez environ 10 secondes pour que le déploiement de la fonction s'achève, puis réessayez.

    • Si au lieu de ce résultat, l'erreur suivante s'affiche :

      error: `Error: function execution attempt timed out.`
      

      Passez à l'étape suivante pour vérifier si cela vient du fait que l'instance met beaucoup de temps à s'arrêter.

    • Si vous n'obtenez aucun résultat, cela peut indiquer que le délai d'exécution de la fonction a été dépassé. Passez à l'étape suivante pour vérifier si cela vient du fait que l'instance met beaucoup de temps à s'arrêter.

  2. Vérifiez que l'instance est à l'état TERMINATED. L'arrêt total de l'instance peut prendre jusqu'à 30 secondes.

    gcloud compute instances describe dev-instance \
        --zone us-west1-b \
        | grep status
    
    status: TERMINATED
    

Démarrer l'instance

  1. Appelez la fonction permettant de démarrer l'instance.

    gcloud functions call startInstancePubSub \
        --data '{"data":"eyJ6b25lIjoidXMtd2VzdDEtYiIsICJsYWJlbCI6ImVudj1kZXYifQo="}'
    
    • Encore une fois, il s'agit simplement de la chaîne encodée en base64 pour {"zone":"us-west1-b", "label":"env=dev"}.

    Lorsque la fonction a terminé, le résultat suivant doit s'afficher :

    result: Successfully started instance dev-instance
    
  2. Vérifiez que l'instance est à l'état RUNNING. Le démarrage effectif de l'instance peut prendre jusqu'à 30 secondes.

    gcloud compute instances describe dev-instance \
        --zone us-west1-b \
        | grep status
    
    status: RUNNING
    

Configurer les tâches Cloud Scheduler pour qu'elles appellent Pub/Sub

Créer les tâches

Console

Créez la tâche de démarrage.

  1. Accédez à la page Cloud Scheduler dans Cloud Console.
    Accéder à la page Cloud Scheduler
  2. Cliquez sur Créer une tâche.
  3. Définissez le paramètre Nom sur startup-dev-instances.
  4. Pour le paramètre Fréquence, saisissez 0 9 * * 1-5.
  5. Pour le paramètre Fuseau horaire, sélectionnez le pays et le fuseau horaire souhaités. Cet exemple utilisera United States et Los Angeles.
  6. Pour Cible, sélectionnez Pub/Sub.
  7. Pour Sujet, saisissez start-instance-event.
  8. Pour le paramètre Charge utile, saisissez les informations suivantes :
    {"zone":"us-west1-b","label":"env=dev"}
    
  9. Cliquez sur Créer.

Créez la tâche d'arrêt.

  1. Vous devez vous trouver sur la page Cloud Scheduler de Cloud Console.
  2. Cliquez sur Créer une tâche.
  3. Définissez le paramètre Nom sur shutdown-dev-instances.
  4. Pour le paramètre Fréquence, saisissez 0 17 * * 1-5.
  5. Pour le paramètre Fuseau horaire, sélectionnez le pays et le fuseau horaire souhaités. Cet exemple utilisera United States et Los Angeles.
  6. Pour Cible, sélectionnez Pub/Sub.
  7. Pour Sujet, saisissez stop-instance-event.
  8. Pour le paramètre Charge utile, saisissez les informations suivantes :
    {"zone":"us-west1-b","label":"env=dev"}
    
  9. Cliquez sur Créer.

gcloud

Créez la tâche de démarrage.

gcloud beta scheduler jobs create pubsub startup-dev-instances \
    --schedule '0 9 * * 1-5' \
    --topic start-instance-event \
    --message-body '{"zone":"us-west1-b", "label":"env=dev"}' \
    --time-zone 'America/Los_Angeles'

Créez la tâche d'arrêt.

gcloud beta scheduler jobs create pubsub shutdown-dev-instances \
    --schedule '0 17 * * 1-5' \
    --topic stop-instance-event \
    --message-body '{"zone":"us-west1-b", "label":"env=dev"}' \
    --time-zone 'America/Los_Angeles'

Vérifier que les tâches sont opérationnelles (facultatif)

Console

Arrêter l'instance

  1. Accédez à la page Cloud Scheduler dans Cloud Console.
    Accéder à la page Cloud Scheduler
  2. Pour la tâche nommée shutdown-dev-instances, cliquez sur le bouton Exécuter maintenant situé à l'extrémité droite de la page.
  3. Accédez à la page Instances de VM de Cloud Console.
    Accéder à la page "Instances de VM"
  4. Vérifiez qu'un carré gris est présent à côté du nom de l'instance nommée dev-instance. Ce carré indique que l'instance s'est arrêtée. L'arrêt total de l'instance peut prendre jusqu'à 30 secondes.

Démarrer l'instance

  1. Accédez à la page Cloud Scheduler dans Cloud Console.
    Accéder à la page Cloud Scheduler
  2. Pour la tâche nommée startup-dev-instances, cliquez sur le bouton Exécuter maintenant situé à l'extrémité droite de la page.
  3. Accédez à la page Instances de VM de Cloud Console.
    Accéder à la page "Instances de VM"
  4. Vérifiez qu'une coche verte est présente à côté du nom de l'instance nommée dev-instance. Cette coche indique que l'instance s'est arrêtée. Le démarrage effectif de l'instance peut prendre jusqu'à 30 secondes.

gcloud

Pour arrêter l'instance, procédez comme suit :

  1. Exécutez la tâche Scheduler permettant d'arrêter l'instance.

    gcloud beta scheduler jobs run shutdown-dev-instances
    
  2. Vérifiez que l'instance est à l'état TERMINATED. L'arrêt total de l'instance peut prendre jusqu'à 30 secondes.

    gcloud compute instances describe dev-instance \
        --zone us-west1-b \
        | grep status
    
    status: TERMINATED
    

Démarrer l'instance

  1. Exécutez la tâche Scheduler permettant de démarrer l'instance.

    gcloud beta scheduler jobs run startup-dev-instances
    
  2. Vérifiez que l'instance est à l'état RUNNING. Le démarrage effectif de l'instance peut prendre jusqu'à 30 secondes.

    gcloud compute instances describe dev-instance \
        --zone us-west1-b \
        | grep status
    
    status: RUNNING
    

Nettoyer

Une fois que vous avez terminé le tutoriel de planification d'instance, vous pouvez procéder au nettoyage des ressources que vous avez créées sur Google Cloud afin qu'elles ne soient plus comptabilisées dans votre quota et qu'elles ne vous soient plus facturées. Dans les sections suivantes, nous allons voir comment supprimer ou désactiver ces ressources.

Supprimer les tâches Cloud Scheduler

  1. Accédez à la page Cloud Scheduler dans Cloud Console.

    Accéder à la page Cloud Scheduler

  2. Cochez les cases situées en regard de vos tâches.

  3. Cliquez sur le bouton Supprimer la tâche en haut de la page et confirmez la suppression.

Supprimer les sujets Pub/Sub

  1. Accédez à la page Pub/Sub dans Cloud Console :

    Accéder à la page Pub/Sub

  2. Cochez les cases situées en regard de vos sujets.

  3. Cliquez sur le bouton Supprimer en haut de la page et confirmez la suppression.

Supprimer les fonctions Cloud Functions

  1. Accédez à la page Cloud Functions dans Cloud Console.

    Accéder à la page Cloud Functions

  2. Cochez les cases situées en regard de vos fonctions.

  3. Cliquez sur le bouton Supprimer en haut de la page et confirmez la suppression.

Supprimer l'instance Compute Engine

Pour supprimer une instance Compute Engine, procédez comme suit :

  1. Dans Cloud Console, accédez à la page Instances de VM :

    Accéder à la page Instances de VM

  2. Cochez la case correspondant à l'instance que vous souhaitez supprimer.
  3. Cliquez sur Supprimer  pour supprimer l'instance.

Supprimer le projet

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. Dans Cloud Console, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Étape suivante

  • Testez d'autres fonctionnalités de Google Cloud. Découvrez nos tutoriels.