この記事は WESEEK Advent Calendar 2020 21日目の記事です。
こんにちは! WESEEK, Inc. で長期インターンをさせていただいております [yamagai] (https://twitter.com/yamagai_0919)と申します。
前回は 今日から始めるKubernetes-nativeなGitOps【CI編 ~pipeline構築~】を書きましたが、
今回は Tekton Triggers を使った Webhook の設定について書きます。
前回に引き続き、CI/CDを導入する対象のプロジェクトはフロントエンドが Next.jsでバックエンドが Rails のアプリです。
フロントエンドとバックエンドは一つのリポジトリにまとめています。
参考リポジトリ
こちらも、前回に引き続き以下のリポジトリを使います。
-
CIを使用するプロジェクトのリポジトリ
- https://github.com/bamboooo-dev/alcatraz
- /api 以下がバックエンドで、/ui 以下がフロントエンド
-
今回使用する CI の設定を書いたマニフェストのリポジトリ
-
アプリのマニフェストリポジトリ
Tekton Triggers を用意する
インストール
- 公式ドキュメント
前提
- Tekton Pipelineの導入が済んでいる
インストールは以下のコマンド
kubectl apply --filename https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
入っているようですね
(⎈ |jukai:tekton-pipelines)❯ kubectl get pod
NAME READY STATUS RESTARTS AGE
image-pipelinerun-api-image-build-push-ppvzp-pod-cvd4z 0/4 Completed 0 46h
image-pipelinerun-ui-image-build-push-crj7d-pod-ckwhb 0/4 Completed 0 46h
tekton-dashboard-6bdbc955c6-crfpt 1/1 Running 0 2d22h
tekton-pipelines-controller-6486ffc547-7xnwl 1/1 Running 0 2d22h
tekton-pipelines-webhook-77d7486ddf-hscxk 1/1 Running 0 2d22h
tekton-triggers-controller-dc77dfb98-mwkj2 1/1 Running 0 2d
tekton-triggers-webhook-856b74b94d-qd8mj 1/1 Running 0 2d
Tekton Triggers の概念を理解する
Tekton Pipeline にもPipelineRun
などの複数のカスタムリソースがありましたが、Tekton Triggers にもいくつかカスタムリソースがあります。
使い始める前にそれらの概念を説明します。
TriggerTemplate
trigger された時に実行する PipelineRun と pipeline で使用する params を指定するカスタムリソース
TriggerBinding
Trigger に渡す params (TriggerTemplate 内の spec.params で設定した params の値) を記述するカスタムリソース
namespace の設定は必須
EventListener
TriggerTemplate と TriggerBinding を結びつけるカスタムリソース
これが作成されると、リクエストを受け付ける Service が作成される仕組み
作成された Service が Github Push events などを受け付けて、TrigggerTemplate に基づき Pipeline を実行する
(引用元: https://github.com/tektoncd/triggers/tree/master/docs)
Webhook を設定する
trigger側の設定
以下の三つのカスタムリソースはリポジトリのここで定義しています。
TriggerTemplate と TriggerBinding については特に注意点はありませんが、EventListener についてはオプションがあるので利用しましょう。
こちらのドキュメントにある通り、
spec:
resources:
kubernetesResource:
serviceType: NodePort
このようにすることで EventListener により作成される Service の Type が指定できます。
今回はNodePort
として作成しましょう。
上記のマニフェストを適用すると以下のように Service が作成されます。
(⎈ |jukai:tekton-ci)❯ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
el-alcatraz-tekton-listener NodePort 10.43.84.50 <none> 8080:32640/TCP 134m
32640番ポートが開いたみたいですね。
github webhook の設定
次は Github 側の設定をしましょう。
リポジトリの [Settings] → [Webhooks] から Add webhook を選択しましょう。
それでは、今回は
Payload URL → http://(ノードのIPアドレス):(ポート番号)
Content Type → application/json
として webhook は push イベントごとにしておきましょう。
これで webhook の設定は完了です!
動作確認
それでは、ブランチの push により PipelineRun
が実行されるかどうかを見ていきましょう。
まずは、Tekton Dashboard をブラウザから見られるようにしましょう。
(⎈ |jukai:tekton-pipelines)❯ kubectl port-forward svc/tekton-dashboard 9097:9097 -n tekton-pipelines
次に push です。
~/bamboooo/alcatraz tekton-test*
(⎈ |jukai:tekton-ci)❯ git add .
~/bamboooo/alcatraz tekton-test*
(⎈ |jukai:tekton-ci)❯ git commit -m "tekton test"
[tekton-test bbbb189] tekton test
1 file changed, 1 insertion(+), 1 deletion(-)
~/bamboooo/alcatraz tekton-test
(⎈ |jukai:tekton-ci)❯ git push origin tekton-test
Enumerating objects: 15, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 4 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (8/8), 640 bytes | 320.00 KiB/s, done.
Total 8 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4), completed with 4 local objects.
remote:
remote: Create a pull request for 'tekton-test' on GitHub by visiting:
remote: https://github.com/bamboooo-dev/alcatraz/pull/new/tekton-test
remote:
To github.com:bamboooo-dev/alcatraz.git
* [new branch] tekton-test -> tekton-test
PipelineRun
で設定した name の後ろにハッシュがくっ付いた名前の PipelineRun が実行されていますね!
成功です。
webhook イベントのフィルタリング
ただ、これだとどのブランチが push されても image の build & push が実行されてしまいます。
そこで main ブランチの push時のみに実行されるように設定していきましょう。
Tekton にはInterceptor
という、EventListener がイベント受信時にリクエストに対してフィルターを行う機能が存在しているのでこれを使っていきましょう!
今回はCEL Interceptorを使用していきます。
triggers:
- bindings:
- ref: alcatraz-tekton-pipelinebinding
template:
ref: alcatraz-tekton-triggertemplate
interceptors:
- cel:
filter: body.ref == "refs/heads/main"
上記のように EventListener のマニフェストの spec.triggers
以下に interceptors
を追加しました。
これにより main ブランチの時のみ PipelineRun が実行されるはずです。見てみましょう。
先ほどの tekton-test ブランチを main ブランチにマージする pull request を作成しました。
これがマージされたら PipelineRun が実行されるはずです。
interceptor
ではなくinceptor
になっているのと、github actions が落ちているのは気にしないでください。
おおっ、PipelineRun が走っていますね、成功です。
ただ何やらエラーになっていますね...
これはまた別の記事で紹介しようと思います。
ちなみに、よりセキュアにするなら GitHub Interceptors を使って Secret に設定してあるのと同じアクセストークンを持つリクエストの場合だけ実行するように設定することも可能です。
最後に
今回は、Tekton Triggers と Webhook の設定をしてブランチのpush時に image の build と push が実行されるようにしていきました。
実はこれだと、フロントとバックエンドが一つのリポジトリにまとまっているために main ブランチの push 時にフロントのイメージもバックエンドのイメージも毎回 push されてしまうという状態です。
フロントとバックエンドのリリースサイクルを揃えざるをえないことになってしまうのはよろしくないので余裕があれば次回の記事で改修してみようと思います。
また次回の記事では、Pipeline にマニフェストリポジトリにイメージタグを更新する pull request を送る task を追加し、それがマージされ次第CDされるようにしていきましょう。
※この記事は WESEEK Tips wiki に 2020/12/21 に投稿された記事の転載です。
Tips wiki では、IT企業の技術的な情報やプロジェクトの情報を公開可能な範囲で公開しています。