- Tekton Trigger는 특정 Event를 WebHook을 통해 받아 등록된 Pipeline을 자동으로 실행시켜주는 컴포넌트이다
- WebHook이란 WebPage or WebApp에서 발생하는 Event( 특정 행동 ) 데이터를 다른 애플리케이션에게 실시간으로 제공하기 위한 방법이다
- 전체 구조는 위와 같다
- EventListener는 Pod로 동작한다. EventListener를 배포하면 Deploy와 SVC가 배포된다
- EventListener는 외부로부터 Event를 받아야 하므로, Ingress를 통해 EventListener Pod를 외부에 노출시켜야 한다
- GitHub에서 Event가 발생하면, EventListener Pod는 WebHook을 통해 Json payload를 Event로 받는다. 받은 Json payload를 내부의 Trigger에게 전달한다
- Trigger는 받은 Event를 검증 및 파싱하고, Trigger Binding에게 전달한다. Trigger는 Trigger Binding과 Trigger Template을 연결해준다
- Trigger Binding은 Trigger로부터 받은 Event 데이터를 연결된 Trigger Template의 파라미터와 매핑해준다
- EventListener Pod는 Trigger Template을 참고하여 PipelineRun을 생성한다. 이를 통해 Pipeline이 실행된다
- Pipeline이 실행되면, Pipeline의 Task들을 실행시키는 TaskRun Pod가 배포된다
참조 : https://github.com/tektoncd/triggers/tree/v0.8.1/examples/role-resources
apiVersion: v1
kind: ServiceAccount
metadata:
name: trigger-sa
namespace: hongspace
- EventListener가 동작하면서 Tekton 오브젝트 및 Kubernetes 오브젝트를 사용하기 위한 ServiceAccount를 생성하자
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: tekton-triggers-role
namespace: hongspace
rules:
# EventListeners need to be able to fetch all namespaced resources
- apiGroups: ["triggers.tekton.dev"]
resources: ["*"]
verbs: ["*"]
- apiGroups: [""]
# secrets are only needed for GitHub/GitLab interceptors
# configmaps is needed for updating logging config
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
# Permissions to create resources in associated TriggerTemplates
- apiGroups: ["tekton.dev"]
resources: ["pipelineruns", "taskruns"]
verbs: ["create"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["impersonate"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: tekton-triggers-clusterrole
rules:
# EventListeners need to be able to fetch any clustertriggerbindings
- apiGroups: ["triggers.tekton.dev"]
resources: ["clustertriggerbindings","clusterinterceptors"]
verbs: ["get","list","watch"]
- Role과 Cluster Role이 필요하다
- Trigger 리소스에 대해 모든 작업이 가능해야 한다
- Interceptors 사용 시, Repo 인증 작업을 위해 ConfigMap과 Secrets에 대해 조회가 가능해야 한다
- Pipeline을 실행해야 하므로, pipelineruns와 taskruns를 생성할 수 있어야 한다
- Impersonate는 다른 보안주체 ( ServiceAccount, User, Group )을 이용하여 Api 요청을 보낼 수 있게 하는 조작이다. 다른 ServiceAccount를 이용할 수 있게 해줘야 한다
- clustertriggerbindings과 clusterinterceptors에 대해 조회가 가능해야 한다
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tekton-triggers-clusterbinding
subjects:
- kind: ServiceAccount
name: trigger-sa
namespace: hongspace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: tekton-triggers-clusterrole
- ServiceAccount와 Role & ClusterRole을 Binding 해주자
참조 : https://tekton.dev/docs/triggers/
참조 : https://github.com/tektoncd/triggers/tree/release-v0.23.x/examples/v1beta1
- 쉽게 말해, EventListener에 들어온 Json Payload의 데이터를 TriggerTemplate의 파라미터로 사용할 수 있도록 매핑해주는 것이다
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerBinding
metadata:
name: hong-pb
namespace: hongspace
spec:
params:
- name: imagetag
value: $(body.head_commit.id)
- name: giturl
value: $(body.repository.url)
- TriggerBinding을 정의하자
- image tag는 Json Payload에 들어있는 Commit 번호를 이용하여, Build할 Image의 Tag를 지정하기 위한 파라미터이다
- giturl은 Json Payload에 들어있는 Repo url을 이용하여, Clone할 Repo 주소를 지정하기 위한 파라미터이다
- 실제 PipelineRun을 생성해주는 것은 EventListener Pod이다. TriggerTemplate과 TriggerBinding을 참고하여 PipelineRun을 생성한다
apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
name: hong-tt
namespace: hongspace
spec:
params:
- name: giturl # git repo url
- name: imagetag # image tag in commit message
resourcetemplates: # automate create pipelinerun
- apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
namespace: hongspace
generateName: hong-cicd-run-
spec:
serviceAccountName: build-bot # sa for git & docker credientials -> pipeline will use for clone private repo
pipelineRef: # select pipeline
name: hong-cicd
podTemplate: # setting taskpod
securityContext: # pod security
fsGroup: 65532 # set volume owner gid = 65532
workspaces: # volume for clone code
- name: shared-data
volumeClaimTemplate: # automatically create pvc -> create pv
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
params: # git address
- name: repo-url
value: $(tt.params.giturl)
- name: image-reference
value: lijahong/tektontest:$(tt.params.imagetag)
- name: kubectl-args
value:
- "apply"
- "-f"
- "test.yaml"
- TriggerTemplate을 정의하자
- spec에는 TriggerBinding으로부터 받을 파라미터 정의와 생성할 PipelineRun 정의를 한다
- resouretemplates를 통해 정의한 PipelineRun을 자동으로 생성할 수 있다. PipelineRun 정의는 이전 편에서 정의한 내용과 동일하다
params: # git address
- name: repo-url
value: $(tt.params.giturl)
- name: image-reference
value: lijahong/tektontest:$(tt.params.imagetag)
- TriggerBinding으로부터 받아온 파라미터는 $(tt.params.파라미터이름) 형식으로 사용해야 한다
apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
name: hong-eventlistner
namespace: hongspace
spec:
serviceAccountName: trigger-sa
triggers:
- name: hong-trigger
bindings:
- ref: hong-pb
template:
ref: hong-tt
- EventListener를 정의하자. EventListener Pod를 실행할 ServiceAccount를 지정하고, Trigger를 정의하면 된다
- Trigger에는 연결할 TriggerBindings와 TriggerTemplate을 정의하면 된다
[ec2-user@ip-100-0-1-19 trigger]$ k get svc -n hongspace | grep el
el-hong-eventlistner ClusterIP 10.100.26.104 <none> 8080/TCP,9000/TCP 3h54m
- EventListener Service Name을 확인하자
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tekton-trigger-ingress
namespace: hongspace
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- http:
paths:
- path: /tektontrigger
pathType: Prefix
backend:
service:
name: el-hong-eventlistner
port:
number: 8080
- Ingress를 정의하자
- Nginx Ingress Controller 앞 단에 위치한 Load Balancer를 이용하여, EventListener Pod가 외부에서 Event를 받게 할 것이다
- Clone할 Repo의 설정에 들어가자
-Webhooks에 들어가자
[ec2-user@ip-100-0-1-19 trigger]$ k get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.100.215.111 ********************.ap-northeast-2.elb.amazonaws.com 80:31676/TCP,443:31231/TCP 25d
- ingress-nginx-controller LB의 DNS 주소를 확인하자
- add Webhook을 눌러서 Webhook을 추가하자. Payload를 보낼 URL과 Payload Type을 지정하면 된다
- ingress에서 Path를 /tektontrigger로 설정했으므로, PayLoad URL에는 http://'LB DNS 주소'/tektontrigger를 입력하면 된다
- Content type은 json으로 지정하자
- 추가했을 때, 위와 같이 체크 모양이 나오면 잘 등록된 것이다
- 따라서 Pipeline과 Task를 수정하여, Clone한 Deploy 매니페스트 파일 내용에 Build한 Image Tag 내용을 적용하자
- name: deploy
runAfter: ["build-push"]
taskRef:
name: kubernetes-actions
workspaces:
- name: manifest-dir
workspace: shared-data
params:
- name: args
value: $(params.kubectl-args[*])
- name: deployimage
value: $(params.image-reference)
- Pipeline 매니페스트 파일에 들어가서 내용을 추가하자
- 넘겨줄 파라미터 정의를 추가하자. 해당 파라미터는 Deploy 매니페스트 파일 수정에 필요한 Image 이름 & Tag 정보를 인자 값으로 갖는다
params:
- name: script # cli command, you setting
description: The Kubernetes CLI script to run
type: string
default: "kubectl $@" # $@ means use all parameter and all parameter is individual. parameter is args
- name: args
description: The Kubernetes CLI arguments to run # args for kubectl command. if you not describe script. then default script " kubectl $@ " activate and use this args like "get" "pod"
type: array # multiple args can come
default:
- "help"
- name: image # image for use kubectl to our cluster or other cluster ( if you set kubeconfig )
default: gcr.io/cloud-builders/kubectl@sha256:8ab94be8b2b4f3d117f02d868b39540fddd225447abf4014f7ba4765cb39f753 #image is huge
description: Kubectl wrapper image
- name: deployimage # deploy image, which kaniko build
description: Name (reference) of the image to build.
steps:
- name: kubectl
image: $(params.image)
script: |
#!/usr/bin/env bash
# if workspace which yaml file saved has bound, go to that directory
[[ "$(workspaces.manifest-dir.bound)" == "true" ]] && \
cd $(workspaces.manifest-dir.path)
# update yaml file image name
sed -i "s@changetagname@$(params.deployimage)@" test.yaml
# if kubeconfig workspace has bound and kubeconfig file exist, set env for kubeconfig path
[[ "$(workspaces.kubeconfig-dir.bound)" == "true" ]] && \
[[ -f $(workspaces.kubeconfig-dir.path)/kubeconfig ]] && \
export KUBECONFIG=$(workspaces.kubeconfig-dir.path)/kubeconfig
# do kubectl command
$(params.script)
args: # args for kubectl command
- "$(params.args)"
- Deploy를 담당하는 Task의 매니페스트 파일 내용을 수정하자
- Params에 넘겨 받을 파라미터를 정의하자
- steps에 sed 명령어를 추가하면 된다. Clone한 매니페스트 파일의 배포할 Image 정의 부분을 Build한 Image 이름 & Tag로 바꿔주는 것이다
- Repo에 저장된 매니페스트 파일 내용도 수정해주자. 배포할 Image 정의 부분을 sed가 인식하기 위해서, 지정한 키워드로 수정해주면 된다. 우리는 changetagname이라는 키워드를 사용할 것이다
[ec2-user@ip-100-0-1-19 trigger]$ k get triggerbindings -n hongspace
NAME AGE
hong-pb 4h
[ec2-user@ip-100-0-1-19 trigger]$ k get triggertemplates -n hongspace
NAME AGE
hong-tt 4h
[ec2-user@ip-100-0-1-19 trigger]$ k get eventlistener -n hongspace
NAME ADDRESS AVAILABLE REASON READY REASON
hong-eventlistner http://el-hong-eventlistner.hongspace.svc.cluster.local:8080 True MinimumReplicasAvailable True
[ec2-user@ip-100-0-1-19 trigger]$ k get ingress -n hongspace
NAME CLASS HOSTS ADDRESS PORTS AGE
tekton-trigger-ingress <none> * *******************************.elb.amazonaws.com 80 4h
- 생성한 오브젝트들을 확인하자
[ec2-user@ip-100-0-1-19 trigger]$ k get deploy -n hongspace | grep el
el-hong-eventlistner 1/1 1 1 4h1m
[ec2-user@ip-100-0-1-19 trigger]$ k get pod -n hongspace | grep el
el-hong-eventlistner-5dc7b955bb-98xdc 1/1 Running 0 4h1m
[ec2-user@ip-100-0-1-19 trigger]$ k get svc -n hongspace | grep el
el-hong-eventlistner ClusterIP 10.100.26.104 <none> 8080/TCP,9000/TCP 4h2m
- EventListener가 실제로 Pod로 배포되었으며, ClusterIP Service가 배포된 것을 확인할 수 있다
- index.html 내용을 수정해서 Push 해주자
- Commit ID를 확인하자
- Push를 하면, Tekton Trigger를 통해 PipelineRun이 생성되어 Pipeline이 실행되었다
- 새로 Build한 Image가 Docker Hub Repo에 Push 되었다
[ec2-user@ip-100-0-1-19 task]$ k get deploy -n hongspace
NAME READY UP-TO-DATE AVAILABLE AGE
tektontest 5/5 5 5 4h21m
[ec2-user@ip-100-0-1-19 task]$ k get pod -n hongspace
NAME READY STATUS RESTARTS AGE
tektontest-57f568cfd6-9gckz 1/1 Running 0 4h21m
tektontest-57f568cfd6-b5wxh 1/1 Running 0 4h21m
tektontest-57f568cfd6-dtsgc 1/1 Running 0 4h21m
tektontest-57f568cfd6-hz456 1/1 Running 0 4h21m
tektontest-57f568cfd6-p9vlw 1/1 Running 0 4h21m
[ec2-user@ip-100-0-1-19 task]$ k get svc -n hongspace
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc-lb-hong LoadBalancer 10.100.28.234 *******************.ap-northeast-2.elb.amazonaws.com 80:30347/TCP 4h21m
- Pod와 Load Balancer Service가 잘 배포되었다
- Deployment의 상세 정보를 확인하면, Pod 배포에 Commit ID를 이용하여 Build한 Image를 사용한 것을 확인할 수 있다
- Load Balancer를 통해 Pod에 잘 접속되며, 수정한 index.html 내용이 Image에 잘 적용되었다