GitHub Actions で AWS CDK
はじめに
AWS Advent Calendar 2019 - Qiita の 10日目への寄稿です。
AWS CDK が 2019年7月11日に、 GitHub Actions が 2019年11月14日にそれぞれ GAと なりました。 qiita.com のようにGitHub へクレデンシャルを登録しておけば、 GitHub Actions を使って CDK によるCloudFormation Stack の構築が出来るのでは無いか?と思い立ったので試してみました。 今回はPythonで記述してみようと思います。
環境構築
GitHub Actions では、Docker コンテナーを使うということで CDK 入りの軽量なコンテナーとなる Dockerfile を github.com 作りました。 そして、CDK を使って CloudFormatuon Stac kを構築するためのコードと、それを動かす GitHub Workflow は GitHub - poad/Advent に置いています。 リポジトリーを分けた方が理解しやすいこともあって分けています。
そもそも Action と Workflow って何?
GitHub Actions では、Action と呼ばれる機能を作成したり、既に用意されている Action を Workflow から呼び出して CI/CD を行います。
Action
後述する Workflow から呼び出して実行するための機能。 Docker コンテナー上で実行される。 action.yml で定義する。
Workflow
前述した Action をパラメーターと共に順に実行していく手順をYAMLで記述したもの。 .github/workflows/main.yml で定義する。
CodePipeline との比較
ざっくりとCodePipeline と比較してみます。
CodePipeline | GitHub Actions | |
---|---|---|
GitHub との親和性 | △ | ◎ |
AWS との親和性 | ◎ | △ |
単発実行 | ○ | × |
※ 上記評価はあくまでも個人的な主観です
GitHub との親和性
CodePipeline では、GitHub のリポジトリーとブランチしか指定出来ません。 一方、GitHub Actions では、リポジトリーとブランチの組み合わせ以外にも、リポジトリーとタグの組み合わせを指定できるほか、 push 以外を起動トリガーと出来ます。
AWS との親和性
当然ながら、CodePipeline であれば CloudFormation や ECS など、様々なサービスのデプロイを既存の Action として指定できます。 また、GitHub Actions はAWSのクレデンシャルを使用して AWS CLI や AWS CDK を使用します。 IAM ロールなどを絞りたい場合に専用の IAM ユーザーを作成して絞る必要があります。 一方、CodePipeline では、CodePipeline 自体やそこから呼び出す AWS のサービス向けの IAM ロールを CodePipeline 毎に作成・指定することが出来ます。
単発実行
GitHub Actions では、リポジトリーへの push などを行わないと実行できません。 同じコード、設定で 再デプロイしたい場合に実行する方法がなさそうです。
Action を作ってみる
実は、AWS CDK GitHub Actions · Actions · GitHub Marketplace · GitHub として既に CDK を使うための GitHub Actions があります。 そのまま使用すればいいのですが、それでは記事にならないどころか、必要となった場合に作り方が分からなくなります。
そこで、上記のActionを参考に自分で作ってみます。
Dockerfile
alpine:3
に npm
と python3
、pip
、awscli
、cdk
をインストールします。
entrypoint.sh として、CDK のコードで使用する Python module のインストールを行い、
workflow で指定された各サブコマンドを実行するシェルスクリプトを ENTRYPOINT とします。
action.yml
Action の定義を行います。
action.yml のシンタックスは Metadata syntax for GitHub Actions - GitHub Help
workflow を作る
.github/workflows/main.yml
を作ります。 main.yml
以外に YAML ファイルを置いた場合にどう動くのかは試してません。
先述したとおり、ビルドやデプロイなど、どういった作業の流れなのかを定義したファイルです。
その名の通りですね。
ちなみに、シンタックスは Workflow syntax for GitHub Actions - GitHub Help
step が CodePipeline の Actionのような位置づけで、uses で GitHub Action を指定して with で指定したパラメーターが、 INPUT_
プレフィックスが付いて、大文字化された値が環境変数としてActionのDockerコンテナーに渡されます。
なので、例えば
cdk_subcommand
→ INPUT_CDK_SUBCOMMAND
となります。
今回は、 working_dir
で指定した相対パスとなるように cdk init
を行っている点がポイントです。
これを、workflow でビルドやデプロイしたいリポジトリーへ push します。
cdk init/CDK を使うコードの作成
ここに関しては、特にこの記事のテーマとしては特記することはありません。
ただ単に、CDK が動く環境で以下のコマンドを実行するだけです。
今回は、 cdk init
で作られる CloudFormation Stack が作られれば良いため、特に Python のコードの追加・変更・削除は行っていません。
cdk init --language python
苦労した点
GitHub Actions という名前の紛らわしさ
Action 定義あっての workflow と勘違いしてしまう。。。
GitHub Workflow なら、やりたい目的を達成するために Action という部品を組み合わせて workflow で処理するんだとわかりやすいと思うのですが、
個々の Action がメインのようなサービス名なのがイマイチ。
Action が使いたいのではなくて、ビルドしたりデプロイしたりするのを自動化したいから、目的を達成するのに名前が非直感的かな?と。
些細なことですが、理解するのに苦労した理由の一つのように思えます。実は workflow やその中のAction で使うコード(ビルド・デプロイ対象) は clone する step が必要
actions/checkout@v1
という Action を指定した step があります。
これは、Action の Docker コンテナーが実行時にマウントする WORKSPACE の場所へ、
その workflow 定義がコミットされているリポジトリーの内容を clone するためのものです。
これが必要であると気づくまでが、最も時間を要しました。
workflow 定義と共に clone されているのですが、そのパスはマウントされないですし、
Action 定義でもマウント出来るようには出来なくて困りました。
まぁ、他のリポジトリーのコードがビルド対象です!と言った場合に、確かにその方が要らぬコードが混入しないので正しいかも。Docker のbest practice に従った対応を入れていると動かないことも
Docker コンテナー内で作業を行うユーザーが root でないと、ファイルアクセスのパーミッションが無くて動きません。 工夫すれば動くのかも知れませんが、流石にそこまでのメリットはなさそう。。。