[AWS] CloudFormationテンプレートをGitHub Actionsで自動デプロイする


概要

本記事ではLambdaをデプロイするためのCloudFormationに必要な、

  • zipファイル
  • ymlファイル

を作成し、S3にアップロードするということをGitHub Actionsを用いてコマンド1つで可能とする設定をまとめました。

背景

以前LambdaをデプロイするCloudFormationテンプレートを作成しました。しかし、当時の構成ではLambda用のプログラムの構成が変わるたびに、以下のステップを踏んでいました。

  1. Lambda用のプログラムを編集
  2. 編集したプログラムをディレクトリごとzipファイルに固める
  3. AWSにログイン
  4. S3バケットにアップロード

上記のステップを踏むにはLambda用のプログラムの編集時間を差し引いても最低5分は要し、非常に手間のかかる作業でした。

そこで、上記ステップの2, 3, 4をGitHub Actionsに実行させるという構成にすることでCloudFormationテンプレート作成にかかる手間を減らすことが可能となりました。本記事はその際の備忘録として残します。

前提条件

GitHub Actionsを利用するため、GitHubアカウントを事前に作成してください。

手順

GitHub Actionsの設定

S3バケットの作成

まず、S3バケットを作成します。本記事ではS3バケット名はqiita-github-actions-bucketとします。

IAMユーザーの作成

次に、GitHub ActionsからS3バケットにアップロードするためのIAMユーザーを作成し、作成したユーザーに必要なIAMポリシーを割り当てます。IAMユーザーはプログラムによるアクセスにチェックをいれて作成してください。そして以下のポリシーを新規作成しユーザーに割り当ててください。
(本記事で作成するIAMユーザーは先程作成したS3バケットqiita-github-actions-bucketのみにアクセス可能なIAMポリシーを割り当てています。)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::qiita-github-actions-bucket",
                "arn:aws:s3:::qiita-github-actions-bucket/*"
            ]
        }
    ]
}

IAMユーザーの作成が完了すると、アクセスキーIDシークレットアクセスキーが画面に表示されます。これらの値は後ほど使用するため、CSVをダウンロードもしくは値を控えておいてください。

GitHubリポジトリの設定

次に、gitリポジトリを作成してください。本記事では例としてqiita-github-actions-repoという名前のレポジトリを作成します。
(gitリポジトリをローカルPCで作成した場合は、git remote addを実行し、GitHubで作成したリポジトリが見れる状態にしてください。)
そしてリポジトリのSettingsタブからSecretsを開き、New repository secretを押し、GitHub Actions用の環境変数を登録します。以下3点の環境変数を登録してください。

Secretsに登録する変数名 説明
AWS_ACCESS_KEY_ID 先程作成したIAMユーザーのアクセスキーID
AWS_SECRET_ACCESS_KEY 先程作成したIAMユーザーのシークレットアクセスキー
AWS_S3_BUCKET_REGION S3バケットを作成したリージョン
S3_UPLOAD_BUCKET 先程作成したS3バケット名

GitHub Actionsのワークフローの作成

次に、GitHub Actionsのワークフローを作成します。リポジトリ直下に/.github/workflows/s3upload.ymlファイルを作成し、以下を記述します。
GitHub Actionsで実行しているステップは以下の通りです。

ステップ名 ステップ詳細
Configure AWS Credentials GitHub Secretsに登録したAWS Credentialsを環境変数として登録
Python to Zip S3に送信するためのディレクトリs3uploadを作成、Lambda用のPythonであるmain.py/s3upload/main_py.zipとしてzip圧縮
Upload Zip to S3 /s3upload/main_py.zipをS3にアップロード

また、mainブランチへのpushがトリガーとなっています。

/.github/workflows/s3upload.yml
name: Amazon S3 Upload

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 3

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_S3_BUCKET_REGION }}

      - name: Python to Zip
        run: |
          mkdir ./s3upload
          zip ./s3upload/main_py ./main.py

      - name: Upload Zip to S3
        env: 
          S3_UPLOAD_BUCKET: ${{ secrets.S3_UPLOAD_BUCKET }}
        run: |
          aws s3 sync ./s3upload s3://$S3_UPLOAD_BUCKET/ --quiet

git pushし、GitHubのActionsタブを開くと先程のgit pushによってGitHub Actionsが正常に動作したかどうかがわかります。

Lambdaにデプロイするためのプログラムの作成

次に、Lambda用のプログラムを作成します。本記事ではPythonプログラムを例にとり解説します。

main.py
def main():
    print('Hello World')

CloudFormationの設定

CloudFormationテンプレートの作成

S3にアップロードしたzipファイルをLambdaにデプロイするCloudFormationを作成しました。リポジトリ直下(main.pyと同じディレクトリ)に作成してください。

template.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: This is a CloudFormation that deploys a Lambda function that outputs Hello World.

Resources:
  HelloPyLambda:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: main.main
      Runtime: python3.8
      Code:
        S3Bucket: qiita-github-actions-bucket
        S3Key: main_py.zip
      Role: !GetAtt 
        - LambdaExecutionRole
        - Arn
      Description: ''
      MemorySize: 128
      Timeout: 10

  LambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'

GitHub Actions実行

CloudFormationテンプレートを作成したあと、もう一度mainブランチにpushしてください。S3にこちらのテンプレートがアップロードされます。

CloudFormationでLambdaをデプロイ

こちらが最後の手順です。AWSコンソールでCloudFormationを開き、Amazon S3 URLに作成したCloudFormationテンプレートファイルのURLを入力します。
URLは以下のフォーマットなっているため、ご自分で作成されたS3バケット名等を適宜代入してください。

https://<s3_bucket_name>.s3-<s3_bucket_region>.amazonaws.com/<cloudformation_template>.yml
# 例:https://qiita-github-actions-bucket.s3-ap-northeast-1.amazonaws.com/template.yml

URLの入力後、スタックを作成するとLambdaがデプロイされます。