2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CLI スクリプトで Aurora Serverless v1 (MySQL) を v2 にアップグレードする

Last updated at Posted at 2024-07-18

サービス終了!

いよいよ Amazon Aurora Serverless v1 のサービス終了日が迫ってきたので、稼働中の v1 データベースを Aurora Serverless v2 にアップグレードする必要があります。

Serverless v1 のまま放置するとサービス終了日以降に強制アップグレードが敢行されてしまうので、事前に動作確認をすることができない上に、パラメータ設定もデフォルト値になってしまいます。

アップグレードの手順

公式ドキュメントに移行手順が紹介されていますが、ちょっと難解でした。
Aurora Serverless v2 への移行 - Amazon Aurora

DevelopersIO の記事がとても分かりやすいです。
Amazon Aurora Serverlessをv1からv2にアップグレードしてみた | DevelopersIO

どうやら、Serverless v1 から v2 に一気にアップグレードする方法は存在しないようです。

スナップショットからクラスターを復元する時にプロパティを変更することで Aurora をアップグレードするのですが、変更できるプロパティには制限があります。

そのため、まず最初のスナップショットから MySQL 5.7 の Provisioned (Serverless でない) クラスターに復元し、次の復元で MySQL 8.0 に変更して、最後にインスタンスを Provisioned から Serverless に変更することで、Serverless v2 へのアップグレードが完了します。

この手順の良いところは、Serverless v2 へのアップグレードが完成した後も元の Serverless v1 がそのまま残るので、本番環境を使ったトライアルが何度でもできることです。

スクリプト実行の所要時間は、テスト用の小規模なクラスターでも 1 時間以上かかりました。本番環境でのトライアルで所要時間を計測しておくことをおすすめします。

事前準備 (パラメータグループ)

MySQL のメジャーバージョンが変わるので、パラメータグループは Serverless v1 用とは別に作成しておく必要があります。以下は CloudFormation で作成する例です。

  • 文字の照合順序を MySQL 5.7 と同じにしたい場合は、以下のように collation_server: utf8mb4_general_ci を指定します
  • mysql_native_password 認証プラグインの警告がログに出力されることを避けたい場合は、以下のように log_error_suppression_list: MY-013360 を指定します
AWSTemplateFormatVersion: "2010-09-09"

Resources:
  RdsDbClusterParameterGroup:
    Type: AWS::RDS::DBClusterParameterGroup
    Properties:
      DBClusterParameterGroupName: mysql80-parameter-group
      Family: aurora-mysql8.0
      Parameters:
        character_set_server: utf8mb4
        collation_server: utf8mb4_general_ci
        log_error_suppression_list: MY-013360
        time_zone: Asia/Tokyo

AWS CLI スクリプト

この章のコードを最後まで続けて実行することで、Serverless v2 へのアップグレードが完了します。

まず定数を定義します。対象とする AWS アカウントのプロファイル名を引数とします。

現在の Serverless v1 クラスターのセキュリティグループ、サブネットグループ、DB クラスター ID を DB_SECURITY_GROUP_NAMEDB_SUBNET_GROUPOLD_CLUSTER_ID に指定してください。

事前準備で作成したパラメータグループを DB_PARAMETER_GROUP に指定してください。

#!/bin/bash
set -eu

readonly PROFILE="${1}"

readonly DB_SECURITY_GROUP_NAME="db-security-group"
readonly DB_SUBNET_GROUP="db-subnet-group"

readonly OLD_CLUSTER_ID="old-db-cluster"
readonly MID_CLUSTER_ID="mid-db-cluster"
readonly NEW_CLUSTER_ID="new-db-cluster"

readonly MID_INSTANCE_ID="mid-db-instance1"
readonly NEW_INSTANCE_ID="new-db-instance1"

readonly OLD_SNAPSHOT="old-snapshot"
readonly MID_SNAPSHOT="mid-snapshot"

readonly DB_PARAMETER_GROUP="mysql80-parameter-group"
readonly MIN_CAPACITY="0.5"
readonly MAX_CAPACITY="1"

1. Serverless v1 のスナップショットを取得

現在のデータベースのスナップショットを取得します。create-db-cluster-snapshot はすぐにリターンするので、完了するまで wait で待機します。

aws rds create-db-cluster-snapshot \
  --db-cluster-identifier "${OLD_CLUSTER_ID}" \
  --db-cluster-snapshot-identifier "${OLD_SNAPSHOT}" \
  --profile "${PROFILE}"

aws rds wait db-cluster-snapshot-available \
  --db-cluster-identifier "${OLD_CLUSTER_ID}" \
  --db-cluster-snapshot-identifier "${OLD_SNAPSHOT}" \
  --profile "${PROFILE}"

2. スナップショットから Provisioned クラスター (MySQL 5.7) を復元

まずセキュリティグループの名前から ID を取得しておきます。jq コマンドを使用するので、なければインストールしておいてください。

db_security_group_id=$(aws ec2 describe-security-groups \
  --filters "Name=group-name,Values=${DB_SECURITY_GROUP_NAME}" \
  --profile "${PROFILE}" \
  --output json | jq -r ".SecurityGroups[0].GroupId")

Serverless v1 のスナップショットから Provisioned クラスターを復元します。ここで MySQL のバージョンを変更することはできないので、元の Serverless v1 と同じ MySQL 5.7 での復元になります。--engine-version は Serverless v1 と同じバージョンにします。

aws rds restore-db-cluster-from-snapshot \
  --availability-zones "ap-northeast-1a" "ap-northeast-1c" \
  --db-cluster-identifier "${MID_CLUSTER_ID}" \
  --snapshot-identifier "${OLD_SNAPSHOT}" \
  --engine "aurora-mysql" \
  --engine-version "5.7.mysql_aurora.2.11.4" \
  --engine-mode "provisioned" \
  --db-subnet-group-name "${DB_SUBNET_GROUP}" \
  --vpc-security-group-ids "${db_security_group_id}" \
  --profile "${PROFILE}"

