Amazon Web Services ブログ

データベース移行のためのクロスアカウントの継続的デリバリーパイプラインの構築

開発を迅速化し、その品質を高めるには、アプリケーションのコード変更を管理してデプロイする継続的なデリバリー戦略を使用することができますが、データベース移行のための継続的デリバリーは、手動プロセスであることがほとんどです。

データベース移行のための継続的インテグレーションと継続的デリバリー (CI/CD) の導入には、次のようなメリットがあります。

  • 自動化されたマルチアカウントセットアップによってデータベース移行がシンプル化される。
  • 適用された変更の信頼レベルが向上する。
  • プロセスの再現が容易になる。
  • データベース移行がより高速で効率的になる。
  • データベースへの接続にジャンプステーションを使用する必要がないので、Amazon EC2 をプロビジョニングし、管理して、パッチを適用する必要がなくなる。

この記事では、マルチアカウントセットアップでデータベース移行を自動化するために AWS 開発者用ツール一式を設定する方法を説明します。対象読者は、AWS CloudFormation に関する知識がある開発者、ソリューションアーキテクト、およびデータベース管理者です。

このソリューションは、マルチアカウントおよびマルチ VPC の CI/CD データベース移行を紹介するために、4 つの AWS アカウントを使用します。

  • 共有サービス – AWS CodePipeline および AWS CodeBuild などの継続的デリバリー/デプロイメントサービスに関連するすべてのツールのための中心的な場所です。共有サービスアカウントは AWS CodeCommit リポジトリもホストし、開発者はここにコードをプッシュできます。
  • 開発、テスト、および本番 – Amazon RDS for SQL Server データベースを作成し、Secrets Manager を使ってデータベースの認証情報を保存するターゲットアカウントです。また、RDS for SQL Server インスタンスと同じ VPC およびプライベートサブネット内で、CodeBuild プロジェクトの作成と設定も行います。

前提条件

開発、テスト、および本番の各ステージを作成するための 3 つのアカウント、および共有サービスアカウントの 4 つの AWS アカウントが必要です。詳細については、「アマゾン ウェブ サービスの新規アカウントを作成してアクティブ化する方法を教えてください」を参照してください。

各ターゲットアカウント (開発、テスト、および本番) には、異なるアベイラビリティーゾーンにある 2 つのプライベートサブネットが含まれる Virtual Private Cloud (VPC) と、NAT ゲートウェイ経由でのインターネットアクセスが必要です。RDS はプライベートサブネットにデプロイします。インターネットからデータベースにアクセスできないようにするためです。詳細については、「コンピューティング環境のためにパブリックサブネットとプライベートサブネットを持つ VPC を作成する」を参照してください。

構築するアイテム

  • RDS for SQL Server は、各ターゲットアカウントにデータベースを作成し、プライベートサブネットにデプロイします。RDS は、クラウド内でのリレーショナルデータベースの設定、運用、およびスケーリングを容易にし、ハードウェアのプロビジョニング、データベースの設定、パッチ適用、およびバックアップなどの時間がかかる管理タスクを自動化しながら、コスト効率に優れ、サイズ変更が可能な容量を提供します。RDS は、ユーザーがアプリケーションに集中して、アプリケーションに必要な高速パフォーマンス、高可用性、セキュリティ、および互換性を提供できるようにします。
  • CodePipeline は CI/CD データベース移行のステージを編成します。
  • IAM ロールとポリシーは、該当する AWS のリソースへのクロスアカウントアクセスを可能にします。
  • CodeCommit は、データベース移行の実行時に使用される SQL ステートメントを保存するためのリポジトリを作成します。
  • Amazon S3 は、パイプラインアーティファクトを保存するためのバケットを作成します。
  • Flyway はオープンソースのデータベース移行ツールで、設定よりもシンプルさと規約を優先します。Flyway 移行は、PL/SQL、T-SQL、または Java などの SQL データベース固有の構文で記述できます。Flyway はデータベースの変更を管理します。詳細については、Flyway を参照してください。
  • CodeBuild は、データベースの変更を適用するために Flyway を使用して、ターゲットアカウントにプロジェクトを作成します。
  • VPC のセキュリティグループは、VPC 内にデプロイされた CodeBuild プロジェクトと、RDS for SQL Server データベース間のトラフィックのセキュアなフローを確実にします。
  • AWS Secrets Manager は、RDS for SQL Server データベースのユーザー名とパスワードなどの秘密をセキュアかつ一元的に保存します。
  • Amazon SNS は、開発者が CodeCommit リポジトリに変更をプッシュするときに E メールで通知します。

ローカル開発環境の設定

  1. 以下のコマンドを使用して、ソリューションのアーティファクトとリソースが保存される db-migration という名前のフォルダを作成します。
    mkdir db-migration
  2. AWS CloudFormation テンプレートが含まれる S3 バケットから templates.zip をダウンロードします。
  3. 以下のコマンドを使用して、templates.zip ファイルを db-migration フォルダに展開します。
    unzip templates.zip -d db-migration
  4. データベース移行のサンプルプロジェクトが含まれている S3 バケットから cicd-db.zip をダウンロードします。
  5. 以下のコマンドを使用して、cicd-db.zip filedb-migration フォルダに展開します。
    unzip cicd-db.zip -d db-migration
  6. 以下のコマンドを使用して、ディレクトリを db-migration フォルダに変更します。
    cd db-migration
  7. AWS CLI をインストールします。詳細については、「AWS CLI のインストール」を参照してください。
  8. 開発、テスト、および本番 の各 AWS アカウントを作成します。詳細については、「アマゾン ウェブ サービスの新規アカウントを作成してアクティブ化する方法を教えてください」を参照してください。
  9. AWS への呼び出しを行うために、アクセスキー、または assume-role AWS CLI コマンドを準備します。アカウントそれぞれに個別のプロファイルを設定することを含めて、「AWS CLI の設定」で説明されている通りに AWS CLI を設定します。

AWS CloudFormation テンプレートのプロビジョニング

これらのステップは順序通りに実行してください。順序を間違うと、リソースが誤って作成される場合があります。

1. 共有サービスアカウントには、AWS CloudFormation テンプレートの db-migration-master.yml をデプロイします。

これは、CodePipeline パイプライン、CodeBuild プロジェクト、CodeCommit リポジトリ、および CodePipeline がパイプラインアーティファクトを保存するために使用する S3 バケットを作成します。CodeCommit リポジトリにプッシュされた変更は SNS トピックをトリガーし、これによって設定された E メールアドレスに E メールが送信されます。このステップは、クロスアカウントアクセスを可能にする IAM ロールとポリシーも作成します。以下の図は、リソースがどのように関連しているかを示しています。

これらのパラメータは、テンプレートをデプロイする時に設定する必要があります。

  • ProjectNamemyProjectX などのプロジェクトの名前です。これは、テンプレートが作成する AWS リソースに名前を付けるときにプレフィックスとして使用します。
  • EmailAddress – 開発者が CodeCommit リポジトリに変更をプッシュするときの通知に使用される E メールアドレスです。
  • DevAccountId – 開発アカウント ID のための AWS アカウント ID です。
  • TestAccountId – テストアカウント ID のための AWS アカウント ID です。
  • ProdAccountId – 本番アカウント ID のための AWS アカウント ID です。

db-migration-master.yml テンプレートをデプロイするには、以下のコマンドを実行します。パラメータには、お使いの AWS 環境に該当するものを代用してください。このコマンドがテンプレートファイルを適切に見つけることができるように、コマンドは前のセクションで作成した db-migration フォルダの root レベルから実行するようにしてください。

aws cloudformation deploy --stack-name db-shared-services-master-pipeline \
--template-file templates/db-migration-master.yml --parameter-overrides \
ProjectName=ENTER_PROJECT_NAME \
EmailAddress=ENTER_EMAIL_ADDR \
DevAccountId=ENTER_DEV_ACCT \
TestAccountId=ENTER_TEST_ACCT \
ProdAccountId=ENTER_PROD_ACCT --capabilities CAPABILITY_NAMED_IAM

以下の例は、db-migration-master.yml のデプロイメントを示しています。

