Devops

Tekton 사용해보기 (5) Tekton에 Human Approval 기능을 추가해보자

Seungwoo Lee 2023. 3. 18. 18:30

본 포스팅은 "Tekton 사용해보기" 시리즈의 다섯번째 글입니다.

 

시리즈의 이전 글들은 아래 링크에서 확인할 수 있습니다.

 

Tekton 사용해보기(4) GCP Terraform 인프라를 Validation하는 파이프라인 구축하기

Tekton 사용해보기(3) Tekton Dashboard에 OIDC를 기반으로 RBAC 적용하기

Tekton 사용해보기(2) Tekton으로 인프라를 자동 배포하는 Terraform Pipeline을 만들어보자

Tekton 사용해보기(1) Tekton으로 쿠버네티스에서 CI/CD 파이프라인을 구성해보자

 

 


 

Tekton은 컨테이너를 기반으로 다양한 기능을 추가할 수 있는 강력한 Opensource CI/CD 파이프라인 도구입니다.

 

본 시리즈의 이전 글들에서 Tekton의 다양한 기능들을 알아보며 그 강력함을 직접 확인해볼 수 있습니다.

 

게다가 이 글에는 소개되어 있지 않아도 Tekton Hub에서 다양한 Component들을 지원하고 있기 때문에 원하는 파이프라인을 구성할 수 있다는 장점도 있는데요.

 

하지만 그런 Tekton에도 Native하게 지원되지 않는 기능이 하나 있습니다.

 

바로 인간의 승인 절차를 통해 다음 Task의 진행 여부나, 분기를 처리할 수 없다는 것입니다.

 

 대부분의 CI/CD 파이프라인은 다음 절차를 실행하기 전 인간이 직접 Approval 여부를 결정할때까지 대기하는 기능이 있기 때문에 적용 내용을 더블체크하거나, 우발적인 실행을 방지할 수 있었는데요.

 

Tekton의 경우 이러한 기능을 제공하고 있지 않기 때문에 파이프라인을 구성하는데 있어 작은 결점이 있을 수 밖에 없었습니다.

 

하지만 Tekton의 장점인 Extension과 Custom 기능 추가를 활용해서 Approval을 구현할 수 있습니다.  

 

이번 포스팅에서는 Tekton에서 Native하게 지원되지 않는 Human Approval 기능을 추가해보고, 이를 통한 파이프라인 구성 방법을 알아보겠습니다.

 


1. Tekton Approval DEMO

 

Tekton Approval에 대해 알아보기 전에 Human Approval을 활용한 Pipeline 데모를 보고 어떤 방식으로 프로세스가 흘러가는지 파악해보겠습니다. 

 

1-1. Tekton Approval을 활용한 Terraform Pipeline

 

Tekton Approval을 활용한 CI/CD Pipeline 구성도는 위와 같습니다. 구성도를 순서대로 나열하면 아래와 같습니다.

 

  1. Tekton Pipeline 내의 Task들을 실행하다가 Tekton Approval Task의 차례가 오면 다음 작업을 멈추고 대기합니다. 
  2. Tekton Approval Task는 지정된 User의 Email로 Approval을 요청하는 Notification mail을 발송합니다.
  3. 지정된 User, 즉 Approver는 Notification mail이 안내한 Dashboard에서 다음 Task 실행의 승낙, 혹은 거절을 선택합니다.
  4. 결과값을 Tekton Approver Task가 받기 전에, 올바른 User가 요청을 처리했는지를 Oauth2.0 인증으로 확인합니다. 
  5. 승낙, 혹은 거절 결과값에 따라 정해진 다음 Task를 실행합니다. 예를 들어 승낙시에는 다음 Task를 실행, 거절시에는 아무런 작업을 처리하지 않아 Pipeline을 Timed-out 상태로 만들 수 있습니다.

 

이와 같은 Tekton Approval을 활용한 CI/CD Pipeline 프로세스를 기반으로 Terraform 코드를 배포하는 Pipeline의 DEMO를 보겠습니다.

 

Terraform Source code가 존재하는 git repository에 Push Webhook을 보내는 것으로 Tekton Pipeline을 시작합니다.

 

Tekton Dashboard에서 Tekton Pipeline이 정상적으로 실행되는 것을 확인합니다

 

Pipeline 상태를 보면 테라폼으로 인프라를 배포하는 "terraform apply" Task를 실행하기 전에 Pipeline이 멈추어 있는 것을 볼 수 있습니다. Pipeline은 "terraform plan" Task에서 terraform plan log를 확인하고 승낙 여부를 결정하기 위해 Approval Task에서 대기합니다.

 