aws rds wait db-cluster-available \
  --db-cluster-identifier "${MID_CLUSTER_ID}" \
  --profile "${PROFILE}"

クラスターの中に Provisioned インスタンスを 1 つ作成します。

aws rds create-db-instance \
  --db-cluster-identifier "${MID_CLUSTER_ID}" \
  --db-instance-identifier "${MID_INSTANCE_ID}" \
  --db-instance-class "db.t3.small" \
  --availability-zone ap-northeast-1a \
  --engine aurora-mysql \
  --no-publicly-accessible \
  --profile "${PROFILE}"

aws rds wait db-instance-available \
  --db-instance-identifier "${MID_INSTANCE_ID}" \
  --profile "${PROFILE}"

3. Provisioned クラスター (MySQL 5.7) のスナップショットを取得

復元したクラスターのスナップショットを取得します。

aws rds create-db-cluster-snapshot \
  --db-cluster-identifier "${MID_CLUSTER_ID}" \
  --db-cluster-snapshot-identifier "${MID_SNAPSHOT}" \
  --profile "${PROFILE}"

aws rds wait db-cluster-snapshot-available \
  --db-cluster-identifier "${MID_CLUSTER_ID}" \
  --db-cluster-snapshot-identifier "${MID_SNAPSHOT}" \
  --profile "${PROFILE}"

スナップショットを取得したらこのクラスターとインスタンスは不要になるので、料金が発生しないように削除か一時停止をしておきます。wait の必要はありません。

以下は一時停止の例なので、1 週間以内に削除しないと起動して料金が発生してしまいます。

aws rds stop-db-cluster \
  --db-cluster-identifier "${MID_CLUSTER_ID}" \
  --profile "${PROFILE}" || :

4. スナップショットから Provisioned クラスター (MySQL 8.0) を復元

2 回目の復元で MySQL のバージョンを 8.0 に変更します。--engine-version は指定できる最新のバージョンにします。

aws rds restore-db-cluster-from-snapshot \
  --availability-zones "ap-northeast-1a" "ap-northeast-1c" \
  --db-cluster-identifier "${NEW_CLUSTER_ID}" \
  --snapshot-identifier "${MID_SNAPSHOT}" \
  --engine "aurora-mysql" \
  --engine-version "8.0.mysql_aurora.3.06.1" \
  --db-subnet-group-name "${DB_SUBNET_GROUP}" \
  --vpc-security-group-ids "${db_security_group_id}" \
  --enable-cloudwatch-logs-exports "audit" "error" "general" "slowquery" \
  --engine-mode "provisioned" \
  --db-cluster-parameter-group-name "${DB_PARAMETER_GROUP}" \
  --no-publicly-accessible \
  --serverless-v2-scaling-configuration \
    "MinCapacity=${MIN_CAPACITY},MaxCapacity=${MAX_CAPACITY}" \
  --profile "${PROFILE}"

aws rds wait db-cluster-available \
  --db-cluster-identifier "${NEW_CLUSTER_ID}" \
  --profile "${PROFILE}"

クラスターの中に Provisioned インスタンスを 1 つ作成します。2 つ目以降のインスタンスは、必要に応じて作成してください。

aws rds create-db-instance \
  --db-cluster-identifier "${NEW_CLUSTER_ID}" \
  --db-instance-identifier "${NEW_INSTANCE_ID}" \
  --db-instance-class "db.t3.medium" \
  --availability-zone ap-northeast-1a \
  --engine aurora-mysql \
  --no-publicly-accessible \
  --profile "${PROFILE}"

aws rds wait db-instance-available \
  --db-instance-identifier "${NEW_INSTANCE_ID}" \
  --profile "${PROFILE}"

5. Provisioned インスタンスを Serverless に変更

最後に、インスタンスクラスを Serverless に変更します。

aws rds modify-db-instance \
  --db-instance-identifier "${NEW_INSTANCE_ID}" \
  --db-instance-class "db.serverless" \
  --apply-immediately \
  --profile "${PROFILE}"

aws rds wait db-instance-available \
  --db-instance-identifier "${NEW_INSTANCE_ID}" \
  --profile "${PROFILE}"

modify-db-instancewait を使用してもすぐにリターンしてしまったので、完了まで待機する処理を自作して追加しました。このループを抜けたら、Serverless v2 へのアップグレードが完了です。

instance_class=""

while [[ "${instance_class}" != "db.serverless" ]]; do
  instance_class=$(aws rds describe-db-instances \
    --db-instance-identifier "${NEW_INSTANCE_ID}" \
    --profile "${PROFILE}" \
    --output json | jq -r '.DBInstances[0].DBInstanceClass')
  sleep 15
done

アップグレード後の Serverless v2 への移行

この時点で元の Serverless v1 と新しい v2 はどちらも動作しています。

データベースを使用するアプリケーションの設定で、参照先を v2 側のエンドポイントに変更することで移行が完了します。

この作業も自動化する場合は、以下のように新しい Serverless v2 クラスターのエンドポイントを CLI で取得することができます。

new_db_endpoint=$(aws rds describe-db-cluster-endpoints \
  --db-cluster-identifier "${NEW_CLUSTER_ID}" \
  --filters "Name=db-cluster-endpoint-type,Values=WRITER" \
  --profile "${PROFILE}" \
  --output json | jq -r ".DBClusterEndpoints[0].Endpoint")

アプリケーションの正常動作が確認できたら、古い Serverless v1 クラスターを削除してください。

参考リンク

2
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?