aws cloudformation deploy --stack-name db-shared-services-master-pipeline \
--template-file templates/db-migration-master.yml --parameter-overrides \
ProjectName=blogg-ci \
EmailAddress=myemail@thinkworks.se \
DevAccountId=123456789012 \
TestAccountId=123456789012 \
ProdAccountId=123456789012 --capabilities CAPABILITY_NAMED_IAM 

2. ターゲットアカウントには、db-migration-rds.yml テンプレートを開発アカウントにデプロイします。

これは、データベースのユーザー名とパスワードを保存するために Secrets Manager を使用する RDS for SQL Server インスタンスを作成します。このステップは、RDS インスタンスと同じ VPC およびプライベートサブネット内での CodeBuild プロジェクトのプロビジョニングとデプロイメントも実行します。以下の図は、作成されたリソースの関係を表しています。

これらのパラメータは、テンプレートをデプロイする時に設定する必要があります。

  • ProjectName db-migration-master.yml のデプロイ時に使用したものと同じ名前です。
  • TargetEnvironment – ターゲット環境の名前で、devtest、または prod です。これは、AWS CloudFormation テンプレートが作成するリソースに名前を付けるときに使用します。
  • PrivateSubnet1A – アベイラビリティーゾーン A にあるプライベートサブネットの ID です。
  • PrivateSubnet1B – アベイラビリティーゾーン B にあるプライベートサブネットの ID です。
  • VPCId – RDS データベースがデプロイされる VPC の ID です。

db-migration-rds.yml テンプレートをデプロイするには、次のコマンドを実行します。以前説明した通り、--profile を使用して AWS CLI プロファイルを指定し、置き換えるようにしてください。このコマンドは各ターゲットアカウントのために 3 回実行します。つまり、テンプレートを 3 回デプロイすることになります。

aws cloudformation deploy --stack-name db-rds \
--template-file templates/db-migration-rds.yml --parameter-overrides \
--profile YOUR_AWS_PROFILE_FOR_TARGET_ACCOUNT \
ProjectName=ENTER_PROJECT_NAME \
TargetEnvironment=dev \
PrivateSubnet1A=ENTER_PRIVATE1A_SUBNETID \
PrivateSubnet1B=ENTER_PRIVATE1B_SUBNETID \
VpcId=ENTER_VPCID

以下の例は、db-migration-rds.yml のプロビジョニングを示しています。

aws cloudformation deploy --stack-name db-rds \
--profile blg-dev \
--template-file templates/db-migration-rds.yml --parameter-overrides \
ProjectName=db-migration \
TargetEnvironment=dev \
PrivateSubnet1A=subnet-047be00d1bb0e2243 \
PrivateSubnet1B=subnet-0e0fece6238dcd115 \
VpcId=vpc-0ac677137a64fcf53

AWS CloudFormation コンソールの出力セクションで、CodeBuildSecurityGroupIdJDBCUrl の値を書き留めます。これらは、次のステップで必要になります。

3. VPC にデプロイされた CodeBuild プロジェクトを作成する db-migration-target.yml テンプレートをデプロイします。db-migration-target.yml テンプレートをデプロイするには、以下のコマンドを実行します。以前説明した通り、–profile を使用して AWS CLI プロファイルを指定し、置き換えるようにしてください。このコマンドは各ターゲットアカウントのために 3 回実行する必要があります。つまり、テンプレートを 3 回デプロイすることになります。

コマンドには、次のようにパラメータの上書きを入力します。

  • SharedServicesAccountId – 共有サービスアカウントからターゲットアカウントへのクロスアカウントアクセスを可能にするために使用する共有サービスアカウントのアカウント ID です。
  • ProjectName db-migration-master.yml のデプロイ時に使用したものと同じ名前です。
  • TargetEnvironment – ターゲット環境の名前で、devtest、または prod のいずれかです。これは、AWS CloudFormation テンプレートが作成するリソースに名前を付けるときに使用します。
  • PrivateSubnet1A – プライベートサブネットにデプロイされた RDS インスタンスです。CodeBuild プロジェクトが RDS インスタンスにアクセスできるようにするため、CodeBuild プロジェクトを RDS インスタンスと同じサブネットに設定します。RDS インスタンス用に指定したものと同じサブネット ID を指定します。
  • PrivateSubnet1B – 2 番目のアベイラビリティーゾーンにあるプライベートサブネットのサブネット ID です。これは、RDS インスタンスと同じものにするようにしてください。
  • VPCId – CodeBuild プロジェクトがデプロイされる VPC の ID です。データベース移行を実行する RDS インスタンスと同じ VPC を使用します。

