Amazon Web Services ブログ
GitHub からの AWS CloudFormation デプロイ自動化
本記事は 2023年11月26日に AWS DevOps Blog で公開された ”Automate safe AWS CloudFormation deployments from GitHub” を翻訳したものです。翻訳は Partner Sales Solutions Architect の 福井 敦 が担当しました。
AWS CloudFormation は、Infrastructure as Code (IaC) サービスで、AWS およびサードパーティのリソースをモデル化、プロビジョニング、管理できます。新しくトラッキングしている Git リポジトリが更新されるたびに、Git 同期 によって自動的にデプロイメントがトリガーされるようになりました。
これにより、開発者は Git ワークフローに統合し、コンテキストの切り替えによる時間の浪費を減らすことで、CloudFormation の開発サイクルを大幅に高速化できます。この新しい Git 同期は、GitHub、GitHub Enterprise、GitLab、Bitbucket に対応しています。
この投稿では、GitHub のネイティブツールと CloudFormation の Git 同期を使った最新の開発体験について説明します。
GitHub CodeSpaces を使用してクラウド開発環境を作成し、GitHub Actions と CloudFormation Linter を使用してプルリクエストに直接フィードバックし、安全なデプロイを自動化します。
要件
- AWS アカウントを所有していること。Amazon Virtual Private Cloud (Amazon VPC) リソースをデプロイします。AWS アカウントには通常リージョン毎に 5 つまでの VPC が作成できますが、制限を引き上げることが可能です。
- GitHub アカウントと、Codespaces、Actions を利用できること。これらは無料利用枠がありますが、制限を超えると課金される可能性があります。
- デベロッパーツールで GitHub への接続を作成しておくこと。
空のリポジトリの作成
今回は、新しい GitHub リポジトリから始めます。GitHub では無料で新しい Git リポジトリを作成できます。この例では、git-sync
という名前のリポジトリを作成します。
Codespace の設定
リポジトリを作成すると、Codespace を作成するオプションが表示されます。Codespace は GitHub が管理するリモートの開発環境で、設定済の仮想マシン環境でどこからでも開発できます。
Codespaces は、Visual Studio Code を選択したコードエディターとして利用します。Visual Studio Code は拡張機能をインストールできるため、非常に柔軟で拡張性に優れたオープンソースのコードエディターです。
作成が完了したら、ローカルの開発環境と同様に環境を設定できます。テンプレート開発時に、エディタ内で即座にフィードバックを得られるよう CloudFormation Linter 拡張機能を追加します。
これにより、検証のためテンプレートを CloudFormation に送信する必要はなく、送信する前にテンプレートが有効であることを確認できます。コマンドラインと Visual Studio Code 拡張機能の両方でインストールを行います。ターミナルで次のコマンドを実行してください。
pip3 install cfn-lint
インストールされたら、拡張機能パネルで CloudFormation Linter をインストールできます。
次に、ベースディレクトリに vpc.yaml
という名前のテンプレートを作成します。
入力を始めると、 CloudFormation Linter が推奨事項とオートコンプリート機能を提供します。
次のテンプレートを新しく作成した vpc.yaml
ファイルにコピーしてください:
AWSTemplateFormatVersion: "2010-09-09"
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
このテンプレートは、CIDR ブロック 10.0.0.0/16 の VPC を作成します。
テンプレートにエラーがないことを確認するには、ターミナルで cfn-lint
を実行し、エラーが返されないことを確認します。
cfn-lint -t vpc.yaml
デプロイファイルの追加
Git 同期では多様なデプロイメントをサポートするため、Git リポジトリから CloudFormation スタックを管理するための柔軟性を提供するスタックデプロイファイルをサポートしています。
この設定ファイルは、テンプレートファイルの場所、使用したいパラメータやタグの管理を行います。
パラメータやタグの管理には、このスタックデプロイファイルを使うことを強くお勧めします。監査や決定論的なデプロイメントが容易になるためです。
リポジトリ内に deployment-file.yaml
という新しいファイルを作成します。このスタックにはパラメータやタグがないため、シンプルです。
template-file-path: ./vpc.yaml
後からコンソールでこのファイルを追加することもできます。
Pull Request アクションの追加
これで開発環境の設定が完了しました。次はプルリクエストを送るだれもが、ローカルで受けているのと同じようなフィードバックを受け取れるようにしたいと思います。
GitHub Actions を使えば、これが可能になります。GitHub Actions は、プルリクエストフィードバックと CI ビルドを自動化する、カスタマイズ可能なワークフローツールです。
次のようなディレクトリとファイルを作成します。.github/workflows/pull-request.yaml
このファイルの内容は以下のとおりです。
name: Pull Request workflow
on:
- pull_request
jobs:
cloudformation-linter:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Linter install
uses: scottbrenner/cfn-lint-action@v2
with:
command: cfn-lint -t ./vpc.yaml
この設定により、プルリクエストに対して linter の結果がフィードバックされるようになります。作業内容をリモートブランチにプッシュしてください。
git add -A
git commit -m "add pull request linting workflow, add base vpc template"
git push origin main
これから VPC にサブネットを追加しますが、VpcId
ではなく VpcName
という無効なプロパティを意図的に追加します。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcName: ! Ref VPC
CidrBlock: 10.0.0.1/16
ローカルの linter は、これが無効であることをすぐに指摘します:
これらは今のところ無視してかまいません。プルリクエストを作成するには、新しいブランチを作成し、ローカルの変更をコミットする必要があります。以下のコマンドを実行してください。
git switch -c add-subnet
git add -A
git commit -m "add subnet"
git push origin add-subnet
これらのコミットをプッシュすると、GitHub から main
ブランチに対するプルリクエストを作成できるようになります。
ただし、プルリクエストを作成すると、GitHub Actions の実行が終わったときにチェックが失敗したことがわかります。
「Files changed」タブを確認すると、どこが間違っているかがわかります。Linter アクションはプルリクエスト上で直接フィードバックを提供し、ブランチ保護を設定した場合はマージのアクションをブロックします。
このリポジトリでは、少なくとも 1 人のレビュアーと全てのチェックの成功が必要なので、これら両方の失敗を解決しなければなりません。
フィードバックと問題があった行番号を取得できたので、テンプレートに戻り、VpcName
を VpcId
に修正しましょう。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: ! Ref VPC
CidrBlock: 10.0.0.1/16
ローカルの linter は問題ありません。コミットしなおすと、リモートの linter も同様に問題がないことを確認できます。レビュアーからの承認を得た後、コミットを main
ブランチにマージできます。
Git 同期の有効化
開発環境が整い、プルリクエストの過程でテンプレートがマージ前に Lint されるようになりました。
main
ブランチに到達した CloudFormation テンプレートはデプロイの準備ができています。
次に、新しく公開された CloudFormation の Git 同期を利用して、デプロイされたスタックを新しいテンプレートに自動的に同期させます。
まず、CloudFormation がスタックをデプロイするために必要な IAM ロールを作成します。このロールは、CloudFormation がデプロイするリソースを制御します。ロールの名前は後の手順で使用するので控えておきましょう。この例ではロール名を vpc-example-cloudformation-deployment-role
とし、次の許可ポリシーを設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:CreateVpc",
"ec2:CreateSubnet",
"ec2:DescribeVpcs",
"ec2:DescribeSubnets",
"ec2:DeleteVpc",
"ec2:DeleteSubnet",
"ec2:ModifySubnetAttribute",
"ec2:ModifyVpcAttribute"
],
"Resource": "*",
"Condition": {
"ForAnyValue:StringEquals": {
"aws:CalledVia": ["cloudformation.amazonaws.com"]
}
}
}
]
}
ロールを作成したら、次はスタックを新しく作成します。
こちらでは、新しいオプション Sync from Git
を選びテンプレートのソースを設定します。既にスタックデプロイファイルを作成済みのため、I am providing my own file in my repository. を選択します。
次に、Git 統合を設定してリポジトリを選択します。あらかじめ作成したデベロッパーツールの Github への接続を使用し、リポジトリを選択する必要があります。
GitHub、接続、リポジトリ、ブランチ、デプロイファイルのパスを選択してください。
最後に新しい IAM ロールを選択して、サービスマネージドロールを作成します。このロールにより、Git 同期がリポジトリに接続できるようになります。この作業は 1 回限りで、今後はここで作成する既存のロールを使用できます。
次のページでは、このスタックをデプロイするために必要な作成済の IAM ロールvpc-example-cloudformation-deployment-role
を選択します。このロールは、CloudFormation がデプロイするリソースを制御します。このように、Git 同期によってスタックを管理するには、事前にロールを作成しておく必要があります。
最後に、「Git と同期」タブで、設定内容、同期のステータス、プロビジョニングのステータス、そして必要に応じて同期の再試行や接続解除が可能であることを確認できます。
結論
この投稿では、CloudFormation テンプレートの作成および更新時にフィードバックを得るためのリモート開発環境を設定しました。プルリクエストを作成する際も同様に、フィードバックを得られます。テンプレートが main
ブランチにマージされると、自動的にスタックにデプロイされます。このように、AWS リソースを Infrastructure as Code として管理するための、堅牢で拡張性のある CI/CD システムが構築されました。この Git 同期についてのフィードバックをお待ちしています!