Todos os produtos
Search
Central de documentação

Elastic Compute Service:Automatize O&M com base em eventos de alteração de estado de instâncias ECS

Última atualização: Aug 29, 2026

O Elastic Compute Service (ECS) publica eventos de alteração de estado por meio do Cloud Monitor sempre que uma instância transita entre estados, seja por ações no console, chamadas de API, operações de SDK, políticas de Auto Scaling, pagamentos em atraso ou exceções do sistema. Ao encaminhar esses eventos para o Simple Message Queue (anteriormente MNS), você pode criar respostas automatizadas, como registrar o ciclo de vida das instâncias, reiniciar instâncias paradas ou remover instâncias preemptíveis de um balanceador de carga antes da liberação.

Este tópico demonstra três cenários de automação usando Python e uma fila de mensagens do MNS como mecanismo de entrega de eventos.

Como funciona

O Cloud Monitor captura todos os eventos de alteração de estado das instâncias ECS e os entrega a uma fila do Simple Message Queue (anteriormente MNS). Um consumidor Python consulta a fila, analisa cada evento e o despacha para listeners registrados com base no nome do evento (por exemplo, Instance:StateChange ou Instance:PreemptibleInstanceInterruption). Cada listener implementa uma ação de automação específica.

O Cloud Monitor oferece quatro métodos para processar alertas acionados por eventos:

Método

Caso de uso

Simple Message Queue (anteriormente MNS)

Processamento assíncrono com lógica de consumidor personalizada (utilizado neste tópico)

Function Compute (FC)

Tratamento de eventos serverless sem gerenciamento de infraestrutura

Callback de URL

Encaminhamento de eventos para um endpoint HTTP externo

Simple Log Service (SLS)

Registro e análise centralizada de eventos

Pré-requisitos

Antes de começar, verifique se você tem:

Para detalhes sobre a instalação do SDK, consulte Instale o SDK do Python. Para outras linguagens de programação, veja a referência do SDK do MNS e a visão geral do SDK do ECS.

Etapa 1: Crie o arquivo de configuração

Defina o endpoint do MNS, as credenciais, a região e o nome da fila em um arquivo de configuração compartilhado. Todos os três cenários reutilizam essa configuração.

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>'

Substitua os seguintes placeholders pelos valores reais:

Placeholder

Descrição

Exemplo

<id>

ID da sua conta Alibaba Cloud

1234567890

<region>

Região da sua fila MNS

cn-beijing

<your-vserver-group-id>

ID do grupo vServer no Server Load Balancer (SLB), necessário apenas para o Cenário 3

rsp-bp1abc...

Encontre o endpoint do MNS na página Queue Details , na seção Endpoint . Estão disponíveis endpoints de Internet Access e de Internal Access .
Importante

Nunca codifique credenciais AccessKey diretamente no código source. O exemplo anterior lê as credenciais de variáveis de ambiente. Para cargas de trabalho em produção, utilize credenciais temporárias do Security Token Service (STS).

Etapa 2: Construa o consumidor MNS

Crie um cliente MNS reutilizável que consulte a fila, despache eventos para listeners registrados e exclua as mensagens processadas. Os três cenários compartilham este consumidor.

# -*- 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

O consumidor utiliza long polling (wait_seconds=5) para recuperar mensagens. Quando uma mensagem chega, ele analisa o corpo JSON, localiza os listeners registrados pelo nome do evento e chama o método process de cada listener. Após o processamento, o sistema exclui a mensagem da fila.

Estrutura do payload do evento

Os eventos de alteração de estado utilizam a seguinte estrutura:

Campo

Descrição

Exemplo

event['name']

Identificador do tipo de evento

Instance:StateChange

event['content']['state']

Estado atual da instância

Created, Starting, Running, Stopped, Deleted

event['content']['resourceId']

ID da instância ECS

i-bp1abc...

