日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

ECS主機(jī)狀態(tài)變化事件的自動(dòng)化運(yùn)維

更新時(shí)間:

本文通過(guò)實(shí)踐案例為您介紹云監(jiān)控如何通過(guò)輕量消息隊(duì)列(原 MNS)的隊(duì)列實(shí)現(xiàn)自動(dòng)化處理ECS主機(jī)狀態(tài)變化事件。

前提條件

  • 請(qǐng)您確保已在輕量消息隊(duì)列(原 MNS)控制臺(tái),創(chuàng)建隊(duì)列,例如:ecs-cms-event。

    關(guān)于如何創(chuàng)建隊(duì)列,請(qǐng)參見(jiàn)創(chuàng)建隊(duì)列

  • 請(qǐng)您確保已在云監(jiān)控控制臺(tái),創(chuàng)建系統(tǒng)事件報(bào)警規(guī)則,有關(guān)具體操作,請(qǐng)參見(jiàn)管理系統(tǒng)事件報(bào)警規(guī)則(舊版)

  • 請(qǐng)您確保已安裝Python依賴(lài)。

    本文所有代碼均以Python 3.6為例,您也可以使用其他編程語(yǔ)言,例如:Java和PHP。

    關(guān)于如何安裝Python SDK,請(qǐng)參見(jiàn)Python SDK安裝

背景信息

ECS在已有的系統(tǒng)事件基礎(chǔ)上,通過(guò)云監(jiān)控新發(fā)布了狀態(tài)變化類(lèi)事件和搶占型實(shí)例的中斷通知事件。每當(dāng)ECS主機(jī)的狀態(tài)發(fā)生變化時(shí),都會(huì)觸發(fā)一條ECS狀態(tài)變化事件。這種變化包括您通過(guò)控制臺(tái)、OpenAPI或SDK操作導(dǎo)致的變化,也包括彈性伸縮或欠費(fèi)等原因而自動(dòng)觸發(fā)的變化,還包括因?yàn)橄到y(tǒng)異常而觸發(fā)的變化。

云監(jiān)控提供四種事件報(bào)警處理方式,包括:輕量消息隊(duì)列(原 MNS)、函數(shù)計(jì)算、URL回調(diào)和日志服務(wù)。本文以輕量消息隊(duì)列(原 MNS)為例,為您介紹云監(jiān)控自動(dòng)化處理ECS主機(jī)狀態(tài)變更事件的三種最佳實(shí)踐。

操作步驟

