본문 바로가기

Cloud/Kubernetes

Tekton Pipelines Tutorial

https://github.com/tektoncd/pipeline/blob/master/docs/tutorial.md

 

tektoncd/pipeline

A K8s-native Pipeline resource. Contribute to tektoncd/pipeline development by creating an account on GitHub.

github.com

Tekton Pipeline은 Kubernetes 환경에서 CI/CD를 제공한다. 튜토리얼을 통해서 이해하고 넘어가려고 한다. Tekton Pipeline은설치 시 아래 엔티티를 정의한다. (설명은 내 마음대로다)

엔티티 설명
Task 하나의 단계 (단위는 컨테이너)
TaskRun 매개변수를 사용하여 Task를 실행 (파이프라인 런을 통해서도 생성된다)
Pipeline Task의 순서를 정해서 정의
PipelineRun 파이프라인을 실행
PipelineResource 태스크를 실행할 때 매개변수를 미리 지정해놓는 리소스

설치는 패스하고 튜토리얼부터 정리해본다.

- Creating and running a Task

- Creating and running a Pipeline

1. Task 생성 및 실행

 태스크는 내가 지정한 작업을 실행한다. 아래 태스크는 Hello, Danika를 출력해준다.

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: echo-task
  namespace: default
spec:
  steps:
    - name: echo
      image: ubuntu
      command:
        - echo
      args:
        - "Hello, Danika!"

생성 이후 조회해준다.

[root@compute ~]# kubectl get task -o yaml
apiVersion: v1
items:
- apiVersion: tekton.dev/v1beta1
  kind: Task
  metadata:
    creationTimestamp: "2020-08-24T08:12:16Z"
    generation: 1
    name: echo-task
    namespace: default
    resourceVersion: "4002206"
    selfLink: /apis/tekton.dev/v1beta1/namespaces/default/tasks/echo-task
    uid: be227432-e99d-4b2a-9e1d-216e65b47302
  spec:
    steps:
    - args:
      - Hello, Danika!
      command:
      - echo
      image: ubuntu
      name: echo
      resources: {}
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

태스크를 실행하기 위해서는 TaskRun을 생성해야한다.

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  name: echo-taskrun
  namespace: default
spec:
  taskRef:
    name: echo-task

TaskRun 생성 이후 파드를 조회하면 새로운 파드가 생성된 것을 볼 수 있다. 해당 파드의 로그를 살펴본다.

[root@compute ~]# kubectl get pods
NAME                                        READY   STATUS      RESTARTS   AGE
echo-taskrun-pod-bppjp                      0/1     Completed   0          35s

[root@compute ~]# kubectl logs echo-taskrun-pod-bppjp
Hello, Danika!

내가 지정한 작업을 잘 마친 다음 Completed 상태에서 은은하게 머물러 있다. 이제 이거보다 조금 더 어려운 태스크를 만들어본다.

2. 입력 출력을 가진 Task 생성 및 실행

 Task의 입력/출력에 사용할 PipelineResource를 만들어둔다. 

- 빌드할 GIT 주소

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: skaffold-git
  namespace: default
spec:
  type: git
  params:
    - name: revision
      value: master
    - name: url
      value: https://github.com/onenumbersol/skaffold

- 푸시 할 저장소 주소

apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: skaffold-image-leeroy-web
  namespace: default
spec:
  type: image
  params:
    - name: url
      value: [Registry_Address]/leeroy-web

git은 skaffold 저장소 포크해왔다.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: build-docker-image-from-git-source
  namespace: default
