티스토리 뷰

728x90
반응형

개요

이번 포스팅에서는 Tekton Pipeline을 실제로 구축해 보도록 하자. 여러 단계에 걸쳐 Tekton에서 수행될 Task를 Pipeline으로 연결하고, 최종적으로 EKS에 배포하는 과정까지 알아보도록 한다.

먼저 이번 포스팅에서는 Docker Image를 생성하고 Docker Registry에 Push하는 과정에 대해 알아보자.

  • git-clone
  • maven build
  • image build
  • image push

0. 구성 전 준비사항

> Kubernetes 1.16 이상 버전 구축 : Amazon EKS(Kubernetes 1.19)

> Service Account 권한 부여 : GitHub / DockerHub

> Workspace 용 pv, pvc 준비: 공유 데이터 저장소

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 500Mi
  nfs:
    path: /share/etc
    server: 192.168.71.110

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: maven-source-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi
  storageClassName: gp2
  volumeMode: Filesystem

1. git-clone task

첫번째 Task는 git-clone이다. git-clone은 소스코드를 다운로드 받아 빌드하기 위한 준비과정을 정의한다.

1) hub.tekton.dev 에서 git-clone task 다운로드 및 메뉴얼 확인

> 앞선 포스팅에서도 확인했듯이 Install 버튼을 클릭하여 기 정의되어 있는 Task Template을 Kubernetes에 적용한다.

[root@ip-192-168-71-110 tekton]# kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.4/git-clone.yaml
task.tekton.dev/git-clone created
[root@ip-192-168-71-110 tekton]#

> 커스터마이징이 필요할 경우 wget으로 다운로드 받아 수정후 반영한다.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-clone
  labels:
    app.kubernetes.io/version: "0.4"
  annotations:
    tekton.dev/pipelines.minVersion: "0.21.0"
    tekton.dev/tags: git
    tekton.dev/displayName: "git clone"
