在 K8S Job 中使用 OCI Connector 构建镜像

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

功能概述

本文将指导您如何在 Kubernetes Job 中使用 OCI Connector 构建镜像并推送到 Registry。借助 OCI Connector 的能力,普通用户无需接触或配置认证凭据,从而最大限度地保障这些凭据的安全。

在 Kubernetes Job 中使用 OCI Connector 时,需要注意以下要点:

  • 将构建的目标镜像地址更改为 connector 的代理地址。什么是 Connector 代理地址
    • 例如:harbor.example.cn/test/abc:v1 -> harbor.default.cluster.local/namespaces/oci-connector-ns/connectors/oci-connector-name/test/abc:v1
  • 挂载 Connector 提供的配置。
  • 为客户端工具配置 insecure registry

本文以 buildkitd 为例,详细介绍如何创建 Kubernetes Job,利用 OCI Connector 完成镜像构建和推送,无需在客户端配置认证信息。

前提条件

  • 创建一个 Connector。
  • 用于构建镜像的 Dockerfile。

Connector

kubectl apply -f - <<EOF
apiVersion: connectors.alauda.io/v1alpha1
kind: Connector
metadata:
  name: harbor
spec:
  address: https://harbor.example.com # 替换为可访问的 OCI registry 地址
  auth:
    name: tokenAuth
    params:
    - name: repository
      value: testing/busybox
    secretRef:
      name: harbor-secret
  connectorClassName: oci
---
apiVersion: v1
stringData: # 替换为实际认证信息
  password: admin
  username: admin
kind: Secret
metadata:
  name: harbor-secret
type: cpaas.io/distribution-registry-token
EOF

Dockerfile

为了演示构建和推送过程,我们需要准备一个 Dockerfile。为简化操作,我们将 Dockerfile 内容存储在 ConfigMap 中,并通过 Kubernetes Pod 卷挂载到 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

操作步骤

创建带有正向代理的 K8S Job

  • 配置 OCI Connector 的正向代理,如 http_proxyhttps_proxyno_proxy 等。

OCI ConnectorClass 提供开箱即用的配置,可通过 connector-csi 挂载。

Job 内容如下:

cat << EOF | kubectl create -f -
kind: Pod
apiVersion: v1
metadata:
  generateName: buildkit-build-
spec:
  restartPolicy: Never
  containers:
  - name: buildkit
    image: moby/buildkit:v0.18.2
    securityContext:
      privileged: true
    env:
    - name: BUILDKITD_FLAGS
      value: "--config /etc/buildkit/buildkitd.toml"
    command:
    - /bin/sh
    - -c
    args:
    - |
      set -ex
      export http_proxy=$(cat /tmp/http.proxy)
      export https_proxy=$(cat /tmp/https.proxy)
      export HTTP_PROXY=$http_proxy
      export HTTPS_PROXY=$https_proxy
      export no_proxy=localhost,127.0.0.1
      export NO_PROXY=$no_proxy
      echo "Using proxy: http_proxy=$http_proxy, https_proxy=$https_proxy, no_proxy=$no_proxy"

      buildctl-daemonless.sh --debug \
      build \
      --progress=plain \
      --frontend=dockerfile.v0 \
      --opt filename=Dockerfile \
      --local context=/workspace \
      --local dockerfile=/workspace \
      --output type=image,name=harbor.example.com/library/image:v1,push=true \
      --export-cache type=inline
    volumeMounts:
    - name: dockerfile
      mountPath: /workspace
    - name: proxyconfig
      mountPath: /tmp/
  volumes:

  # 将 dockerfile 挂载到 Pod
  - name: dockerfile
    configMap:
      name: dockerfile

  # 将 proxyconfig 挂载到 Pod
  - name: proxyconfig
    csi:
      readOnly: true
      driver: connectors-csi
      volumeAttributes:
        connector.name: "harbor"
EOF

创建带有反向代理的 K8S Job

  • 为使用 connector 的代理功能,需要将代理所需的认证信息注入到 docker/config.json,需提供卷挂载 docker/config.json
  • 为使客户端能访问 HTTP 代理,需要为客户端配置 insecure-registries,需提供卷挂载 buildkitd.toml
  • 修改推送镜像的地址为 connector 的代理地址。

关于获取 Connector 代理地址的信息,请参见:OCI Connector Class 代理信息说明

Job 内容如下:

cat << EOF | kubectl create -f -
kind: Pod
apiVersion: v1
metadata:
  generateName: buildkit-build-
spec:
  restartPolicy: Never
  containers:
  - name: buildkit
    image: moby/buildkit:v0.18.2
    securityContext:
      privileged: true
    env:
    - name: BUILDKITD_FLAGS
      value: "--config /etc/buildkit/buildkitd.toml"
    command:
    - /bin/sh
    - -c
    args:
    - |
      set -ex
      buildctl-daemonless.sh --debug \
      build \
      --progress=plain \
      --frontend=dockerfile.v0 \
      --opt filename=Dockerfile \
      --local context=/workspace \
      --local dockerfile=/workspace \
      --output type=image,name=c-harbor.default.svc.cluster.local/namespaces/oci-connector-demo/connectors/oci-connector/test-cjt:v1,push=true \
      --export-cache type=inline
    volumeMounts:
    - name: dockerfile
      mountPath: /workspace
    - name: docker-config
      mountPath: /root/.docker
    - name: buildkitd-config
      mountPath: /etc/buildkit

  volumes:

  # 将 dockerfile 挂载到 Pod
  - name: dockerfile
    configMap:
      name: dockerfile

  # 将 docker 的 config.json 挂载到 Pod
  - name: docker-config
    csi:
      readOnly: true
      driver: connectors-csi
      volumeAttributes:
        connector.name: "harbor"
        configuration.names: "docker-config"

  # 将 buildkitd.toml 挂载到 Pod
  - name: buildkitd-config
    csi:
      readOnly: true
      driver: connectors-csi
      volumeAttributes:
        connector.name: "harbor"
        configuration.names: "buildkitd"
EOF

操作结果

您可以使用以下命令检查 Job 是否执行成功:

$ kubectl get job

总结

我们完成了“在 K8S Job 中使用 OCI Connector 构建镜像”的全过程。可以看到,在 Job 执行过程中,用户需要指定镜像仓库的认证信息,而在运行 Job 的 Pod 中,用户无法访问为 Connector 配置的认证数据。这极大地保证了凭据在实际使用中的不泄露,保障了工具认证信息的安全性。