이 상태에서 Approver로 지정된 Email의 메일함을 확인해보면 Approval을 요청하는 Notification mail이 온 것을 확인할 수 있습니다.

 

해당 Mail을 클릭하면 Approval을 기다리는 Pipelinerun의 이름을 확인할 수 있습니다. 아래의 "Go to approval task" 버튼을 통해 Approve 작업을 실행할 수 있는 Dashboard로 진입할 수 있습니다.

 

Approval Dashboard로 진입하면 해당 Task를 승낙, 혹은 거절 여부를 선택할 수 있습니다.

 

Approval 여부를 결정하기 위해 이전의 "terraform plan" Task에서 terraform plan 로그를 확인합니다.

 

plan 로그가 적절하다면 Tekton approval dashbaord에서 "Approve" 버튼을 클릭해 작업을 승낙합니다. 해당 Approval에 대한 Comment도 남길 수 있습니다.

 

Approve를 클릭하면 해당 Pipelinerun이 승낙되었음을 알리는 페이지를 볼 수 있습니다.

 

이후 Tekton Dashboard에서 Pipeline 상태를 보면 다음 Task가 실행되는 것을 확인할 수 있습니다. 이 DEMO의 경우 "terraform apply" Task를 실행해 테라폼 코드를 기반으로 인프라를 배포합니다.

 

추가적으로 Tekton Dashboard 좌측의 Extension -> Approval Tasks 페이지에서 현재까지 Approval Task 실행 내역을 확인할 수 있습니다. 

 

Approval 내역을 클릭하면 YAML 페이지에서 Comment에 입력했던 내용과 승낙 여부, 승인자 등의 내용을 확인할 수 있습니다.

 

2. Tekton Approval 소개

이전 장에서 Tekton Approval을 활용한 Pipeline이 어떤 방식으로 흘러가는지 DEMO를 통해 확인해봤습니다. 

 

그럼 이제 본격적으로 Tekton Approval이 무엇인지, 어떤 기능이 있는지 알아보겠습니다.

 

Tekton Approval을 개발한 Automatiko의 Blog를 참고하면 더 많은 정보를 얻을 수 있습니다.

 

https://blog.automatiko.io/2022/02/12/tekton-approvals.html

 

Tekton approvals based on Automatiko - Automatiko Blog

Approvals - "the missing" part of Tekton "Tekton is a powerful and flexible open-source framework for creating CI/CD systems, allowing developers to build, test, and deploy across cloud providers and on-premise systems." Tekton is a fantastic project that

blog.automatiko.io

 

2-1. Automatiko Approval Task 개요

 

Tekton Pipeline을 사용하던 중 Manual Approval이 필요해 기능을 찾아봤지만, 아래 Tekton Issue에서 볼 수 있듯이 해당 기능이 Native하게 지원하지 않는다는 것을 알게 됐었는데요.

 

대체 기능을 찾던 중 Automatiko Approval Task를 알게 되어 사용 중입니다.

 

Tekton의 Roadmap에서는 Approval 기능의 지원 계획은 가지고 있지만 언제 출시될지 모르니 현재는 해당 Approval task를 유용하게 사용 중입니다.

 

https://github.com/tektoncd/pipeline/issues/2159

 

Support for Tasks that require manual "approval" · Issue #2159 · tektoncd/pipeline

In a Pipeline I'd like to be able to declare a Task that requires "approval" that may or may not contains a taskRef. When started, it immediately moves into a "suspend" stat...

github.com

 

Automatiko 사의 Tekton Approval은 Tekton에 내장되어 있지 않은 Approval 기능을 사용할 수 있게끔 하기 위해 Tekton의 다양한 컴포넌트와 통합된 기능입니다.

 

Tekton Approval은 승인 절차를 구현하기 위해서 Tekton Pipeline, Tekton Dashboard, 그리고 Email을 통한 Notification 등의 기능들을 제공하고 있습니다.

 

 

2-2. Approval Task의 기능

 

Approval Task에서 Approval을 구현하기 위해 제공하는 기능들은 크게 다음과 같습니다.

 

  • Custom Task를 통한 Tekton Pipeline과의 연동
  • Extension을 통한 Tekton Dashboard와의 연동
  • email을 통한 notification 기능
  • Oauth2.0을 통한 Authentication 기능
  • 다양한 Approval 전략 제공

