一、背景
1.1 问题:
在目前大IT企业大环境下,一个稳定安全可靠的云厂商对于在云计算大背景下,用云企业是非常高兴的事情,免去了传统IDC运维的长时间周期,降低运维人员对底层设备的技术门槛,按需按量根据业务动态弹性使用云资源,可谓大小企业的IT利好。对于数据安全,国内外公有云及各私有云厂商都存在令人触目惊心的时刻,更何况其他厂商和我们的日常操作,有人操作的地方就有误操作,百分之一的风险但如果一旦发生就是100%的问题,虽SLA但或多或少存在影响,客户反馈如果阿里的A地域发生故障,例如地质灾害或不可控因素引发的ecs无法访问,用户数据都在云上无法操作情况下该如何,在此就国内非常优秀的公有云阿里云来说,可以参考云服务器的数据备份和恢复来将我们的数据备份,提高数据安全可靠性,用户创建ECS数据盘的快照,并使用快照进行磁盘的回滚,同时可以通过自定义镜像来长久保存我们的数据。在此基础上考虑到不同地域灾备的高额度IT成本,对此可以通过制作快照策略,快照级别备份,但是当遇到跨地域级别的灾难时,我们的数据是否高可用呢?
1.2 思路:
在最大程度的降低IT成本,又想在不可控大规模地域性灾难面前做些什么,每天凌晨业务低峰期对ECS制作镜像,同时复制到其他的不同地域,如北京的镜像复制到上海,当北京整个region异常情况下,可利用复制在目标地域的ECS创建出来,在此抛砖引玉,后续可以将ecs在目标地域开出来并关机,归档删除之前的镜像,等等。同样可以将RDS备份也同样备份到异地OSS内,目前阿里已经有EBS非常方便的灾难情况下恢复RDS。利用此思路同意的适用于其他场景下。
在人生苦短,我用Python/连高中课本都有Python的IT大环境下,我们也蹭着热度,利用这门简单实用简洁方便的语言,简单来实现我们的功能。在此有很多附加的功能,我们可以通过开放的公有云API来实现,例如另一篇博文同样提供思路。
大家可以参考:
Python自定义阿里云RDS备份策略
1.3 blog地址
readthedocs
二、代码
2.1 结构
github地址
2.2 核心代码
首先需要我们获取阿里云账号的ak,在此强烈建议使用子用户创建,为此子用户授权可以镜像操作的权限,精细控制防止ak泄露导致的比必要损失。
其次简单利用Python实现创建镜像操作->将镜像复制到其他地域。
配置文件
# 阿里云ak配置,建议采用子账户只授权ecs镜像操作
[common]
# 阿里云acccesskeyid
accessKeyId = LTAIhfXxxxxxxxx
# 阿里云accesssecret
accessSecret = GwfAMvR4K2ELxxxxxxxxxxxxx
# 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 查看日志
四、优化
- 可以后续增加对指定天数的镜像进行归档删除
五、思考
- 一定要知道没有百分之百的数据安全,提高我们IT人的安全意识非常重要。
- 一定做好数据安全冗余,数据无价
- 选择可信安全放心的公有云厂商为我们的业务保驾护航
- 利用API来操作共有云灵活实现我们多方面定制需求