Last active
December 5, 2017 09:24
-
-
Save yomon8/742ec6e756499902aded4d7c3e00ceab to your computer and use it in GitHub Desktop.
upgrade MySQL engine of AWS RDS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
if [ $# -lt 2 ];then | |
echo "Usage: $(basename "$0") your-rds-identifier target-version" | |
exit -1 | |
fi | |
########################################################### | |
# Funcitons | |
########################################################### | |
function logger(){ echo "[$(date +%Y/%m/%dT%H:%M:%S)] $1"; } | |
function prompt(){ | |
while true | |
do | |
read -rp "$1 (y/N):> " yn | |
case "$yn" in [yY]*) break ;; [nN]*) echo "canceled";exit 1;; *) ;; esac | |
done | |
} | |
function create_readreplica(){ | |
logger "start to create read replica ${RDS_SLAVE_ID} at ${MASTER_AZ}" | |
aws rds create-db-instance-read-replica \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--source-db-instance-identifier "${RDS_MASTER_ID}" \ | |
--availability-zone "${MASTER_AZ}" | |
while true | |
do | |
master_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
slave_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
logger "create status (master/slave): ${master_status}/${slave_status}" | |
if [ "${master_status}" = "available" ] && [ "${slave_status}" = "available" ] ;then break;fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
logger "read replica ${RDS_SLAVE_ID} created at ${MASTER_AZ}" | |
} | |
function upgrade_readreplica(){ | |
logger "start to upgrade read replica ${RDS_SLAVE_ID} from ${CURRENT_VERSION} to ${TARGET_VERSION}" | |
aws rds modify-db-instance \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--engine-version "${TARGET_VERSION}" \ | |
--allow-major-version-upgrade \ | |
--apply-immediately | |
while true | |
do | |
upgrade_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
logger "waiting for start upgrading... ${RDS_SLAVE_ID} status is : ${upgrade_status}" | |
if [ "${upgrade_status}" = "upgrading" ] ;then break;fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
while true | |
do | |
upgrade_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
logger "now upgrading... status is : ${upgrade_status}" | |
if [ "${upgrade_status}" = "available" ] ;then break;fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
logger "read replica upgrade completed" | |
} | |
function promote_readreplica(){ | |
logger "start to promote read replica" | |
aws rds promote-read-replica --db-instance-identifier "${RDS_SLAVE_ID}" | |
while true | |
do | |
promote_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
statusinfo=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--query 'DBInstances[].StatusInfos[]' \ | |
--out text) | |
logger "now promoting... status is : ${promote_status}/ status info : ${statusinfo}" | |
if [ "${promote_status}" == "backing-up" ] || [ "${promote_status}" == "available" ] && [ "${statusinfo}" = "" ];then break;fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
} | |
function switch_endpoint(){ | |
logger "rename from ${RDS_MASTER_ID} to ${RDS_MASTER_ID_old}" | |
aws rds modify-db-instance \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--new-db-instance-identifier "${RDS_MASTER_ID_old}" \ | |
--apply-immediately | |
while true | |
do | |
rds_master_count=$(aws rds describe-db-instances \ | |
--query "length(DBInstances[?DBInstanceIdentifier==\`${RDS_MASTER_ID}\`])") | |
if [ "${rds_master_count}" -eq 0 ];then | |
break | |
else | |
logger "waiting for renamed from ${RDS_MASTER_ID} to ${RDS_MASTER_ID_old}" | |
fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
logger "rename from ${RDS_MASTER_ID} to ${RDS_MASTER_ID_old} completed" | |
logger "rename from ${RDS_SLAVE_ID} to ${RDS_MASTER_ID}" | |
aws rds modify-db-instance \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--new-db-instance-identifier "${RDS_MASTER_ID}" \ | |
--apply-immediately | |
while true | |
do | |
rds_master_count=$(aws rds describe-db-instances \ | |
--query "length(DBInstances[?DBInstanceIdentifier==\`${RDS_MASTER_ID}\`])") | |
if [ "${rds_master_count}" -eq 1 ];then | |
break | |
else | |
logger "waiting for renamed from ${RDS_SLAVE_ID} to ${RDS_MASTER_ID}" | |
fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
while true | |
do | |
master_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
logger "rds status is : ${master_status}" | |
if [ "${master_status}" = "available" ] ;then break;fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
} | |
function update_config(){ | |
while true | |
do | |
sleep "${LOOP_INTERVAL_SEC}" | |
master_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
logger "rds status is : ${master_status}" | |
if [ "${master_status}" = "available" ] ;then break;fi | |
done | |
aws rds modify-db-instance \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--backup-retention-period "${BACKUP_RETENTION}" \ | |
--preferred-backup-window "${BACKUP_TIME_WINDOW}" \ | |
--copy-tags-to-snapshot \ | |
--monitoring-interval "${MONITORING_INTERVAL}" \ | |
--monitoring-role-arn "${MONITORING_RORE_ARN}" \ | |
--apply-immediately | |
while true | |
do | |
master_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
logger "waiting for configured ${RDS_MASTER_ID} status is : ${master_status}" | |
if [ "${master_status}" != "available" ] ;then break;fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
while true | |
do | |
master_status=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].DBInstanceStatus' \ | |
--out text) | |
logger "waiting for configured ${RDS_MASTER_ID} status is : ${master_status}" | |
if [ "${master_status}" = "available" ] ;then break;fi | |
sleep "${LOOP_INTERVAL_SEC}" | |
done | |
} | |
########################################################### | |
# Main | |
########################################################### | |
################################ | |
### Get Paramters | |
readonly RDS_MASTER_ID=$1 | |
readonly TARGET_VERSION=$2 | |
readonly LOOP_INTERVAL_SEC=10 | |
readonly CURRENT_VERSION=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].EngineVersion' \ | |
--out text) | |
readonly MASTER_AZ=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].AvailabilityZone' \ | |
--out text) | |
readonly MONITORING_RORE_ARN=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].MonitoringRoleArn' \ | |
--out text) | |
readonly MONITORING_INTERVAL=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].MonitoringInterval' \ | |
--out text) | |
readonly BACKUP_TIME_WINDOW=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].PreferredBackupWindow' \ | |
--out text) | |
readonly BACKUP_RETENTION=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_MASTER_ID}" \ | |
--query 'DBInstances[].BackupRetentionPeriod' \ | |
--out text) | |
readonly RDS_SLAVE_ID=${RDS_MASTER_ID}-slave | |
readonly RDS_MASTER_ID_old=${RDS_MASTER_ID}-$(echo "${CURRENT_VERSION}" | tr . -) | |
################################ | |
### Create Readreplica | |
echo "-------------------" | |
echo "master : ${RDS_MASTER_ID}" | |
echo "read replica : ${RDS_SLAVE_ID}" | |
echo "current version : ${CURRENT_VERSION}" | |
echo "target version : ${TARGET_VERSION}" | |
echo "az : ${MASTER_AZ}" | |
echo "-------------------" | |
prompt "start to create read replica" | |
create_readreplica | |
upgrade_readreplica | |
################################ | |
### Upgrade and Switching | |
readonly SLAVE_VERSION=$(aws rds describe-db-instances \ | |
--db-instance-identifier "${RDS_SLAVE_ID}" \ | |
--query 'DBInstances[].EngineVersion' \ | |
--out text) | |
echo "-------------------" | |
echo "master : ${RDS_MASTER_ID}" | |
echo "read replica : ${RDS_SLAVE_ID}" | |
echo "backup instance : ${RDS_MASTER_ID_old}" | |
echo "master version : ${CURRENT_VERSION}" | |
echo "target version : ${TARGET_VERSION}" | |
echo "read replica version : ${SLAVE_VERSION}" | |
echo "CONFIG-------------" | |
echo "az : ${MASTER_AZ}" | |
echo "backup retantion : ${BACKUP_RETENTION}" | |
echo "backup window : ${BACKUP_TIME_WINDOW}" | |
echo "monitoring role : ${MONITORING_RORE_ARN}" | |
echo "monitoring interval : ${MONITORING_INTERVAL}" | |
echo "-------------------" | |
echo "start switching master and read replica." | |
prompt "[caution!] downtime occured while switching" | |
promote_readreplica | |
switch_endpoint | |
update_config | |
logger "Completed !!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment