Tous les produits
Search
Centre de documentation

Cloud Monitor:Automate O&M based on ECS instance state change events

Dernière mise à jour :Aug 29, 2026

Elastic Compute Service (ECS) publie des événements de changement d'état via Cloud Monitor chaque fois qu'une instance passe d'un état à un autre, que ce soit déclenché par des actions dans la console, des appels API, des opérations SDK, des politiques Auto Scaling, des impayés ou des exceptions système. En acheminant ces événements vers Simple Message Queue (anciennement MNS), vous pouvez mettre en place des réponses automatisées telles que l'enregistrement du cycle de vie des instances, le redémarrage des instances arrêtées ou la suppression des instances spot d'un équilibreur de charge avant leur libération.

Cette rubrique présente trois scénarios d'automatisation utilisant Python et une file d'attente MNS comme mécanisme de distribution des événements.

Fonctionnement

Cloud Monitor capture tous les événements de changement d'état des instances ECS et les transmet à une file d'attente Simple Message Queue (anciennement MNS). Un consommateur Python interroge la file d'attente, analyse chaque événement et le distribue aux écouteurs enregistrés en fonction du nom de l'événement (par exemple, Instance:StateChange ou Instance:PreemptibleInstanceInterruption). Chaque écouteur implémente une action d'automatisation spécifique.

Cloud Monitor prend en charge quatre méthodes pour traiter les alertes déclenchées par des événements :

Méthode

Cas d'utilisation

Simple Message Queue (anciennement MNS)

Traitement asynchrone avec une logique de consommateur personnalisée (utilisée dans cette rubrique)

Function Compute (FC)

Gestion des événements sans serveur sans gestion de l'infrastructure

Rappel URL

Transfert des événements vers un endpoint HTTP externe

Simple Log Service (SLS)

Journalisation et analyse centralisées des événements

Prérequis

Avant de commencer, assurez-vous d'avoir :

Pour plus de détails sur l'installation du SDK, consultez la section Installer le SDK Python. Pour les autres langages de programmation, reportez-vous à la référence du SDK MNS et à la vue d'ensemble du SDK ECS.

Étape 1 : Créer le fichier de configuration

Définissez l'endpoint MNS, les identifiants, la région et le nom de la file d'attente dans un fichier de configuration partagé. Les trois scénarios réutilisent cette configuration.

import os

class Conf:
    endpoint = 'http://<id>.mns.<region>.aliyuncs.com/'
    access_key = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID']
    access_key_secret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
    region_id = 'cn-beijing'
    queue_name = 'ecs-cms-event'
    vserver_group_id = '<your-vserver-group-id>'

Remplacez les espaces réservés suivants par les valeurs réelles :

Espace réservé

Description

Exemple

<id>

Votre ID de compte Alibaba Cloud

1234567890

<region>

La région de votre file d'attente MNS

cn-beijing

<your-vserver-group-id>

L'ID du groupe de serveurs virtuels dans Server Load Balancer (SLB), requis uniquement pour le scénario 3

rsp-bp1abc...

Retrouvez l'endpoint MNS sur la page Queue Details sous la section Endpoint . Les endpoints Internet Access et Internal Access sont disponibles.
Important

Ne codez jamais en dur les identifiants AccessKey dans le code source. L'exemple ci-dessus lit les identifiants à partir des variables d'environnement. Pour les charges de travail de production, utilisez des identifiants temporaires Security Token Service (STS).

Étape 2 : Construire le consommateur MNS

Créez un client MNS réutilisable qui interroge la file d'attente, distribue les événements aux écouteurs enregistrés et supprime les messages traités. Les trois scénarios partagent ce consommateur.

# -*- coding: utf-8 -*-
import json
import logging
from mns.mns_exception import MNSExceptionBase
from mns.account import Account
from . import Conf

class MNSClient(object):
    def __init__(self):
        self.account = Account(Conf.endpoint, Conf.access_key, Conf.access_key_secret)
        self.queue_name = Conf.queue_name
        self.listeners = dict()

    def regist_listener(self, listener, eventname='Instance:StateChange'):
        if eventname in self.listeners.keys():
            self.listeners.get(eventname).append(listener)
        else:
            self.listeners[eventname] = [listener]

    def run(self):
        queue = self.account.get_queue(self.queue_name)
        while True:
            try:
                message = queue.receive_message(wait_seconds=5)
                event = json.loads(message.message_body)
                if event['name'] in self.listeners:
                    for listener in self.listeners.get(event['name']):
                        listener.process(event)
                queue.delete_message(receipt_handle=message.receipt_handle)
            except MNSExceptionBase as e:
                if e.type == 'QueueNotExist':
                    logging.error('Queue %s not exist, please create queue before receive message.', self.queue_name)
                else:
                    logging.error('No Message, continue waiting')

class BasicListener(object):
    def process(self, event):
        pass

Le consommateur utilise l'interrogation longue (wait_seconds=5) pour récupérer les messages. Lorsqu'un message arrive, il analyse le corps JSON, recherche les écouteurs enregistrés par nom d'événement et appelle la méthode process de chaque écouteur. Après le traitement, il supprime le message de la file d'attente.

Structure de la charge utile de l'événement

Les événements de changement d'état utilisent la structure suivante :

Champ

Description

Exemple

event['name']

Identifiant du type d'événement

Instance:StateChange

event['content']['state']

État actuel de l'instance

Created, Starting, Running, Stopped, Deleted

event['content']['resourceId']

ID de l'instance ECS

i-bp1abc...

Scénario 1 : Journaliser les événements de création et de libération d'instances

Suivez le cycle de vie complet des instances ECS en journalisant les changements d'état Created et Deleted. Les instances libérées n'apparaissent plus dans la console ECS ; l'enregistrement de ces événements fournit une piste d'audit pour la planification de la capacité et l'analyse post-incident.

Créer l'écouteur

# -*- coding: utf-8 -*-
import logging
from .mns_client import BasicListener

class ListenerLog(BasicListener):
    def process(self, event):
        state = event['content']['state']
        resource_id = event['content']['resourceId']
        if state == 'Created':
            logging.info(f'The instance {resource_id} state is {state}')
        elif state == 'Deleted':
            logging.info(f'The instance {resource_id} state is {state}')

Exécuter le consommateur

mns_client = MNSClient()

mns_client.regist_listener(ListenerLog())

mns_client.run()

Vérifier le résultat

  1. Créez ou libérez une instance ECS dans la console.

  2. Vérifiez les journaux du consommateur pour un message tel que The instance i-bp1abc... state is Created.

En production, stockez les événements dans une base de données ou Simple Log Service (SLS) au lieu de les journaliser sur stdout. Cela permet de rechercher et d'auditer les données historiques du cycle de vie des instances.

Scénario 2 : Redémarrer automatiquement les instances arrêtées

Une instance ECS peut s'arrêter de manière inattendue en raison d'exceptions système ou d'impayés. Cet écouteur surveille les événements Stopped et appelle l'API ECS StartInstance pour redémarrer l'instance concernée.

Créer l'écouteur

Réutilisez le consommateur MNS de l'étape 2 et enregistrez un nouvel écouteur :

# -*- coding: utf-8 -*-
import logging

from alibabacloud_ecs20140526.client import Client as Ecs20140526Client
from alibabacloud_ecs20140526.models import StartInstanceRequest
from alibabacloud_tea_openapi.models import Config

from .config import Conf
from .mns_client import BasicListener

class ECSClient(object):
    def __init__(self, client):
        self.client = client

    def start_instance(self, instance_id):
        logging.info(f'Start instance {instance_id} ...')
        request = StartInstanceRequest(
            instance_id=instance_id
        )
        self.client.start_instance(request)

class ListenerStart(BasicListener):
    def __init__(self):
        ecs_config = Config(
            access_key_id=Conf.access_key,
            access_key_secret=Conf.access_key_secret,
            endpoint=f'ecs.{Conf.region_id}.aliyuncs.com'
        )
        client = Ecs20140526Client(ecs_config)
        self.ecs_client = ECSClient(client)

    def process(self, event):
        detail = event['content']
        instance_id = detail['resourceId']
        if detail['state'] == 'Stopped':
            self.ecs_client.start_instance(instance_id)

Exécuter le consommateur

mns_client = MNSClient()

mns_client.regist_listener(ListenerStart())

mns_client.run()

Vérifier le résultat

  1. Arrêtez manuellement une instance ECS en cours d'exécution.

  2. Vérifiez les journaux du consommateur pour Start instance i-bp1abc... ....

  3. Confirmez que l'état de l'instance revient à Running dans la console ECS.