spec:
  params:
    - name: pathToDockerFile
      type: string
      description: The path to the dockerfile to build
      default: $(resources.inputs.docker-source.path)/Dockerfile
    - name: pathToContext
      type: string
      description: |
        The build context used by Kaniko
        (https://github.com/GoogleContainerTools/kaniko#kaniko-build-contexts)
      default: $(resources.inputs.docker-source.path)
  resources:
    inputs:
      - name: docker-source
        type: git
    outputs:
      - name: builtImage
        type: image
  steps:
    - name: build-and-push
      image: gcr.io/kaniko-project/executor:v0.16.0
      # specifying DOCKER_CONFIG is required to allow kaniko to detect docker credential
      env:
        - name: "DOCKER_CONFIG"
          value: "/tekton/home/.docker/"
      command:
        - /kaniko/executor
      args:
        - --dockerfile=$(params.pathToDockerFile)
        - --destination=$(resources.outputs.builtImage.url)
        - --context=$(params.pathToContext)

Task를 생성해준다. YAML을 보면 이전에는 없었던 것들이 보인다.

위치 이름 내용
spec.params pathToDockerFile Build 할 dockerfile의 위치
spec.params pathToContext Kaniko를 통해 build할 context의 위치
spec.resources docker-source Git 주소
spec.resources builtImage Image 주소

Step을 보면 kaniko-project라는 애를 통해서 build 및 push를 해주는 것을 볼 수 있다. 튜토리얼에서는 credentials를 사용할 수 있는 SA를 생성해주는데 난 내부 저장소라서 필요없으니 패스한다.

 이제 TASK를 실행해본다.

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  name: build-docker-image-from-git-source-task-run
  namespace: default
spec:
  serviceAccountName: default
  taskRef:
    name: build-docker-image-from-git-source
  params:
    - name: pathToDockerFile
      value: Dockerfile
    - name: pathToContext
      value: $(resources.inputs.docker-source.path)/examples/microservices/leeroy-web #configure: may change according to your source
  resources:
    inputs:
      - name: docker-source
        resourceRef:
          name: skaffold-git
    outputs:
      - name: builtImage
        resourceRef:
          name: skaffold-image-leeroy-web
위치 이름 내용
spec.params pathToDockerFile dockerfile 이름
spec.params pathToContext Kaniko를 통해 build할 context의 위치
spec.resources docker-source PipelineResource 이름과 매핑 (GIT)
spec.resources builtImage PipelineResource 이름과 매핑 (IMAGE)

실행하면 빌드 및 푸시를 수행하는 파드를 확인할 수 있다.

[root@compute ~]# kubectl get pods
NAME                                                    READY   STATUS            RESTARTS   AGE
build-docker-image-from-git-source-task-run-pod-6ts69   0/4     PodInitializing   0          2m

Completed 상태로 변경되면 지정한 이미지 저장소에 이미지가 들어갔는지 확인해본다.

[root@compute ~]# curl -X GET REGISTRY_ADDRESS/v2/_catalog
{"repositories":["leeroy-web"]}

이상없이 진행되었음을 볼 수 있다.

3. 파이프라인 생성 및 실행

 파이프라인은 생성한 태스크들의 순서를 정해주고 입력/출력의 결과를 매핑해주는 역할을 한다. 빌드 및 푸쉬를 진행했으면 해당 이미지를 통해 웹서비스를 띄우는 작업까지 한 번에 진행해주는 파이프라인을 생성한다.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: tutorial-pipeline
  namespace: default
spec:
  resources:
    - name: source-repo
      type: git
    - name: web-image
      type: image
  tasks:
    - name: build-skaffold-web
      taskRef:
        name: build-docker-image-from-git-source
      params:
        - name: pathToDockerFile
          value: Dockerfile
        - name: pathToContext
          value: /workspace/docker-source/examples/microservices/leeroy-web #configure: may change according to your source
      resources:
        inputs:
          - name: docker-source
            resource: source-repo
        outputs:
          - name: builtImage
            resource: web-image
    - name: deploy-web
      taskRef:
        name: deploy-using-kubectl
      resources:
        inputs:
          - name: source
            resource: source-repo
          - name: image
            resource: web-image
            from:
              - build-skaffold-web
      params:
        - name: path
          value: /workspace/source/examples/microservices/leeroy-web/kubernetes/deployment.yaml #configure: may change according to your source
        - name: yamlPathToImage
          value: "spec.template.spec.containers[0].image"

spec.tasks.taskRef를 보면 name으로 이전에 생성한 task를 지정해주는 것을 볼 수 있다. 이전에 build-docker-image-form-git-source는 생성해주었으나 deploy-using-kubectl은 존재하지 않으므로 만들어준다.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: deploy-using-kubectl
  namespace: default
spec:
  params:
    - name: path
      type: string
      description: Path to the manifest to apply
    - name: yamlPathToImage
      type: string
      description: |
        The path to the image to replace in the yaml manifest (arg to yq)
  resources:
    inputs:
      - name: source
        type: git
      - name: image
        type: image
  steps:
    - name: replace-image
      image: mikefarah/yq
      command: ["yq"]
      args:
        - "w"
        - "-i"
        - "$(params.path)"
        - "$(params.yamlPathToImage)"
        - "$(resources.inputs.image.url)"
    - name: run-kubectl
      image: lachlanevenson/k8s-kubectl
      command: ["kubectl"]
      args:
        - "apply"
        - "-f"
        - "$(params.path)"

생성한 tutorial-pipeline에는 총 2개의 태스크가 존재한다. 첫번째는 build and push를 진행해주는 build-docker-image-form-git-source 태스크이고, 두번째는 kubectl을 이용하여 웹 파드를 생성해주는 deploy-using-kubectl 태스크이다.  task는 정해진 순서가 있어야 한다. spec.tasks.name.resources.input 아래를 보면 from을 통해 이전 작업을 지정해주는 것을 볼 수 있다.

특정 namespace에 deploy를 하려면 service account에 해당 롤이 지정되어 있어야 한다.  난 미리 지정해두었는데 없으면 롤 생성 이후 바인딩을 해준다. 그리고 파이프라인 런을 실행해준다.

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: tutorial-pipeline-run-1
  namespace: default
spec:
  serviceAccountName: sa-test
  pipelineRef:
    name: tutorial-pipeline
  resources:
    - name: source-repo
      resourceRef:
        name: skaffold-git
    - name: web-image
      resourceRef:
        name: skaffold-image-leeroy-web

실행 된 이후 파드들을 확인해본다.

[root@compute ~]# kubectl get pods
NAME                                                         READY   STATUS      RESTARTS   AGE
leeroy-web-65b7986d78-j76dr                                  1/1     Running     0          2m7s
tutorial-pipeline-run-1-build-skaffold-web-qjdz5-pod-9xqq4   0/4     Completed   0          3m34s
tutorial-pipeline-run-1-deploy-web-c7wbs-pod-jfnxb           0/3     Completed   0          2m38s

leeroy-web 파드가 실행되어 Running 상태를 가지고 있다. 로그를 보자...

[root@compute ~]# k logs leeroy-web-65b7986d78-j76dr
2020/08/24 09:15:02 leeroy web server ready

제대로 배포되었음을 볼 수 있다. 이 정도면 해당 오브젝트들이 각각 어느 역할을 하는지에 대해서는 쪼끔이라도 이해한 것 같다.