DevOps

Tekton으로 CI 하기

mokpolar 2022. 4. 19. 11:08
반응형

배경

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.

출처: https://tekton.dev/

powerful하고 flexible 하다고 한다. 멋있다.
같은 말이지만 Google Cloud 페이지에는 번역이 잘 되어있어서 갖고와봤다.

 

Tekton은 지속적 통합 및 배포(CI/CD) 시스템을 만들 수 있는 강력하면서도 유연한 Kubernetes 기반 오픈소스 프레임워크입니다. 기본 구현 세부정보를 추상화하여 여러 클라우드 제공업체 또는 온프레미스 시스템에서 빌드, 테스트, 배포가 가능합니다.

Tekton은 여러 공급업체, 언어, 배포 환경의 CI/CD 도구 및 프로세스를 표준화할 수 있는 오픈소스 구성요소를 제공합니다. Tekton에서 사용할 수 있는 파이프라인, 릴리스, 워크플로, 기타 CI/CD 구성요소의 업계 사양은 Jenkins, Jenkins X, Skaffold, Knative 등의 기존 CI/CD 도구와 잘 연동됩니다.

Tekton에 내장된 권장사항을 따르면 클라우드 기반 CI/CD 파이프라인을 빠르게 만들 수 있습니다. 개발자가 불변성 이미지를 만들고 배포하거나 인프라 버전 제어를 관리하거나 쉽게 롤백을 수행하도록 지원하는 데 그 목표가 있습니다. Tekton을 사용하면 순차적 배포, 블루/그린 배포, 카나리아 배포 또는 GitOps 워크플로 등의 고급 배포 패턴도 활용할 수 있습니다.

출처 : https://cloud.google.com/tekton?hl=ko

이 소개를 보니 Tekton으로 무엇을 할 수 있는지 좀 더 이해를 할 수 있게 되었다.

그러면 왜 Tekton을 쓰게 되었는가?

쿠버네티스 환경에서 AI 모델을 서비스 하는 상황이다.
모델 서빙을 위한 코드와 모델이 탑재된 컨테이너 이미지를 생성해야 하고 이 이미지는 지속적으로 변화할 수 있다.
이런 기능을 하는 도구는 여러가지가 있지만 특정 노드에 구애받지 않고 쿠버네티스 클러스터의 자원들을 자유롭게 사용하는 CI/CD 파이프라인을 구축하고 싶었다.

쿠버네티스를 잘 이해하고 있다면 사용자가 원하는 대로 유연하고 쉽게 Tekton의 구성요소들을 조립하고 분해하여 CI/CD 파이프라인을 구축할 수 있다. 그러니까, 모듈화가 잘 되어있고 확장성이 있다.
또 각각의 구성요소들은 독립적이고 따로 재사용을 할 수 있다. 그러니까, 중복을 막기가 쉽다.
또한 실제 작업이 시작될때 Pod가 생성되며 작업을 시작한다. Serverless인 셈이고, 평소에는 자원을 먹지 않는다.
그리고 Tekton은 UI가 보기좋게 잘 되어있다.

 

테스트

샘플용으로 만든 Github 리포지토리에 Dockerfile이 있고 Tekton을 사용하여 이 Dockerfile을 다운로드하고 컨테이너 이미지를 빌드 후
마찬가지로 테스트용으로 만든 개인 DockerHub에 push할 것이다.

 

Tekton Concepts

Tekton Concepts Documentation에서 구조를 확인할 수 있다.
https://tekton.dev/docs/concepts/
Tekton의 구조를 설명하는 것까지는 내가 쓰는 글의 범위가 아니기도 하고, 분량이 방대하기도 하다.
아래 작업의 설명을 위해서 간단하게 구조도만 갖고와 보면,

출처: https://tekton.dev/docs/concepts/

Tekton의 CI/CD Workflow는 Pipeline > Task > Step 으로 구성되어 있다.
그러니까 Step이 모여서 Task를 이루고, Task가 모여서 Pipeline을 이루는 건데, 각 Task는 Kubernetes의 Pod로 구성되어 있다.
그러니, Task(Pod)간 데이터(작업내용) 전달을 위해서는 별도의 Volume이 필요하다. 이에 PVC를 사용한다.
이 Volume을 Tekton에서는 Workspace라고 부른다.

설치

준비물

  • 쿠버네티스 환경 (작성자의 경우 EKS 1.21)
  • 사용자 환경에 따라 PVC를 위한 Volume 준비 (작성자의 경우 테스트용으로 AWS EFS)

이제는 글에 설치 코드를 그대로 적는게 좋은지는 모르겠다.
오픈소스의 경우 금방금방 바뀌는데, 예전 글을 그때그때 동기화하기는 어려울 것 같다....
https://tekton.dev/docs/getting-started/
사실 홈페이지 documentation을 보고 버전을 확인하고 설치하는게 제일 좋다.
결국은 documentation을 꼼꼼히 읽는게 삽질 시간을 줄여주는 지름길인것 같다.

Tekton

버전 변경을 원한다면 latest 를 변경해야 한다.

kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

Tekton 컴포넌트들이 다 떴는지 확인

kubectl get pods -n tekton-pipelines

 

PVC

대략 아래와 같이 해당 네임스페이스에 pvc를 준비한다.
이런 공간을 Tekton에서는 workspace라고 부른다.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: tekton-pvc
  namespace: tekton
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 50Gi
  volumeMode: Filesystem

 

Pipeline

