Knative Tutorial

At the end of this chapter you will be able to :

  • Understand what is a Task ?

  • Create a Task

  • Create a TaskRun

  • Use the pipeline resource with TaskRun

Prerequisite

The following checks ensure that each chapter exercises are done with the right environment settings.

  • Kubernetes

  • OpenShift

  • Set your local docker to use minikube docker daemon

eval $(minikube docker-env)

  • Kubernetes should be v1.12+

kubectl version

  • OpenShift CLI should be v4.1+

oc version

The output should be like

oc version
Client Version: version.Info{Major:"4", Minor:"1+", GitVersion:"v4.1.0+b4261e0", GitCommit:"b4261e07ed", GitTreeState:"clean", BuildDate:"2019-07-06T03:16:01Z", GoVersion:"go1.12.6", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14+", GitVersion:"v1.14.6+73b5d76", GitCommit:"73b5d76", GitTreeState:"clean", BuildDate:"2019-09-23T16:18:51Z", GoVersion:"go1.12.8", Compiler:"gc", Platform:"linux/amd64"}
  • Make sure to be on knativetutorial OpenShift project

oc project -q

If you are not on knativetutorial project, then run following command to change to knativetutorial project:

oc project knativetutorial

Ensure Tekton piplines is deployed and the API is available for use

  • Kubernetes

  • OpenShift

kubectl api-resources --api-group='tekton.dev'

oc api-resources --api-group='tekton.dev'

The command show an output like:

NAME                SHORTNAMES   APIGROUP     NAMESPACED   KIND
clustertasks                     tekton.dev   false        ClusterTask
conditions                       tekton.dev   true         Condition
pipelineresources                tekton.dev   true         PipelineResource
pipelineruns        pr,prs       tekton.dev   true         PipelineRun
pipelines                        tekton.dev   true         Pipeline
taskruns            tr,trs       tekton.dev   true         TaskRun
tasks                            tekton.dev   true         Task

Verify the Tekton cli

tkn version

The command should show a result like:

Client version: 0.4.0

Create a Task

If you are not in tutorial chapter folder, then navigate to the folder:

cd $TUTORIAL_HOME/06-pipelines

The following snippet shows what a Tekton Task YAML looks like:

apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: build-app
spec:
  inputs:
   resources:
    - name: source
      type: git
   params:
   - name: contextDir
     description: the context dir within source
     default: .
   - name: mavenMirrorUrl
     description: the maven mirrror url
     default: http://repo1.maven.apache.org/maven2
   - name: destinationImage
     description: the fully qualified image name
     default: "$(outputs.resources.builtImage.url)"
   - name: dockerFile
     description: the docker file to used for building the application
     default: Dockerfile.jvm
  outputs:
   resources:
    - name: builtImage
      type: image
  stepTemplate:
    resources:
      limits:
        cpu: 4
        memory: 4Gi
      requests:
        cpu: 2
        memory: 2Gi
    securityContext:
       allowPrivilegeEscalation: false
       privileged: false
       # the default underprivileged user to be used
       runAsUser: 10001
  steps:
   - name: build-sources
     image: quay.io/rhdevelopers/tutorial-tools:0.0.2
     workingDir: "/workspace/source/$(inputs.params.contextDir)"
     args:
      - mvn
      - -DskipTests
      - clean
      - package
     env:
     - name: MAVEN_MIRROR_URL
       value: "$(inputs.params.mavenMirrorUrl)"
   - name: build-image
     image: quay.io/buildah/stable
     workingDir: "/workspace/source/$(inputs.params.contextDir)"
     command: ['buildah', 'bud', '--tls-verify=false', '--layers','-f', '$(inputs.params.dockerFile)', '-t', '$(inputs.params.destinationImage)', '.']
     volumeMounts:
     - name: varlibc
       mountPath: /var/lib/containers
     # override security context as container image build need to run as root
     securityContext:
       allowPrivilegeEscalation: true
       runAsUser: 0
       privileged: true
   - name: build-push
     image: quay.io/buildah/stable
     workingDir: "/workspace/source/$(inputs.params.contextDir)"
     command: ["buildah","push", "--tls-verify=false","$(inputs.params.destinationImage)","docker://$(inputs.params.destinationImage)"]
     volumeMounts:
     - name: varlibc
       mountPath: /var/lib/containers
     # override security context as container image build need to run as root
     securityContext:
       allowPrivilegeEscalation: true
       runAsUser: 0
       privileged: true
  volumes:
  - name: varlibc
    emptyDir: {}

Each Task has the following:

  • name - the unique name using which the task can be referred

  • inputs - the inputs to the task

    • resources - the pipeline resources that will be used in the task e.g. git-source

      • name - the name of the input resource using which it can be referenced and bound via TaskRun

      • type - the type of the input resource, typically the pipeline resource type

    • params - the parameters that will be used in the task steps. Each parameter has

      • name - the name of the parameter

      • description - the description of the parameter

      • default - the default value of parameter

The TaskRun could override the parameter values, if no parameter value is passed then the default value will be used.
  • outputs the pipeline resource that will end artifact of the task. In the above example the build will produce a container image artifact.

    • resources - the pipeline resources that will be used in the task e.g. builtImage

      • name - the name of the input resource using which it can be referenced and bound via TaskRun

      • type - the type of the input resource, typically the pipeline resource type

  • steps - One or more sub-tasks that will be executed in the defined order. The step has all the attributes like a Pod spec

  • stepTemplate - when there is a need to have similar container configuration across all steps of a the task, we can have them defined in the stepTemplate, the task steps will inherit them implicitly in all steps. In the example above we define the resources and securityContext for all the steps

  • volumes - the task can also mount external volumes using the volumes attribute.

The parameters that were part of the spec  inputs  params can be used in the steps using the notation $(<variable-name>).

The task build-app is used to build the Java application that is part of the tutorial. As a step one(build-sources) the application will be built using Apache Maven, then the step two (build-image) the application artifacts a jar in this case will be used to built the linux container image using buildah, the Dockerfile in the sources will be used as base to build the linux container image and as part of the last step(build-push) the built linux container image will be pushed to the container registry.

If you plan to do the build Task multiple times then its better to have a maven repository manager like Nexus to cache the maven artifacts for faster builds. You can deploy nexus using:

  • Kubernetes

  • OpenShift

kubectl create -n knativetutorial \
  -f $TUTORIAL_HOME/apps/nexus/skaffold.yaml

It might take few minutes for nexus to be deployed, you can watch the status using the command kubectl get pods -n knativetutorial -w.

oc create -n knativetutorial \
  -f $TUTORIAL_HOME/apps/nexus/skaffold.yaml

It might take few minutes for nexus to be deployed, you can watch the status using the command oc get pods -n knativetutorial -w.

Deploy a task

The application build task could be created using the command:

  • Kubernetes

  • OpenShift

kubectl create -n knativetutorial -f build-app-task.yaml

oc create -n knativetutorial -f build-app-task.yaml

We will use the Tekton cli to inspect the created resources

tkn task ls

The above command should list one Task as shown below:

NAME        AGE
build-app   12 seconds ago
  • Use the command help tkn task --help

TaskRun

The TaskRun is used to run a specific task independently. In the following section we will run the build-app task created in the previous step

Create TaskRun

The following snippet shows what a Tekton TaskRun YAML looks like:

apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
  generateName: build-app-
spec:
  serviceAccount: pipeline
  taskRef:
    name:  build-app
  inputs:
   resources:
    - name: source
      resourceRef:
        name: git-source
   params:
    - name: contextDir
      value: apps/greeter/java/quarkus
    # Enable if you have maven mirrors to use
    # - name: mavenMirrorUrl
    #   value: http://nexus:8081/nexus/content/groups/public
  outputs:
   resources:
    - name: builtImage
      resourceRef:
        name: knative-tutorial-greeter-image
  • generateName - since the TaskRun can be run many times, in order to have unqiue name across the TaskRun ( helpful when checking the TaskRun history) we use this generateName instead of name. When Kubernetes sees generateName it will generate unquie set of characters and suffix the same to build-app-, similar to how pod names are generated

  • serviceAccount - it is always recommended to have a service account associated with TaskRun, which can then be used to define fine grained roles.

  • taskRef - this is used to refer to the Task by its name that will be run as part of this TaskRun. In this example we use build-app Task.

As described in the earlier section that the Task inputs and outputs could be overridden via TaskRun. When executing TaskRun the spec  inputs  resources and spec  outputs  resources can refer to the pipeline resources that already defined in the same namespace.

In this example we make the Task’s spec  inputs  resources  source to refer to pipeline resource git-source via the resourceRef. Similarly spec  outputs  resources  builtImage to refer to pipeline resource knative-tutorial-greeter-image via the resourceRef.

The spec  inputs  resources  source and spec  outputs  resources  builtImage were defined as part of the Task specification.

Before we run the Task using TaskRun let us create the Kubernetes service account and attach the needed permissions to the service account, the following Kubernetes resource defines a service account called pipeline in namespace knativetutorial who will have administrative role within the knativetutorial namespace.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pipeline
  namespace: knativetutorial
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pipeline-role
  namespace: knativetutorial
rules:
- apiGroups: ["serving.knative.dev"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["eventing.knative.dev"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["sources.eventing.knative.dev"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups:
  - ""
  resources:
  - pods
  - services
  - endpoints
  - configmaps
  - secrets
  verbs:
  - '*'
- apiGroups:
  - apps
  resources:
  - deployments
  - daemonsets
  - replicasets
  - statefulsets
  verbs:
  - '*'
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pipeline-role-binding
  namespace: knativetutorial
roleRef:
  kind: Role
  name: pipeline-role
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: pipeline
  namespace: knativetutorial
  • Kubernetes

  • OpenShift

kubectl create -n knativetutorial -f pipeline-sa-role.yaml

oc create -n knativetutorial -f pipeline-sa-role.yaml

The application build task(build-app) could be run using the command:

  • Kubernetes

  • OpenShift

kubectl create -n knativetutorial -f build-app-task-run.yaml

As tasks will use generated name, never use kubectl apply -f build-app-task-run.yaml
oc create -n knativetutorial -f build-app-task-run.yaml

As tasks will use generated name, never use oc apply -f build-app-task-run.yaml

We will use the Tekton cli to inspect the created resources:

tkn taskrun ls

The above command should list one TaskRun as shown below:

NAME              STARTED   DURATION   STATUS
NAME              STARTED        DURATION   STATUS
build-app-skgpq   1 minute ago   ---        Running(Pending)
It will take few seconds for the TaskRun to show status as Running as it needs to download the container images.
  • Use the command help via tkn taskrun --help

  • Use tr as shorcut for taskrun commands e.g to list taskruns run the command tkn tr ls

To check the status of the TaskRun use the logs command of taskrun like:

#list running using the command tkn tr ls
tkn tr ls
# use one task run for which you need the log from list above
tkn tr logs -f -a <task-run-name> (1)

1 The -f or -a allows to tail the logs from all the containers of the task. For more options run tkn tr --help
Each task step will be run within a container of its own.

If you see the TaskRun status as Failed or Error use the following command to check the reason for error:

tkn taskrun describe <taskrun-name>

Test Task output

Lets try running the image build using the build-app task:

  • Kubernetes

  • OpenShift

kubectl run demo-greeter -n knativetutorial \
 --generator='run-pod/v1' \
 --image='dev.local/rhdevelopers/knative-tutorial-greeter' && \
kubectl expose pod demo-greeter -n knativetutorial --port 8080 --type=NodePort

oc run demo-greeter -n knativetutorial --generator='run-pod/v1' --image='dev.local/rhdevelopers/knative-tutorial-greeter' && \
oc expose pod demo-greeter -n knativetutorial --port 8080 --type=NodePort && \
oc expose svc -n knativetutorial demo-greeter

Lets try checking the application:

  • Kubernetes

  • OpenShift

SVC_URL=$(minikube ip):$(kubectl get svc -n knativetutorial demo-greeter -o yaml | yq r - 'spec.ports[0].nodePort') && \
http --body $SVC_URL

SVC_URL=$(oc get routes -o yaml | yq r - 'spec.url.host' )
http --body $SVC_URL

The above command should show an output like Hi greeter ⇒ 'demo-greeter' : 1

Cleanup

  • Kubernetes

  • OpenShift

kubectl delete pod -n knativetutorial demo-greeter &&\
kubectl delete svc -n knativetutorial demo-greeter

oc delete pod -n knativetutorial demo-greeter &&\
oc delete svc -n knativetutorial demo-greeter &&\
oc delete route -n knativetutorial demo-greeter