云監(jiān)控將ECS主機(jī)所有的狀態(tài)變化事件投遞到輕量消息隊(duì)列(原 MNS),輕量消息隊(duì)列(原 MNS)獲取消息并進(jìn)行消息處理。

  • 實(shí)踐一:對(duì)所有ECS主機(jī)的創(chuàng)建和釋放事件進(jìn)行記錄。

    目前ECS控制臺(tái)無(wú)法查詢(xún)已經(jīng)釋放的實(shí)例。如果您有查詢(xún)需求,可以通過(guò)ECS主機(jī)狀態(tài)變化事件將所有ECS主機(jī)的生命周期記錄在數(shù)據(jù)庫(kù)或日志服務(wù)中。每當(dāng)您創(chuàng)建ECS主機(jī)時(shí),會(huì)發(fā)送一個(gè)Pending事件,每當(dāng)您釋放ECS主機(jī)時(shí),會(huì)發(fā)送一個(gè)Deleted事件。

    1. 編輯一個(gè)Conf文件。

      Conf文件中需要包含輕量消息隊(duì)列(原 MNS)的endpoint、阿里云的access_keyaccess_key_secretregion_id(例如:cn-beijing)和queue_name

      說(shuō)明

      endpoint可以在輕量消息隊(duì)列(原 MNS)控制臺(tái)的隊(duì)列頁(yè)面,單擊獲取Endpoint

      import os
      
      # 請(qǐng)確保代碼運(yùn)行環(huán)境設(shè)置了環(huán)境變量 ALIBABA_CLOUD_ACCESS_KEY_ID 和 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
      # 工程代碼泄露可能會(huì)導(dǎo)致 AccessKey 泄露,并威脅賬號(hào)下所有資源的安全性。以下代碼示例使用環(huán)境變量獲取 AccessKey 的方式進(jìn)行調(diào)用,僅供參考,建議使用更安全的 STS 方式
      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 = 'test'
          vsever_group_id = '<your_vserver_group_id>'
                                          
    2. 使用輕量消息隊(duì)列(原 MNS)的SDK編寫(xiě)一個(gè)MNS Client用來(lái)獲取MNS消息。

      # -*- coding: utf-8 -*-
      import json
      from mns.mns_exception import MNSExceptionBase
      import logging
      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
                                      

      上述代碼只對(duì)輕量消息隊(duì)列(原 MNS)獲取的數(shù)據(jù),調(diào)用Listener消費(fèi)消息之后刪除消息。

    3. 注冊(cè)一個(gè)指定Listener消費(fèi)事件。這個(gè)簡(jiǎn)單的Listener判斷收到Pending和Deleted事件時(shí),打印一行日志。

       # -*- 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 == 'Panding':
                  logging.info(f'The instance {resource_id} state is {state}')
              elif state == 'Deleted':
                  logging.info(f'The instance {resource_id} state is {state}')
                                      

      Main函數(shù)寫(xiě)法如下:

      mns_client = MNSClient()
      
      mns_client.regist_listener(ListenerLog())
      
      mns_client.run()

      實(shí)際生產(chǎn)環(huán)境下,可能需要將事件存儲(chǔ)在數(shù)據(jù)庫(kù)或日志服務(wù)SLS中,方便后期的搜索和審計(jì)。

  • 實(shí)踐二:ECS主機(jī)關(guān)機(jī)自動(dòng)重啟。

    在某些場(chǎng)景下,ECS主機(jī)會(huì)非預(yù)期地關(guān)機(jī),您可能需要自動(dòng)重啟已經(jīng)關(guān)機(jī)的ECS主機(jī)。

    為了實(shí)現(xiàn)ECS主機(jī)關(guān)機(jī)后自動(dòng)重啟,您可以復(fù)用實(shí)踐一中的MNS Client,添加一個(gè)新的Listener。當(dāng)您收到Stopped事件時(shí),對(duì)該ECS主機(jī)執(zhí)行Start命令。

    # -*- coding: utf-8 -*-
    import logging
    from aliyunsdkecs.request.v20140526 import StartInstanceRequest
    from aliyunsdkcore.client import AcsClient
    from .mns_client import BasicListener
    from .config import Conf
    
    
    class ECSClient(object):
        def __init__(self, acs_client):
            self.client = acs_client
    
        # 啟動(dòng)ECS主機(jī)
        def start_instance(self, instance_id):
            logging.info(f'Start instance {instance_id} ...')
            request = StartInstanceRequest.StartInstanceRequest()
            request.set_accept_format('json')
            request.set_InstanceId(instance_id)
            self.client.do_action_with_exception(request)
    
    
    class ListenerStart(BasicListener):
        def __init__(self):
            acs_client = AcsClient(Conf.access_key, Conf.access_key_secret, Conf.region_id)
            self.ecs_client = ECSClient(acs_client)
    
        def process(self, event):
            detail = event['content']
            instance_id = detail['resourceId']
            if detail['state'] == 'Stopped':
                self.ecs_client.start_instance(instance_id)
                        

    在實(shí)際生產(chǎn)環(huán)境下,執(zhí)行完Start命令后,可能還需要繼續(xù)接收后續(xù)的Starting、Running或Stopped等事件,再配合計(jì)時(shí)器和計(jì)數(shù)器,進(jìn)行成功或失敗之后的處理。

  • 實(shí)踐三:搶占型實(shí)例釋放前,自動(dòng)從負(fù)載均衡SLB移除。

    搶占型實(shí)例在釋放之前五分鐘左右,會(huì)發(fā)出釋放告警事件,您可以在這短暫的時(shí)間運(yùn)行業(yè)務(wù)不中斷邏輯,例如:主動(dòng)從負(fù)載均衡SLB的后端服務(wù)器中去掉這臺(tái)即將被釋放的搶占型實(shí)例,而非被動(dòng)等待實(shí)例釋放后負(fù)載均衡SLB的自動(dòng)處理。

    您復(fù)用實(shí)踐一的MNS Client,添加一個(gè)新的Listener,當(dāng)收到搶占型實(shí)例的釋放告警時(shí),調(diào)用負(fù)載均衡SLB的SDK。

    # -*- coding: utf-8 -*-
    from aliyunsdkcore.client import AcsClient
    from aliyunsdkcore.request import CommonRequest
    from .mns_client import BasicListener
    from .config import Conf
    
    
    class SLBClient(object):
        def __init__(self):
            self.client = AcsClient(Conf.access_key, Conf.access_key_secret, Conf.region_id)
            self.request = CommonRequest()
            self.request.set_method('POST')
            self.request.set_accept_format('json')
            self.request.set_version('2014-05-15')
            self.request.set_domain('slb.aliyuncs.com')
            self.request.add_query_param('RegionId', Conf.region_id)
    
        def remove_vserver_group_backend_servers(self, vserver_group_id, instance_id):
            self.request.set_action_name('RemoveVServerGroupBackendServers')
            self.request.add_query_param('VServerGroupId', vserver_group_id)
            self.request.add_query_param('BackendServers',
                                         "[{'ServerId':'" + instance_id + "','Port':'80','Weight':'100'}]")
            response = self.client.do_action_with_exception(self.request)
            return str(response, encoding='utf-8')
    
    
    class ListenerSLB(BasicListener):
        def __init__(self, vsever_group_id):
            self.slb_caller = SLBClient()
            self.vsever_group_id = Conf.vsever_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.vsever_group_id, instance_id)
                        
    重要

    搶占型實(shí)例釋放告警的event name與前面不同,應(yīng)該是mns_client.regist_listener(ListenerSLB(Conf.vsever_group_id), 'Instance:PreemptibleInstanceInterruption')

    在實(shí)際生產(chǎn)環(huán)境下,您需要再申請(qǐng)一臺(tái)新的搶占型實(shí)例,掛載到負(fù)載均衡SLB,來(lái)保證服務(wù)能力。