위 기능들을 하나씩 알아보도록 하겠습니다.

 

 

2-2-1. Custom Task를 통한 Tekton Pipeline과의 연동

 

Tekton Approval은 Tekton의 확장 기능인 Custom Task 기능을 통해 Tekton Pipeline과 통합되어 있습니다.

 

Custom Task는 CRD(Custom Resource Definition)를 통해 기존의 Task가 아닌 다른 Task를 만들어서 사용할 수 있는 기능인데요.

 

Approval Task 또한 ApprovalTask라는 이름의 CRD로 정의되어 이를 참조해 사용할 수 있습니다.

 

 

apiservice에서는 "v1beta1.tekton.automatiko.io"로 Approval Task의 API를 확인할 수 있습니다.

 

다음은 "ApprovalTask" Custom Task를 이용한 Tekton Pipeline의 예입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
    - name: approval
      taskRef:
        apiVersion: tekton.automatiko.io/v1beta1
        kind: ApprovalTask
        name: approvaltask
      params:
        - name: pipeline
          value: "$(context.pipelineRun.name)"
        - name: description
          value: "Sample approval from pipeline $(context.pipeline.name)"
        - name: approvers
          value:
            - "john"






cs

 

"taskRef" Attribute에 아래와 같이 적어 Approval Task를 이용할 수 있습니다.

 

apiVersion: tekton.automatiko.io/v1beta1

kind: ApprovalTask

name: approvaltask

 

그리고 아래와 같은 Parameter들을 사용할 수 있습니다.

 

  • pipeline - Approval Task가 포함된 pipeline명입니다.
  • description - Approval Task를 설명하기 위한 설명란입니다.
  • approvers - 승낙,혹은 거절 행위를 할 수 있는 승인자를 지정합니다. 지정된 승인자만이 승낙,혹은 거절을 할 수 있습니다. Appro Array를 이용해 여러명을 지정할 수 있으며 UsernameEmail 계정을 사용할 수 있습니다. Oauth2.0 인증을 사용할 시 지정된 승인자만 인증을 수행할 수 있습니다.
  • groups - 승낙,혹은 거절 행위를 할 수 있는 승인 Group을 지정합니다. approval과 groups는 동시에 사용할 수 없습니다.
  • strategy - Approval 전략을 지정합니다. 현재는 SINGLEMULTI, FOUR_EYES 전략을 제공하고 있습니다. 지정하지 않을  시 SINGLE 전략을 사용합니다.

 

 

2-2-2. Extension을 통한 Tekton Dashboard와의 연동

 

Tekton Approval을 Tekton Dashboard를 통해 Web UI 환경에서 확인할 수 있습니다.

 

Tekton Dashboard의 Extension 기능을 통해 Tekton Approval의 현황을 표시할 수 있는데요.

 

Tekton Dashboard Extension은 "Extension" CRD를 통해 대시보드상에 추가적인 리소스를 표시할 수 있는 기능입니다.

 

Tekton Approval Task를 대시보드에 표시하기 위한 Extension 리소스는 아래와 같이 확인할 수 있습니다.

 

 

여기에 추가적으로 Tekton Dashboard Service account에게 approval task 리소스를 표시하기 위해 필요한 권한들을 부여해야 하는데요.

 

아래와 같은 Approval Task에 대한 접근 권한들을 담은 Clusterrole을 Tekton Dashboar의 Service account에게 Binding하는 방식으로 권한을 부여할 수 있습니다.

 

 

Extension 리소스와 권한 부여를 모두 준비했다면 아래와 같이 Tekton Dashboard에서 Extension 탭 아래에 Approval Tasks가 추가된 것을 확인할 수 있습니다.

 

 

Approval Tasks에는 현재까지 진행된 Approval Task들의 목록을 볼 수 있으며, Overview 탭에서 각 Approval Task의 현재 상태(승낙, 거절, 진행 중)과 Description을 확인할 수 있습니다.

 

YAML 탭에서는 Approval Task의 yaml 매니페스트를 볼 수 있으며, 여기서 Approval 시 적었던 Comment와 해당 Approval Task의 Approval 작업을 할 수 있는 페이지 URL을 확인할 수 있습니다.

 

 

2-2-3. email을 통한 Notification 기능

 

Tekton Approval이 제공하는 기능 중에는 email을 통해 Approval 작업이 생성되었음을 알려주는 Notification 기능이 있습니다.

 

