GitLabからWebhookでTekton Pipelineを実行する
前回構築したTekton
と
Helmで構築したGitLab
を連携させてみます。
全てオンプレで構築したセルフマネージドな環境です。
やりたいこと
GitLabのpushイベントをトリガーにTektonのEventListenerにwebhookを送信します。
そのwebhookをトリガーにGitLabからDockerfileをcloneしてbuild、その後GitLabと連携しているprivate container registryにビルドしたイメージをpushするパイプラインを実行します。
公式ドキュメントのHow-to Guides に git cloneやコンテナビルドやプッシュの手順が紹介されているのでこれを参考にします。
GitLab側の準備
今回テスト用にtekton-testというプロジェクトを作成しました。
リポジトリ直下に以下のDockerfileだけプッシュしておきます。
内容はタイムゾーンを変えているだけです。
FROM nginx:latest
ENV TZ Asia/Tokyo
RUN echo "${TZ}" > /etc/timezone \
&& dpkg-reconfigure -f noninteractive tzdata
また、前回構築時は有効化していませんでしたが、今回GitLabでContainer Registryを使えるようにしました。
認証情報の作成
Tektonのタスク内でgit cloneやdocker pullするために認証情報が必要となります。
今回はひとまずGitLabのrootユーザーで認証しようと思います。
git clone
の認証方法はいくつかあるようですが、
ガイドと同じssh-directoryで認証してみます。
鍵を作成します。
ubuntu@k8s1:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ubuntu/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ubuntu/.ssh/id_rsa
Your public key has been saved in /home/ubuntu/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:JjmEBeWbkzewCYvZQOXhJ4ZfaWrBILZfVIxOgUwCP40 ubuntu@k8s1
The key's randomart image is:
+---[RSA 3072]----+
|+o=o==B. |
|.+o@.B o |
| .E &.O |
| .O.% O |
| o.* @ S |
| . * . |
| |
| |
| |
+----[SHA256]-----+
公開鍵をGitLabのrootユーザーに登録します。
ubuntu@k8s1:~$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCVpofTvETduq9g/L2n9zmn9mfHyZXtd4IbUaY2Gq8JFsDi+zPmgaJ1u75XHzyD5HBktG7xFWvmFmLt77Wq7pWhNAuZz9+hG6d8PyxfrhfP7eTe7i17VswwgMr+RQ96CKzlyU4bMZaFNNKafA0tpPML1pe4+LTxX669vZDpBs204l4IQNHK5uREyaQHp06JODnVgKcxCb2Z2QbI75aXZ3/G/mFypFDGOv7wv/mF+G83blEZiZ/LRJJq4B2tcI7BKvgWyo0r5S2NXsU34FSkxEymUPwkH6+YMZ7hiTE/UY9mKT2TpXYL8JolvpdkDTlgDc4/+VOTTFNxQzDPAYA5Hx+oFtemWKOR7nRbRUw2Rbbd611ll4P+zKlYxXDXBqsNTuYL9PT01gz9u9jGDARz3wUxVtemr7SQDwAFGCfMFz8UxsqALUup/Ihu0/YSTQFXIjVeIV949dY2Otm2YCSHM5x9mnfv3UtLs6XGAH7WeRQT7LIQStTOXQ71UxqNUIAD/+8= ubuntu@k8s1
configファイルを.sshディレクトリに作成します。
ubuntu@k8s1:~$ cat .ssh/config
Host gitlab.example.tsuchinokometal.com
HostName gitlab.example.tsuchinokometal.com
IdentityFile ~/.ssh/id_rsa
User root
接続テストをします。
ubuntu@k8s1:~$ ssh -T git@gitlab.example.tsuchinokometal.com
The authenticity of host 'gitlab.example.tsuchinokometal.com (192.168.0.225)' can't be established.
ECDSA key fingerprint is SHA256:WVrpzH92P+iSYjYrUX5RayZymxlf+c/FWlgmrm6e+ik.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'gitlab.example.tsuchinokometal.com,192.168.0.225' (ECDSA) to the list of known hosts.
Welcome to GitLab, @root!
ubuntu@k8s1:~$ ll .ssh/
total 28
drwx------ 2 ubuntu ubuntu 4096 Sep 24 16:00 ./
drwxr-xr-x 13 ubuntu ubuntu 4096 Sep 24 10:56 ../
-rw------- 1 ubuntu ubuntu 574 Sep 24 16:00 authorized_keys
-rw-rw-r-- 1 ubuntu ubuntu 127 Sep 23 17:45 config
-rw------- 1 ubuntu ubuntu 2590 Sep 24 11:00 id_rsa
-rw-r--r-- 1 ubuntu ubuntu 565 Sep 24 11:00 id_rsa.pub
-rw-r--r-- 1 ubuntu ubuntu 444 Sep 24 11:44 known_hosts
ファイルが揃ったのでsecretを作成します。
今回tekton-testというNamespaceでパイプラインを作成します。
ubuntu@k8s1:~$ kubectl create ns tekton-test
namespace/tekton-test created
ubuntu@k8s1:~$ kubectl create secret generic --save-config git-credentials --from-file=.ssh/id_rsa --from-file=.ssh/known_hosts --from-file=.ssh/config -n tekton-test
secret/git-credentials created
次にContainer Registry用の認証情報を作成します。
こちらもガイドと同じくconfig.jsonを利用します。
ubuntu@k8s1:~$ docker login registry.example.tsuchinokometal.com
Username: root
Password:
WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
ubuntu@k8s1:~$ kubectl create secret generic --save-config docker-credentials --from-file=.docker/config.json -n tekton-test
secret/docker-credentials created
ubuntu@k8s1:~$ kubectl get secret -n tekton-test
NAME TYPE DATA AGE
docker-credentials Opaque 1 40s
git-credentials Opaque 3 61s
Tekton pipelineの準備
まずTekton hubから
git-clone
と
kaniko
の
Taskをインストールします。
kanikoはコンテナの中でコンテナイメージをビルドすることができるツールらしいです。
$ kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.6/git-clone.yaml -n tekton-test
task.tekton.dev/git-clone created
$ kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/kaniko/0.6/kaniko.yaml -n tekton-test
task.tekton.dev/kaniko created
$ tkn task list -n tekton-test
NAME DESCRIPTION AGE
git-clone These Tasks are Git... 32 seconds ago
kaniko This Task builds a ... 11 seconds ago
次にこれらのタスクを実行するパイプラインを作成します。
workspaceに先ほど作成したgitとdockerの認証情報をマウントしています。
pipeline.yaml
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: clone-build-push
namespace: tekton-test
spec:
description: |
This pipeline clones a git repo, builds a Docker image with Kaniko and
pushes it to a registry
params:
- name: repo-url
type: string
- name: image-reference
type: string
workspaces:
- name: shared-data
- name: git-credentials
- name: docker-credentials
tasks:
- name: fetch-source
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-data
- name: ssh-directory
workspace: git-credentials
params:
- name: url
value: $(params.repo-url)
- name: build-push
runAfter: ["fetch-source"]
taskRef:
name: kaniko
workspaces:
- name: source
workspace: shared-data
- name: dockerconfig
workspace: docker-credentials
params:
- name: IMAGE
value: $(params.image-reference)
テストのために手動実行用のpipelinerunを作ります。
workspaceのボリュームを動的プロビジョニングしたいため、longhornをインストールしました。
gitリポジトリやdocker registryのURLはここで指定しています。
pod内で名前解決できるようにしてください。
pipelinerun.yaml
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: clone-build-push-run-
namespace: tekton-test
spec:
pipelineRef:
name: clone-build-push
podTemplate:
securityContext:
fsGroup: 65532
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: longhorn
- name: git-credentials
secret:
secretName: git-credentials
- name: docker-credentials
secret:
secretName: docker-credentials
params:
- name: repo-url
value: git@gitlab.example.tsuchinokometal.com:root/tekton-test.git
- name: image-reference
value: registry.example.tsuchinokometal.com/root/tekton-test/my_nginx:latest
リソースを作成します。
pipelinerunを作成すると指定したパラメータでパイプラインが実行されます。
$ kubectl apply -f pipeline.yaml
pipeline.tekton.dev/clone-build-push created
$ kubectl create -f pipelinerun.yaml
pipelinerun.tekton.dev/clone-build-push-run-4bsm7 created
無事パイプラインが走り切りました。
Container Registryにイメージもpushされています。
良さそうですね!
リソースを確認すると以下が作成されていますね。
これらはpipelinerunを削除すると合わせて削除されます。
$ kubectl get pod,pv,pvc -n tekton-test
NAME READY STATUS RESTARTS AGE
pod/clone-build-push-run-4bsm7-build-push-pod 0/2 Completed 0 10m
pod/clone-build-push-run-4bsm7-fetch-source-pod 0/1 Completed 0 11m
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pvc-ae42b42e-18d8-41e2-878e-7229c427061f 1Gi RWO Delete Bound tekton-test/pvc-379cd0b737 longhorn 11m
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc-379cd0b737 Bound pvc-ae42b42e-18d8-41e2-878e-7229c427061f 1Gi RWO longhorn 11m
Tekton Triggerの準備
Webhookからパイプラインを実行するためにTriggerリソースを作成します。
まずEventListenerからTektonリソースを作成するためのサービスアカウントを準備します。
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-trigger
namespace: tekton-test
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: role-trigger
namespace: tekton-test
rules:
- apiGroups:
- triggers.tekton.dev
resources:
- eventlisteners
- triggers
- triggerbindings
- triggertemplates
- interceptors
verbs:
- get
- list
- watch
- apiGroups:
- tekton.dev
resources:
- pipelineruns
- pipelineresources
verbs:
- create
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: triggers-role-binding
namespace: tekton-test
subjects:
- kind: ServiceAccount
name: sa-trigger
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: role-trigger
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: clusterrole-trigger
rules:
- apiGroups: ["triggers.tekton.dev"]
resources: ["clustertriggerbindings", "clusterinterceptors"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: clusterbinding-trigger
subjects:
- kind: ServiceAccount
name: sa-trigger
namespace: tekton-test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: clusterrole-trigger
$ kubectl apply -f sa-tekton-test.yaml
serviceaccount/sa-trigger created
role.rbac.authorization.k8s.io/role-trigger created
rolebinding.rbac.authorization.k8s.io/triggers-role-binding created
clusterrole.rbac.authorization.k8s.io/clusterrole-trigger created
clusterrolebinding.rbac.authorization.k8s.io/clusterbinding-trigger created
次にTrigger関連のリソースを作成します。
resourcetemplatesで先ほど手動で実行したPipelineRunを定義しています。
これrefできないんですかね。
ちなみにTriggerBindingでパラメータ指定していますが、使ってません。
とりあえず書いただけです。
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerTemplate
metadata:
name: template-tekton-test
namespace: tekton-test
spec:
params:
- name: gitrevision
description: The git revision
default: master
resourcetemplates:
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
generateName: clone-build-push-run-
namespace: tekton-test
spec:
pipelineRef:
name: clone-build-push
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: longhorn
- name: git-credentials
secret:
secretName: git-credentials
- name: docker-credentials
secret:
secretName: docker-credentials
params:
- name: repo-url
value: git@gitlab.example.tsuchinokometal.com:root/tekton-test.git
- name: image-reference
value: registry.example.tsuchinokometal.com/root/tekton-test/my_nginx:latest
---
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
name: binding-tekton-test
namespace: tekton-test
spec:
params:
- name: gitrevision
value: $(body.head_commit.id)
---
apiVersion: triggers.tekton.dev/v1alpha1
kind: EventListener
metadata:
name: tekton-test
namespace: tekton-test
spec:
serviceAccountName: sa-trigger
triggers:
- name: trigger-tekton-test
bindings:
- ref: binding-tekton-test
template:
ref: template-tekton-test
gitlab interceptorを使おうとしましたが、なぜか自己証明書エラーが発生してうまくいきませんでした。
リソースを作成します。
$ kubectl apply -f trigger-tekton-test.yaml
triggertemplate.triggers.tekton.dev/template-tekton-test created
triggerbinding.triggers.tekton.dev/binding-tekton-test created
eventlistener.triggers.tekton.dev/tekton-test created
EventListenerを作成するとclusterIPのServiceが自動的に作成されていると思います。
$ kubectl get svc -n tekton-test
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
el-tekton-test ClusterIP 10.43.194.40 <none> 8080/TCP,9000/TCP 7m11s
EventListenerが正常に稼働できているかどうかはtknコマンドでも確認できます。
$ tkn el list -n tekton-test
NAME AGE URL AVAILABLE
tekton-test 7 minutes ago http://el-tekton-test.tekton-test.svc.cluster.local:8080 True
このままでは外部からアクセスできないので、ingressで公開します。
$ cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tekton-test
namespace: tekton-test
spec:
rules:
- host: tekton-test.domain.tld
http:
paths:
- pathType: ImplementationSpecific
backend:
service:
name: el-tekton-test
port:
number: 8080
$ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/tekton-test created
以下のようになりました。
GitLab側で名前解決できるようにする必要があります。
$ kubectl get ingress -n tekton-test
NAME CLASS HOSTS ADDRESS PORTS AGE
tekton-test nginx tekton-test.domain.tld 192.168.0.52,192.168.0.53 80 22s
webhookからpipelineを実行する
では、GitLabからwebhookを飛ばしてみます。
Ingressで指定したhostを指定します。
gitlab interceptorを使えばここで指定したシークレットトークンで検証することができます。
作成後、テスト実行します。
ひとまず以下のメッセージが表示されればOKです。
Hook executed successfully: HTTP 202
もし以下のメッセージが表示されたらAdmin areaのネットワーク設定の
Outbound requestsでローカルネットワークを許可してください。
Url is blocked: Requests to the local network are not allowed
Dashboardで実行できているか確認します。
良さそうですね!
Kubernetesカスタムリソースでパイプラインをyaml管理できるのはいいですね。