Skip to content

Instantly share code, notes, and snippets.

@alochym01
Created August 10, 2022 09:59
Show Gist options
  • Save alochym01/d104b84aa3e5316682f09185efc8a442 to your computer and use it in GitHub Desktop.
Save alochym01/d104b84aa3e5316682f09185efc8a442 to your computer and use it in GitHub Desktop.

Tekton with Kind

Software

  1. kind version 0.14.0
  2. kubernetes version 1.23.6
    1. kubectl version 1.23.6
  3. tekton version
    1. Client version 0.25.0
    2. Pipeline version 0.38.0

Installation

Kind

  1. Download kind for linux - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.14.0/kind-linux-amd64
  2. Change file executor - chmod +x ./kind
  3. Move it to default search PATH - sudo mv ./kind /usr/local/bin/

Tekton

  1. Download tekton - curl -LO https://github.com/tektoncd/cli/releases/download/v0.25.0/tkn_0.25.0_Linux_x86_64.tar.gz
  2. Untar file - sudo tar xvzf tkn_0.25.0_Linux_x86_64.tar.gz -C /usr/local/bin/ tkn

kubectl

  1. Download kubectl - curl -LO https://dl.k8s.io/release/v1.23.6/bin/linux/amd64/kubectl
  2. Change file executor - chmod +x kubectl
  3. Move it to default search PATH - sudo mv kubectl /usr/local/bin/

Configuration

Kind

  1. Create Kind cluster - kind create cluster
  2. Create Kind cluster with specific image - kind create cluster --image kindest/node:v1.23.6

Tekton

  1. Apply Tekton deployment - kubectl apply -f https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

Using Tekton

Step

  • A Step is a reference to a container image that executes a specific tool on a specific input and produces a specific output.
  • The order in which the Steps appear in Task is the order in which they will execute.
  • The following requirements apply to each container image referenced in a steps field:
    1. The container image must abide by the container contract.
    2. Each container image runs to completion or until the first failure occurs.
    3. The CPU, memory, and ephemeral storage resource requests set on Steps will be adjusted to comply with any LimitRanges present in the Namespace.
    4. In addition, Kubernetes determines a pod’s effective resource requests and limits by summing the requests and limits for all its containers, even though Tekton runs Steps sequentially.
  • Define a Steps:
    spec:
      steps:
        - name: step-with-limts
          resources:
            requests:
              memory: 1Gi
              cpu: 500m
            limits:
              memory: 2Gi
              cpu: 800m    

Task

  • Tasks are the basic building block that you will use to build your larger pipelines.
  • Tasks should perform a single operation in your CI/CD pipeline.
  • A Task is a collection of Steps that you define and arrange in a specific order of execution as part of your continuous integration flow.
  • A Task executes as a Pod on your Kubernetes cluster.
  • A Task is available within a specific namespace.
  • A ClusterTask is available across the entire cluster.
  • You should also try to make them as reusable as possible.
  • Examples:
    1. Tasks could include cloning a repository
    2. Compiling some code.
    3. Running a series of tests.

Tekton CLI

  1. Create task - kubectl apply -f echo-hello.yaml
  2. tkn task ls - list task
  3. tkn task start <task_name> - start task.
  4. tkn task start <task_name> --showlog - start task to see output
  5. tkn task start <task_name> -p <params_name>=value --showlog - start task with setting params value to see output
  6. tkn taskrun logs <pod_name> -f -n <name_space> - get logs of task
  7. tkn task start <task_name> -w name=<source_name>,<type_of_volume>=<path_of_folder> --showlog - start task with passing workspace value to see output

Simple Task

  • Define a Task YAML file
      # echo-hello.yaml file
      apiVersion: tekton.dev/v1beta1
      kind: Task
      metadata:
       name: echo-hello
      spec:
       steps: # define steps for a task
       - image: registry.access.redhat.com/ubi8/ubi-minimal
         command:
         - /bin/bash
         - -c
         - echo "Hello World"  

Task with Params

  • Define a Task with params YAML file
    # echo-hello-param.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
     name: echo-hello-param
    spec:
     params:
     - name: who # reuse params.who
       type: string
     steps:
     - image: registry.access.redhat.com/ubi8/ubi-minimal
       command:
       - /bin/bash
       - -c
       - echo "Hello $(params.who)"    
  • Define a Task with default params YAML file
    # echo-hello-share-data.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
     name: echo-hello-default-param
    spec:
     params:
     - name: who # reuse params.who
       type: string
       default: World # default value for params.who
     steps:
     - image: registry.access.redhat.com/ubi8/ubi-minimal
       command:
       - /bin/bash
       - -c
       - echo "Hello $(params.who)"

