카테고리 없음

Tekton 으로 하는 CI 소개

mokpolar 2025. 3. 29. 04:25
반응형

안녕하세요?

AEWS 8주차 CI/CD 과제로 Tekton CI에 대해서 소개해보겠습니다.

 

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을 쓰는가?

 

쿠버네티스 환경에서 서비스를 할때 컨테이너 이미지는 지속적으로 변화할 수 있습니다.
이런 기능을 하는 도구는 여러가지가 있지만 특정 노드에 구애받지 않고 쿠버네티스 클러스터의 자원들을 자유롭게 사용하는 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/
아래 작업의 설명을 위해서 간단하게 구조도만 갖고와 보면,

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

 

 

Tekton의 CI Workflow는 Pipeline > Task > Step 으로 구성되어 있습니다.

 

  • Step는 CI/CD 워크플로우 내에서 수행되는 하나의 작업입니다. 예를 들어, Python 웹 애플리케이션의 유닛 테스트 실행이나 Java 프로그램의 컴파일 등이 해당됩니다. Tekton은 각 step을 사용자가 제공한 컨테이너 이미지를 사용해 실행합니다. 예를 들어, Go 프로그램을 빌드하기 위해 공식 Go 이미지를 사용할 수 있으며, 이는 로컬 워크스테이션에서 go build를 실행하는 것과 동일한 방식입니다.
  • Task는 순차적으로 실행되는 step들의 집합입니다. Tekton은 각 task를 Kubernetes Pod의 형태로 실행하며, 각 step은 해당 pod 내에서 실행되는 하나의 컨테이너가 됩니다. 이 구조를 통해 관련 있는 여러 step이 공유된 실행 환경에서 실행될 수 있습니다. 예를 들어, Kubernetes 볼륨을 task에 마운트하면 해당 볼륨은 task의 모든 step에서 접근할 수 있게 됩니다.
  • Pipeline은 순차적으로 연결된 task들의 집합입니다. Tekton은 모든 task를 모아 DAG(유향 비순환 그래프) 형태로 연결하고, 이 그래프를 순서대로 실행합니다. 즉, 여러 Kubernetes pod를 생성하고, 각 pod가 원하는 방식대로 성공적으로 실행되도록 보장합니다. Tekton은 개발자에게 프로세스에 대한 완전한 제어권을 제공합니다. 예를 들어:
    • 여러 task의 결과를 모으거나 분기(fan-in/fan-out) 구조로 설정할 수 있으며,
    • 불안정한 테스트에 대해 자동으로 재시도(retry)하도록 지정할 수 있고,
    • 특정 조건이 만족되어야 다음 task로 진행하도록 조건(condition)을 설정할 수 있습니다.

 

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

  • PipelineRun은 이름 그대로 특정 파이프라인의 한 번의 실행을 의미합니다. 예를 들어, Tekton에게 CI/CD 워크플로우를 하루에 두 번 실행하도록 요청하면, 각 실행은 Kubernetes 클러스터에서 추적 가능한 하나의 pipelineRun 리소스로 생성됩니다. pipelineRun을 통해 각 task 실행의 세부 사항을 포함한 CI/CD 워크플로우의 상태를 확인할 수 있습니다.
  • TaskRun도 마찬가지로 특정 task의 한 번의 실행을 나타냅니다. pipeline 외부에서 task를 단독으로 실행할 경우에도 TaskRun이 생성되며, 이를 통해 해당 task 내 step 각각의 실행 세부 정보를 확인할 수 있습니다.
  • TaskRun과 PipelineRun은 리소스를 task 및 pipeline과 연결하는 역할을 합니다. 실행 시에는 실제 리소스의 주소를 포함해야 하며, 예를 들어 필요한 리포지토리의 URL 등을 지정해야 합니다. 이러한 설계를 통해 동일한 task와 pipeline을 다양한 입력과 출력에 대해 재사용할 수 있습니다.
  • TaskRun이나 PipelineRun은 수동으로 생성할 수도 있으며, 이 경우 Tekton은 즉시 해당 task 또는 pipeline을 실행합니다. 또는 Tekton의 구성 요소 중 하나인 Tekton Triggers를 이용해 자동으로 실행되도록 설정할 수도 있습니다. 예를 들어, 새로운 Pull Request가 Git 리포지토리에 등록될 때마다 pipeline을 자동으로 실행되게 만들 수 있습니다.

 