Tekton Pipeline에서는 Task의 순서와 사용되는 parameter등을 정의한다.
아래 manifest를 순서대로 설명해보면,
resource는 지금은 deprecated된 (아래 다시 설명하겠다) Tekton PipelineResource를 의미한다.
result는 task에서 뽑아낸 parameter이며,
workspace는 미리 배포해 둔 PersistentVolumeClaim이다.
task가 순서대로 2개 정의되어 있는 모습을 볼 수 있다.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: test-pipeline
spec:
  resources:
    - name: git-pipelineresource
      type: git
  results:
    - name: commitshashort
      value: "$(tasks.git-clone.results.commitshashort)"
  workspaces:
    - name: tekton-pvc
  tasks:
    - name: git-clone
      taskRef:
        name: git-clone
      workspaces:
        - name: tekton-pvc
          workspace: tekton-pvc
      resources:
        inputs:
          - name: git-pipelineresource
            resource: git-pipelineresource
    - name: build-container-and-push
      taskRef:
        name: build-container-and-push
      runAfter: 
        - "git-clone"
      params:
        - name: commitshashort
          value: "$(tasks.git-clone.results.commitshashort)"
      workspaces:
        - name: tekton-pvc
          workspace: tekton-pvc

 

PipelineRun

Pipeline에서 정의한 내용을 PipelineRun을 통해 실행한다.
위에서 정의한 내용들에 값을 넣어준다. PipelineResource는 실제 무엇을 사용하는지, PVC는 실제 뭘 쓸것인지 등이다.
권한을 가지는 ServiceAccount도 넣어준다.

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: test-pipelinerun
spec:
  resources:
    - name: git-pipelineresource
      resourceRef:
        name: git-pipelineresource
  workspaces:
  - name: tekton-pvc
    persistentvolumeclaim:
      claimName: tekton-pvc
  serviceAccountName: my-sa
  pipelineRef:
    name: test-pipeline

PipelineResource

PipelineResource는 5개월 전 (2021년 11월경)에 deprecated되었다.
https://github.com/tektoncd/pipeline/blob/main/docs/resources.md
그래서 PipelineResource를 테스트 해본 이후에 Task로 전환했지만 이렇게 테스트용으로 돌려보는 데는 무리가 없기에
PipelineResource로 테스트한 후기를 그대로 올린다.
이걸 Task로 전환한 건 다른 글에서 또 써야겠다.

아래 PipelineResource는 git type이고 상세한 내용은 아래 글에 있다.
https://github.com/tektoncd/pipeline/blob/main/docs/resources.md#git-resource
git resource를 Tekton task에 input으로 넣으면 repository를 clone 한다.

manifest에는 clone의 대상이 되는 git url과 revision을 입력해주어야 한다.
여기서는 테스트용으로 만든 Github repository를 넣어주었다.

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: git-pipelineresource
spec:
  type: git
  params:
    - name: revision
      value: main
    - name: url
      value: https://github.com/yourid/your-pipeline # your git url

 

Task

task1.
앞서 설명했듯이 Tekton task는 실제 pod 단위가 된다.
아래 manifest에 나와있듯이 PipelineResource를 통해서 clone한 repository를 kaniko를 통해 build 및 push 하기 전에
Dockerhub에 image tag를 생성하는 동작을 담고 있다.
해시값을 사용하며 해당 값은 result로 넘겨서 다음 task로 전달한다.

 

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-clone
spec:
  results:
  - name: commitshashort
  workspaces:
  - name: tekton-pvc
  resources:
    inputs:
      - name: git-pipelineresource
        type: git
        targetPath: tekton-pvc
  steps:
    - name: generate-tag
      image: bitnami/git
      script: |
        #!/usr/bin/env bash
        cd /workspace/tekton-pvc

        git config --global --add safe.directory /workspace/tekton-pvc

        COMMIT_SHA_SHORT="$(git rev-parse --short HEAD | tr -d '\n')"
        echo -n "$COMMIT_SHA_SHORT" > $(results.commitshashort.path)
      timeout: 20s

task2.
Kanilo 를 통해 container image를 build 후 destination(테스트용 개인 DockerHub)으로 push하는 동작을 담고 있다.
image의 tag는 이전 task의 result를 통해서 넘어왔다.

Dockerfile은 테스트용 repository에 간단하게 빌드가 가능하도록 만들어두었다.
Dockerhub에 접근하기 위한 인증을 담은 secret을 사용할 수 있게 volumeMount해준다.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: build-container-and-push
spec:
  workspaces:
  - name: tekton-pvc
  params:
    - name: commitshashort
      type: string
  steps:
    - name: kaniko
      image: gcr.io/kaniko-project/executor:latest
      workingDir: $(workspaces.tekton-pvc.path)
      args:
        - --dockerfile=$(workspaces.tekton-pvc.path)/Dockerfile
        - --destination=your/dockerhub:$(params.commitshashort)
        - --context=$(workspaces.tekton-pvc.path)
      volumeMounts:
        - name: my-secret
          mountPath: /kaniko/.docker/
  volumes:
    - name: my-secret
      secret:
        secretName: my-secret
        items:
        - key: .dockerconfigjson
          path: config.json

 

ServiceAccount

이건 그냥 ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-sa
secrets:
 - name: my-secret

Secret

DockerHub에 접근하기 위한 정보를 담은 secret
이를 위한 secret 생성 방법

kubectl create secret docker-registry my-secret --docker-server=https://index.docker.io/v1/ --docker-username=yourid --docker-password=yourpassword --docker-email=youremail --dry-run=client -o yaml > my-secret.yaml

아래와 같은 형태가 된다.

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: ##

 

결과

해당 동작을 다 완료하면 Tekton dashboard에서 아래와 같이 보일 것이고,


Dockerhub의 repository에는 이렇게 이미지가 들어와있을 것이다.

 

Reference

* https://tekton.dev/
* https://tekton.dev/docs/getting-started/
* https://github.com/tektoncd/pipeline/blob/main/docs/resources.md#git-resource

반응형