今回は、前回までに作成したCloud Formationテンプレートを、GitHub Actionsを使ってデプロイする方法についてアウトプットしていきます。
- 事前知識
- 全体構成
- 処理の流れ
- 対応手順
- まとめ
事前知識
GitHub Actions
GitHub Actionsは、GitHubが提供するワークフロー自動化サービスで、GitHub Actionsを使うことで、CI/CD、デプロイ、テスト、パッケージングなど、作業を効率的に実行できます。ワークフローの定義ファイルを作成し、GitHub上で設定することで、自動化された処理を実行できます。
CI/CD
CI/CD(継続的インテグレーションと継続的デリバリー)は、ソフトウェア開発プロセスの一部であり、開発プロセスを効率化し、品質を向上させるための重要な手法です。
- 継続的インテグレーション (CI):
- 継続的デリバリー (CD):
全体構成
今回の作業を実装した後の構成は下図のとおりとなります。AWS VPC内部の構造は、Cloud Formationテンプレートで記述したものであり、前回と同様です。
処理の流れ
Actionsが動作する大まかな流れは、次の通りとなります。
- (開発者)GitHubにテンプレートファイルとワークフローyamlをプッシュする。
- (GitHub Actions)プッシュを受けて、AWSにCloudFormationをDeployする
- (AWSが)Cloud Formationに基づいてスタックを構成する
【ポイント】手順2で、ActionsからCloudFormationを操作する際、AWSへの接続・認証には、AWS IAMの「IDプロバイダ」で指定するOIDC(OpenID Connect)を使用します。詳細は後述します。
対応手順
それでは、GitHub Actionsの構成作業に入ります。作業手順はおおまかに以下の流れで実施していきます。
- CloudFormationテンプレートの作成
- AWS IDプロバイダの作成
- AWS IAMロールの作成
- GitHubレポジトリ設定(シークレットの登録)
- GitHub Actionsワークフローの作成
- GitHubへのPush
- 動作確認
CloudFormationテンプレートの作成
こちらは前回までの内容をそのまま使用します。テンプレートは、以下のGitHubにある「cf.yaml」を使用します。
AWS IDプロバイダの作成
こちらの手順を始める前に、GitHub Actionsが行うAWS認証について、少し説明します。
OIDCについて
OpenID Connect(OIDC)は、OAuth2.0メカニズムを使用した認証プロトコルのひとつです。GitHubから、AWS CloudFormationにDeployを指示する際、AWSへの接続に使用します。
この方法として、以前は、IAMユーザのアクセスキーとシークレットキーを使用してデプロイする手段もあったのですが(現在も使用可能ですが)、昨今では、よりセキュアなアプローチとして、今回のIDプロバイダを使用する方法が主流となっているようです。
シークレットアクセスキーのような固有のキーを発行、管理するのではなく、AWSにプロバイダ(今回の場合、GitHub)を登録し、これを信頼するロールを定義することでAWSに、特定のGitHubからのAPIリクエストを受け入れることができるようになります。またロールの信頼ポリシーに、対象リポジトリを指定することで、受け入れる対象を限定できます。下図にイメージを示します。
なお、本手順についてはGitHubのドキュメントに詳細がありますので、詳しくは以下をご確認ください。
IDプロバイダの作成
ここでは、GitHub ActionsをIDプロバイダとして登録します。
- AWSのマネジメントコンソールで、IAMサービスを開きます。
- サイドメニューから「アクセス管理」-「IDプロバイダ」を選択し、「プロバイダを追加」ボタンをクリックします。
画面には、次の内容を登録します。
- プロバイダのタイプ:OpenID Connect
- プロバイダ名:「https://token.actions.githubusercontent.com」
入力後「サムプリントを取得」をクリックします。 - 対象者:「sts.amazonaws.com」
※ 上記「プロバイダ名」のURLや対象者の値は、GitHub固有の値であり、固有値です(前述のドキュメントに記載があります)
入力が終わりましたら、右下の「プロバイダを追加」ボタンをクリックします。
- 作成後、IDプロバイダ画面にプロバイダ
token.actions.githubusercontent.com
が表示されます。こちらをクリックして表示される、ARNの値arn:aws:iam::xxxxxxxxxxxx:oidc-provider/token.actions.githubusercontent.com
を控えておいてください。
AWS IAMロールの作成
ここでは、GitHub Actionsを受け入れるためのロールを作成します。
- AWSのマネジメントコンソールで、IAMサービスを開きます。
- サイドメニューから「アクセス管理」-「ロール」を選択し、「ロールを作成」ボタンをクリックします。
- 「信頼されたエンティティを選択」画面では、GitHub Actionsのトリガとなるレポジトリの情報を指定します。例として、レポジトリ
https://github.com/camelrush/aws_cloudformation_tutorial
の master ブランチへのpushをトリガにする場合、以下のように登録します。入力したら「次へ」をクリックします。 - 「許可を追加」画面では、Cloud Formationの動作に必要なリソースへのアクセス権限を設定します。本来はAWSのWell Architected に従い、必要最低限の権限を指定すべきですが、今回は暫定的に「AdministratorAccess」を設定します。設定したら、「次へ」をクリックします。
- 「名前、確認、および作成」画面で任意のロール名(
cf-tutorial-dev-githubactionsiam-role
としました)、説明を登録し、「ロールを作成」ボタンをクリックします。 - 作成されたロールの「信頼関係」を確認すると、下図のようにポリシーが定義されています。
以上で、AWS側の設定は終わりです。
GitHubレポジトリ設定(シークレットの登録)
次に、上記で作成したIAMロールを、GitHubレポジトリに登録します。
- WebブラウザでGitHubレポジトリを開き、サインインします。
上部メニューの「Settings」をクリックし、再度メニューから「Secrets and variables」-「Actions」をクリックします。
「New repository secret」ボタンをクリックし、表示される画面に、次の情報を登録して「Add secret」ボタンをクリックします。
- Name:「AWS_IAM_ROLE_ARN」
- Secret:(前述で作成したロール名(例では、
cf-tutorial-dev-githubactionsiam-role
))
以上で、GitHubに対して、AWSアクセスのためのロール名を設定できました。
GitHub Actionsワークフローの作成
ここでは、GitHub Actionsのワークフローファイルを作成していきます。フォーマットについても、簡単な解説を挟みます。
ディレクトリ構成
対象となるGitリポジトリのルート配下に、ディレクトリ「.github」「workflows」を作成し、その下にymlファイルを作成してください。ymlファイルの名前は任意です。
.github(dir)
└ workflows(dir)
└ deploy-on-push.yml
ワークフローファイルymlファイルの記述
最初に、作成するパラメタファイルの全体を示します。
name: "CloudFormation Deploy on Push Event" on: push: branches: master env: AWS_REGION: ap-northeast-1 CF_ENVIRONMENT: Dev CF_SOURCEIP: 0.0.0.0 permissions: id-token: write contents: read jobs: deploy: name: deploy for CloudFormation runs-on: ubuntu-latest steps: - name: Checkout Source. uses: actions/checkout@v4 - name: Configure AWS Credential uses: aws-actions/configure-aws-credentials@v4 with: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }} - name: deployCloudformation uses: aws-actions/aws-cloudformation-github-deploy@master with: name: cf-tutorial-stack template: cf.yaml no-fail-on-empty-changeset: "1" parameter-overrides: >- cftMyIpAddress=${{ env.CF_SOURCEIP }}, cftEnv=${{ env.CF_ENVIRONMENT }}
以下、ブロックごとに詳細を説明します。
on(トリガ)
on: push: branches: master
ワークフローを実行するトリガーを記載します。上記の場合、masterブランチへのpushがトリガーとなります。これ以外に、pull_request
という記述でプルリクをトリガーとしたり、path指定で特定の階層への操作をトリガ―に指定することもできます。
env(環境変数)
env: AWS_REGION: ap-northeast-1 CF_ENVIRONMENT: Dev CF_SOURCEIP: 0.0.0.0
ワークフロー内で環境変数を使用する場合、ここで任意の変数を定義します。定義した変数は、後述のjobs等で使用します。今回定義した内容は次の通りです。
AWS_REGION: ap-northeast-1
:後述のOIDC接続で使用するパラメタ(リージョン)CF_ENVIRONMENT: Dev
:CloudFormationテンプレートに引き渡すパラメタ1(環境)CF_SOURCEIP: 0.0.0.0
:CloudFormationテンプレートに引き渡すパラメタ2(SSH接続元IP)
permission(権限)
permissions: id-token: write contents: read
GitHub ActionsがOIDCを使用してワークフローを実行するために必要な権限を指定します。上記2つが必要となりますので、必ず設定してください(この指定は、前述で紹介したGitHub Actionsのドキュメントに記載されています)
jobs(ワークフロー内容)① runs-on迄
jobs: deploy: name: deploy for CloudFormation runs-on: ubuntu-latest
jobs
には、ワークフローの処理内容を記述します。上記3行の設定内容を以下に示します。
deploy
:jobの識別名です。値は任意ですので、なんでも構いません。name
:こちらも任意ですのでなんでもかいませんが、後ほどGitHub画面で進捗を確認する際、画面に表示されます。runs-on
: ワークフローを実行する環境(ジョブランナー)を指定します。大きく分けて、Githubがホストしている固有の環境と、自身が提供するセルフホストが指定できます。今回は、Githubホストのubuntuの最新バージョンを指定しました。ほかに、Windowsや、MacOSも指定が可能です。指定するや、詳細を知りたい方はこちらを参照ください。
jobs(ワークフロー内容)② steps
jobsの内訳として、steps
で複数の実行内容を定義していきます。今回は以下の3ステップを実行しています。
- Checkout Source:リポジトリから、ジョブランナーにソースをチェックアウト(取得)する。
- Configure AWS Credential:AWS接続のためのクレデンシャルをセットする
- deployCloudformation:Cloud Formationテンプレートをデプロイする。
jobs(ワークフロー内容)② step 1. ソースをチェックアウト(取得)する
steps: - name: Checkout Source. uses: actions/checkout@v4
ここで、上記のuses: actions/checkout@v4
について、マーケットプレイスActionsについて説明します。
Actions実行内容 uses
とマーケットストアについて
各steps
で実行する内容は、さまざまあるのですが、代表的なものは run
またはuses
の2つです。
run
は、ジョブランナー環境で実行するスクリプト命令を直接記述します。ファイルにコピーや移動など、ShellやBatで実行するような命令があれば、このタイプを宣言します。
steps: - name: File Create # ↓ 複数以上のコマンドは run | と記載します run: | touch sample.txt cat sample.txt pwd
uses
は、他で定義されたActionを参照して使用します。定義済のActionには、GitHub Marketplaceで公開されているアクションを活用することができます。下の例では、AWSのOIDC接続で必要となる認証Actionを使用しています。
steps: - name: Configure AWS Credential # ↓ Marketplace Actionの「aws-actions/configure-aws-credentials@v4」 を実行します uses: aws-actions/configure-aws-credentials@v4 # ↓ 上記Actionに対するパラメタを指定しています with: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
GitHub Marketplaceは、GitHubのサイドバーから「Marketplace」を選択することで参照でき、誰でも自由に使用できます。多様なActionが定義されており、中には「プルリクされたソースを、ChatGPTがコードレビューしてくれる」といったものもあります。
使用するActionのリンクを参照することで、具体的な使用方法や、指定できるパラメタの説明が書かれています。
今回のJobでは、uses
を使用した3つの定義済ActionをStep実行します。
ソースをチェックアウト(取得)する
話を戻しまして、Step1 のソースチェックアウトです。
steps: - name: Checkout Source. uses: actions/checkout@v4
ここでは、MarketplaceのActions actions/checkout@v4
を使用して、ジョブランナー環境にレポジトリのソースを取得しています。
jobs(ワークフロー内容)② step 2. AWS接続のためのクレデンシャルをセットする
- name: Configure AWS Credential uses: aws-actions/configure-aws-credentials@v4 with: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
ここでは、Actions aws-actions/configure-aws-credentials@v4
を使用して、AWS接続のためのクレデンシャルを設定しています。with
以下にあるのがActionのためのパラメタであり、リージョンと、ロールを指定しています。
変数の使用について
with
の内容にある ${{ env.AWS_REGION }}
、${{ secrets.AWS_IAM_ROLE_ARN }}
について解説します。
${{ xxx.yyy }}
は、予め定義された変数を使用することを宣言しています。- 変数には、GitHubによって定義された変数(
github.actor
等)の他、env、secretsの定義が使用できます。env
はワークフローファイル内で定義された値を示しており、これらは本ファイル上部で定義済みです。secrets
は、GitHubのレポジトリにあるSettings
ページで登録したシークレット情報を参照します。こちらは、前述の手順でGitHubにセットしたロールのシークレット名を参照しています。
このようにsecrets
を使用することで、外部に公開したくない情報を、定義ファイルの外で管理することができます。
jobs(ワークフロー内容)② step 3. Cloud Formationテンプレートをデプロイする
- name: deployCloudformation uses: aws-actions/aws-cloudformation-github-deploy@master with: name: cf-tutorial-stack template: cf.yaml no-fail-on-empty-changeset: "1" parameter-overrides: >- cftMyIpAddress=${{ env.CF_SOURCEIP }}, cftEnv=${{ env.CF_ENVIRONMENT }}
Cloud Formationをコールして、テンプレートファイルをAWS環境にデプロイします。Action
には「aws-actions/aws-cloudformation-github-deploy@master」を使用します。パラメタには、次の内容を指定しています。
- name:Cloud Formationのスタック名
- template:テンプレートファイル名
- no-fail-on-empty-changeset:"1"を指定することでChange Set(変更点)が存在しない場合であっても、正常終了となります。
- parameter-overrides:Cloud Formationのparameterに渡す値を指定。
parameter-overrides
はテンプレートファイル内に定義している内容ですので、具体的な内容は、前回までのコラムを参照してください。なお設定しているCF_SOURCEIP
、CF_ENVIRONMENT
は、env
として本ファイル上部に設定済みです。
以上で、ymlファイルの解説は終わりです。
GitHubへのPush
- 最初に、上記で作成したワークフローyamlファイルを、GitHubにPushします。
- 次に、Cloud Formationのテンプレートファイル「cf.yaml」を更新して、GitHubにPushします。
Push後、ブラウザでGitHubのActionタブを参照すると、定義したワークフローに従ってStepが実行されている進捗状況が表示されます。
ちょうど、上の図ではCloud Formationを呼び出しているところなので、別のブラウザでを使ってAWSマネージメントコンソールを開き、Cloud Formationを確認します。下図のとおり、スタックが実行中であることがわかります。
しばらくすると、ステータスが緑色(Complete)となり、デプロイが完了します。
動作確認
前述のワークフロー動作によって、下図のVPC内構成が作成されました。
SSHで接続し、動作確認を行います。
無事接続できました。
まとめ
CI/CD構成を作ることが目的でしたが、GitHub Actionsでできることが幅広くあり、Marketplace等を含めて知ることができたことはよかったです。今度、プルリクをChatGPTがコードレビューしてくれるActionなどは、試してみたいですね。
IaCについては、Terraformの使用や、ステート管理(実際の構成との差分)など、実運用に載せるにはまだまだ奥が深そうですが、精進して学んでいきたいと思います。