CircleCI OrbsでAWS SAM CLIを超簡単に導入して使ってみる

CircleCI Orbsを使えば、AWS SAM CLIの導入が超簡単にできました。
2021.02.04

CircleCI Orbsを使って、AWS SAM CLIを超簡単に導入してみました。

おすすめの方

  • CircleCIでAWS SAM CLIを使いたい方

AWS SAMでサーバーレスアプリを作成する

sam init

sam init \
    --runtime python3.8 \
    --name circleci-aws-sam-deploy-test \
    --app-template hello-world \
    --package-type Zip \
    --output-dir .

SAMテンプレート

template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: circleci-aws-sam-deploy-test

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
      Timeout: 5
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get

Outputs:
  HelloWorldApi:
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"

Lambdaコード

デフォルトのままです。

app.py

import json

def lambda_handler(event, context):
    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
        }),
    }

CircleCI用のIAMユーザを準備する

IAMユーザの作成

まずは前準備としてCircleCI用のIAMユーザを作成します。

aws iam create-user \
    --user-name circleci-test-user

IAMユーザにIAMポリシーをアタッチ

さきほど作成したIAMユーザに対して、デプロイするための権限を付与します。

aws iam attach-user-policy \
    --user-name circleci-test-user \
    --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

aws iam attach-user-policy \
    --user-name circleci-test-user \
    --policy-arn arn:aws:iam::aws:policy/AWSCloudFormationFullAccess

aws iam attach-user-policy \
    --user-name circleci-test-user \
    --policy-arn arn:aws:iam::aws:policy/IAMFullAccess

aws iam attach-user-policy \
    --user-name circleci-test-user \
    --policy-arn arn:aws:iam::aws:policy/AWSLambdaFullAccess

aws iam attach-user-policy \
    --user-name circleci-test-user \
    --policy-arn arn:aws:iam::aws:policy/AmazonAPIGatewayAdministrator

aws iam attach-user-policy \
    --user-name circleci-test-user \
    --policy-arn arn:aws:iam::aws:policy/CloudWatchFullAccess

なお、実際にCI/CDを構築するときは、AssumeRoleを用いたセキュアな方法を推奨します。

アクセスキーの取得

下記コマンドでアクセスキーを取得します。

aws iam create-access-key \
    --user-name circleci-test-user

取得したアクセスキーは、あとでCircleCIの環境変数に設定します。

CircleCIのワークフローを作成する

sam buildsam deployを実行させるため、2つの方法で記載ができます。どちらでもOKです。

  • コマンドを自分で書く方法
  • 用意されているJobを使う方法

スタック名などのパラメータにdev/stg/prdなどを付与したい場合などは、環境変数を参照するコマンドを自分で書く必要がありそうです。

まずは設定ファイルを作成します。

mkdir .circleci
touch .circleci/config.yml

コマンドを自分で書く方法

.config.yml

version: 2.1
executors:
  deploy_container:
    docker:
      - image: circleci/python:3.8.7
    working_directory: ~/work

orbs:
  sam: circleci/aws-sam-serverless@2.1.0

commands:
  lint_and_unit_test:
    steps:
      - run:
          name: lint and unit test
          command: |
            echo "any lint and unit test command"
  deploy:
    steps:
      - run:
          name: deploy
          command: |
            aws --version
            sam --version

            sam build --use-container
            sam deploy \
              --s3-bucket cm-fujii.genki-deploy \
              --stack-name circleci-sam-deploy-test \
              --capabilities CAPABILITY_NAMED_IAM \
              --no-fail-on-empty-changeset

jobs:
  lint_and_unit_test:
    executor: deploy_container
    steps:
      - checkout
      - lint_and_unit_test

  deploy:
    executor: sam/default
    steps:
      - checkout
      - sam/install
      - deploy

workflows:
  version: 2
  release-workflow:
    jobs:
      - lint_and_unit_test:
          filters:
            tags:
              only: /.*/
      - deploy:
          filters:
            branches:
              only: /.*/
            tags:
              only: /.*/
          requires:
            - lint_and_unit_test

デプロイするJobのexecutordeploy_containersam build --use-containerを実行したとき、下記エラーが発生しました。

Starting Build inside a container
Building codeuri: hello_world/ runtime: python3.8 metadata: {} functions: ['HelloWorldFunction']

Build Failed
Error: Docker is unreachable. Docker needs to be running to build inside a container.

Exited with code exit status 1
CircleCI received exit code 1

そのため、デプロイするJobのexecutorを、sam/defaultにしています。

用意されているJobを使う方法

すでに用意されているJob(deploy)を使うことで、さらに簡潔な書き方もできます。

config.yml

version: 2.1
executors:
  deploy_container:
    docker:
      - image: circleci/python:3.8.7
    working_directory: ~/work

orbs:
  sam: circleci/aws-sam-serverless@2.1.0

commands:
  lint_and_unit_test:
    steps:
      - run:
          name: lint and unit test
          command: |
            echo "any lint and unit test command"

jobs:
  lint_and_unit_test:
    executor: deploy_container
    steps:
      - checkout
      - lint_and_unit_test

workflows:
  version: 2
  release-workflow:
    jobs:
      - lint_and_unit_test:
          filters:
            tags:
              only: /.*/
      - sam/deploy:
          filters:
            branches:
              only: /.*/
            tags:
              only: /.*/
          requires:
            - lint_and_unit_test
          s3-bucket: cm-fujii.genki-deploy
          stack-name: circleci-sam-deploy-test
          template: template.yaml

CircleCIの設定を行う

プロジェクトのセットアップ

リポジトリをPushし、CircleCIでSet Up Projectを選択します。

CircleCIのプロジェクトセットアップをする

CircleCIのワークフローが動きますが、環境変数を設定していないので失敗します。

環境変数を設定

下記の環境変数を設定します。

Name Value
AWS_ACCESS_KEY_ID 取得したAccessKeyId
AWS_SECRET_ACCESS_KEY 取得したSecretAccessKey
AWS_DEFAULT_REGION ap-northeast-1

プロジェクトの環境変数を設定する

動作確認をする

失敗したパイプラインをRerunします。

失敗したJobをRerunする

成功しました!!

デプロイが成功する(CircleCI)

CloudFormationのスタックも作成されています。

デプロイが成功する(CloudFormation)

さいごに

デプロイするJobのexecutorsam/defaultにする部分でしばらくハマりました。どなたかの参考になれば幸いです。

参考