Kaniko:在 Kubernetes 中无特权构建镜像

FreeGuideOnline 最新 2026-07-04

bash kubectl create secret docker-registry regcred
--docker-server=https://index.docker.io/v1/
--docker-username=your-username
--docker-password=your-password
--docker-email=your-email@example.com
-n kaniko-builds


如果使用其他镜像仓库,请相应调整 `--docker-server` 地址。

### 编写 Kaniko Pod 或 Job 配置
通常使用一次性 Job 来执行构建任务。以下是最小化配置示例(将 Dockerfile 和上下文放在 Git 仓库中,需配合 `initContainer` 或使用 kaniko 内置的 Git 上下文支持)。更简单的方式是将上下文直接通过 `tar` 文件提供给 Kaniko。

我们采用 Kaniko 自带的 `kaniko executor` 镜像,并通过挂载 Secret 提供推送凭据。以下 YAML 展示了使用 `BusyBox` 作为辅助容器生成一个简单的 Dockerfile 并传递给 Kaniko 的思路,但实际上 Kaniko 可以直接使用 `gs://`, `s3://`, `git://` 等上下文。这里演示最通用的方法:使用 `initContainer` 生成构建上下文并复制给主容器。

```yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: kaniko-build-job
spec:
  template:
    spec:
      initContainers:
      - name: create-context
        image: busybox
        command: ['sh', '-c']
        args:
        - |
          mkdir -p /workspace
          cat > /workspace/Dockerfile <<EOF
          FROM alpine:latest
          RUN echo "Hello Kaniko!" > /hello.txt
          CMD ["cat", "/hello.txt"]
          EOF
        volumeMounts:
        - name: workspace
          mountPath: /workspace
      containers:
      - name: kaniko
        image: gcr.io/kaniko-project/executor:latest
        args:
          - "--dockerfile=/workspace/Dockerfile"
          - "--context=dir:///workspace"
          - "--destination=your-dockerhub-username/kaniko-demo:latest"
        volumeMounts:
        - name: workspace
          mountPath: /workspace
        - name: kaniko-secret
          mountPath: /kaniko/.docker
      restartPolicy: Never
      volumes:
      - name: workspace
        emptyDir: {}
      - name: kaniko-secret
        secret:
          secretName: regcred
          items:
            - key: .dockerconfigjson
              path: config.json

注意:Kaniko 默认会在 /kaniko/.docker/config.json 读取 push 凭据,因此将 Secret 挂载到该路径。

参数详解

常用参数:

  • --dockerfile:指定 Dockerfile 路径(在构建上下文内或绝对路径)。
  • --context:构建上下文地址。支持:
    • dir:///path:本地目录(通过卷挂载获得)。
    • git://repo-url:直接克隆 Git 仓库,可指定分支 #branch
    • gs://bucket/path:Google Cloud Storage。
    • s3://bucket/path:AWS S3。
    • tar:// / stdin 等。
  • --destination:目标镜像地址,可多次指定以推送到多个仓库。格式:registry/repo:tag
  • --cache=true:启用分层缓存,会将中间层推送为 cache repo 的独立镜像,默认缓存到基础镜像所在仓库的 cache 命名空间下(可自定义)。
  • --cache-repo:指定缓存存储仓库,例如 yourrepo/cache
  • --target:多阶段构建时指定阶段名。
  • --build-arg:传入构建参数(ARG)。
  • --skip-tls-verify:跳过 TLS 证书验证(仅测试环境)。

执行构建并检查结果

应用 Job 配置:

kubectl apply -f kaniko-build-job.yaml -n kaniko-builds

查看 Pod 日志:

kubectl logs job/kaniko-build-job -n kaniko-builds

若一切正常,将看到 “Pushed image to ...” 信息。随后可从镜像仓库拉取验证。

高级配置

启用分层缓存加速构建

在后续构建中显著加快速度:

args:
  - "--cache=true"
  - "--cache-repo=your-dockerhub-username/kaniko-cache"
  - "--context=dir:///workspace"
  ...

注意缓存镜像会污染仓库标签列表,建议使用专用凭据或单独仓库。

使用多阶段构建

Kaniko 原生支持 Dockerfile 多阶段构建,无需额外配置。例如:

FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

FROM alpine:latest
COPY --from=builder /app/myapp /usr/local/bin/myapp
CMD ["myapp"]

只需在 Kaniko 参数中正常引用该 Dockerfile 即可。

构建上下文从 Git 仓库直接获取

无需事先挂载代码,直接指定 Git 地址:

args:
  - "--context=git://github.com/user/repo.git#main"
  - "--dockerfile=Dockerfile"
  - "--destination=user/app:latest"

注意:Kaniko 容器需要能访问互联网,并且仓库为公开或可使用 Git 凭据辅助(通过挂载 .git-credentials 等方式)。

在 CI/CD 流水线中集成

在 GitLab CI、Tekton Pipelines、Argo Workflows 等平台中,可直接使用 Kaniko executor 镜像作为步骤执行者。例如在 GitLab CI 中:

build:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]
  script:
    - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG

debug 标签内置 shell,方便脚本操作。)

构建性能优化与常见问题

优化缓存命中率

  • 尽量将不经常变动的层放在 Dockerfile 前面(例如安装系统依赖)。
  • 使用 --cache-dir 参数配置缓存目录位置,配合持久化卷使用,但注意 Kaniko 注重无状态构建,每次 Pod 重启缓存将丢失,推荐使用远程仓库缓存。

调试构建失败

  • 添加 --verbosity=debug 获取详细日志。
  • 如果推送失败,检查 Secret 格式:config.json 必须包含正确的认证信息,且挂载路径为 /kaniko/.docker/config.json
  • 网络问题:确保集群可访问目标镜像仓库,必要时设置 http_proxy 环境变量。

与 Docker 构建的差异

  • Kaniko 不支持 ONBUILD 触发器。
  • 某些遗留镜像的 RUN 指令如果依赖特权操作(如挂载 /proc)会失败,需调整 Dockerfile。
  • 基础镜像必须能被 Kaniko 拉取(公共或凭据可访问)。

安全加固建议

  • 使用 securityContext 限制容器权限,避免提升权限。推荐:
    securityContext:
      runAsNonRoot: true
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - ALL