tekton notes

run my own ci...?

SEAN K.H. LIAO

tekton notes

run my own ci...?

tekton pipelines

Tekton sits somewhere on the spectrum between a building block and a product of a CI system. Or maybe not a CI system, a generalized graph of arbitrary code execution.

cloud build

There was a build task I wanted to move over from Google Cloud Build: a nightly build of Go (plus some extra tools). This was setup as a Dockerfile in a git repo subdirectory, a Cloud Build config file, and a Google Cloud Scheduler to trigger the build.

Dockerfile:

FROM golang:alpine AS build
ENV CGO_ENABLED=0 \
    GOFLAGS=-trimpath
RUN apk add --no-cache bash curl gcc git musl-dev && \
    go install golang.org/dl/gotip@latest && \
    gotip download && \
    rm -rf /root/sdk/gotip/pkg/linux_* && \
    curl -Lo /usr/local/bin/skaffold https://storage.googleapis.com/skaffold/builds/latest/skaffold-linux-amd64 && \
    chmod +x /usr/local/bin/skaffold

FROM alpine
RUN apk add --no-cache git
ENV CGO_ENABLED=0 \
    GOFLAGS=-trimpath
ENV PATH=/root/sdk/gotip/bin:/root/go/bin:$PATH
COPY --from=build /usr/local/bin/skaffold /usr/local/bin/skaffold
COPY --from=build /root/sdk/gotip /root/sdk/gotip
WORKDIR /workspace
ENTRYPOINT [ "go" ]

cloudbuild.yaml:

steps:
  - id: build-push-gotip
    name: "gcr.io/kaniko-project/executor"
    args:
      - "--context=gotip"
      - "--destination=${_REGISTRY}/gotip:latest"
      - "--image-name-with-digest-file=.image.gotip.txt"
      - "--reproducible"
      - "--single-snapshot"
      - "--snapshot-mode=redo"
      - "--ignore-var-run"

  - id: sign-gotip
    name: "gcr.io/projectsigstore/cosign"
    entrypoint: sh
    env:
      - "TUF_ROOT=/tmp" # cosign tries to create $HOME/.sigstore
      - "COSIGN_EXPERIMENTAL=1"
      - "GOOGLE_SERVICE_ACCOUNT_NAME=cosign-signer@com-seankhliao.iam.gserviceaccount.com"
    args:
      - "-c"
      - "cosign sign --force $(head -n 1 .image.gotip.txt)"

substitutions:
  _REGISTRY: us-central1-docker.pkg.dev/com-seankhliao/build

options:
  env:
    - GOGC=400

timeout: "1800s" # 30m gotip build is slow

tekton build

Moving over to Tekton, I went with inlining the entire build config into a TriggerTemplate. No more cloning a repo first just for a file. I think I could have done this with Cloud Build too, but I haven't been consistent in managing my config as code consistently...

apiVersion: triggers.tekton.dev/v1beta1
kind: TriggerTemplate
metadata:
  name: gotip-trigger
spec:
  resourcetemplates:
    - apiVersion: tekton.dev/v1beta1
      kind: TaskRun
      metadata:
        generateName: build-gotip-tr-
      spec:
        taskSpec:
          params:
            - name: image-ref
              type: string
              default: us-central1-docker.pkg.dev/com-seankhliao/build/gotip:latest
          results:
            - name: image-digest
          steps:
            - name: write-dockerfile
              image: busybox
              script: |
                cat << EOF > /workspace/src/Dockerfile
                FROM golang:alpine AS build
                ENV CGO_ENABLED=0 \
                    GOFLAGS=-trimpath
                RUN apk add --no-cache bash curl gcc git musl-dev && \
                    go install golang.org/dl/gotip@latest && \
                    gotip download && \
                    rm -rf /root/sdk/gotip/pkg/linux_* && \
                    curl -Lo /usr/local/bin/skaffold https://storage.googleapis.com/skaffold/builds/latest/skaffold-linux-amd64 && \
                    chmod +x /usr/local/bin/skaffold

                FROM alpine
                RUN apk add --no-cache git
                ENV CGO_ENABLED=0 \
                    GOFLAGS=-trimpath
                ENV PATH=/root/sdk/gotip/bin:/root/go/bin:$PATH
                COPY --from=build /usr/local/bin/skaffold /usr/local/bin/skaffold
                COPY --from=build /root/sdk/gotip /root/sdk/gotip
                WORKDIR /workspace
                ENTRYPOINT [ "go" ]
                EOF
              volumeMounts:
                - name: src
                  mountPath: /workspace/src
            - name: build-gotip
              image: "gcr.io/kaniko-project/executor"
              args:
                - "--context=/workspace/src"
                - "--destination=$(params.image-ref)"
                - "--image-name-with-digest-file=$(results.image-digest.path)"
                - "--reproducible"
                - "--single-snapshot"
                - "--snapshot-mode=redo"
                - "--ignore-var-run"
                - "--ignore-path=/product_uuid" # kind specific? https://github.com/GoogleContainerTools/kaniko/issues/2164
              volumeMounts:
                - name: src
                  mountPath: /workspace/src
                - name: docker-auth
                  mountPath: /kaniko/.docker/config.json
                  subPath: .dockerconfigjson
          volumes:
            - name: src
              emptyDir: {}
            - name: docker-auth
              secret:
                secretName: gcp-ar-docker

Next up, an EventListener to turn HTTP requests into TaskRuns:

apiVersion: triggers.tekton.dev/v1beta1
kind: EventListener
metadata:
  name: gotip-event
spec:
  serviceAccountName: tekton-triggers
  triggers:
    - name: default
      template:
        ref: gotip-trigger

And a CronJob to make the HTTP requests:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: trigger-gotip
spec:
  schedule: "*/30 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: trigger
            image: curlimages/curl:latest
            args:
              - --data
              - '{}'
              - http://el-gotip-event.default.svc.cluster.local:8080
          restartPolicy: OnFailure