Kpackのイメージ作成完了をGithubに通知するKubernetes Controllerを実装してみた
ソースコードのコミットしたあとに Kpackでのイメージが作成完了したのかわかりにくい!と思ったので、通知機能をKubernetesのControllerを使って実施しました。
ソースコード
出来上がったものはここにあるよ。
https://github.com/mhoshi-vm/kpack-gh-status-updater
まずは用語の説明から
以下この記事で登場する用語です。
- kpack:
Cloud Native Buildpacks を使い、ソースコードからイメージ作成およびStack/StoreやビルドパックをKubernetesのCustom Resource Definition(CRD)経由で管理するツールです。 - Kubernetes Controller:
KubernetesでCRDに対して何かイベントが発生したときに、特定の操作をおこなうことができるものです。今回はこれをJavaのSpring Bootで実装しました。 - Github Commit Status:
Githubのコミットごとに何かのチェックが発生させ、そのステータスをみることができます。通常はCIパイプラインの成功可否を表示するものですが、RestAPI経由で直接アップデートできます。詳細は、こちら
この中で、Kubernetes Controller、特にそれをJavaのフレームワーク、Springで実装するのが理解の難易度が高いと思います。
以下のSpringOneのコンテンツからかなり流用しているので、時間があればみていただくこととより理解ができます。
https://www.youtube.com/watch?v=5IROOj7sLKg
何を解決したかったか?
以下がkpackで今回の成果物なしのイメージ図です。kpack自体は素晴らしいツールなのですが、ソースコードのコミットをしたときに、イメージが作成が問題なくできたかどうかは、いちいち、Kubernetesのリソースのステータスを確認しにいく、というオペレーションが必要でした。
ちなみに、ビルドの状態は以下の感じです。
ほしい情報も詳細な情報ではなく、成功したか、否か程度でした。 何かポーリングするようなスクリプトをつくってもいいのですが、もっとイベント駆動型、可能な限りリアルタイムがほしく、これをKubernetes Controllerとして実装してみようと考えてみました。
以下の図のイメージへの更新です。Githubだけみていれば、イメージが完了したかいなかをみれるようにしてみました。
完成したもの
特定のコミットでkpackのビルドが開始すると、以下のイメージでビルド中なのがわかります。
特定のコミットでkpackのイメージが完了すると、この感じで反映されます。
失敗すると、以下のようになって、「あー、失敗したな、みにいかなきゃ」となる感じです。
ソースコード開発風景
「Spring BootでKubernetes Controller!?」な人もいると思うので開発方法を紹介します。
1. pom.xml にKubernetes Clientの登録
mavenでビルドしていますが、pom.xml は start.spring.ioで作るようなシンプルなものです。Kuberetes Clientの依存関係だけ手動で追加します。
2. CRDのYAMLファイルを作成する
Kubernetes Controllerを作る上で最初に開発するのが、KubernetesのCRDの定義YAMLファイルを作成します。 今回は以下のように開発しています。
https://github.com/mhoshi-vm/kpack-gh-status-updater/blob/main/k8s/crd/build.yaml
ちなみに、kpackそのもののCRD定義は以下です。
https://github.com/pivotal/kpack/blob/main/config/build.yaml
比べるとわかるのですが、だいぶ違います。元のkpackがスキーマにあまり値を定義していないのですが、このままだと後続の手順で、困るので必要な箇所は自分で定義しています。
3. CRDからCodeGenしてModelを生成する
CRDを定義後以下のようなGithub Actionsを使って構成します。オフィシャルガイドはこちらに。
私はGithub Actionsの方式でやっており、以下のように定義しています。
https://github.com/mhoshi-vm/kpack-gh-status-updater/blob/main/.github/workflows/generate-crd.yaml
この状態で先ほどのCRDをインプットに定義するとModelが含まれたZipファイルが生成されます。 それをほぼそのまま状態で展開したのが以下です。
このディレクトリのこれらのファイルです。
4. Controllerの定義
このフェーズはほぼ「呪文」です。言われた通りにつくったものが以下です。
細かいところで、手順3. で作成したModelに一部向く必要がありますが、それ以外はここで大差になることは少ないようです。
5. Reconcilerの定義
Reconciler の定義です。
基本的には @Override
部にビジネスロジックを書き加えます。注意が必要なところが以下であり、
- 最終的な実行結果は、正常終了の場合、
new Result(false)
という結果を返し、処理がかんりょうしたことを通知します。Result(true)
を返すとイベントがキューされ直されてしまいます。 - イベントに通知されたリソースが存在しない場合は、「削除された」と解釈します。なのでその処理をいれます。
- 何かのリソースを
get
するたびに、存在するかしないかのチェックを入れるように。
6. ビジネスロジック(Github通知)をうめる
ここまでくれば、ただのJavaのコードです。この行からGithubのステータス更新の処理をかきます。
7. Kubernetes環境にデプロイする
出来上がったコードをコンテナ化したら(ここでまさにkpackを利用)これをKubernetes環境にデプロイします。YAMLファイルはここにあります。
Role権限でCRDに正しくアクセスできるように設定が必要なので注意が必要です。私の場合は、2.で定義したBuild Resourceにアクセスします。
結論
簡単ですが、Kubernetes Controller をつかってGithubの通知方法を紹介しました。Kubernetes Controllerが手慣れたSpringで開発できたことでグッと導入難易度が下がった印象です。
コード自体はまだまだアップデートするつもりですし、その他の応用にも使っていきます。