Build container images in Kubernetes using Knative

Staffan Olsson

Staffan Olsson

Dec 6, 2018
Build container images in Kubernetes using Knative
Build container images in Kubernetes using Knative

Knative Build Pipeline is the successor to Knative Build. It aims to support complete CI/CD flows and is under alpha development, but you can already use it to build container images in your Kubernetes cluster.

Where Knative Build used BuildTemplates, pipeline uses Tasks. The migration is quite straightforward. Let’s say we have a two-step function (as-a-service) build, the first generates a Dockerfile that the second builds using Kaniko. The old template would have looked like this:

apiVersion: build.knative.dev/v1alpha1
kind: BuildTemplate
metadata:
  name: function-runtime
spec:
  parameters:
  - name: IMAGE
    description: The URI of the image to push, including registry host
  - name: HANDLER
    description: The import used to load the handler
    default: "handler.js"
  steps:
  - name: dockerfile
    image: gcr.io/kaniko-project/executor:debug
    command:
    - /busybox/sh
    args:
    - -c
    - |
      cat <<EOF >> Dockerfile
      FROM docker-registy.local/our-function-runtime:latest
      COPY . .
      ENV HTTP_HANDLER=${HANDLER}
      EOF
  - name: export
    image: gcr.io/kaniko-project/executor
    args:
    - --destination=${IMAGE}


To run that you would have a Build – possibly generated through a Configuration – that specified the source, i.e. git url, along with the parameter values as template arguments.

Tasks use a similar structure but different conventions for parameters, which we’ll get to shortly. First more juicy yaml:

apiVersion: pipeline.knative.dev/v1alpha1
kind: Task
metadata:
  name: function-build
spec:
  inputs:
    resources:
    - name: workspace
      type: git
    params:
    - name: handler
      description: The import used to load the handler
      default: "handler.js"
  outputs:
    resources:
    - name: builtImage
      type: image
  steps: ...

Where steps are identical to those in the BuildTemplate… almost. For now copy your steps along to the new yaml and let’s see below what to update.

Run your build

Build Pipeline represents your source repository and target image as Resources. While migrating from Build to TaskRun you’ll want to extract those. Note how the Task definition takes some parameters TaskRun and some for resources:

  steps:
  - name: dockerfile
    ...
      ENV HTTP_HANDLER=${inputs.params.handler}
    ...
  - name: export
    ...
    - --destination=${outputs.resources.builtImage.url}

The Task definition is complete, so go ahead and apply it. Now in order to run the build you must provide PipelineResource “git” and “buildImage” together with a TaskRun. See for example our azure example for the yaml. We keep the resources in a separate yaml because we might want to some day reuse them in a PipelineRun, where they have the role of carrying state between tasks.

What a build looks like in Kubernetes

Let’s run our nodejs example to see what it looks like. After the “kubectl apply” we might see a pod, but if not maybe:

$ kubectl describe taskrun nodejs-riff
Name: nodejs-riff
...
Status:
Conditions:
Last Transition Time: 2018-12-04T14:08:25Z
Message: couldn't retrieve referenced input PipelineResource "nodejs-riff-module-git": pipelineresource.pipeline.knative.dev "nodejs-riff-module-git" not found

Oops, forgot to apply the resources yaml. Apply that and a pod starts:

$ kubectl get pods
NAME                     READY   STATUS     RESTARTS   AGE
nodejs-riff-pod-0e9f40   0/1     Init:4/5   0          24s

The build steps are init containers. We can see the output of each step using the container name:

$ kubectl logs nodejs-riff-pod-0e9f40 -c build-step-build-and-push
INFO[0000] Downloading base image projectriff/node-function-invoker@sha256:ae7f87c524bb46dbfd7acc986b827f74d93d1301ea137f52734c7607295a919c 
...
INFO[0011] COPY . ${FUNCTION_URI}                       
INFO[0011] Taking snapshot of files...                  
...
2018/12/04 14:11:50 pushed blob sha256:4ccf8f766ca3c8bac929d3cf316001a7d3255ce6c067b0465294254b27b7ae17
2018/12/04 14:11:50 knative.registry.svc.cluster.local/knative-training/nodejs-riff-module:latest: digest: sha256:b72354b6af226e0aef7524a8e2bd8340e6fd3e209760b0dfc1abafbd1341a04a size: 1886

Build completed and pushed to our registry. That’s it. Note that things are under heavy development. These yamls might not be valid as development progresses. Stay tuned for more information.

Create your first event flow in under 5 minutes