Software development of explosion! -夢の破片(カケラ)たちの日々-

ソフトウェア開発を中心としたコンピューター関連のネタを扱ったブログです

Software development is passion and explosion!

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 CLIAWS 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:3npmpython3pipawsclicdk をインストールします。 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_subcommandINPUT_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 でないと、ファイルアクセスのパーミッションが無くて動きません。 工夫すれば動くのかも知れませんが、流石にそこまでのメリットはなさそう。。。

参考にしたサイト

qiita.com