Notification 기능을 이용하기 위해서는 mail을 발신하기 위한 smtp 서버가 필요한데요.

 

직접 smtp 서버를 구성해 사용하거나, Google 등의 미리 준비된 smtp 서버를 사용할 수 있습니다.

 

 

메일은 지정된 Approver에게 발신해야 하며, 이 때문에 Notification 기능을 이용하면 Approver에는 Username이 아니라 아래와 같이 User email address를 사용해야만 합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  tasks:
    - name: approval
      taskRef:
        apiVersion: tekton.automatiko.io/v1beta1
        kind: ApprovalTask
        name: approvaltask
      params:
        - name: pipeline
          value: "$(context.pipelineRun.name)"
        - name: description
          value: "Sample approval from pipeline $(context.pipeline.name)"
        - name: approvers
          value:
            - "john@email.com"
            - "mary@email.com"  
cs

 

 

 

2-2-4. Oauth2.0을 통한 Authentication 기능

 

Tekton Approval은 기본적으로 Approval이 필요한 Pipelinerun명Approver의 이름만 알고 있으면 Approval 행위를 할 수 있습니다. 

 

하지만 이들은 모두 확인하기 쉬운 정보들이기 때문에 승인되지 않은 User가 몰래 Approval을 할 수도 있다는 문제점이 존재하는데요.

 

이같은 문제를 해결하기 위해 Tekton Approval은 Oauth2 proxy를 통한 Oauth2.0 Authentication을 지원하고 있습니다.

 

Oauth2.0 인증을 사용하면 Google, MS, Okta 등의 Provider들에게서 인증 정보를 받은 뒤, 인증을 성공한 User만 Approval Dashboard에 접근하도록 할 수 있습니다.

 

이를 통해 Approval 행위를 하려면 Pipelinerun과 Approver 정보 뿐만이 아니라, 타 Provider에서 받은 인증 Token도 요구함으로써 보안성을 강화할 수 있습니다.

 

이 기능은 앞의 Email Notification과 연계하여 Approver의 Email로 Notification mail을 보내고 그 계정으로 Oauth2.0 인증까지 처리하는 방식으로 사용할 수도 있습니다.

 

 

 

 

2-2-5. 다양한 Approval 전략 제공

 

앞서 Tekton Approval은 "strategy" parameter를 사용해 Approval 전략을 지정할 수 있다고 했는데요.

 

Tekton Approval은 다양한 승인 전략을 제공하여 Approval에 필요한 절차 및 인원을 조정할 수 있습니다.

 

현재 제공되는 승인 전략 및 기능은 다음과 같습니다.

 

  • SINGLE : 얼마나 많은 수의 Approver가 지정되어 있는지에 상관없이 단 한 명의 Approver가 승인 절차를 실행하면 그 결과를 토대로 Pipeline을 진행합니다. 아무 승인 전략도 지정되어 있지 않을 시 기본적으로 사용하는 전략입니다.
  • MULTI : 지정된 Approver들이 모두 승낙 의사를 밝힐 시에만 Pipeline을 진행합니다. 하지만 Approver들 중 한 명이라도 거절 의사를 밝힐 시 Pipeline은 바로 중단됩니다.
  • FOUR_EYES : "Four eyes principle"에 기반을 둔 전략으로, 승인 절차를 2단계로 구성해 진행합니다. 각 절차는 같은 Approver가 참여할 수 있으나 첫번째 절차에서 의사를 밝힌 인원은 두번째 절차에서 의사를 밝혀도 이를 반영하지 않습니다. Pipeline이 진행되려면 두 절차 모두 승낙되어야 하며, 첫번째 절차에서 거절 의사가 나오면 두번째 의사는 진행되지 않고 Pipeline이 중단됩니다.

 

 

3. Tekton Approval을 이용한 파이프라인 구성

 

지금까지 Tekton Approval이 어떤 특징과 기능이 있는지 알아봤습니다.

 

그럼 이제 본격적으로 Tekton Approval을 구성해 사용하는 방법에 대해 알아보겠습니다.

 

본 포스팅에서는 Tekton Pipeline의 구성에 대해서는 담고 있지 않습니다. 해당 내용에 대해 알고 싶다면 Tekton 사용해보기(1) Tekton으로 쿠버네티스에서 CI/CD 파이프라인을 구성해보자 등 Tekton 사용해보기 시리즈의 글을 참고 바랍니다.

 

