Skip to content

Instantly share code, notes, and snippets.

@pocari
Last active July 7, 2017 06:14
Show Gist options
  • Save pocari/a363d0d56589f6a571e478f09b513c1b to your computer and use it in GitHub Desktop.
Save pocari/a363d0d56589f6a571e478f09b513c1b to your computer and use it in GitHub Desktop.
Auroraのクラスタのスナップショットを既存のAurora環境に復元する
require 'logger'
require 'aws-sdk'
LOGGER = Logger.new(STDOUT)
def current_timestamp
Time.new.strftime("%Y-%m-%d-%H-%M-%S")
end
# 最大一時間待つ
def wait_for(wait_time: 60, retry_max: 60)
i = 0
loop {
result = yield
break result if result
i += 1
break false if i >= retry_max
sleep wait_time
}
end
def get_instance_class(rds, identifier)
rds.describe_db_instances(db_instance_identifier: identifier).db_instances.first.db_instance_class
end
def main
src_db_cluster_identifier = "ams-api-alpha"
dest_db_cluster_identifier = "ams-api-stg"
rds = Aws::RDS::Client.new(region: 'ap-northeast-1')
LOGGER.info("find latest snapshot")
#対象クラスタの最新のスナップショット取得
src_snapshot = rds.describe_db_cluster_snapshots(db_cluster_identifier: src_db_cluster_identifier).db_cluster_snapshots.first
if src_snapshot
# 置き換え対象のクラスタ取得
dest_cluster = rds.describe_db_clusters(db_cluster_identifier: dest_db_cluster_identifier).db_clusters.first
vpc_security_groups = dest_cluster.vpc_security_groups
engine = dest_cluster.engine
instance_classes = {}
# 置き換え対象のクラスタ内のインスタンスをすべて削除
dest_cluster.db_cluster_members.each do |member|
instance_classes[member.db_instance_identifier] = get_instance_class(rds, member.db_instance_identifier)
LOGGER.info("delete dest instances: #{member.db_instance_identifier}")
rds.delete_db_instance(
db_instance_identifier: member.db_instance_identifier
)
end
result = wait_for {
LOGGER.info("check instances ...")
cluster = rds.describe_db_clusters(db_cluster_identifier: dest_db_cluster_identifier).db_clusters.first
count = cluster.db_cluster_members.count
count == 0
}
# かなり時間かかるので待ち足りない可能性もある
raise "インスタンスの削除に失敗しました" unless result
LOGGER.info("wait delete instances: end")
# 置き換え対象のクラスタを削除
LOGGER.info("delete dest cluster")
rds.delete_db_cluster(
db_cluster_identifier: dest_db_cluster_identifier,
skip_final_snapshot: true
)
# 削除されるのを待つ
LOGGER.info("delete cluster: start")
result = wait_for {
begin
LOGGER.info("check delete cluster ...")
rds.describe_db_clusters(db_cluster_identifier: dest_db_cluster_identifier)
false
rescue Aws::RDS::Errors::DBClusterNotFoundFault
# 見つからない場合例外になるのでそれで削除確認
true
end
}
raise "削除に失敗しました" unless result
LOGGER.info("delete cluster: end")
# スナップショットから復元
rds.restore_db_cluster_from_snapshot(
db_cluster_identifier: dest_db_cluster_identifier,
engine: engine,
snapshot_identifier: src_snapshot.db_cluster_snapshot_identifier,
vpc_security_group_ids: vpc_security_groups.map(&:vpc_security_group_id),
db_subnet_group_name: dest_cluster.db_subnet_group
)
# 復元が完了するまで待つ
LOGGER.info("restore cluster: start")
result = wait_for {
begin
LOGGER.info("check restore cluster ...")
cluster = rds.describe_db_clusters(db_cluster_identifier: dest_db_cluster_identifier)
cluster.db_clusters.first.status == "available"
rescue Aws::RDS::Errors::DBClusterNotFoundFault
false
end
}
LOGGER.info("restore cluster: end")
# クラスタパラメータグループ変更
rds.modify_db_cluster(
db_cluster_identifier: dest_db_cluster_identifier,
db_cluster_parameter_group_name: dest_cluster.db_cluster_parameter_group
)
# 復元後インスタンス起動
LOGGER.info("start cluster members(instances): start")
dest_cluster.db_cluster_members.each do |member|
rds.create_db_instance(
db_instance_identifier: member.db_instance_identifier,
db_instance_class: instance_classes[member.db_instance_identifier],
engine: dest_cluster.engine,
db_cluster_identifier: dest_cluster.db_cluster_identifier
)
end
result = wait_for {
cluster = rds.describe_db_clusters(db_cluster_identifier: dest_db_cluster_identifier).db_clusters.first
count = cluster.db_cluster_members.count
puts count
count == dest_cluster.db_cluster_members.size
}
LOGGER.info("check cluster instances in aws console")
LOGGER.info("restore done!")
end
end
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment