一、背景:
使用aws redis,因为某些更新情况等会造成主从切换,原来自动备份的节点为从库,现在就变成了自动备份的节点为主库,因为aws中自动备份一旦指定节点之后就不会更换,除非手动更改,这样就造成了流量都打到了主节点,所以做了自动脚本来实现这个功能
二、准备工作
1.基本命令准备
aws cli官网地址: https://docs.aws.amazon.com/cli/latest/reference/
1.1 列出所有复制组
aws elasticache --profile test describe-replication-groups --output json
- output json 以json格式输出,默认是文本
1.2 列出指定复制组的信息
aws elasticache --profile test describe-replication-groups --replication-group-id 复制组的id
–output json
1.3 查看节点是否为备份节点
aws elasticache --profile nova describe-cache-clusters --cache-cluster-id 集群id --output json
- 查看SnapshotRetentionLimit是否大于0,如果它大于0,则为当前备份节点
2.链接aws的准备
参考之前写的链接:https://blog.csdn.net/line_on_database/article/details/115906061
aws configure --profile test(test项目名)
AWS Access Key ID [None]: ******
AWS Secret Access Key [None]: ******
Default region name [None]: ******
Default output format [None]: text
3.正式编码
代码如下:
import os,sys
import json
import smtplib
import time
import logging
from email.header import Header
from email.mime.text import MIMEText
# 创建一个logger
logger = logging.getLogger()
logger.setLevel(logging.INFO) # Log等级总开关
# 创建一个handler,用于写入日志文件
log_name = '/home/loginfo.log'
logfile = log_name
fh = logging.FileHandler(logfile, mode='a')
fh.setLevel(logging.DEBUG) # 输出到file的log等级的开关
# 定义handler的输出格式
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
fh.setFormatter(formatter)
logger.addHandler(fh)
def send_email(info_num):
try:
mail_host = "smtp.exmail.qq.com" # SMTP服务器
mail_user = "abc@qq.com" # 用户名
mail_pass = "123456" # 密码(这里的密码不是登录邮箱密码,而是授权码)
sender = 'abc@qq.com' # 发件人邮箱
receivers = ['bcd@qq.com',"efg@qq.com"] # 接收人邮箱
if info_num == 1:
body = "当前备份节点是主节点,开始切换备份节点"
elif info_num == 2:
body = "切换备份节点已经完成"
else:
body = "您的程序出现了问题,请尽快查看"
title = '切换备份节点' # 邮件主
message = MIMEText(body, 'html', 'utf-8') # 内容, 格式, 编码
message['From'] = "{}".format(sender)
message['To'] = ",".join(receivers)
message['Subject'] = title
smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 启用SSL发信, 端口一般是465
smtpObj.login(mail_user, mail_pass) # 登录验证
smtpObj.sendmail(sender, receivers, message.as_string()) # 发送
logger.info("邮件成功发送")
except smtplib.SMTPException as e:
logger.error('邮件发送出现问题')
print(e)
def check_change_snap(repl_group):
try:
# 列出复制集情况
aws_rpl = '/usr/local/bin/aws elasticache describe-replication-groups --replication-group-id %s --profile test --output json' % repl_group
# 把命令结果传给变量
rpl_info = os.popen(aws_rpl)
rpl_info = rpl_info.read()
rpl_info_json = json.loads(rpl_info)
redis_node_all = rpl_info_json["ReplicationGroups"][0]["NodeGroups"][0]["NodeGroupMembers"]
# 找出主从节点对应的集群id
for redis_node in redis_node_all:
if redis_node["CurrentRole"] == "primary":
pri_node = redis_node["CacheClusterId"]
else:
slave_node = redis_node["CacheClusterId"]
# 检测主节点是不是对应的快照节点
is_snap_str = '/usr/local/bin/aws elasticache describe-cache-clusters --cache-cluster-id %s --profile test --output json' % pri_node
is_snap_node = os.popen(is_snap_str)
is_snap_node = is_snap_node.read()
is_snap_node_json = json.loads(is_snap_node)
# 备份天数大于0即是快照节点,否则不开启自动备份
snap_day = is_snap_node_json["CacheClusters"][0]["SnapshotRetentionLimit"]
if snap_day > 0:
logger.warning('当前备份节点是主节点,开始切换备份节点')
send_email(1)
# 改变复制集的备份节点为从节点,备份时间为2:00-3:00
change_snap = "/usr/local/bin/aws elasticache modify-replication-group --replication-group-id %s --snapshotting-cluster-id %s --snapshot-window 02:00-03:00 --profile nova" % (repl_group, slave_node)
os.system(change_snap)
logger.warning('换备份节点已经完成')
send_email(2)
else:
logger.info('当前备份节点是从节点,不做处理')
except:
logger.error('您的程序出现了问题,请尽快查看')
send_email(3)
if __name__ == "__main__":
repl_group = "my-cluster"
check_change_snap(repl_group)