Tekton Approval의 설치에 대한 자세한 내용은 공식 Github 페이지에서 확인할 수 있습니다.

 

https://github.com/automatiko-io/automatiko-approval-task

 

GitHub - automatiko-io/automatiko-approval-task: Tekton Pipeline Custom task implementation to add approval capabilities into th

Tekton Pipeline Custom task implementation to add approval capabilities into the pipelines - GitHub - automatiko-io/automatiko-approval-task: Tekton Pipeline Custom task implementation to add appro...

github.com

 

3-1. Tekton Approval 설치 및 구성

가장 먼저 Tekton Approval에 필요한 Kubernetes 오브젝트들을 구성해보겠습니다. 

 

필요한 오브젝트들은 크게 Tekton Dashboard의 Extension을 위한 ClusterRole & ClusterRolebinding,

 

Tekton Approval의 CRD(CustomResourceDefinition),

 

그리고 Approval의 Oauth2.0 인증 및 메일 발신과 같은 핵심 기능을 담당하는 Deployment로 이루어져 있습니다.

 

 

 

3-1-1. Tekton Dashboard Extension 구성

 

먼저 Tekton Dashobard Extension에 Approval을 띄우기 위한 RBAC 오브젝트를 구성하겠습니다.

 

아래 Manifest를 적용합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tekton-dashboard-approvaltasks-extension
rules:
  - apiGroups: ["tekton.automatiko.io"]
    resources: ["approvaltasks"]
    verbs: ["get""list""watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tekton-dashboard-approvaltasks-role-binding
roleRef:
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
  name: tekton-dashboard-approvaltasks-extension
subjects:
  - kind: ServiceAccount
    name: tekton-dashboard
    namespace: tekton-pipelines
cs

 

Manifest는 Tekton Dashboard의 ServiceAccount에 "approvaltasks" 리소스에 대한 get, list, watch 권한을 부여하는 Clusterrole & Clusterrolebinding으로 이루어져 있습니다.

 

이 구성을 통해 Tekton Dashboard가 Approval Task에 접근하여 대시보드에 Approval 리스트를 띄울 수 있습니다.

 

적용 뒤 Tekton Dashboard에 아래와 같이 Extensions -> Approval Tasks가 나타났다면 정상적으로 적용된 것입니다.

 

 

 

 

3-1-2. Tekton Approval CRD 구성

 

다음으로는 Tekton Approval 리소스를 정의하기 위한 CRD를 구성하겠습니다.

 

아래 Manifest를 적용합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: approvaltasks.tekton.automatiko.io
spec:
  group: tekton.automatiko.io
  names:
    kind: ApprovalTask
    plural: approvaltasks
    singular: approvaltask
  scope: Namespaced
  versions:
  - name: v1beta1
    schema:
      openAPIV3Schema:
        properties:
          spec:
            properties:
              strategy:
                enum:
                - FOUR_EYES
                - MULTI
                - SINGLE
                type: string
              approvers:
                items:
                  type: string
                type: array
              groups:
                items:
                  type: string
                type: array
              pipeline:
                type: string
              description:
                type: string
            type: object
          status:
            properties:
              results:
                properties:
                  decision:
                    type: string
                  comment:
                    type: string
                type: object
              status:
                type: string
              reason:
                type: string
              approvalUrl:
                type: string
              message:
                type: string
            type: object
        type: object
    served: true
    storage: true
    subresources:
      status: {}
cs

 

이 Manifest를 통해 ApprovalTask 리소스를 사용할 수 있습니다.

 

"kubectl get crd" 명령어를 실행했을때 아래와 같이 approvaltasks.tekton.automatiko.io가 리스트에 있다면 정상적으로 적용된 것입니다.

 

 

 

 

3-1-3. Tekton Approval Deployment 구성

 

마지막으로 Tekton Approval의 핵심 구성 요소인 Deployment를 구성해보겠습니다.

 

Approval Deployment는 Approval 기능과 oauth2 proxy Sidecar container를 이용한 Oauth2.0 인증, 그리고 메일 발송 기능을 담당합니다.

 

아래 Manifest를 적용합니다. Manifest는 메일 발송을 위한 SMTP 서버를 smtp.google.com으로, Oauth2.0 인증을 위한 Provider를 Google로 설정한 예시입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
---
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2022-02-05 - 11:22:03 +0000
  labels:
    app.kubernetes.io/version: 0.6.0
    app.kubernetes.io/name: automatiko-approval-task
  name: automatiko-approval-task
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2022-02-05 - 11:22:03 +0000
  labels:
    app.kubernetes.io/name: automatiko-approval-task
    app.kubernetes.io/version: 0.6.0
  name: automatiko-approval-task
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8888
  selector:
    app.kubernetes.io/name: automatiko-approval-task
    app.kubernetes.io/version: 0.6.0
  type: ClusterIP
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: automatiko-approval-task-view
roleRef:
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
  name: view
subjects:
  - kind: ServiceAccount
    name: automatiko-approval-task
    namespace: TEKTON_NAMESPACE
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: approvals-cluster-role
rules:
  - apiGroups:
      - tekton.automatiko.io
    resources:
      - approvaltasks
      - approvaltasks/status
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: josdk-crd-validating-cluster-role
rules:
  - apiGroups:
      - apiextensions.k8s.io
    resources:
      - customresourcedefinitions
    verbs:
      - get
      - list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: customruns-cluster-role
rules:
  - apiGroups:
      - tekton.dev
    resources:
      - customruns
      - customruns/status
    verbs:
      - get
      - list
      - watch
      - patch
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: approvals-cluster-role-binding
roleRef:
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
  name: approvals-cluster-role
subjects:
  - kind: ServiceAccount
    name: automatiko-approval-task
    namespace: TEKTON_NAMESPACE
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: approvals-crd-validating-role-binding
roleRef:
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
  name: josdk-crd-validating-cluster-role
subjects:
  - kind: ServiceAccount
    name: automatiko-approval-task
    namespace: TEKTON_NAMESPACE
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: customruns-cluster-role-binding
roleRef:
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
  name: customruns-cluster-role
subjects:
  - kind: ServiceAccount
    name: automatiko-approval-task
    namespace: TEKTON_NAMESPACE
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: runs-crd-validating-role-binding
roleRef:
  kind: ClusterRole
  apiGroup: rbac.authorization.k8s.io
  name: josdk-crd-validating-cluster-role
subjects:
  - kind: ServiceAccount
    name: automatiko-approval-task
    namespace: TEKTON_NAMESPACE
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    app.quarkus.io/build-timestamp: 2022-02-05 - 11:22:03 +0000
  labels:
    app.kubernetes.io/version: 0.6.0
    app.kubernetes.io/name: automatiko-approval-task
  name: automatiko-approval-task
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/version: 0.6.0
      app.kubernetes.io/name: automatiko-approval-task
  template:
    metadata:
      annotations:
        app.quarkus.io/build-timestamp: 2022-02-05 - 11:22:03 +0000
      labels:
        app.kubernetes.io/version: 0.6.0
        app.kubernetes.io/name: automatiko-approval-task
    spec:
      volumes:
      containers:
        - env:
            - name: KUBERNETES_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: QUARKUS_OPERATOR_SDK_NAMESPACES
              value: default
            - name: QUARKUS_AUTOMATIKO_SERVICE_URL
              value: SERVICE_URL
            - name: QUARKUS_PROFILE
              value: securedwithemail
            - name: QUARKUS_MAILER_FROM
              value: FROM_MAILER_NAME
            - name: QUARKUS_MAILER_HOST
              value: smtp.gmail.com
            - name: QUARKUS_MAILER_PORT
              value: "587"
            - name: QUARKUS_MAILER_USERNAME
              value: MAILER_NAME
            - name: QUARKUS_MAILER_PASSWORD
              value: MAILER_PASSWORD
          image: automatiko/automatiko-approval-task
          imagePullPolicy: Always
          name: automatiko-approval-task
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/live
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 0
            periodSeconds: 30
            successThreshold: 1
            timeoutSeconds: 10
          name: automatiko-approval-task
          ports:
            - containerPort: 8080
              name: http
              protocol: TCP
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /q/health/ready
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 0
            periodSeconds: 30
            successThreshold: 1
            timeoutSeconds: 10
        - name: oauth-proxy
          args:
            - --provider=google
            - --redirect-url=REDIRECT_URL          
            - --http-address=:8888
            - --email-domain=*
            - --prefer-email-to-user=true
            - --upstream=http://localhost:8080
            - --client-id=CLIENt_ID
            - --client-secret=CLIENT_SECRET
            - --pass-access-token=true
            - --cookie-secret=COOKIE_SECRET
            - --cookie-secure=false
          image: quay.io/oauth2-proxy/oauth2-proxy
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /ping #Thus "/" path return 403, Define readinessProbe manually to define healthcheck path to "/ping"
              port: 8888
              scheme: HTTP
          imagePullPolicy: IfNotPresent
          ports:
            - name: oauth-proxy
              containerPort: 8888   
              protocol: TCP          
      serviceAccountName: automatiko-approval-task
cs

 

위 Manifest는 Deployment 및 다양한 RBAC 리소스로 이루어져 있습니다.

 

Deployment를 적용하기 전에 각 컨테이너에 기입해야 할 Attribute를 수정해야 하는데요.

 

먼저 "Approval Task" 컨테이너의 Attribute 설명과 넣어야 할 주요 값의 리스트는 아래와 같습니다.

 

Attribute Description Value
QUARKUS_AUTOMATIKO_SERVICE_URL Approval Service의 URL Approval Service의 호스트 네임
QUARKUS_MAILER_FROM Notification Mail의 수신인 Mail을 수신받을 계정 Mail
QUARKUS_MAILER_HOST Notification Mail을 발송할 smtp 서버 smtp.gmail.com
QUARKUS_MAILER_PASSWORD Notification Mail의 발신인 PW* Mail을 발신할 계정의 App password
QUARKUS_MAILER_PORT Notifcation Mail을 발송할 Port 587
QUARKUS_MAILER_USERNAME Notification Mail의 발신인 ID Mail을 발신할 계정 Mail
QUARKUS_OPERATOR_SDK_NAMESPACE Approval Operator가 존재하는 Namespace Namespace 명
QUARKUS_PROFILE "secured"와 "securedwithemail" 값 선택 가능. 인증만 필요하면 secured, 인증과 메일 Notification이 필요하면 securedwithemail을 기입 securedwithemail

* Google 계정의 경우 일반 PW가 아닌 App Password를 발급받아 사용하는 것이 안전합니다. Google의 App Password에 대한 자세한 내용은 아래 링크를 참조하세요.

https://support.google.com/accounts/answer/185833?hl=en

 

Sign in with App Passwords - Google Account Help

Tip: App Passwords aren’t recommended and are unnecessary in most cases. To help keep your account secure, use "Sign in with Google" to connect apps to your Google Account.  An App Password is a 16-digit passcode that gives a less secure app or device p

support.google.com

 

다음은 oauth2 proxy 컨테이너의 Attribute 설명과 넣어야 할 주요 값의 리스트입니다.

 

Attribute Description Value
provider Oauth2.0 서비스 제공자 google
redirect-url Oauth2.0 Redirect URL* Redirect URL
http-address HTTP Client가 Listen할 주소 :8888
email-domain 인증 메일의 도메인명 *
prefer-email-to-user upstream으로 정보를 보낼 시, Emil 주소를 Username으로 보낼 지 여부 true
upstream Upstream endpoint 주소 http://localhost:8080
client-id Oauth Client ID** 발급받은 Oauth Client ID
client-secret Oauth Client Secret 발급받은 Oauth Client Secret
pass-access-token Oauth access_token을 X-Forwarded_acces_Token 헤더로 보낼지 여부 true
cookie-secret Cookie Secret 값*** 발급받은 Cookie Secret
cookie-secure Secure Cookie 설정 여부 false

* Google의 경우 Oauth Origin URL에 "/oauth2/callback"을 붙인 값을 사용합니다.

** Google Cloud에서 발급받은 Oauth Client ID에서 Client ID값과 Client Secret을 사용합니다. 자세한 내용은 Tekton 사용해보기(3) Tekton Dashboard에 OIDC를 기반으로 RBAC 적용하기 에서 확인할 수 있습니다.

*** Cookie Secret을 생성하는 방법은 아래 oauth2 proxy 문서에서 확인할 수 있습니다.

https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview

 

Overview | OAuth2 Proxy

oauth2-proxy can be configured via command line options, environment variables or config file (in decreasing order of precedence, i.e. command line options will overwrite environment variables and environment variables will overwrite configuration file set

oauth2-proxy.github.io

 

Approval Deployment를 정의하는 Manifest에서 oauth-proxy 컨테이너의 readiness probe attribute는 기존에 존재하지 않았지만, 나중에 추가한 코드입니다.
GCP의 GKE 클러스터에서 이 구성을 적용할 경우, readiness probe를 정의하지 않으면 해당 Deployment와 연결된 GCP Load Balancer는  "/" Path로 HealthCheck를 보내게 됩니다. HealthCheck가 실패하면 Load Balancer는 Backend로 트래픽을 보내지 않습니다.
하지만 Oauth-proxy는 "/ping" Path에서 200을 return하도록 되어 있으므로, readiness probe를 따로 정의해서 "/ping" Path로 Probe를 보내 HealthCheck가 성공하도록 구성했습니다.

 

3-2. Tekton Approval Pipeline 사용

 

모든 구성을 마쳤으면 Tekton Approval을 사용할 수 있습니다. 

 

가장 기본적인 사용 방법은 Tekton Pipeline에 Approval Task를 추가하는 것입니다.

 

아래는 Approval Task를 사용한 Terraform Deployment Pipeline의 예시입니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: clone-terraform-cli
spec:
  description: |
    This pipeline clones a git repo, run "terraform plan" command based on .tf config file
    
  params:
    - name: repo-url
      type: string
  tasks:
    - name: fetch-source
      params:
        - name: url
          value: $(params.repo-url)
      taskRef:
        kind: Task
        name: git-clone
      workspaces:
        - name: output
          workspace: shared-data
        - name: ssh-directory
          workspace: ssh-key
    - name: terraform-plan
      params:
        - name: chdir
          value: ''
        - name: ARGS
          value:
            - plan
      runAfter:
        - fetch-source
      taskRef:
        kind: Task
        name: terraform-cli
      workspaces:
        - name: source
          workspace: shared-data
    - name: terraform-approval
      params:
        - name: pipeline
          value: $(context.pipelineRun.name)
        - name: description
          value: Approval from pipeline $(context.pipeline.name) for development environment
        - name: approvers
          value:
            - APPROVER_NAME
      runAfter:
        - terraform-plan
      taskRef:
        apiVersion: tekton.automatiko.io/v1beta1
        kind: ApprovalTask
        name: approvaltask
    - name: terraform-apply
      params:
        - name: chdir
          value: ''
        - name: ARGS
          value:
            - apply
            - '-auto-approve'
      runAfter:
        - terraform-approval
      taskRef:
        kind: Task
        name: terraform-cli
      when:
        - input: $(tasks.terraform-approval.results.decision)
          operator: in
          values:
            - 'true'
      workspaces:
        - name: source
          workspace: shared-data
    - name: terraform-rejected
      params:
        - name: decision
          value: REJECTED
        - name: comment
          value: $(tasks.terraform-approval.results.comment)
      runAfter:
        - terraform-approval
      taskRef:
        kind: Task
        name: print-decision
      when:
        - input: $(tasks.terraform-approval.results.decision)
          operator: in
          values:
            - 'false'
  workspaces:
    - name: shared-data
    - name: ssh-key
cs

 

위 Manifest에 사용된 Approval 관련 Attribute은 아래와 같습니다.

 

Attribute : Key Description Value
params.name : decision Approval Task의 PIpeline명 $(context.pipeline.name)
params.name : description Approval Task의 설명 Approval을 설명할 문구를 기재
params.name : approver Approval을 실행할 계정, 기재되지 않은 계정이 Approval을 시도할시 인증에 실패 Approver 계정 Email
runAfter Approval을 실행하기 전 Task명 terraform-plan
taskRef 참조할 Tekton Task apiVersion: tekton.automatiko.io/v1beta1
kind: ApprovalTask
name: approvaltask

 

위 Pipeline을 실행했을 시, Dashboard의 Approval Tasks란에 아래와 같이 Task가 추가되면 성공적으로 적용된 것입니다. 

 

Approval Task가 실행될 차례가 되면 Email로 Notification이 오며, Approval을 진행할 수 있는 Dashboard에서 의사 결정을 내릴 수 있습니다.

 

4. 마무리

지금까지 Tekton Approval Task로 Tekton에서 Human Approval 기능을 구현하는 방법에 대해 알아봤습니다.

 

Tekton은 현재 Native하게 제공되는 Approval 기능이 없지만, Extension과 CRD를 이용한 Tekton Approval을 통해 Task가 실행되기 전 Email Notification로 승인 절차를 밟을 수 있게 됩니다.

 

아직 Web UI에서 승인 절차를 밟을 수 없다는 점, Approval을 처리해야 할 Deployment가 따로 구성되어 있어야 한다는 점 등 단점이 존재하기는 하지만, 아직 나온지 얼마 안된 기능이기 때문에 발전의 여지가 있는 것 같습니다.

 

이 포스팅을 보시는 분들이 Tekton으로 Approval 기능을 구현하는데 도움을 받으셨으면 합니다.