[AWS CDK] CircleCIでサーバーレスアプリ(WebAPI)を自動デプロイしてみた(本番環境と開発環境)
AWS CDK(Cloud Development Kit)とCircleCIを組み合わせて、自動デプロイする仕組みを作ってみました。
これで運用がますます楽々になりまね!
なお、デプロイのみを対象とします。(テストは扱いません)
目次
- 環境
- リポジトリとブランチ運用
- AWS CDKのインストール
- AWS CDKで適当にサーバーレスアプリ(WebAPI)を作る
- WebAPIの仕様
- AWS CDKプロジェクトの構築
- Lambdaコードを書く!
- インフラをコードで書く!!!
- サーバーレスアプリのStack
- CircleCI用ユーザのStack
- スタックのデプロイ準備をする
- ビルドする
- bootstrapの実行
- CircleCIの事前準備
- Python仮想環境の構築
- pyenvの導入
- Python仮想環境の作成
- AWS CLIの導入
- AWS認証情報のセットファイルを作成
- CircleCI用の設定ファイルを作成
- CircleCI用のユーザー作成
- AWS認証情報の取得(アクセスキーIDとシークレットキー)
- リポジトリのPush
- CircleCIの設定
- ログイン
- CircleCIのプロジェクトを作成
- 環境変数の設定
- CircleCIでデプロイする!
- 開発環境にデプロイ
- 本番環境にデプロイ
- 動作確認
- 開発環境
- 本番環境
- AWSの様子
- CloudFormation
- API Gateway
- Lambda
- さいごに
- 参考
環境
項目 | バージョン |
---|---|
macOS | High Mojave 10.14.6 |
AWS CLI | aws-cli/1.16.220 Python/3.7.2 Linux/4.15.0-1043-aws botocore/1.12.210 |
Python | 3.7 |
Node.js | 10.15.3 |
npm | 6.4.1 |
AWS CDK | 1.4.0 (build 175471f) |
リポジトリ | GitHub |
主にDocker Imageで使用しています。
リポジトリとブランチ運用
Gitリポジトリは、GitHubフローみたいな運用とし、Pushされたタグを本番環境にデプロイします。
自動デプロイの対象は、下記とします。デプロイ先は、同じAWSアカウントです。
種類 | 名前の例 | 環境 | AWSスタック名 |
---|---|---|---|
ブランチ | master | 開発環境 | AWS-CDK-CircleCI-Deploy-Sample-App-Stack-dev |
ブランチ | issues/123 | 開発環境 | AWS-CDK-CircleCI-Deploy-Sample-App-Stack-dev |
タグ | v1.2.3 | 本番環境 | AWS-CDK-CircleCI-Deploy-Sample-App-Stack-prod |
AWS CDKのインストール
インストール済みの場合はSkipしてください。
$ npm install -g aws-cdk
AWS CDKで適当にサーバーレスアプリ(WebAPI)を作る
WebAPIの仕様
Method | Path |
---|---|
GET | /message/:id |
たとえば、/message/hoge
に対してアクセスしたとき、下記のJSONを取得します。
{ "env": "dev", "message": "your request message id is hoge" }
env
の値は、開発環境ならdev
で、本番環境ならprod
とします。
AWS CDKプロジェクトの構築
フォルダを作成し、AWS CDKプロジェクトの初期化を行います。
$ mkdir AWSCDK-CircleCIDeploySample $ cd AWSCDK-CircleCIDeploySample $ cdk init app --language=typescript
必要なライブラリをインストールします。
$ npm install --save @aws-cdk/aws-lambda $ npm install --save @aws-cdk/aws-apigateway $ npm install --save @aws-cdk/aws-iam
Lambdaコードを書く!
まずはファイルを作ります。
$ mkdir -p src/lambda/ $ touch src/lambda/app.ts
続いてコードを下記にします。
インフラをコードで書く!!! (AWS CDK)
2つのStackを作成します。
- サーバーレスアプリのStack
- CircleCI用ユーザのStack
サーバーレスアプリのStack
デフォルトで作成されているlib/awscdk-circle_ci_deploy_sample-stack.ts
をlib/app-stack.ts
にリネームします。
$ mv lib/awscdk-circle_ci_deploy_sample-stack.ts lib/app-stack.ts
内容は下記です。
対象環境の情報をコンストラクタの引数(systemEnv
)で受け取っています。
CircleCI用ユーザのStack
lib/circleci-user-stack.ts
を新規作成します。
$ touch lib/circleci-user-stack.ts
内容は下記です。
簡略化のため雑に作成しています。よりセキュアに作るためには、必要最低限のポリシーを作成するなど、ベストプラクティス等を参照してください。 IAM のベストプラクティス
スタックのデプロイ準備をする
bin/awscdk-circle_ci_deploy_sample.ts
を下記にします。
環境変数から「環境名」を取得し、スタック名に含めています。
ビルドする
ビルドエラーが無ければOKです。
$ npm run build
bootstrapの実行
Lambdaコード格納用のS3バケットを作るcdk bootstrap
は、最初の1回だけ実行すればOKです。
$ cdk bootstrap
CircleCIの事前準備
Python仮想環境の構築
AWS CLI自体は、Python上で動いているため、Python仮想環境を作成してからインストールします。
pyenvの導入
導入済みの場合は、次へどうぞ!
pyenvを導入します。
$ brew install pyenv $ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile $ exec $SHELL -l
Python仮想環境の作成
Pythonをインストールします。すでにある場合は次へ。
$ pyenv install 3.7.2
pipenvを導入します。すでにある場合は次へ。
$ pip install pipenv
Python仮想環境を作成します。
$ pipenv install --python 3.7.2
Python仮想環境に入ります。
$ pipenv shell
AWS CLIの導入
$ pipenv install awscli
これで、AWS CLIが使えるようになりました!
ついでに、.gitignore
も更新しておきます。
$ echo ".venv" >> .gitignore
AWS認証情報のセットファイルを作成
$ mkdir scripts $ touch scripts/set_aws.sh $ chmod 755 scripts/set_aws.sh
set_aws.sh
の内容は下記とします。AWS CLIを使うための環境変数を設定します。
#!/bin/bash # https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-envvars.html echo AWS ENV setting: $1 export SYSTEM_ENV=$1 export AWS_DEFAULT_REGION="ap-northeast-1" export AWS_DEFAULT_OUTPUT="json" if [ $1 = "dev" ]; then export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID_DEV export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_DEV else export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID_PROD export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_PROD fi
CircleCI用の設定ファイルを作成
.circelci
ディレクトリを作成し、その中にconfig.yml
を作成します。
$ mkdir .circleci $ touch .circleci/config.yml
続いて、config.yml
ファイルを下記にします。
CircleCI用のユーザー作成
ローカルにて、スタック指定しつつcdk deploy
を実行してユーザーを作成します。
$ SYSTEM_ENV=dev cdk deploy AWS-CDK-CircleCI-Deploy-Sample-User-Stack-dev $ SYSTEM_ENV=prod cdk deploy AWS-CDK-CircleCI-Deploy-Sample-User-Stack-prod
AWS認証情報の取得(アクセスキーIDとシークレットキー)
まずは、開発環境用のユーザです。忘れないようメモしておきます。
$ aws iam create-access-key --user-name aws-cdk-circleci-deploy-user-dev { "AccessKey": { "UserName": "aws-cdk-circleci-deploy-user-dev", "AccessKeyId": "aaaaa", "Status": "Active", "SecretAccessKey": "bbbbb", "CreateDate": "2019-08-19T03:59:42Z" } }
続いて、本番環境用のユーザです。同じくメモしておきます。
$ aws iam create-access-key --user-name aws-cdk-circleci-deploy-user-prod { "AccessKey": { "UserName": "aws-cdk-circleci-deploy-user-prod", "AccessKeyId": "ccccc", "Status": "Active", "SecretAccessKey": "ddddd", "CreateDate": "2019-08-19T03:59:57Z" } }
リポジトリのPush
ここまでの内容をmasterブランチ
にコミットし、pushしておきます。
$ git add . $ git commit -m "create sample" $ git push origin master
CircleCIの設定
ここから先は、Web画面で行います。
ログイン
CircleCIにログインします。
CircleCIのプロジェクトを作成
「ADD PROJECT」を選択し、さきほどGitHubにPushしたリポジトリを選択します。
続いて、「Start building」を選択します。
初めてのジョブが走りますが、AWS関連の環境変数が未設定なので失敗します。
環境変数の設定
プロジェクト一覧の設定マークを押し、設定画面に移ります。
Environment Variables
を選択します。
次の環境変数を追加します。
Name | Value |
---|---|
AWS_ACCESS_KEY_ID_DEV | 取得したAccessKeyId(開発用) |
AWS_ACCESS_KEY_ID_PROD | 取得したAccessKeyId(本番用) |
AWS_SECRET_ACCESS_KEY_DEV | 取得したSecretAccessKey(開発用) |
AWS_SECRET_ACCESS_KEY_PROD | 取得したSecretAccessKey(本番用) |
CircleCIでデプロイする!
開発環境にデプロイ
さきほど失敗したWorkflowsの「Return」を選択し、そこの「Return from failed」を選択します。
再びデプロイが始まり、しばらくすると成功します!!! (ブラウザによっては自動更新してくれないため、手動更新してください)
本番環境にデプロイ
タグを付けて、そのタグをPushします!
$ git tag v1.0.0 $ git push origin v1.0.0
CircleCIによる本番環境へのデプロイが始まり、しばらくすると完了します!!!
動作確認
開発環境
WebAPIのエンドポイントを取得します。
$ aws cloudformation describe-stacks \ --stack-name AWS-CDK-CircleCI-Deploy-Sample-App-Stack-dev \ --query 'Stacks[].Outputs' [ [ { "OutputKey": "sampleapiEndpoint1234", "OutputValue": "https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/" } ] ]
適当にWebAPIを叩きます。
$ curl https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/message/aiueo {"env":"dev","message":"your request message id is aiueo"}
OKですね!
本番環境
同じく、WebAPIのエンドポイントを取得します。
$ aws cloudformation describe-stacks \ --stack-name AWS-CDK-CircleCI-Deploy-Sample-App-Stack-prod \ --query 'Stacks[].Outputs' [ [ { "OutputKey": "sampleapiEndpoint1234", "OutputValue": "https://yyyyy.execute-api.ap-northeast-1.amazonaws.com/prod/" } ] ]
適当にWebAPIを叩きます。
$ curl https://yyyyy.execute-api.ap-northeast-1.amazonaws.com/prod/message/kakikukeko {"env":"prod","message":"your request message id is kakikukeko"}
こちらもOKですね!
AWSの様子
ブラウザでログインして、それぞれの様子を確認しました。バッチリです!
CloudFormation
API Gateway
Lambda
さいごに
慣れない部分もあって手こずりましたが、実現できました。
まだまだ荒削りなので、ブラッシュアップしつつ、もっと活用していきたいです。
参考
- AWS Cloud Development Kit (AWS CDK)
- AWS CDK Tools
- API Reference
- AWS CDK Tools
- CircleCI と GitHub で AWS SAM のサーバーレスアプリを自動デプロイしてみた (開発環境 & 本番環境) | Developers.IO
- [AWS CDK] スタック名に本番環境と開発環境の名前を含めて、それぞれデプロイしてみた | Developers.IO
- AWS CDK が GA! さっそく TypeScript でサーバーレスアプリケーションを構築するぜ【 Cloud Development Kit 】 | Developers.IO