在 Tekton Pipeline 中使用 OCI Connector 构建镜像

阅读前请参考 K8S 工作负载中使用 OCI Connector 代理的一般逻辑

目录

功能概述

本文将教你如何在 Tekton Pipeline 中使用 OCI Connector 来构建镜像并推送到 Registry。借助 OCI Connector 的能力,普通用户无需处理认证信息,从而最大限度地保障凭据的安全。

在 Tekton Pipeline 中使用 OCI Connector 时,有几个关键点需要注意:

  • 目标构建镜像的地址改为 Connector 的代理地址。
    • 例如,build-harbor.alauda.cn/test/abc:v1 -> harbor.default.cluster.local/test/abc:v1
  • 挂载 Connector 提供的配置。
  • 为客户端工具配置 insecure registry

本文将以 buildkit-daemonless task 为例,详细说明如何使用 OCI Connector 完成镜像构建和推送流程,而无需在客户端配置认证信息。

前提条件

  • buildkit-daemonless Tekton Task
  • 用于构建镜像的 Dockerfile

buildkit-daemonless task

我们需要基于 TektonHub buildkit-daemonless 做一些修改:

  • 新增一个 docker config workspace,允许用户指定 docker/config.json
  • 新增一个 buildkitd config workspace,允许用户指定 buildkitd.toml

内容如下。你可以使用以下命令将该 Task 安装到集群中。

kubectl apply -f - <<'EOF'
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: buildkit-daemonless
  labels:
    app.kubernetes.io/version: "0.1"
  annotations:
    tekton.dev/pipelines.minVersion: "0.12.1"
    tekton.dev/categories: Image Build
    tekton.dev/tags: image-build
    tekton.dev/displayName: "buildkit daemonless"
    tekton.dev/platforms: "linux/amd64"
    tekton.dev/deprecated: "true"
spec:
  description: >-
    This Task builds source into a container image using Moby BuildKit.
    This buildkit-daemonless Task is similar to buildkit but does not need
    creating Secret, Deployment, and Service resources for setting up the
    buildkitd daemon cluster.
  params:
    - name: Dockerfile
      description: The name of the Dockerfile
      default: "Dockerfile"
    - name: repository
      description: The name of the repository
  workspaces:
    - name: source
    - name: docker-config
    - name: buildkitd-config
  steps:
    - name: build-and-push
      image: moby/buildkit:v0.18.2
      workingDir: $(workspaces.source.path)
      securityContext:
        privileged: true
      script: |
        #!/bin/sh

        set -ex

        mkdir -p ~/.docker
        cp $(workspaces.docker-config.path)/config.json ~/.docker

        export BUILDKITD_FLAGS="--config $(workspaces.buildkitd-config.path)/buildkitd.toml $BUILDKITD_FLAGS"

        buildctl-daemonless.sh --debug \
          build \
          --progress=plain \
          --frontend=dockerfile.v0 \
          --opt filename=$(params.Dockerfile) \
          --local context=. \
          --local dockerfile=. \
          --output type=image,name=$(params.repository),push=true \
          --export-cache type=inline
EOF

Dockerfile

为了演示构建和推送流程,我们需要准备一个 Dockerfile。为简化操作,我们将 Dockerfile 内容保存在 ConfigMap 中,然后通过 Tekton Task 的 workspace 挂载到 Pod。

kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: dockerfile
data:
  Dockerfile: |
    FROM scratch
    LABEL maintainer="example@example.com"
    WORKDIR /app
    ENV APP_VERSION="1.0.0"
EOF

操作步骤

执行 TaskRun

向 TaskRun 传递以下参数:

  • 指定 docker-config workspace 为 OCI connector 的 docker-config 配置,从而挂载 docker/config.json
  • 指定 buildkitd-config workspace 为 OCI connector 的 buildkitd 配置,从而挂载 buildkitd.toml
  • 将推送的目标镜像地址调整为代理地址。
kubectl create -f - <<EOF
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  generateName: buildkit-build-
spec:
  taskRef:
    name: buildkit-daemonless
  workspaces:
    - name: source # 挂载 Dockerfile 到 Pod
      configMap:
        name: dockerfile
    - name: docker-config
      csi: # 挂载 docker/config.json
        driver: connectors-csi
        readOnly: true
        volumeAttributes:
          connector.name: "harbor"
          configuration.names: "docker-config"
    - name: buildkitd-config
      csi: # 挂载 buildkitd.toml
        driver: connectors-csi
        readOnly: true
        volumeAttributes:
          connector.name: "harbor"
          configuration.names: "buildkitd"
  params:
    - name: repository
      value: "c-harbor.default.svc.cluster.local/test/demo:v1" # 推送到代理地址
EOF

获取 Connector 代理地址,请参考:OCI Connectorclass 代理信息说明

操作结果

我们可以通过以下命令检查 TaskRun 是否执行成功。

$ kubectl get taskrun

总结

我们完成了“在 Tekton Pipeline 中使用 OCI Connector 构建并推送镜像”的整个流程。可以看到,执行 TaskRun 时无需用户指定镜像仓库的认证信息,且用户也无法访问执行 TaskRun 的 Pod 中由 Connector 配置的认证数据。这极大地保证了凭据不被泄露,保障了工具认证信息的安全性。