설치

준비물

  • 쿠버네티스 환경 
  • 사용자 환경에 따라 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를 순서대로 설명해보면,
result는 task에서 뽑아낸 parameter이며,
workspace는 미리 배포해 둔 PersistentVolumeClaim입니다.
task가 순서대로 정의되어 있는 모습을 볼 수 있습니다.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: test-pipeline
  namespace: tekton
spec:
  workspaces:
    - name: shared-directory
  tasks:
    - name: git-clone
      taskRef:
        name: git-clone
      workspaces:
        - name: shared-directory
          workspace: shared-directory
    - 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: shared-directory
          workspace: shared-directory
    - name: yaml-update
      taskRef:
        name: yaml-update
      runAfter: 
        - "build-container-and-push"
      params:
        - name: imageurl
          value: mokpolar/tekton-pipeline-test:$(tasks.git-clone.results.commitshashort)
      workspaces:
        - name: shared-directory
          workspace: shared-directory

 

 

PipelineRun

Pipeline에서 정의한 내용을 PipelineRun을 통해 실행합니다.

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: test-pipelinerun
  namespace: tekton
spec:
  workspaces:
  - name: shared-directory
    persistentvolumeclaim:
      claimName: shared-directory
  serviceAccountName: my-sa
  pipelineRef:
    name: test-pipeline

 

 

 

Task

task1.
앞서 설명했듯이 Tekton task는 실제 pod 단위가 됩니다.

동작은 script에 정의합니다.

repo를 clone해오는 동작을 담고 있습니다.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-clone
  namespace: tekton
spec:
  results:
  - name: commitshashort
  workspaces:
  - name: shared-directory
  params:
    - name: repositoryurl
      description: git url to clone
      type: string
      default: https://github.com/mokpolar/gitops-tekton-argocd
  steps:
    - name: generate-tag
      image: mokpolar/test-cloner
      script: |
        #!/bin/bash

        CHECKOUT_DIR="$(workspaces.shared-directory.path)/"

        cd $CHECKOUT_DIR

        git clone $(params.repositoryurl)
        
        cd gitops-tekton-argocd

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

 

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

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

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.8

COPY app /app

# Install any additional dependencies here (if required)

# Expose port 80
EXPOSE 80

# Start the server
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

 

task3.

3번째 Task에서는 GitOps 대상 repo에 있는 대상 manifest를 업데이트 해주는 과정입니다.

1번째 Task에서 넘어온 commitshashort가 반영된 image url로

yq를 이용해서 pod manifest의 image 부분을 변경해주었습니다.

 

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: yaml-update
  namespace: tekton
spec:
  workspaces:
  - name: shared-directory
  params:
  - name: repositoryurl
    type: string
    default: https://github.com/mokpolar/gitops-tekton-argocd
  - name: imageurl
    type: string
  steps:
    - name: deploy-to-argocd
      image: mokpolar/test-cloner
      script: |
        #!/bin/bash        
        
        CHECKOUT_DIR="$(workspaces.shared-directory.path)/"

        cd gitops-tekton-argocd

        yq e --inplace '.spec.containers.[0].image = "$(params.imageurl)"' -i ./deploy/pod.yaml

    
        git add ./deploy/pod.yaml
        git commit -m "tekton : deploy image version $(params.imageurl)"
        git push

 

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: ##

 

결과

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

 

Reference

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

반응형