Task with Share Data using Results

  • Define a Task with params YAML file
    # echo-hello-share-data.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
     name: echo-hello-share-data
    spec:
     results:
     - name: message
       description: Message to be shared
     steps:
     - name: write 
       image: registry.access.redhat.com/ubi8/ubi-minimal
       command:
       - /bin/bash
       args:
       - "-c"
       - echo "Secret Message" > $(results.message.path)
     - name: read 
       image: registry.access.redhat.com/ubi8/ubi-minimal
       command:
         - /bin/bash
       args: ["-c", "cat $(results.message.path)"]       

Task using Kubernetes volumes

  • Define a Task with params YAML file
    # echo-hello-k8s-volumes.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
     name: colors-map
    data:
     error: "\e[31m"
     info: "\e[34m"
     debug: "\e[32m" 
    ---
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
     name: echo-hello-k8s-volumes
    spec:
     volumes:
     - name: colors
       configMap:
         name: colors-map    
     steps:
     - name: write 
       image: registry.access.redhat.com/ubi8/ubi-minimal
       volumeMounts:
       - name: colors
         mountPath: /var/colors 
       script: |   
         echo $(cat /var/colors/info)Logging information
         echo $(cat /var/colors/debug)Logging information
         echo $(cat /var/colors/error)Logging information

TaskRun

  • A TaskRun allows you to instantiate and execute a Task on-cluster.
  • A TaskRun executes the Steps in the Task in the order they are specified until all Steps have executed successfully or a failure occurs.
  • Define simple TASKRUN YAML file.
    apiVersion: tekton.dev/v1beta1
    kind: TaskRun
    metadata:
      name: echo-hello-run
    spec:
      taskRef:
        name: echo-hello    

Pipeline

  1. Pipelines are a collection of tasks that are designed to produce an output from your inputs.
  2. You can reuse a Task multiple times.

Tkn PIPELINE CLI

  1. Create pipeline - kubectl apply -f simple-pipeline.yaml
  2. tkn pipeline ls - list pipeline
  3. tkn pipeline start <pipeline_name> - start pipeline.
  4. tkn pipeline start <pipeline_name> --showlog - start pipeline
  5. tkn pipeline start <pipeline_name> -p <param_name>=value --showlog - start pipeline with setting params value to see output
  6. tkn pipeline start <pipeline_name> --use-param-default --showlog - start pipeline with default params value to see output
  7. tkn pipelinerun logs <pod_name> -f -n <name_space> - get logs of pipeline

Simple Pipeline

  • Define simple pipeline YAML file.
    # simple-pipeline.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
     name: pipeline-hello
    spec: 
     tasks:
     - name: first
       taskRef:
         name: echo-hello    

Pipeline with Params

  • Define a Pipeline with params YAML file
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
     name: pipeline-hello-params
    spec: 
     params:
     - name: who_of_pipeline
       type: string
       default: "Alochym World"
     tasks:
     - name: first
       taskRef:
         name: echo-hello
     - name: second
       params:
       - name: who # as same as the param's name of Task.spec.params.name
         value: "$(params.who_of_pipeline)" # reference to spec.params.name of PIPELINE
       taskRef:
         name: echo-hello-defaut-param    

Pipeline for running Task in ORDER

  • Define a Pipeline with order Task YAML file
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
     name: pipeline-hello-order
    spec: 
     params:
     - name: who_of_pipeline
       type: string
       default: "Alochym World"
     tasks:
     - name: first
       taskRef:
         name: echo-hello
     - name: second
       runAfter: # run in order
       - first
       params:
       - name: who # as same as the param's name of Task.spec.params.name
         value: "$(params.who_of_pipeline)" # reference to spec.params.name of PIPELINE
       taskRef:
         name: echo-hello-defaut-param    

Pipeline with Passing RESULT as Params for other Task

  • Define a Pipeline with params YAML file
    # simple-task-read-result.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
     name: echo-hello-read-result
    spec:
     params:
     - name: message
       description: Message to be shared
     steps:
     - name: read
       image: registry.access.redhat.com/ubi8/ubi-minimal
       command:
       - /bin/bash
       - -c
       - echo $(params.message)
    ---
    # simple-task-write-result.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
     name: echo-hello-write-result
    spec:
     results:
     - name: message
       description: Message to be shared
     steps:
     - name: write
       image: registry.access.redhat.com/ubi8/ubi-minimal
       command:
       - /bin/bash
       args:
       - "-c"
       - echo "Secret Message" > $(results.message.path)
    ---
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
     name: pipeline-hello-w-result
    spec: 
     tasks:
     - name: first
       taskRef:
         name: echo-hello-write-result
     - name: second
       params:
       - name: message # as same as the param's name of Task.spec.params.name - simple-task-read-result.yaml
         value: $(tasks.first.results.message) # as same as the param's name of Task.spec.result.name - simple-task-write-result.yaml
       runAfter:
       - first
       taskRef:
         name: echo-hello-read-result   

