Skip to content

Instantly share code, notes, and snippets.

@yomon8
Last active December 5, 2017 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yomon8/742ec6e756499902aded4d7c3e00ceab to your computer and use it in GitHub Desktop.
Save yomon8/742ec6e756499902aded4d7c3e00ceab to your computer and use it in GitHub Desktop.
upgrade MySQL engine of AWS RDS
#!/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