En production, surveillez les transitions d'état ultérieures ( Starting , Running ou Stopped ) après l'émission de la commande de démarrage. Utilisez des minuteurs et des compteurs de nouvelles tentatives pour gérer les cas où le redémarrage échoue.

Scénario 3 : Supprimer une instance spot de SLB avant sa libération

Environ cinq minutes avant la récupération d'une instance spot, Cloud Monitor envoie un événement Instance:PreemptibleInstanceInterruption . Profitez de cette fenêtre pour supprimer proactivement l'instance du groupe de serveurs backend d'une instance Server Load Balancer (SLB), plutôt que d'attendre que SLB détecte passivement la libération.

Créer l'écouteur

Réutilisez le consommateur MNS de l'étape 2 et enregistrez un écouteur pour l'événement d'interruption d'instance spot :

# -*- coding: utf-8 -*-
from alibabacloud_slb20140515.client import Client as Slb20140515Client
from alibabacloud_slb20140515.models import RemoveVServerGroupBackendServersRequest
from alibabacloud_tea_openapi.models import Config

from .config import Conf
from .mns_client import BasicListener

class SLBClient(object):
    def __init__(self):
        self.client = self.create_client()

    def create_client(self):
        config = Config()
        config.access_key_id = Conf.access_key
        config.access_key_secret = Conf.access_key_secret
        config.endpoint = 'slb.aliyuncs.com'
        return Slb20140515Client(config)

    def remove_vserver_group_backend_servers(self, vserver_group_id, instance_id):
        request = RemoveVServerGroupBackendServersRequest(
            region_id=Conf.region_id,
            vserver_group_id=vserver_group_id,
            backend_servers="[{'ServerId':'" + instance_id + "','Port':'80','Weight':'100'}]"
        )
        response = self.client.remove_vserver_group_backend_servers(request)
        return response

class ListenerSLB(BasicListener):
    def __init__(self, vserver_group_id):
        self.slb_caller = SLBClient()
        self.vserver_group_id = Conf.vserver_group_id

    def process(self, event):
        detail = event['content']
        instance_id = detail['instanceId']
        if detail['action'] == 'delete':
            self.slb_caller.remove_vserver_group_backend_servers(self.vserver_group_id, instance_id)
Important

Le nom de l'événement pour les interruptions d'instances spot diffère des événements de changement d'état. Enregistrez cet écouteur avec le nom d'événement Instance:PreemptibleInstanceInterruption :

mns_client = MNSClient()

mns_client.regist_listener(ListenerSLB(Conf.vserver_group_id), 'Instance:PreemptibleInstanceInterruption')

mns_client.run()

Structure de l'événement d'interruption d'instance spot

Les événements d'interruption d'instance spot utilisent des noms de champs différents de ceux des événements de changement d'état :

Champ

Description

Exemple

event['name']

Identifiant du type d'événement

Instance:PreemptibleInstanceInterruption

event['content']['instanceId']

ID de l'instance ECS

i-bp1abc...

event['content']['action']

Action d'interruption

delete

Vérifier le résultat

  1. Attendez un événement d'interruption d'instance spot (ou simulez-en un dans un environnement de test).

  2. Confirmez que l'instance est supprimée du groupe de serveurs virtuels SLB avant la libération.

En production, demandez une instance spot de remplacement et attachez-la immédiatement à l'instance SLB pour maintenir la disponibilité du service.

Exécuter tous les écouteurs ensemble

Enregistrez les trois écouteurs sur un seul consommateur MNS pour gérer plusieurs types d'événements simultanément :

mns_client = MNSClient()

# Scenario 1: Log lifecycle events
mns_client.regist_listener(ListenerLog())

# Scenario 2: Auto-restart stopped instances
mns_client.regist_listener(ListenerStart())

# Scenario 3: Remove spot instances from SLB before release
mns_client.regist_listener(ListenerSLB(Conf.vserver_group_id), 'Instance:PreemptibleInstanceInterruption')

mns_client.run()

Référence des types d'événements

Nom de l'événement

Déclencheur

Champs clés

Instance:StateChange

Transitions d'état de l'instance (Created, Starting, Running, Stopped, Deleted)

content.state, content.resourceId

Instance:PreemptibleInstanceInterruption

Instance spot programmée pour la libération (~5 min avant la récupération)

content.instanceId, content.action

Références