db-migration-rds.yml テンプレートをデプロイするには、次のコマンドを実行します。

aws cloudformation deploy --stack-name db-migration \
--profile YOUR_AWS_PROFILE_FOR_TARGET_ACCOUNT \
--template-file templates/db-migration-target.yml --capabilities CAPABILITY_NAMED_IAM --parameter-overrides \
SharedServicesAccountId=ENTER_SHARED_ACCOUNT_ID
ProjectName=ENTER_PROJECT_NAME \
PrivateSubnet1AId=ENTER_PRIVATE_SUBNETID \
PrivateSubnet1BId=ENTER_PRIVATE_SUBNETID \
VpcId=ENTER_VPCID \
CodeBuildSecurityGroupId=ENTER_CODEBUILD_SG \
JDBCUrl=ENTER_JDBC_URL \
TargetEnvironment=ENTER_TARGET_ENVIRONMENT --capabilities CAPABILITY_NAMED_IAM

以下の例は、db-migration-target.yml のプロビジョニングを示しています。

aws cloudformation deploy --stack-name db-migration \
--profile blg-dev \
--template-file templates/db-migration-target.yml --capabilities CAPABILITY_NAMED_IAM --parameter-overrides \
SharedServicesAccountId=123456789012 \
ProjectName=db-migration \
PrivateSubnet1AId=subnet-047be00ddbb0e0843 \
PrivateSubnet1BId=subnet-0e0fece6208dcd845 \
VpcId=vpc-0ac677247a64fcf53  \
CodeBuildSecurityGroupId=sg-0b033d424a8a8d141 \
JDBCUrl=jdbc:sqlserver://db-migration-rds-instance-sqlserver-se-eu-central-1-dev:1433;databaseName=tempdb \
TargetEnvironment=dev --capabilities CAPABILITY_NAMED_IAM

テストおよび本番の各アカウントには、ステップ 2 と 3 を繰り返しますが、TargetEnvironment パラメータをそれぞれ test および prod に変更してください。それぞれの --profile パラメータを使った正しいアカウントプロファイルが提供されていることを確認してください。

3 つのターゲットアカウントがない既存の環境にこれを適用するには、使用するターゲットアカウントの数だけステップ 2 および 3 を適用します。

4. 以下のコードを実行して、移行スクリプトを CodeCommit リポジトリにプッシュします。

cd to_folder_that_you_unzipped_the_cicd_db_zip_file
git init
git remote add origin https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/your_project_name
git add .
git commit -m "Initial commit"
git push -u origin master

以下の例は、移行スクリプトの CodeCommit へのプッシュを示しています。

cd cicd-db
git init
git remote add origin https://git-codecommit.eu-central-1.amazonaws.com/v1/repos/db-migration
git add .
git commit -m "Initial commit"
git push -u origin master

共有サービスアカウントの AWS CodePipeline コンソールに移動し、パイプラインがトリガーされていることを確認します。

プロセスの要約

この例では、変更を CodeCommit リポジトリにコミットし、プッシュします。このアクションは、パイプラインにあるすべてのアクティビティを開始します。

CodePipeline パイプラインは、ソース、検証、テスト、およびデプロイの 4 つのステージで構成されています。

ソースステージでは、CodeCommit リポジトリのソースブランチに行われたプッシュが CodePipeline パイプラインをトリガーします。このプロセスは、CodeCommit リポジトリのコンテンツをプルし、圧縮して、S3 バケットに保存します。バケットポリシーは、開発、テスト、および本番の各アカウントが共有サービスアカウント内の S3 バケットにアクセスすることを許可するように設定されています。例として、以下のバケットポリシーを参照してください。

