Python實現ECS自動映象建立&映象複製至其他地域

kaliarch發表於2018-07-28

一、背景

1.1 問題:

同事反饋有可以鑑於目前幾次大的公有云事故,騰訊雲/阿里雲兩大公有云廠商尚且存在這樣令人觸目驚心的時刻,更何況其他廠商和我們的日常操作,有人的地方就有誤操作,百分之一的風險但如果一旦發生就是100%的問題,雖SLA但或多或少存在影響,客戶反饋如果阿里的A地域發生故障,例如地質災害或不可控因素引發的ecs無法訪問,使用者資料都在雲上無法操作情況下該如何,但考慮到不同地域災備的高額度IT成本,想採用每天ecs的冷備。

1.2 思路:

在最大程度的降低IT成本,又想在不可控大規模地域性災難面前做些什麼,每天凌晨業務低峰期對ECS製作映象,同時複製到其他的不同地域,如北京的映象複製到上海,當北京整個region異常情況下,可利用複製在目標地域的ECS建立出來,在此拋磚引玉,後續可以將ecs在目標地域開出來並關機,歸檔刪除之前的映象,等等。同樣可以將RDS備份也同樣備份到異地OSS內,目前阿里已經有EBS非常方便的災難情況下恢復RDS。利用此思路同意的適用於其他場景下。

二、程式碼

2.1 結構


如果多個例項可同時寫入配置檔案,用,進行分割。

2.2 核心程式碼

配置檔案

# 阿里雲ak配置,建議採用子賬戶只授權ecs映象操作
[common]
# 阿里雲acccesskeyid
accessKeyId = LTAIhfXlcjyln6tW
# 阿里雲accesssecret
accessSecret = GwfAMvR4K2ELmt76184oqLTVgRfAso
# log目錄名稱
logdir_name = logdir
# log檔名稱
logfile_name = ecsoperlog.log

# ecs源地域配置資訊段
#支援在華北 1、華北 2、華北 3、華北 5、華東 1、華東 2 和華南 1 地域之間複製映象。涉及其他國家和地區地域時,可以 提交工單 申請
[source]
# 源地域例項regionid,可以參考:https://help.aliyun.com/document_detail/40654.html?spm=a2c1g.8271268.10000.5.5f98df25B98bhJ
s_RegionId = cn-shanghai

# 源例項id,可指定多個用,進行分隔
s_InstanceId =  i-uf661wb708uvqc9jyhem,i-uf661wb708uvqc9jyhel

# 源端製作映象name
s_ImageName = api-source-image

# 源映象描述資訊
s_Description = api-source-image源映象描述資訊

# 映象複製目的地域配置資訊段
[destination]
# 目的地域例項regionid,
d_DestinationRegionId = cn-qingdao

# 複製過來的映象名稱
d_DestinationImageName = api-destination-image

# 複製過來的映象描述資訊
d_DestinationDescription = api-destination-image目的映象描述資訊

image操作(製作映象->檢視映象製作狀態->複製映象)

    # 建立例項生成器
    def _get_Instance(self):
        for Instance in self.s_InstanceId_list.split(`,`):
            yield Instance
                        
    def _create_image(self):
        """
        建立映象
        :return:返回映象id
        """
        s_timer = time.strftime("%Y-%m-%d-%H:%M", time.localtime(time.time()))
        request = CreateImageRequest.CreateImageRequest()
        request.set_accept_format(`json`)
        request.add_query_param(`RegionId`, self.s_RegionId)
        request.add_query_param(`InstanceId`, self.s_InstanceId)
        request.add_query_param(`ImageName`, self.s_ImageName + s_timer)
        request.add_query_param(`Description`, self.s_Description + s_timer)
        response = self.ecshelper.do_action_with_exception(request)
        self.logoper.info(`建立映象任務已提交,映象id:%s` % json.loads(response)["ImageId"])
        print(`建立映象任務已提交,映象id:%s` % json.loads(response)["ImageId"])
        return json.loads(response)["ImageId"]
                
 def _describe_image(self,imageid):
        """
        查詢image狀態
        :param imageid:
        :return:
        """
        request = DescribeImagesRequest.DescribeImagesRequest()
        request.set_accept_format(`json`)
        request.add_query_param(`RegionId`, self.s_RegionId)
        request.add_query_param(`ImageId`, imageid)
        response = self.ecshelper.do_action_with_exception(request)
        # 進度 json.loads(response)[`Images`][`Image`][0][`Progress`]
        self.logoper.info(`映象建立進度:%s` %json.loads(response)[`Images`][`Image`][0][`Progress`])
        # 映象狀態
        return json.loads(response)[`Images`][`Image`][0][`Status`]


    #映象複製
    def _copy_image(self,imageid):
        """
        映象複製
        :param imageid:源映象id
        :return: 複製成功後的映象id
        """
        flag = True
        while flag:
            try:
                if self._describe_image(imageid) == `Available`:
                    flag = False
                else:
                    time.sleep(300)
            except Exception as e:
                pass
        print(`映象已經建立完成`)
        d_timer = time.strftime("%Y-%m-%d-%H:%M", time.localtime(time.time()))
        request = CopyImageRequest.CopyImageRequest()
        request.set_accept_format(`json`)
        request.add_query_param(`RegionId`, self.s_RegionId)
        request.add_query_param(`DestinationRegionId`, self.d_DestinationRegionId)
        request.add_query_param(`DestinationImageName`, self.d_DestinationImageName + d_timer)
        request.add_query_param(`DestinationDescription`, self.d_DestinationDescription + d_timer)
        request.add_query_param(`ImageId`, imageid)
        response = self.ecshelper.do_action_with_exception(request)
        self.logoper.info(`複製映象任務已提交,映象id:%s` % json.loads(response)[`ImageId`])
        print(`複製映象任務已提交,映象id:%s` % json.loads(response)[`ImageId`])
        return json.loads(response)[`ImageId`]

三、測試

3.1 檢視執行結果

3.2 檢視web控制檯

源映象

新增了時間戳,方便檢視

目的地域映象

3.3 檢視日誌

四、優化

  • 可以後續增加對制定天數的映象進行歸檔刪除


相關文章