spec:
  description: >-
    These Tasks are Git tasks to work with repositories used by other tasks
    in your Pipeline.

    The git-clone Task will clone a repo from the provided url into the
    output Workspace. By default the repo will be cloned into the root of
    your Workspace. You can clone into a subdirectory by setting this Task's
    subdirectory param. This Task also supports sparse checkouts. To perform
    a sparse checkout, pass a list of comma separated directory patterns to
    this Task's sparseCheckoutDirectories param.
  workspaces:
    - name: output
      description: The git repo will be cloned onto the volume backing this Workspace.
    - name: ssh-directory
      optional: true
      description: |
        A .ssh directory with private key, known_hosts, config, etc. Copied to
        the user's home before git commands are executed. Used to authenticate
        with the git remote when performing the clone. Binding a Secret to this
        Workspace is strongly recommended over other volume types.
    - name: basic-auth
      optional: true
      description: |
        A Workspace containing a .gitconfig and .git-credentials file. These
        will be copied to the user's home before any git commands are run. Any
        other files in this Workspace are ignored. It is strongly recommended
        to use ssh-directory over basic-auth whenever possible and to bind a
        Secret to this Workspace over other volume types.
  params:
    - name: url
      description: Repository URL to clone from.
      type: string
    - name: revision
      description: Revision to checkout. (branch, tag, sha, ref, etc...)
      type: string
      default: ""
    - name: refspec
      description: Refspec to fetch before checking out revision.
      default: ""
    - name: submodules
      description: Initialize and fetch git submodules.
      type: string
      default: "true"
    - name: depth
      description: Perform a shallow clone, fetching only the most recent N commits.
      type: string
      default: "1"
    - name: sslVerify
      description: Set the `http.sslVerify` global git config. Setting this to `false` is not advised unless you are sure that you trust your git remote.
      type: string
      default: "true"
    - name: subdirectory
      description: Subdirectory inside the `output` Workspace to clone the repo into.
      type: string
      default: ""
    - name: sparseCheckoutDirectories
      description: Define the directory patterns to match or exclude when performing a sparse checkout.
      type: string
      default: ""
    - name: deleteExisting
      description: Clean out the contents of the destination directory if it already exists before cloning.
      type: string
      default: "true"
    - name: httpProxy
      description: HTTP proxy server for non-SSL requests.
      type: string
      default: ""
    - name: httpsProxy
      description: HTTPS proxy server for SSL requests.
      type: string
      default: ""
    - name: noProxy
      description: Opt out of proxying HTTP/HTTPS requests.
      type: string
      default: ""
    - name: verbose
      description: Log the commands that are executed during `git-clone`'s operation.
      type: string
      default: "true"
    - name: gitInitImage
      description: The image providing the git-init binary that this Task runs.
      type: string
      default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.21.0"
    - name: userHome
      description: |
        Absolute path to the user's home directory. Set this explicitly if you are running the image as a non-root user or have overridden
        the gitInitImage param with an image containing custom user configuration.
      type: string
      default: "/tekton/home"
  results:
    - name: commit
      description: The precise commit SHA that was fetched by this Task.
    - name: url
      description: The precise URL that was fetched by this Task.
  steps:
    - name: clone
      image: "$(params.gitInitImage)"
      env:
      - name: HOME
        value: "$(params.userHome)"
      - name: PARAM_URL
        value: $(params.url)
      - name: PARAM_REVISION
        value: $(params.revision)
      - name: PARAM_REFSPEC
        value: $(params.refspec)
      - name: PARAM_SUBMODULES
        value: $(params.submodules)
      - name: PARAM_DEPTH
        value: $(params.depth)
      - name: PARAM_SSL_VERIFY
        value: $(params.sslVerify)
      - name: PARAM_SUBDIRECTORY
        value: $(params.subdirectory)
      - name: PARAM_DELETE_EXISTING
        value: $(params.deleteExisting)
      - name: PARAM_HTTP_PROXY
        value: $(params.httpProxy)
      - name: PARAM_HTTPS_PROXY
        value: $(params.httpsProxy)
      - name: PARAM_NO_PROXY
        value: $(params.noProxy)
      - name: PARAM_VERBOSE
        value: $(params.verbose)
      - name: PARAM_SPARSE_CHECKOUT_DIRECTORIES
        value: $(params.sparseCheckoutDirectories)
      - name: PARAM_USER_HOME
        value: $(params.userHome)
      - name: WORKSPACE_OUTPUT_PATH
        value: $(workspaces.output.path)
      - name: WORKSPACE_SSH_DIRECTORY_BOUND
        value: $(workspaces.ssh-directory.bound)
      - name: WORKSPACE_SSH_DIRECTORY_PATH
        value: $(workspaces.ssh-directory.path)
      - name: WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND
        value: $(workspaces.basic-auth.bound)
      - name: WORKSPACE_BASIC_AUTH_DIRECTORY_PATH
        value: $(workspaces.basic-auth.path)
      script: |
        #!/usr/bin/env sh
        set -eu

        if [ "${PARAM_VERBOSE}" = "true" ] ; then
          set -x
        fi

        if [ "${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}" = "true" ] ; then
          cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials" "${PARAM_USER_HOME}/.git-credentials"
          cp "${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig" "${PARAM_USER_HOME}/.gitconfig"
          chmod 400 "${PARAM_USER_HOME}/.git-credentials"
          chmod 400 "${PARAM_USER_HOME}/.gitconfig"
        fi

        if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then
          cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh
          chmod 700 "${PARAM_USER_HOME}"/.ssh
          chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
        fi

        CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}"

        cleandir() {
          # Delete any existing contents of the repo directory if it exists.
          #
          # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"
          # or the root of a mounted volume.
          if [ -d "${CHECKOUT_DIR}" ] ; then
            # Delete non-hidden files and directories
            rm -rf "${CHECKOUT_DIR:?}"/*
            # Delete files and directories starting with . but excluding ..
            rm -rf "${CHECKOUT_DIR}"/.[!.]*
            # Delete files and directories starting with .. plus any other character
            rm -rf "${CHECKOUT_DIR}"/..?*
          fi
        }

        if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then
          cleandir
        fi

        test -z "${PARAM_HTTP_PROXY}" || export HTTP_PROXY="${PARAM_HTTP_PROXY}"
        test -z "${PARAM_HTTPS_PROXY}" || export HTTPS_PROXY="${PARAM_HTTPS_PROXY}"
        test -z "${PARAM_NO_PROXY}" || export NO_PROXY="${PARAM_NO_PROXY}"

        /ko-app/git-init \
          -url="${PARAM_URL}" \
          -revision="${PARAM_REVISION}" \
          -refspec="${PARAM_REFSPEC}" \
          -path="${CHECKOUT_DIR}" \
          -sslVerify="${PARAM_SSL_VERIFY}" \
          -submodules="${PARAM_SUBMODULES}" \
          -depth="${PARAM_DEPTH}" \
          -sparseCheckoutDirectories="${PARAM_SPARSE_CHECKOUT_DIRECTORIES}"
        cd "${CHECKOUT_DIR}"
        RESULT_SHA="$(git rev-parse HEAD)"
        EXIT_CODE="$?"
        if [ "${EXIT_CODE}" != 0 ] ; then
          exit "${EXIT_CODE}"
        fi
        printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
        printf "%s" "${PARAM_URL}" > "$(results.url.path)"

2) Tekton Dashboard 확인

> Task는 다음과 같이 추가된 것을 알 수 있다.

3) Pipeline 구성

첫번째 파이프라인 Task로 clone-repository를 등록한다.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: tekton-sample-pipeline
spec:
  workspaces:
    - name: pipeline-shared-data
  tasks:
    - name: clone-repository
      params:
        - name: url
          value: https://github.com/sonnaraon/Xray-Sample
        - name: revision
          value: "master"
        - name: deleteExisting
          value: "true"
      taskRef:
        kind: Task
        name: git-clone
      workspaces:
        - name: output
          workspace: pipeline-shared-data

> git-clone은 다음과 같은 필수 요소를 충족하게 구성해야 한다.

  • The URL of a git repo to clone provided with the url param.
  • A Workspace called output.

위 필수 파라미터는 url로부터 clone 받은 소스코드를 output으로 정의된 workspace로 복제하는 역할을 한다. 기본적으로 소스코드는 workspace의 루트 디렉토리에 복사된다. 해당 경로에 파일이 존재할 경우 deleteExisting 옵션으로 삭제 후 다운로드 받을 것인지를 결정할 수 있다.

> git-clone에서 사용되는 workspaces는 크게 3가지 존재한다.

  • output: A workspace for this Task to fetch the git repository in to.
  • ssh-directory: An optional workspace to provide SSH credentials. At minimum this should include a private key but can also include other common files from .ssh including config and known_hosts. It is strongly recommended that this workspace be bound to a Kubernetes Secret.
  • basic-auth: An optional workspace containing .gitconfig and .git-credentials files. This allows username/password/access token to be provided for basic auth.Note: Settings provided as part of a .gitconfig file can affect the execution of git in ways that conflict with the parameters of this Task. For example, specifying proxy settings in .gitconfig could conflict with the httpProxy and httpsProxy parameters this Task provides. Nothing prevents you setting these parameters but it is not advised.
  • It is strongly recommended that this workspace be bound to a Kubernetes Secret. For details on the correct format of the files in this Workspace see Using basic-auth Credentials below.

> git-clone에 적용가능한 parameter는 다음과 같다.

  • url: Repository URL to clone from. (required)
  • revision: Revision to checkout. (branch, tag, sha, ref, etc...) (default: "")
  • refspec: Refspec to fetch before checking out revision. (default:"")
  • submodules: Initialize and fetch git submodules. (default: true)
  • depth: Perform a shallow clone, fetching only the most recent N commits. (default: 1)
  • sslVerify: Set the http.sslVerify global git config. Setting this to false is not advised unless you are sure that you trust your git remote. (default: true)
  • subdirectory: Subdirectory inside the output workspace to clone the repo into. (default: "")
  • deleteExisting: Clean out the contents of the destination directory if it already exists before cloning. (default: true)
  • httpProxy: HTTP proxy server for non-SSL requests. (default: "")
  • httpsProxy: HTTPS proxy server for SSL requests. (default: "")
  • noProxy: Opt out of proxying HTTP/HTTPS requests. (default: "")
  • verbose: Log the commands that are executed during git-clone's operation. (default: true)
  • sparseCheckoutDirectories: which directories to match or exclude when performing a sparse checkout (default: "")
  • gitInitImage: The image providing the git-init binary that this Task runs. (default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:TODO")
  • userHome: The user's home directory. Set this explicitly if you are running the image as a non-root user. (default: "/tekton/home")

4) PipelineRun 구성

먼저, workspaces를 연동할 pvc를 등록하고 반영한다.

[root@ip-192-168-71-110 git-clone]# kubectl get pv,pvc
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                      STORAGECLASS   REASON   AGE
persistentvolume/pv                                         500Mi      RWO            Retain           Available                                                      11h
persistentvolume/pvc-4ad1a0b6-ab3a-4fcd-86e7-85362465ed98   1Gi        RWO            Delete           Bound       default/maven-source-pvc   gp2                     11h

NAME                                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/maven-source-pvc   Bound    pvc-4ad1a0b6-ab3a-4fcd-86e7-85362465ed98   1Gi        RWO            gp2            11h
[root@ip-192-168-71-110 git-clone]#

> 아래와 같이 claimName을 지정한다. 이때 pipeline-shared-data는 git-clone task가 수행되며, cloning 된 소스코드가 저장되는 workspace 공간이 된다.

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: tekton-sample-pipeline-run
spec:
  pipelineRef:
    name: tekton-sample-pipeline
  workspaces:
    - name: pipeline-shared-data
      persistentvolumeclaim:
        claimName: maven-source-pvc

5) 대시보드 확인

아래와 같이 반영 후 대시보드를 확인한다.

[root@ip-192-168-71-110 git-clone]# kubectl apply -f pipelinerun.yaml 
pipelinerun.tekton.dev/tekton-sample-pipeline-run created
[root@ip-192-168-71-110 git-clone]#

> PipelineRuns와 Pipeline은 다음과 같이 등록되어 있다.

> PipelineRuns의 tekton-sample-pipeline-run을 선택하고 들어가면 다음과 같이 상세 정보를 확인할 수 있다.

> 위 상세 화면에서 실행 가능한 또는 확인 가능한 정보는 5가지로 구분해 볼 수 있다.

  • 성공여부 : 위와 같이 초록색 박스로 체크되어 있을 경우 의도한데로 동작하는 경우이며, 빨간색으로 표시될 경우 2,3,4를 통해 원인을 진단해 보아야 한다.
  • Logs : 해당 Task가 동작하는 동안의 로그 정보를 확인할 수 있다. 아래와 같이 주요 액션을 확인하고, 오류 발생 시 발생 원인을 파악할 수 있다.
+ '[' false '=' true ]
+ '[' false '=' true ]
+ CHECKOUT_DIR=/workspace/output/
+ '[' true '=' true ]
+ cleandir
+ '[' -d /workspace/output/ ]
+ rm -rf /workspace/output//Dockerfile /workspace/output//ReadMe.txt /workspace/output//bin /workspace/output//deployment.yaml /workspace/output//logstash.conf /workspace/output//mvnw /workspace/output//mvnw.cmd /workspace/output//pom.xml /workspace/output//src
+ rm -rf /workspace/output//.git /workspace/output//.gitignore /workspace/output//.mvn /workspace/output//.tern-project
+ rm -rf '/workspace/output//..?*'
+ test -z 
+ test -z 
+ test -z 
+ /ko-app/git-init '-url=https://github.com/sonnaraon/Xray-Sample' '-revision=master' '-refspec=' '-path=/workspace/output/' '-sslVerify=true' '-submodules=true' '-depth=1' '-sparseCheckoutDirectories='
{"level":"info","ts":1625968012.138267,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/sonnaraon/Xray-Sample @ d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217 (grafted, HEAD, origin/master) in path /workspace/output/"}
{"level":"info","ts":1625968012.164239,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/output/"}
+ cd /workspace/output/
+ git rev-parse HEAD
+ RESULT_SHA=d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217
+ EXIT_CODE=0
+ '[' 0 '!=' 0 ]
+ printf '%s' d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217
+ printf '%s' https://github.com/sonnaraon/Xray-Sample
  • Status : Status에서는 Task가 수행되면서 발생되는 액션의 in/out을 정의한다. 대체로 확인해야 할 정보는 terminated.message 정보이며, 해당 정보에서 commit(git-clone task에서 가져온 commit 정보), url(git-clone task에서 가져온 url 정보)를 확인하여 수행하고자 했던데로 동작하였는 확인할 필요가 있다.
container: step-clone
imageID: >-
  docker-pullable://gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init@sha256:db18a9c1607c8cbbcd72f61d0c4d795b9ff528669deacd5f8a1672e4ef198ffd
name: clone
terminated:
  containerID: 'docker://1032480e52de5d0db2368cc2152384cb7633d9758aa01e67af67856bd949af43'
  exitCode: 0
  finishedAt: '2021-07-11T01:46:52Z'
  message: >-
    [{"key":"commit","value":"d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217","type":"TaskRunResult"},{"key":"url","value":"https://github.com/sonnaraon/Xray-Sample","type":"TaskRunResult"}]
  reason: Completed
  startedAt: '2021-07-11T01:46:51Z'
  • Details : Task의 상세 정보를 확인한다.
  • Rerun : 동일 동작을 재빌드한다.

> 위와 같이 Rerun을 선택하면 동일한 동작이 재 실행된다.

> 이때 위와 같이 동작하며, 상태를 재 진단할 수 있다. Pipeline/PipelineRun/Task 등에 수정이 발생된 경우 tkn 또는 kubectl로 반영하고 이를 재빌드하는 방법이다.

6) tkn 명령어 확인

마지막으로 tkn 명령어 확인방법이다.

> tkn pr list (pipelinerun list)

[root@ip-192-168-71-110 pipeline]# tkn pr list
NAME                                 STARTED         DURATION     STATUS               
tekton-sample-pipeline-run-r-fdvmw   2 minutes ago   14 seconds   Succeeded   
tekton-sample-pipeline-run-r-d2gm6   3 minutes ago   14 seconds   Succeeded   
tekton-sample-pipeline-run           1 hour ago      23 seconds   Succeeded   
[root@ip-192-168-71-110 pipeline]#

> tkn pr logs [pr_name or --last -f] (pipelinerun log 확인)

[root@ip-192-168-71-110 pipeline]# tkn pr logs --last -f 
[clone-repository : clone] + '[' false '=' true ]
[clone-repository : clone] + '[' false '=' true ]
[clone-repository : clone] + CHECKOUT_DIR=/workspace/output/
[clone-repository : clone] + '[' true '=' true ]
[clone-repository : clone] + cleandir
[clone-repository : clone] + '[' -d /workspace/output/ ]
[clone-repository : clone] + rm -rf /workspace/output//Dockerfile /workspace/output//ReadMe.txt /workspace/output//bin /workspace/output//deployment.yaml /workspace/output//logstash.conf /workspace/output//mvnw /workspace/output//mvnw.cmd /workspace/output//pom.xml /workspace/output//src
[clone-repository : clone] + rm -rf /workspace/output//.git /workspace/output//.gitignore /workspace/output//.mvn /workspace/output//.tern-project
[clone-repository : clone] + rm -rf '/workspace/output//..?*'
[clone-repository : clone] + test -z 
[clone-repository : clone] + test -z 
[clone-repository : clone] + test -z 
[clone-repository : clone] + /ko-app/git-init '-url=https://github.com/sonnaraon/Xray-Sample' '-revision=master' '-refspec=' '-path=/workspace/output/' '-sslVerify=true' '-submodules=true' '-depth=1' '-sparseCheckoutDirectories='
[clone-repository : clone] {"level":"info","ts":1625971686.682756,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/sonnaraon/Xray-Sample @ d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217 (grafted, HEAD, origin/master) in path /workspace/output/"}
[clone-repository : clone] {"level":"info","ts":1625971686.6967826,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/output/"}
[clone-repository : clone] + cd /workspace/output/
[clone-repository : clone] + git rev-parse HEAD
[clone-repository : clone] + RESULT_SHA=d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217
[clone-repository : clone] + EXIT_CODE=0
[clone-repository : clone] + '[' 0 '!=' 0 ]
[clone-repository : clone] + printf '%s' d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217
[clone-repository : clone] + printf '%s' https://github.com/sonnaraon/Xray-Sample

[root@ip-192-168-71-110 pipeline]# tkn pr logs tekton-sample-pipeline-run-r-fdvmw
[clone-repository : clone] + '[' false '=' true ]
[clone-repository : clone] + '[' false '=' true ]
[clone-repository : clone] + CHECKOUT_DIR=/workspace/output/
[clone-repository : clone] + '[' true '=' true ]
[clone-repository : clone] + cleandir
[clone-repository : clone] + '[' -d /workspace/output/ ]
[clone-repository : clone] + rm -rf /workspace/output//Dockerfile /workspace/output//ReadMe.txt /workspace/output//bin /workspace/output//deployment.yaml /workspace/output//logstash.conf /workspace/output//mvnw /workspace/output//mvnw.cmd /workspace/output//pom.xml /workspace/output//src
[clone-repository : clone] + rm -rf /workspace/output//.git /workspace/output//.gitignore /workspace/output//.mvn /workspace/output//.tern-project
[clone-repository : clone] + rm -rf '/workspace/output//..?*'
[clone-repository : clone] + test -z 
[clone-repository : clone] + test -z 
[clone-repository : clone] + test -z 
[clone-repository : clone] + /ko-app/git-init '-url=https://github.com/sonnaraon/Xray-Sample' '-revision=master' '-refspec=' '-path=/workspace/output/' '-sslVerify=true' '-submodules=true' '-depth=1' '-sparseCheckoutDirectories='
[clone-repository : clone] {"level":"info","ts":1625971686.682756,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/sonnaraon/Xray-Sample @ d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217 (grafted, HEAD, origin/master) in path /workspace/output/"}
[clone-repository : clone] {"level":"info","ts":1625971686.6967826,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/output/"}
[clone-repository : clone] + cd /workspace/output/
[clone-repository : clone] + git rev-parse HEAD
[clone-repository : clone] + RESULT_SHA=d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217
[clone-repository : clone] + EXIT_CODE=0
[clone-repository : clone] + '[' 0 '!=' 0 ]
[clone-repository : clone] + printf '%s' d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217
[clone-repository : clone] + printf '%s' https://github.com/sonnaraon/Xray-Sample

[root@ip-192-168-71-110 pipeline]#

이제 git-clone task에 대한 pipeline 동작이 완료된 것을 확인할 수 있다. 다음으로 maven 빌드 task를 살펴보도록 하자.


2. maven task

두번째 Task는 maven이다. maven은 git-clone을 통해 다운로드 받은 소스코드를 빌드하는 과정에 대해 정의한다.

1) hub.tekton.dev 에서 maven task 다운로드 및 메뉴얼 확인

> Install 버튼을 클릭하여 기 정의되어 있는 Task Template을 Kubernetes에 적용한다.

[root@ip-192-168-71-110 ~]# kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/maven/0.2/maven.yaml
task.tekton.dev/maven created
[root@ip-192-168-71-110 ~]#

> 커스터마이징이 필요할 경우 wget으로 다운로드 받아 수정후 반영한다.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: maven
  labels:
    app.kubernetes.io/version: "0.2"
  annotations:
    tekton.dev/pipelines.minVersion: "0.12.1"
    tekton.dev/tags: build-tool
spec:
  description: >-
    This Task can be used to run a Maven build.

  workspaces:
    - name: source
      description: The workspace consisting of maven project.
    - name: maven-settings
      description: >-
        The workspace consisting of the custom maven settings
        provided by the user.
  params:
    - name: MAVEN_IMAGE
      type: string
      description: Maven base image
      default: gcr.io/cloud-builders/mvn@sha256:57523fc43394d6d9d2414ee8d1c85ed7a13460cbb268c3cd16d28cfb3859e641 #tag: latest
    - name: GOALS
      description: maven goals to run
      type: array
      default:
        - "package"
    - name: MAVEN_MIRROR_URL
      description: The Maven repository mirror url
      type: string
      default: ""
    - name: SERVER_USER
      description: The username for the server
      type: string
      default: ""
    - name: SERVER_PASSWORD
      description: The password for the server
      type: string
      default: ""
    - name: PROXY_USER
      description: The username for the proxy server
      type: string
      default: ""
    - name: PROXY_PASSWORD
      description: The password for the proxy server
      type: string
      default: ""
    - name: PROXY_PORT
      description: Port number for the proxy server
      type: string
      default: ""
    - name: PROXY_HOST
      description: Proxy server Host
      type: string
      default: ""
    - name: PROXY_NON_PROXY_HOSTS
      description: Non proxy server host
      type: string
      default: ""
    - name: PROXY_PROTOCOL
      description: Protocol for the proxy ie http or https
      type: string
      default: "http"
    - name: CONTEXT_DIR
      type: string
      description: >-
        The context directory within the repository for sources on
        which we want to execute maven goals.
      default: "."
  steps:
    - name: mvn-settings
      image: registry.access.redhat.com/ubi8/ubi-minimal:8.2
      script: |
        #!/usr/bin/env bash

        [[ -f $(workspaces.maven-settings.path)/settings.xml ]] && \
        echo 'using existing $(workspaces.maven-settings.path)/settings.xml' && exit 0

        cat > $(workspaces.maven-settings.path)/settings.xml <<EOF
        <settings>
          <servers>
            <!-- The servers added here are generated from environment variables. Don't change. -->
            <!-- ### SERVER's USER INFO from ENV ### -->
          </servers>
          <mirrors>
            <!-- The mirrors added here are generated from environment variables. Don't change. -->
            <!-- ### mirrors from ENV ### -->
          </mirrors>
          <proxies>
            <!-- The proxies added here are generated from environment variables. Don't change. -->
            <!-- ### HTTP proxy from ENV ### -->
          </proxies>
        </settings>
        EOF

        xml=""
        if [ -n "$(params.PROXY_HOST)" -a -n "$(params.PROXY_PORT)" ]; then
          xml="<proxy>\
            <id>genproxy</id>\
            <active>true</active>\
            <protocol>$(params.PROXY_PROTOCOL)</protocol>\
            <host>$(params.PROXY_HOST)</host>\
            <port>$(params.PROXY_PORT)</port>"
          if [ -n "$(params.PROXY_USER)" -a -n "$(params.PROXY_PASSWORD)" ]; then
            xml="$xml\
                <username>$(params.PROXY_USER)</username>\
                <password>$(params.PROXY_PASSWORD)</password>"
          fi
          if [ -n "$(params.PROXY_NON_PROXY_HOSTS)" ]; then
            xml="$xml\
                <nonProxyHosts>$(params.PROXY_NON_PROXY_HOSTS)</nonProxyHosts>"
          fi
          xml="$xml\
              </proxy>"
          sed -i "s|<!-- ### HTTP proxy from ENV ### -->|$xml|" $(workspaces.maven-settings.path)/settings.xml
        fi

        if [ -n "$(params.SERVER_USER)" -a -n "$(params.SERVER_PASSWORD)" ]; then
          xml="<server>\
            <id>serverid</id>"
          xml="$xml\
                <username>$(params.SERVER_USER)</username>\
                <password>$(params.SERVER_PASSWORD)</password>"
          xml="$xml\
              </server>"
          sed -i "s|<!-- ### SERVER's USER INFO from ENV ### -->|$xml|" $(workspaces.maven-settings.path)/settings.xml
        fi

        if [ -n "$(params.MAVEN_MIRROR_URL)" ]; then
          xml="    <mirror>\
            <id>mirror.default</id>\
            <url>$(params.MAVEN_MIRROR_URL)</url>\
            <mirrorOf>central</mirrorOf>\
          </mirror>"
          sed -i "s|<!-- ### mirrors from ENV ### -->|$xml|" $(workspaces.maven-settings.path)/settings.xml
        fi

    - name: mvn-goals
      image: $(params.MAVEN_IMAGE)
      workingDir: $(workspaces.source.path)/$(params.CONTEXT_DIR)
      command: ["/usr/bin/mvn"]
      args:
        - -s
        - $(workspaces.maven-settings.path)/settings.xml
        - "$(params.GOALS)"

2) Tekton Dashboard 확인

> Task는 다음과 같이 추가된 것을 알 수 있다.

3) Pipeline 구성

두번째 파이프라인 Task로 maven-run를 등록한다.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: tekton-sample-pipeline
spec:
  workspaces:
    - name: pipeline-shared-data
    - name: maven-settings
  tasks:
    - name: clone-repository
      params:
        - name: url
          value: https://github.com/sonnaraon/Xray-Sample
        - name: revision
          value: "master"
        - name: deleteExisting
          value: "true"
      taskRef:
        kind: Task
        name: git-clone
      workspaces:
        - name: output
          workspace: pipeline-shared-data
    - name: maven-run
      taskRef:
        name: maven
      runAfter:
        - clone-repository
      params:
        - name: GOALS
          value:
            - clean
            - package
      workspaces:
        - name: maven-settings
          workspace: maven-settings
        - name: source
          workspace: pipeline-shared-data

> Maven에 적용 가능한 Parameter는 다음과 같다.

  • MAVEN_IMAGE: The base image for maven (default: gcr.io/cloud-builders/mvn)
  • GOALS: Maven goals to be executed
  • MAVEN_MIRROR_URL: Maven mirror url (to be inserted into ~/.m2/settings.xml)
  • SERVER_USER: Username to authenticate to the server (to be inserted into ~/.m2/settings.xml)
  • SERVER_PASSWORD: Password to authenticate to the server (to be inserted into ~/.m2/settings.xml)
  • PROXY_USER: Username to login to the proxy server (to be inserted into ~/.m2/settings.xml)
  • PROXY_PASSWORD: Password to login to the proxy server (to be inserted into ~/.m2/settings.xml)
  • PROXY_HOST: Hostname of the proxy server (to be inserted into ~/.m2/settings.xml)
  • PROXY_NON_PROXY_HOSTS: Non proxy hosts to be reached directly bypassing the proxy (to be inserted into ~/.m2/settings.xml)
  • PROXY_PORT: Port number on which the proxy port listens (to be inserted into ~/.m2/settings.xml)
  • PROXY_PROTOCOL: http or https protocol whichever is applicable (to be inserted into ~/.m2/settings.xml)
  • CONTEXT_DIR: The context directory within the repository for sources on which we want to execute maven goals. (Default: ".")

mvn clean package를 수행하기 위해 GOALS를 등록한다.

4) PipelineRun 구성

다음으로 PipelineRun을 구성하고 적용한다.

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: tekton-sample-pipeline-run
spec:
  pipelineRef:
    name: tekton-sample-pipeline
  workspaces:
    - name: maven-settings
      emptyDir: {}
    - name: pipeline-shared-data
      persistentvolumeclaim:
        claimName: maven-source-pvc

> 위와 같이 maven-settings workspace를 생성한다. 생성타입이 emptyDir로 Pod 기동 후 생성되는 임시 공유 볼륨으로 사용한다. Pod가 종료되면 해당 공유 볼륨은 제거된다.

[root@ip-192-168-71-110 tekton]# kubectl apply -f pipelinerun.yaml 
pipelinerun.tekton.dev/tekton-sample-pipeline-run configured
[root@ip-192-168-71-110 tekton]#

5) 대시보드 확인

> 반영이 완료되면 다음과 같이 PipelineRun을 Rerun한다.

> 위와 같이 clone-repository 이외에 maven-run step이 추가된 것을 확인할 수 있다. maven-run task 내에는 mvn-settings/mvn-goals로 step이 구분되어 처리된다.

> 모든 동작이 완료되면 다음과 같이 Completed 상태로 변경된다.


3. buildah task

세번째 Task는 buildah이다. buildah는 컴파일한  정의한다.

1) hub.tekton.dev 에서 buildah task 다운로드 및 메뉴얼 확인

> 앞선 포스팅에서도 확인했듯이 Install 버튼을 클릭하여 기 정의되어 있는 Task Template을 Kubernetes에 적용한다.

[root@ip-192-168-71-110 tekton]# kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/buildah/0.2/buildah.yaml
task.tekton.dev/buildah created
[root@ip-192-168-71-110 tekton]#

> 커스터마이징이 필요할 경우 wget으로 다운로드 받아 수정후 반영한다.

---
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: buildah
  labels:
    app.kubernetes.io/version: "0.2"
  annotations:
    tekton.dev/pipelines.minVersion: "0.17.0"
    tekton.dev/tags: image-build
spec:
  description: >-
    Buildah task builds source into a container image and
    then pushes it to a container registry.

    Buildah Task builds source into a container image using Project Atomic's
    Buildah build tool.It uses Buildah's support for building from Dockerfiles,
    using its buildah bud command.This command executes the directives in the
    Dockerfile to assemble a container image, then pushes that image to a
    container registry.

  params:
  - name: IMAGE
    description: Reference of the image buildah will produce.
  - name: BUILDER_IMAGE
    description: The location of the buildah builder image.
    default: quay.io/buildah/stable:v1.17.0
  - name: STORAGE_DRIVER
    description: Set buildah storage driver
    default: overlay
  - name: DOCKERFILE
    description: Path to the Dockerfile to build.
    default: ./Dockerfile
  - name: CONTEXT
    description: Path to the directory to use as context.
    default: .
  - name: TLSVERIFY
    description: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry)
    default: "true"
  - name: FORMAT
    description: The format of the built container, oci or docker
    default: "oci"
  - name: BUILD_EXTRA_ARGS
    description: Extra parameters passed for the build command when building images.
    default: ""
  - name: PUSH_EXTRA_ARGS
    description: Extra parameters passed for the push command when pushing images.
    type: string
    default: ""
  workspaces:
  - name: source
  - name: sslcertdir
    optional: true
  results:
  - name: IMAGE_DIGEST
    description: Digest of the image just built.
  steps:
  - name: build
    image: $(params.BUILDER_IMAGE)
    workingDir: $(workspaces.source.path)
    script: |
      [[ "$(workspaces.sslcertdir.bound)" == "true" ]] && CERT_DIR_FLAG="--cert-dir $(workspaces.sslcertdir.path)"
      buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) bud \
        $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) \
        --tls-verify=$(params.TLSVERIFY) --no-cache \
        -f $(params.DOCKERFILE) -t $(params.IMAGE) $(params.CONTEXT)
    volumeMounts:
    - name: varlibcontainers
      mountPath: /var/lib/containers
    securityContext:
      privileged: true

  - name: push
    image: $(params.BUILDER_IMAGE)
    workingDir: $(workspaces.source.path)
    script: |
      [[ "$(workspaces.sslcertdir.bound)" == "true" ]] && CERT_DIR_FLAG="--cert-dir $(workspaces.sslcertdir.path)"
      buildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) push \
        $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \
        --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \
        docker://$(params.IMAGE)
    volumeMounts:
    - name: varlibcontainers
      mountPath: /var/lib/containers
    securityContext:
      privileged: true

  - name: digest-to-results
    image: $(params.BUILDER_IMAGE)
    script: cat $(workspaces.source.path)/image-digest | tee /tekton/results/IMAGE_DIGEST

  volumes:
  - name: varlibcontainers
    emptyDir: {}

2) Tekton Dashboard 확인

> Task는 다음과 같이 추가된 것을 알 수 있다.

3) Pipeline 구성

세번째 파이프라인 Task로 build-image를 등록한다.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: tekton-sample-pipeline
spec:
  workspaces:
    - name: pipeline-shared-data
    - name: maven-settings
  params:
    - name: image-repo
      type: string
      description: Docker image name
      default: sonnaraon/tekton-sample-repository
  tasks:
    - name: clone-repository
      params:
        - name: url
          value: https://github.com/sonnaraon/Xray-Sample
        - name: revision
          value: "master"
        - name: deleteExisting
          value: "true"
      taskRef:
        kind: Task
        name: git-clone
      workspaces:
        - name: output
          workspace: pipeline-shared-data
    - name: maven-run
      taskRef:
        name: maven
      runAfter:
        - clone-repository
      params:
        - name: GOALS
          value:
            - clean
            - package
      workspaces:
        - name: maven-settings
          workspace: maven-settings
        - name: source
          workspace: pipeline-shared-data
    - name: build-image
      runAfter:
        - maven-run
      params:
        - name: IMAGE
          value: "$(params.image-repo):$(tasks.clone-repository.results.commit)"
      taskRef:
        kind: Task
        name: buildah
      workspaces:
        - name: source
          workspace: pipeline-shared-data

> buildah에 적용 가능한 Parameter는 다음과 같다.

  • IMAGE: The name (reference) of the image to build.
  • BUILDER_IMAGE:: The name of the image containing the Buildah tool. See note below. (default: quay.io/buildah/stable:v1.17.0)
  • DOCKERFILE: The path to the Dockerfile to execute (default: ./Dockerfile)
  • CONTEXT: Path to the directory to use as context (default: .)
  • TLSVERIFY: Verify the TLS on the registry endpoint (for push/pull to a non-TLS registry) (default: true)
  • FORMAT: The format of the built container, oci or docker (default:oci)
  • BUILD_EXTRA_ARGS: Extra parameters passed for the build command when building images. (default: "")
  • PUSH_EXTRA_ARGS: Extra parameters passed for the push command when pushing images. (default: "")

> workspaces는 source와 sslcertdir를 적용할 수 있다.

  • source: A Workspace containing the source to build.
  • sslcertdir: An optional Workspace containing your custom SSL certificates to connect to the registry. Buildah will look for files ending with *.crt, *.cert, *.key into this workspace. See this sample for a complete example on how to use it with OpenShift internal registry.

4) PipelineRun 구성

다음으로 PipelineRun을 구성하고 적용한다.

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: tekton-sample-pipeline-run
spec:
  pipelineRef:
    name: tekton-sample-pipeline
  workspaces:
    - name: maven-settings
      emptyDir: {}
    - name: pipeline-shared-data
      persistentvolumeclaim:
        claimName: maven-source-pvc

> 위와 같이 maven-settings workspace를 생성한다. 생성타입이 emptyDir로 Pod 기동 후 생성되는 임시 공유 볼륨으로 사용한다. Pod가 종료되면 해당 공유 볼륨은 제거된다.

[root@ip-192-168-71-110 tekton]# kubectl apply -f pipelinerun.yaml 
pipelinerun.tekton.dev/tekton-sample-pipeline-run configured
[root@ip-192-168-71-110 tekton]#

5) 대시보드 확인

> 반영이 완료되면 다음과 같이 PipelineRun을 Rerun한다.

> 위와 같이 clone-repository, maven-run 이외에 build-image step이 추가된 것을 확인할 수 있다. build-image task 내에는 build/push/digest-to-result로 step이 구분되어 처리된다.

> 위와 같이 Pipeline 동작 시 실패가 발생할 경우 빨간색으로 표시된다. 조치를 위해선느 Logs를 확인하여 상태를 점검한다. 현재 Failed가 발생한 원인은 Docker Image를 빌드하는 상황에서 Maven Build시 생성한 war 파일과 Dockerfile 내 복사대상인 war 파일명이 달라 복사에 실패하여 에러가 발생하였다. 이를 조치하고 다시 Rerun을 수행해 보자.

+ [[ false == \t\r\u\e ]]
+ buildah --storage-driver=overlay bud --format=oci --tls-verify=true --no-cache -f ./Dockerfile -t sonnaraon/tekton-sample-repository:d1ed4ef5138ee2d0eb2e4a00a347fbf6d071f217 .
STEP 1: FROM tomcat:8-jdk8-openjdk
Getting image source signatures
Copying blob sha256:96ebf150606575a0e557aa7349033a274221a8ad5ac09ba35736e7b344a4033f
Copying blob sha256:a110e58716600c199fc95f633b30735c33a25b5adcfb16d1d7edbcb78a3f1b62
Copying blob sha256:83d3c0fa203acbade733bff627daa75b84c97f9d0553bcdf967a3f1d37471277
Copying blob sha256:26b72ffca293d7e6fd2f11bf2642cd47d74053bf88c43f9e196412926cf20372
Copying blob sha256:0bc3020d05f1e08b41f1c5d54650a157b1690cde7fedb1fafbc9cda70ee2ec5c
Copying blob sha256:a8fd09c11b021b756b7a92a4f70a3d444ce7e63a1c24e5749d236dc2c6e68514
Copying blob sha256:0bffa2ea17aac1bf6e4f06f8ee4bb8d8d08efec7e75a7a4880102a86d15f0444
Copying blob sha256:d880cebcc7a6e70ee655bba1a8287be46b199cad2a3d2574ec48a3fe5f2c8454
Copying blob sha256:bed01058e36667d2dc290ae1914fc650e40b02c7b1cdf538999602bd56051dac
Copying blob sha256:0f2ce10b8ddf8f6da706db36c50945eb5953273096853b32d69e4accbc7c4e59
Copying config sha256:ecd199dd86fe6f2b9fb8424bc80ae4f391061764f51f4620b477f37071de94a7
Writing manifest to image destination
Storing signatures
STEP 2: RUN apt-get update && apt-get install apt-file -y && apt-file update && apt-get install vim -y && apt-get install telnet -y 
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://deb.debian.org/debian buster InRelease [122 kB]
Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Get:4 http://security.debian.org/debian-security buster/updates/main amd64 Packages [293 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 Packages [7907 kB]
Get:6 http://deb.debian.org/debian buster-updates/main amd64 Packages [15.2 kB]
Fetched 8454 kB in 2s (4203 kB/s)
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  libapt-pkg-perl libexporter-tiny-perl liblist-moreutils-perl
  libregexp-assemble-perl
The following NEW packages will be installed:
  apt-file libapt-pkg-perl libexporter-tiny-perl liblist-moreutils-perl
  libregexp-assemble-perl
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 297 kB of archives.
After this operation, 825 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian buster/main amd64 libapt-pkg-perl amd64 0.1.34+b1 [71.2 kB]
Get:2 http://deb.debian.org/debian buster/main amd64 libexporter-tiny-perl all 1.002001-1 [36.9 kB]
Get:3 http://deb.debian.org/debian buster/main amd64 liblist-moreutils-perl amd64 0.416-1+b4 [64.2 kB]
Get:4 http://deb.debian.org/debian buster/main amd64 libregexp-assemble-perl all 0.36-1 [86.6 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 apt-file all 3.2.2 [38.5 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 297 kB in 0s (1089 kB/s)
Selecting previously unselected package libapt-pkg-perl.
(Reading database ... 
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 12572 files and directories currently installed.)
Preparing to unpack .../libapt-pkg-perl_0.1.34+b1_amd64.deb ...
Unpacking libapt-pkg-perl (0.1.34+b1) ...
Selecting previously unselected package libexporter-tiny-perl.
Preparing to unpack .../libexporter-tiny-perl_1.002001-1_all.deb ...
Unpacking libexporter-tiny-perl (1.002001-1) ...
Selecting previously unselected package liblist-moreutils-perl.
Preparing to unpack .../liblist-moreutils-perl_0.416-1+b4_amd64.deb ...
Unpacking liblist-moreutils-perl (0.416-1+b4) ...
Selecting previously unselected package libregexp-assemble-perl.
Preparing to unpack .../libregexp-assemble-perl_0.36-1_all.deb ...
Unpacking libregexp-assemble-perl (0.36-1) ...
Selecting previously unselected package apt-file.
Preparing to unpack .../apt-file_3.2.2_all.deb ...
Unpacking apt-file (3.2.2) ...
Setting up libapt-pkg-perl (0.1.34+b1) ...
Setting up libexporter-tiny-perl (1.002001-1) ...
Setting up libregexp-assemble-perl (0.36-1) ...
Setting up liblist-moreutils-perl (0.416-1+b4) ...
Setting up apt-file (3.2.2) ...
The system-wide cache is empty. You may want to run 'apt-file update'
as root to update the cache.
Hit:1 http://security.debian.org/debian-security buster/updates InRelease
Hit:2 http://deb.debian.org/debian buster InRelease
Hit:3 http://deb.debian.org/debian buster-updates InRelease
Get:4 http://deb.debian.org/debian buster/main amd64 Contents (deb) [37.3 MB]
Get:5 http://deb.debian.org/debian buster-updates/main amd64 Contents (deb) [422 kB]
Fetched 37.7 MB in 7s (5130 kB/s)
Reading package lists...
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  libgpm2 vim-common vim-runtime xxd
Suggested packages:
  gpm ctags vim-doc vim-scripts
The following NEW packages will be installed:
  libgpm2 vim vim-common vim-runtime xxd
0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
Need to get 7425 kB of archives.
After this operation, 33.8 MB of additional disk space will be used.
Get:1 http://deb.debian.org/debian buster/main amd64 xxd amd64 2:8.1.0875-5 [140 kB]
Get:2 http://deb.debian.org/debian buster/main amd64 vim-common all 2:8.1.0875-5 [195 kB]
Get:3 http://deb.debian.org/debian buster/main amd64 libgpm2 amd64 1.20.7-5 [35.1 kB]
Get:4 http://deb.debian.org/debian buster/main amd64 vim-runtime all 2:8.1.0875-5 [5775 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 vim amd64 2:8.1.0875-5 [1280 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 7425 kB in 1s (12.1 MB/s)
Selecting previously unselected package xxd.
(Reading database ... 
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 12702 files and directories currently installed.)
Preparing to unpack .../xxd_2%3a8.1.0875-5_amd64.deb ...
Unpacking xxd (2:8.1.0875-5) ...
Selecting previously unselected package vim-common.
Preparing to unpack .../vim-common_2%3a8.1.0875-5_all.deb ...
Unpacking vim-common (2:8.1.0875-5) ...
Selecting previously unselected package libgpm2:amd64.
Preparing to unpack .../libgpm2_1.20.7-5_amd64.deb ...
Unpacking libgpm2:amd64 (1.20.7-5) ...
Selecting previously unselected package vim-runtime.
Preparing to unpack .../vim-runtime_2%3a8.1.0875-5_all.deb ...
Adding 'diversion of /usr/share/vim/vim81/doc/help.txt to /usr/share/vim/vim81/doc/help.txt.vim-tiny by vim-runtime'
Adding 'diversion of /usr/share/vim/vim81/doc/tags to /usr/share/vim/vim81/doc/tags.vim-tiny by vim-runtime'
Unpacking vim-runtime (2:8.1.0875-5) ...
Selecting previously unselected package vim.
Preparing to unpack .../vim_2%3a8.1.0875-5_amd64.deb ...
Unpacking vim (2:8.1.0875-5) ...
Setting up libgpm2:amd64 (1.20.7-5) ...
Setting up xxd (2:8.1.0875-5) ...
Setting up vim-common (2:8.1.0875-5) ...
Setting up vim-runtime (2:8.1.0875-5) ...
Setting up vim (2:8.1.0875-5) ...
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vim (vim) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vimdiff (vimdiff) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rvim (rvim) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rview (rview) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vi (vi) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/view (view) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/ex (ex) in auto mode
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/editor (editor) in auto mode
Processing triggers for libc-bin (2.28-10) ...
Processing triggers for mime-support (3.62) ...
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
  telnet
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 70.4 kB of archives.
After this operation, 167 kB of additional disk space will be used.
Get:1 http://deb.debian.org/debian buster/main amd64 telnet amd64 0.17-41.2 [70.4 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 70.4 kB in 0s (683 kB/s)
Selecting previously unselected package telnet.
(Reading database ... 
(Reading database ... 5%
(Reading database ... 10%
(Reading database ... 15%
(Reading database ... 20%
(Reading database ... 25%
(Reading database ... 30%
(Reading database ... 35%
(Reading database ... 40%
(Reading database ... 45%
(Reading database ... 50%
(Reading database ... 55%
(Reading database ... 60%
(Reading database ... 65%
(Reading database ... 70%
(Reading database ... 75%
(Reading database ... 80%
(Reading database ... 85%
(Reading database ... 90%
(Reading database ... 95%
(Reading database ... 100%
(Reading database ... 14597 files and directories currently installed.)
Preparing to unpack .../telnet_0.17-41.2_amd64.deb ...
Unpacking telnet (0.17-41.2) ...
Setting up telnet (0.17-41.2) ...
update-alternatives: using /usr/bin/telnet.netkit to provide /usr/bin/telnet (telnet) in auto mode
STEP 3: RUN rm -f /usr/local/tomcat/webapps/ROOT
STEP 4: COPY ROOT.war /usr/local/tomcat/webapps
error building at STEP "COPY ROOT.war /usr/local/tomcat/webapps": error adding sources [/workspace/source/ROOT.war]: error checking on source /workspace/source/ROOT.war under "/workspace/source": copier: stat: "/ROOT.war": no such file or directory

> 위와 같이 로그를 대시보드 상에서 확인이 가능하지만, 대시보드에 접근하기 어려운 상황에서는 다음과 같이 Pod Logs를 통해서도 확인이 가능하다. Tekton을 수행하는 Pipeline Task 들은 Pod로 기동되어 동작하면 동작이 완료되면 종료한다.

[root@ip-192-168-71-110 tekton]# kubectl get pods -A
NAMESPACE          NAME                                                              READY   STATUS      RESTARTS   AGE
default            affinity-assistant-0a5e832af3-0                                   1/1     Running     0          4m22s
default            my-nginx-5b56ccd65f-5ld6s                                         1/1     Running     0          27h
default            my-nginx-5b56ccd65f-s7ffr                                         1/1     Running     0          27h
default            tekton-sample-pipeline-run-clone-repository-jzrf2-pod-2p58g       0/1     Completed   0          174m
default            tekton-sample-pipeline-run-r-d2gm6-clone-repository-2fkwx-4h2kv   0/1     Completed   0          113m
default            tekton-sample-pipeline-run-r-dnpt9-build-image-c9f5t-pod-lwrgz    3/3     Running     0          14s
default            tekton-sample-pipeline-run-r-dnpt9-clone-repository-vwz8v-jzb9l   0/1     Completed   0          4m22s
default            tekton-sample-pipeline-run-r-dnpt9-maven-run-5xpkc-pod-gf2zk      0/2     Completed   0          3m59s
default            tekton-sample-pipeline-run-r-fdvmw-clone-repository-dkc4v-pqtph   0/1     Completed   0          113m
default            tekton-sample-pipeline-run-r-sh2cg-build-image-p9f5c-pod-99jbp    0/3     Error       0          10m
default            tekton-sample-pipeline-run-r-sh2cg-clone-repository-zb5br-wlpbr   0/1     Completed   0          14m
default            tekton-sample-pipeline-run-r-sh2cg-maven-run-lwxwr-pod-smmlw      0/2     Completed   0          13m
default            tekton-sample-pipeline-run-r-wctvf-clone-repository-ls7hh-dwqzp   0/1     Completed   0          92m
default            tekton-sample-pipeline-run-r-wctvf-maven-run-vjmr7-pod-98bnp      0/2     Completed   0          91m
kube-system        alb-ingress-controller-7bd489b997-dvfbh                           1/1     Running     0          28h
kube-system        aws-node-m2zwv                                                    1/1     Running     0          43h
kube-system        aws-node-x869f                                                    1/1     Running     0          43h
kube-system        coredns-78fb67b999-rv7b4                                          1/1     Running     0          43h
kube-system        coredns-78fb67b999-xnwrt                                          1/1     Running     0          43h
kube-system        kube-proxy-h76x7                                                  1/1     Running     0          43h
kube-system        kube-proxy-zn822                                                  1/1     Running     0          43h
tekton-pipelines   tekton-dashboard-748fb458c7-xn8v7                                 1/1     Running     0          28h
tekton-pipelines   tekton-pipelines-controller-558cc574b7-jglz5                      1/1     Running     0          29h
tekton-pipelines   tekton-pipelines-webhook-575b9bcd9f-s28p6                         1/1     Running     0          29h
tekton-pipelines   tekton-triggers-controller-7bdc5c466-dlkjp                        1/1     Running     0          29h
tekton-pipelines   tekton-triggers-webhook-7b59947444-2r7d4                          1/1     Running     0          29h
[root@ip-192-168-71-110 tekton]# kubectl logs -f   tekton-sample-pipeline-run-r-dnpt9-build-image-c9f5t-pod-lwrgz step-build
+ [[ false == \t\r\u\e ]]
+ buildah --storage-driver=overlay bud --format=oci --tls-verify=true --no-cache -f ./Dockerfile -t sonnaraon/tekton-sample-repository:a0d0146bfeb8eee94ab678ac7d609d0e383f2a18 .
STEP 1: FROM tomcat:8-jdk8-openjdk
Getting image source signatures
Copying blob sha256:26b72ffca293d7e6fd2f11bf2642cd47d74053bf88c43f9e196412926cf20372
Copying blob sha256:83d3c0fa203acbade733bff627daa75b84c97f9d0553bcdf967a3f1d37471277
Copying blob sha256:96ebf150606575a0e557aa7349033a274221a8ad5ac09ba35736e7b344a4033f
Copying blob sha256:a8fd09c11b021b756b7a92a4f70a3d444ce7e63a1c24e5749d236dc2c6e68514
Copying blob sha256:0bc3020d05f1e08b41f1c5d54650a157b1690cde7fedb1fafbc9cda70ee2ec5c
Copying blob sha256:a110e58716600c199fc95f633b30735c33a25b5adcfb16d1d7edbcb78a3f1b62
Copying blob sha256:0bffa2ea17aac1bf6e4f06f8ee4bb8d8d08efec7e75a7a4880102a86d15f0444
Copying blob sha256:d880cebcc7a6e70ee655bba1a8287be46b199cad2a3d2574ec48a3fe5f2c8454
Copying blob sha256:bed01058e36667d2dc290ae1914fc650e40b02c7b1cdf538999602bd56051dac
Copying blob sha256:0f2ce10b8ddf8f6da706db36c50945eb5953273096853b32d69e4accbc7c4e59
Copying config sha256:ecd199dd86fe6f2b9fb8424bc80ae4f391061764f51f4620b477f37071de94a7
Writing manifest to image destination
Storing signatures
STEP 2: RUN apt-get update && apt-get install apt-file -y && apt-file update && apt-get install vim -y && apt-get install telnet -y 
..
..
..
STEP 3: RUN rm -f /usr/local/tomcat/webapps/ROOT
STEP 4: COPY ROOT.war /usr/local/tomcat/webapps
error building at STEP "COPY ROOT.war /usr/local/tomcat/webapps": error adding sources [/workspace/source/ROOT.war]: error checking on source /workspace/source/ROOT.war under "/workspace/source": copier: stat: "/ROOT.war": no such file or directory
[root@ip-192-168-71-110 tekton]#

> 빌드시 다음과 같은 error가 발생할 경우 참고하여 조치한다.

+ [[ false == \t\r\u\e ]]
+ buildah --storage-driver=overlay push --tls-verify=true --digestfile /workspace/source/image-digest sonnaraon/tekton-sample-repository:b106bc30785a4f8ba2633db6e7c8bef05fcd7035 docker://sonnaraon/tekton-sample-repository:b106bc30785a4f8ba2633db6e7c8bef05fcd7035
Getting image source signatures
Copying blob sha256:79c550eb7bd278d360284d86c39e05852c2026b64232267a43947300bcf54a2c
Copying blob sha256:c3d00b097cce7df7dff99107ed0005fc4ceb14abaeac24316c8b120b4cd4c03a
Copying blob sha256:fe6a4fdbedc0cbc560437fa700b3b034114e31a264f0818d0d32ed2ee6cbe7a3
Copying blob sha256:7095af798ace32173839a61cbf101048434e1065185c0f29cc888e67158d990b
Copying blob sha256:e4d0e810d54a9c47e3dface412b0b88045d156b18809a2e0bbfb0fc8a45d8127
Copying blob sha256:4e006334a6fdea37622f72b21eb75fe1484fc4f20ce8b8526187d6f7bd90a6fe
Copying blob sha256:027dc7e9e77b575f17662b90b7429cc34725e9ae0101a33c5545f5fed3a22fbc
Copying blob sha256:aed5f5426b278d2800d114b061cc51b745d042ca1ef9294f8f9a77dfa5c19315
Copying blob sha256:8fa53538e6277c5529be88cb00d4d302d79c76797dd825a24761f4cd3ea8527c
Copying blob sha256:9d48355da13b8a355aaf6c479d386dc4280cb1e491271490e9f85d88831adb9b
Copying blob sha256:a78544ee94c6c00bd76e2df5696390010f58242f06eb998edd9e60f32f29fb99
error copying layers and metadata from "containers-storage:[overlay@/var/lib/containers/storage+/var/run/containers/storage]localhost/sonnaraon/tekton-sample-repository:b106bc30785a4f8ba2633db6e7c8bef05fcd7035" to "docker://sonnaraon/tekton-sample-repository:b106bc30785a4f8ba2633db6e7c8bef05fcd7035": Error writing blob: Error initiating layer upload to /v2/sonnaraon/tekton-sample-repository/blobs/uploads/ in registry-1.docker.io: errors:
denied: requested access to the resource is denied
unauthorized: authentication required

pipeline에 paramerter를 다음과 같이 추가하였으나, image를 push하기 위해서는 아래 image registry에 접속하기 위한 secret을 등록해야 한다.

  params:
    - name: image-repo
      type: string
      description: Docker image name
      default: sonnaraon/tekton-sample-repository

먼저 docker registry 접속을 위한 Secret을 생성한다.

kubectl create secret docker-registry regcred --docker-username={USERNAME} --docker-password={PASSWD} --docker-email={EMAIL}

다음으로 ServiceAccount를 생성한다.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-bot
secrets:
  - name: regcred

생성한 ServiceAccount build-bot을 PipelineRun에 연결한다.

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  name: tekton-sample-pipeline-run
spec:
  serviceAccountName: build-bot
  pipelineRef:
    name: tekton-sample-pipeline
  workspaces:
    - name: maven-settings
      emptyDir: {}
    - name: pipeline-shared-data
      persistentvolumeclaim:
        claimName: maven-source-pvc

위와 같이 조치 후 다시 Pipeline을 동작해 보자.

> 모든 동작이 완료되면 다음과 같이 Completed 상태로 변경된다.

6) Docker Push 이미지 확인

마지막으로 Docker 이미지 Push 상태를 확인해 보자.

위와 같이 Docker Hub에 접속하여 확인해 보니, sonnaraon/tekton-sample-repository Repositoy에는 pipeline에 정의한 형태로 이미지가 push 된것을 확인할 수 있다.

      params:
        - name: IMAGE
          value: "$(params.image-repo):$(tasks.clone-repository.results.commit)"

마지막으로 도커 이미지를 직접 기동해 보도록 하자.

[root@ip-192-168-71-110 tekton]# docker run -it sonnaraon/tekton-sample-repository:b106bc30785a4f8ba2633db6e7c8bef05fcd7035
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/local/openjdk-8
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
11-Jul-2021 05:08:48.171 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name:   Apache Tomcat/8.5.69
11-Jul-2021 05:08:48.183 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Jun 30 2021 18:00:00 UTC
11-Jul-2021 05:08:48.183 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 8.5.69.0
11-Jul-2021 05:08:48.184 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Linux
11-Jul-2021 05:08:48.184 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            4.14.232-177.418.amzn2.x86_64
11-Jul-2021 05:08:48.185 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          amd64
11-Jul-2021 05:08:48.185 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /usr/local/openjdk-8/jre
11-Jul-2021 05:08:48.186 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           1.8.0_292-b10
11-Jul-2021 05:08:48.186 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
11-Jul-2021 05:08:48.187 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         /usr/local/tomcat
11-Jul-2021 05:08:48.187 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         /usr/local/tomcat
11-Jul-2021 05:08:48.188 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
11-Jul-2021 05:08:48.189 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
11-Jul-2021 05:08:48.189 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.security.egd=file:/dev/./urandom
11-Jul-2021 05:08:48.190 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
11-Jul-2021 05:08:48.190 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
11-Jul-2021 05:08:48.191 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
11-Jul-2021 05:08:48.194 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs=
11-Jul-2021 05:08:48.196 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat
11-Jul-2021 05:08:48.197 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat
11-Jul-2021 05:08:48.197 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp
11-Jul-2021 05:08:48.198 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded Apache Tomcat Native library [1.2.30] using APR version [1.6.5].
11-Jul-2021 05:08:48.198 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
11-Jul-2021 05:08:48.198 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true]
11-Jul-2021 05:08:48.218 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1d  10 Sep 2019]
11-Jul-2021 05:08:48.399 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
11-Jul-2021 05:08:48.433 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read
11-Jul-2021 05:08:48.470 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 1407 ms
11-Jul-2021 05:08:48.543 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
11-Jul-2021 05:08:48.544 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/8.5.69]
11-Jul-2021 05:08:48.589 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/usr/local/tomcat/webapps/ROOT.war]
11-Jul-2021 05:08:54.598 INFO [localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.4.RELEASE)

2021-07-11 05:08:56.771  INFO [springAppName_IS_UNDEFINED,,] Starting ServletInitializer v0.0.1-SNAPSHOT on 1dc433657674 with PID 1 (/usr/local/tomcat/webapps/ROOT/WEB-INF/classes started by root in /usr/local/tomcat)
2021-07-11 05:08:56.785  INFO [springAppName_IS_UNDEFINED,,] No active profile set, falling back to default profiles: default
2021-07-11 05:08:56.990  INFO [springAppName_IS_UNDEFINED,,] For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2021-07-11 05:08:59.566  INFO [springAppName_IS_UNDEFINED,,] Root WebApplicationContext: initialization completed in 2571 ms

위와 같이 push 된 이미지가 정상 기동되는 것을 확인할 수 있다.

728x90
반응형