Pipeline with FINALLY TASK

  • When you will need to clean up your persisted data to start with a clean environment each time.
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
     name: exitcodes
    spec:
     tasks:
     - name: first
       taskRef:
         name: echo-hello-write-result    
     finally:
     - name: cleanup-task
       taskRef:
         name: cleanup

Pipeline Run

  1. Pipeline runs are to pipelines what task runs are to tasks
  2. Get pipeline runs - kubectl get pipelineruns
  3. Define simple PIPELINERUN YAML file
    apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
      generateName: simple-pipelinerun
    spec:
      pipelineRef:
        name: pipeline-hello 

Workspace

  • Workspaces are shared volumes used to transfer data between the various steps of a task.
  • You can also use workspaces to share data across tasks in a Tekton pipeline
  • Workspaces need some sort of volume to mount the files to be shared. These types of volumes are called VolumeSources:
    • emptyDir
    • ConfigMap - This volume source enables you to use a Kubernetes ConfigMap object
    • Secret - This volume source enables you to use a Kubernetes Secret object
    • mountPath
      • Can be either absolute or relative. Absolute paths start with / and relative paths start with the name of a directory
      • A mountPath of "/foobar" is absolute and exposes the Workspace at /foobar inside the Task's Steps, but a mountPath of "foobar" is relative and exposes the Workspace at /workspace/foobar
    • Persistent volume claims:
      • To share a folder across your tasks that can be mounted as a writable file system, you will need to use a persistent volume claim.
      • When using a persistent volume claim, only one run at a time will be able to use the volume.
      • You might need to use a finally task to clean everything up once you are done.
    • Persistent volume claim templates:
      • You could also use a volumeClaimTemplate in your task run or pipeline run.
      • In this case, a PVC would be created and automatically be deleted once the run is deleted.
      • It would also have the added benefit that you can run multiple pipelines at once.
      • This can be useful when you don't need to persist data outside of your pipelines. Because volume claim template creates a new PVC for each pipeline execution.
  • Define a Task with workspace
    # echo-hello-workspace.yaml file
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: echo-hello-workspace
    spec:
      params:
      - name: repo
        type: string
        description: Git repository to be cloned
        default: https://github.com/joellord/handson-tekton
      workspaces: # define workspace
      - name: source
      steps: # define steps for a task
      - name: clone
        image: alpine/git
        workingDir: $(workspaces.source.path) # using workspace to store data.
        command:
          - /bin/sh
          - -c
          - git clone -v $(params.repo) ./source
      - name: list
        image: registry.access.redhat.com/ubi8/ubi-minimal
        workingDir: $(workspaces.source.path) # using workspace.
        command:
          - /bin/bash
          - -c
          - ls ./source
  • Define a TaskRun with workspace
    apiVersion: tekton.dev/v1beta1
    kind: TaskRun
    metadata:
      generateName: git-clone-tr
    spec:
      workspaces:
      - name: source
        emptyDir: {}
      taskRef:
        name: echo-hello-workspace
  • Define a Pipeline with workspace
    • workspace should be persistent volume - not emptyDir
    # pv.yaml
    apiVersion: v1
    kind: PersistentVolume
    metadata: 
      name: tekton-pv
    spec:
      storageClassName: alochym
      capacity:
        storage: 2Gi 
      accessModes:
        - ReadWriteMany
      hostPath:
        path: "/www" 
    ---
    # pvc.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: tekton-pvc
    spec: 
      storageClassName: alochym
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 1Gi 
    ---
    # task-git-clone.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: echo-hello-git-clone
    spec:
      params:
      - name: repo
        type: string
        description: Git repository to be cloned
        default: https://github.com/joellord/handson-tekton
      workspaces: # define workspace
      - name: source
      steps: # define steps for a task
      - name: clone
        image: alpine/git
        workingDir: $(workspaces.source.path) # using workspace to store data.
        command:
          - /bin/sh
          - -c
          - git clone -v $(params.repo) ./source
    ---
    # task-list-file.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: echo-hello-list-files
    spec:
      params:
      workspaces: # define workspace
      - name: source
      steps: # define steps for a task
      - name: list
        image: registry.access.redhat.com/ubi8/ubi-minimal
        workingDir: $(workspaces.source.path) # using workspace.
        command:
          - /bin/bash
          - -c
          - ls source
    ---
    # task-clean-up.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: echo-hello-clean-up
    spec:
      params:
      workspaces: # define workspace
      - name: source
      steps: # define steps for a task
      - name: remove-source-folder
        image: registry.access.redhat.com/ubi8/ubi-minimal
        workingDir: $(workspaces.source.path) # using workspace.
        command:
          - /bin/bash
          - -c
          - rm -rf source    
    ---
    # pipeline-w-workspace.yaml
    apiVersion: tekton.dev/v1beta1
    kind: Pipeline
    metadata:
      name: clone-and-list
    spec:
      workspaces:
        - name: codebase
      tasks:
        - name: clone
          taskRef:
            name: echo-hello-git-clone
          workspaces:
            - name: source
              workspace: codebase
        - name: list
          taskRef:
            name: echo-hello-list-files
          workspaces:
            - name: source
              workspace: codebase
          runAfter:
            - clone 
      finally: # should be clean up folder for second run
        - name: clean
          taskRef:
            name: cleanup
          workspaces:
            - name: source
              workspace: codebase 
    ---
    # run cli - tkn pipeline start clone-and-list -w name=codebase,claimName="tekton-pvc" --showlog
  • Define a PipelineRun with workspace
    # pipeline-run-w-workspace.yaml
    apiVersion: tekton.dev/v1beta1
    kind: PipelineRun
    metadata:
       generateName: clone-and-ls-pr-
    spec:
      pipelineRef:
        name: clone-and-list 
      workspaces:
        - name: codebase
          persistentVolumeClaim:
            claimName: tekton-pvc
    # kubectl create -f pipeline-run-w-workspace.yaml