Cenário 1: Registre eventos de criação e liberação de instâncias

Acompanhe todo o ciclo de vida das instâncias ECS registrando as alterações de estado Created e Deleted. Instâncias liberadas deixam de aparecer no console ECS. Registrar esses eventos fornece um rastro de auditoria para planejamento de capacidade e análise pós-incidente.

Crie o listener

# -*- 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}')

Execute o consumidor

mns_client = MNSClient()

mns_client.regist_listener(ListenerLog())

mns_client.run()

Verifique o resultado

  1. Crie ou libere uma instância ECS no console.

  2. Verifique nos logs do consumidor se há uma mensagem como The instance i-bp1abc... state is Created.

Em ambientes de produção, armazene eventos em um banco de dados ou no Simple Log Service (SLS) em vez de registrar logs no stdout. Isso permite pesquisar e auditar dados históricos do ciclo de vida das instâncias.

Cenário 2: Reinicie automaticamente instâncias paradas

Uma instância ECS pode parar inesperadamente devido a exceções do sistema ou pagamentos em atraso. Este listener monitora eventos Stopped e chama a API StartInstance do ECS para reiniciar a instância afetada.

Crie o listener

Reutilize o consumidor MNS da Etapa 2 e registre um novo listener:

# -*- 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)

Execute o consumidor

mns_client = MNSClient()

mns_client.regist_listener(ListenerStart())

mns_client.run()

Verifique o resultado

  1. Pare manualmente uma instância ECS em execução.

  2. Verifique nos logs do consumidor a mensagem Start instance i-bp1abc... ....

  3. Confirme se o estado da instância retornou para Running no console ECS.

Em produção, monitore as transições de estado subsequentes ( Starting , Running ou Stopped ) após emitir o comando de início. Utilize temporizadores e contadores de tentativas para lidar com casos em que a reinicialização falha.

Cenário 3: Remova uma instância preemptível do SLB antes da liberação

Cerca de cinco minutos antes de uma instância preemptível ser recuperada, o Cloud Monitor envia um evento Instance:PreemptibleInstanceInterruption. Use essa janela para remover proativamente a instância do grupo de servidores backend de uma instância do Server Load Balancer (SLB), em vez de esperar que o SLB detecte a liberação passivamente.

Crie o listener

Reutilize o consumidor MNS da Etapa 2 e registre um listener para o evento de interrupção de instância preemptível:

# -*- 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)
Importante

O nome do evento para interrupções de instâncias preemptíveis difere dos eventos de alteração de estado. Registre este listener com o nome de evento Instance:PreemptibleInstanceInterruption:

mns_client = MNSClient()

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

mns_client.run()

Estrutura do evento de interrupção de instância preemptível

Os eventos de interrupção de instância preemptível usam nomes de campos diferentes dos eventos de alteração de estado:

Campo

Descrição

Exemplo

event['name']

Identificador do tipo de evento

Instance:PreemptibleInstanceInterruption

event['content']['instanceId']

ID da instância ECS

i-bp1abc...

event['content']['action']

Ação de interrupção

delete

Verifique o resultado

  1. Aguarde um evento de interrupção de instância preemptível (ou simule um em ambiente de teste).

  2. Confirme se a instância foi removida do grupo vServer do SLB antes da liberação.

Em produção, solicite uma instância preemptível substituta e anexe-a à instância do SLB imediatamente para manter a disponibilidade do service.

Execute todos os listeners juntos

Registre todos os três listeners em um único consumidor MNS para lidar com vários tipos de eventos simultaneamente:

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()

Referência de tipos de eventos

Nome do evento

Gatilho

Campos principais

Instance:StateChange

Transições de estado da instância (Created, Starting, Running, Stopped, Deleted)

content.state, content.resourceId

Instance:PreemptibleInstanceInterruption

Instância preemptível agendada para liberação (~5 min antes da recuperação)

content.instanceId, content.action

Referências