検証ステージでは、CodeBuild が Linux コンテナを作成し、コンテナ内にその依存性を作成します。CodeBuild は次に、S3 バケットからソースコードが含まれる圧縮ファイルをダウンロードし、アンパックして、検証を実行します。検証が正常に行われると、CodePipeline のテストステージがトリガーされます。

この検証の目的は、SQL ステートメントのリンティングを実行することです。この記事の例は、マルチアカウントセットアップでデータベースの変更を管理する方法を説明することに重点を置いているため、リンティングメカニズムは実装しません。検証は、CodePipeline のステージの異なる可能性を示すために存在します。

テストステージでは、CodeBuild が Linux コンテナの作成、コンテナでの依存性の設定 (または依存性のインストール)、ソースコードが含まれる圧縮ファイルの S3 バケットからのダウンロード、圧縮ファイルのアンパック、およびテストの実行を行います。テストが正常に行われると、CodePipeline のデプロイステージがトリガーされます。

デプロイステージでは、共有サービスアカウントの 3 つの CodeBuild プロジェクト設定が、ターゲットアカウントの CodeBuild プロジェクトをトリガーします。CodeBuild の buildspec は、CodeBuild プロジェクトが開始されたときに何を実行するかを指定します。

buildspec は以下のステップを実行します。

  1. AWS CLI を使用してターゲットアカウントの IAM ロール (flyway-deploy-role*) を引き受け、一時的な AWS 認証情報を返します。
  2. この一時的な認証情報を環境変数として設定します。これは、すべての AWS CLI コマンドが特定のターゲットアカウントで呼び出されることを確実にします。
  3. AWS CLI を使用してターゲットアカウントの CodeBuild プロジェクトをトリガーします。
  4. ステータスに失敗または成功したかが表示されるまで、AWS CLI を使用してターゲットアカウントの CodeBuild プロジェクトのステータスをポーリングします。

File: db-migration-master.yml

ターゲットアカウントのための CodeBuild プロジェクト

各ターゲットアカウントの CodeBuild プロジェクトと buildspec が以下のステップを実行します。

  1. 共有サービスアカウントの S3 バケットから SQL ファイルをダウンロードします。クロスアカウントバケットポリシーを設定したため、ターゲットアカウントはバケットにアクセスしなければなりません。
  2. AWS CLI (以下のコード例の 89 行目) を使用して、Secrets Manager に保存されたデータベースのユーザー名とパスワードを検索します。環境のシェル変数として保存されているユーザー名とパスワードを抽出するために、コマンド aws secretsmanager get-secret-value からの JSON レスポンスが jq を使って解析されます。
  3. docker run コマンド (以下のコード例の 93 行目) を使用して Docker Flyway コンテナを実行します。同じコマンドで、どのフォルダをマウントするか、および Flyway 移行を実行するために必要なパラメータ (usernamepasswordjdbcUrl) を指定します。

File: db-migration-target.yml

  1. データベース移行を適用します。CodeBuild プロジェクトログの出力は以下の通りです。

まとめ

Flyway と組み合わされた AWS CI/CD サービスは、データベースライフサイクルのためにマルチアカウントセットアップでの継続的デリバリーをサポートできます。これで、データベースの変更のために明確に定義されたデプロイメントプロセスが設定され、データベースを簡単に再作成できるようにもなりました。AWS 固有ではない他の CI/CD ツールで同じパターンを適用することも可能です。

データベースのために CI/CD オートメーションを使用することによって、デプロイメントを迅速化し、ソフトウェアチームの敏捷性を向上させることができます。

 


著者について

Pierre Petersson はアマゾン ウェブ サービスの DevOps コンサルタントです。 Pierre は 80 年代半ばに初めて Luxor ABC 80 に触れて以来コードを書き続けており、情熱、熱意、カスタマーアドボカシー、好奇心、そして創造力の秘密のブレンドを用いて、コードビルダーに AWS クラウドの価値を明らかにする意欲を起こさせます。彼は、ソフトウェアアーキテクチャと開発者ツールに関する事柄に興味を持っています。開発者としての経歴がある Pierre は、この分野に 16 年以上携わっていましたが、現在は DevOps の旅においてお客様を助けることに焦点を移しています。