Tekton with Kaniko

  • software
    • tekton
    • kaniko
    • harbor - self sign certificate
    # harbor secret crendential
    # kubectl create secret docker-registry regcred --docker-server=https://harbor.io --docker-username=admin --docker-password=Harbor12345 [email protected] --dry-run=client -oyaml
    apiVersion: v1
    data:
      .dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2hhcmJvci5pbyI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJIYXJib3IxMjM0NSIsImVtYWlsIjoiYWRtaW5AaGFyYm9yLmlvIiwiYXV0aCI6IllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSJ9fX0=
    kind: Secret
    metadata:
      creationTimestamp: null
      name: regcred
    type: kubernetes.io/dockerconfigjson
    
    # storage class
    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: tekton
      annotations:
        storageclass.kubernetes.io/is-default-class: "true"
    provisioner: kubernetes.io/no-provisioner
    reclaimPolicy: Retain
    volumeBindingMode: WaitForFirstConsumer
    
    # persistent volume
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: tekton
    spec:
      storageClassName: harbor      
      accessModes:
      - ReadWriteOnce
      capacity:
        storage: 1Gi
      local:
        path: /home/hadn/tekton-kaniko-build
      nodeAffinity:
        required:
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/os
              operator: In
              values:
              - linux
      persistentVolumeReclaimPolicy: Delete
      
    # persistent volume claim
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: tekton-pvc
    spec: 
      storageClassName: harbor
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
          
    # tekton task git clone
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: git-clone
    spec:
      params:
      - name: repo
        type: string
        description: Git repository to be cloned
        default: https://github.com/alochym01/cicd
      workspaces: # define workspace
      - name: source
      steps: # define steps for a task
      - name: clone
        image: alpine/git
        workingDir: $(workspaces.source.path) # using workspace to store data.
        command:
          - /bin/sh
          - -c
          - git clone -v $(params.repo) .
          
    # tekton task kaniko
    apiVersion: tekton.dev/v1alpha1
    kind: Task
    metadata:
      name: build-push-kaniko
    spec:
      workspaces:
        - name: source
      steps:
        - name: build
          image: gcr.io/kaniko-project/executor:debug
          workingDir: $(workspaces.source.path) # using workspace.
          command:
            - /kaniko/executor 
          args: [
                "--dockerfile=./python/Dockerfile",
                "--context=./python",
                "--insecure=true",
                "--skip-tls-verify=true",
                "--destination=harbor.io/library/flask-web:v2",
                ]
          volumeMounts:
            - name: docker-config
              mountPath: /kaniko/.docker
      volumes:
        - name: docker-config
          secret:
            secretName: regcred
            items:
              - key: .dockerconfigjson
                path: config.json      
    
    # tekton task clean up
    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
     name: cleanup
    spec:
      workspaces:
      - name: source
      steps:
      - name: remove-source
        image: registry.access.redhat.com/ubi8/ubi
        command:
        - /bin/bash
        args:
        - "-c"
        - "rm -rf $(workspaces.source.path)/*"
    # run cli - tkn pipeline start clone-and-list -w name=codebase,claimName="tekton-pvc" --showlog

Link Reference

  1. https://developer.ibm.com/articles/introduction-to-tekton-architecture-and-design/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment