You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitLab模板兼容改造:单模板触发构建与扫描多作业方案咨询

解决方案:GitLab CI模板兼容扩展镜像扫描功能

问题背景

现有一个供用户通过extend关键字复用的GitLab作业模板.build_kaniko,需在完全保持向后兼容性的前提下为其添加镜像扫描功能。部分用户会多次扩展该模板构建多镜像,核心需求:

  • 模板名称不变,用户无需修改现有引用逻辑
  • 每次扩展模板时,自动生成对应构建作业和依赖该构建的扫描作业,流水线结构示例:
. (stages)
├── build
│   ├── build_container(用户自定义作业)
│   └── scan_build_container(自动生成,依赖build_container)
├── deploy
│   ├── deploy_container(用户自定义作业)
│   └── scan_deploy_container(自动生成,依赖deploy_container)
└── ...其他阶段

尝试trigger关键字无法实现需求,因其仅支持触发单个作业。

用户现有使用模板的场景示例:

单镜像构建/部署场景

include: 
- project : 'ci-tools/container-image-ci-templates'
  file : 'kaniko-image.gitlab-ci.yml'
  ref: master

stages:
  - build
  - deploy

build_container:
  rules:
  - if: $CI_COMMIT_BRANCH
  stage: build
  extends: .build_kaniko
  variables:
    REGISTRY_IMAGE_PATH : "registry.foo.bar/MYPROJECT/MYIMAGE:$CI_COMMIT_SHORT_SHA"
    CONTEXT_DIR: "dockerfiles_folder"
    DOCKER_FILE_NAME: "Dockerfile_ubuntu"  

deploy_container:
  rules:
    - if: $CI_COMMIT_TAG
  stage: deploy
  extends: .build_kaniko
  variables:
    PUSH_IMAGE: "true"
    REGISTRY_IMAGE_PATH : "registry.foo.bar/MYPROJECT/MYIMAGE:$CI_COMMIT_TAG"
    CONTEXT_DIR: "dockerfiles_folder"
    DOCKER_FILE_NAME: "Dockerfile_ubuntu"  

多镜像构建场景

...
build_container_container1:
  rules:
  - if: $CI_COMMIT_BRANCH
  stage: build
  extends: .build_kaniko
  variables:
    REGISTRY_IMAGE_PATH : "registry.foo.bar/MYPROJECT/MYIMAGE:$CI_COMMIT_SHORT_SHA"
    CONTEXT_DIR: "dockerfiles_folder"
    DOCKER_FILE_NAME: "Dockerfile_ubuntu_1"  

build_container_container2:
  rules:
  - if: $CI_COMMIT_BRANCH
  stage: build
  extends: .build_kaniko
  variables:
    REGISTRY_IMAGE_PATH : "registry.foo.bar/MYPROJECT/MYIMAGE:$CI_COMMIT_SHORT_SHA"
    CONTEXT_DIR: "dockerfiles_folder"
    DOCKER_FILE_NAME: "Dockerfile_fedora" 
...

实现方案

推荐方案(GitLab 15.0+):动态作业生成

利用GitLab CI的generate关键字(15.0及以上支持),在原模板中自动生成扫描作业,完全保持用户现有使用方式不变。

模板文件kaniko-image.gitlab-ci.yml内容

# 自动合并扫描阶段到用户流水线
stages:
  - build
  - scan
  - deploy

# 基础构建逻辑模板(保留原构建逻辑)
.build_kaniko_base:
  image: gcr.io/kaniko-project/executor:v1.9.0-debug
  script:
    - # 生成Docker认证配置
    - echo "{\"auths\":{\"$(echo $REGISTRY_IMAGE_PATH | cut -d/ -f1)\":{\"auth\":\"$(echo -n "$REGISTRY_USER:$REGISTRY_PASS" | base64)\"}}}" > /kaniko/.docker/config.json
    - # 执行Kaniko构建
    - /kaniko/executor --context "${CI_PROJECT_DIR}/${CONTEXT_DIR}" --dockerfile "${CI_PROJECT_DIR}/${CONTEXT_DIR}/${DOCKER_FILE_NAME}" --destination "${REGISTRY_IMAGE_PATH}" $( [ "${PUSH_IMAGE}" = "true" ] && echo "--push" )

# 基础扫描逻辑模板(可替换为实际使用的扫描工具)
.scan_kaniko_base:
  image: aquasec/trivy:0.44.0
  script:
    - trivy image --severity HIGH,CRITICAL --exit-code 1 "${REGISTRY_IMAGE_PATH}"
  rules:
    - if: $SKIP_SCAN != "true"  # 提供跳过扫描的兼容开关
  stage: scan

# 原模板名称不变,用户直接extends即可
.build_kaniko:
  extends: .build_kaniko_base
  generate:
    # 动态生成扫描作业,作业名为scan_<当前构建作业名>
    scan_${CI_JOB_NAME}:
      extends: .scan_kaniko_base
      variables:
        REGISTRY_IMAGE_PATH: "${REGISTRY_IMAGE_PATH}"
      needs: ["${CI_JOB_NAME}"]  # 扫描作业依赖对应构建作业

效果说明

  • 用户无需修改任何现有代码,继续使用extends: .build_kaniko
  • 每个构建/部署作业会自动生成对应扫描作业,例如build_container对应scan_build_container
  • 扫描作业在scan阶段执行,仅在对应构建作业成功后触发
  • 通过设置SKIP_SCAN=true变量可临时跳过扫描,保持向后兼容

兼容方案(GitLab <15.0):子流水线触发

针对不支持generate关键字的旧版本GitLab,使用子流水线实现扫描作业的自动生成。

模板文件kaniko-image.gitlab-ci.yml内容

# 自动合并扫描阶段到用户流水线
stages:
  - build
  - scan
  - deploy

# 基础构建逻辑模板
.build_kaniko_base:
  image: gcr.io/kaniko-project/executor:v1.9.0-debug
  script:
    - # 执行原构建逻辑
    - echo "{\"auths\":{\"$(echo $REGISTRY_IMAGE_PATH | cut -d/ -f1)\":{\"auth\":\"$(echo -n "$REGISTRY_USER:$REGISTRY_PASS" | base64)\"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor --context "${CI_PROJECT_DIR}/${CONTEXT_DIR}" --dockerfile "${CI_PROJECT_DIR}/${CONTEXT_DIR}/${DOCKER_FILE_NAME}" --destination "${REGISTRY_IMAGE_PATH}" $( [ "${PUSH_IMAGE}" = "true" ] && echo "--push" )
    - # 生成扫描作业配置文件
    - |
      cat > scan_job.yml << EOF
      scan_${CI_JOB_NAME}:
        image: aquasec/trivy:0.44.0
        stage: scan
        script:
          - trivy image --severity HIGH,CRITICAL --exit-code 1 "${REGISTRY_IMAGE_PATH}"
        rules:
          - if: \$SKIP_SCAN != "true"
        needs: ["${CI_JOB_NAME}"]
      EOF
    - # 触发子流水线执行扫描
    - curl --request POST --form "token=${CI_JOB_TOKEN}" --form "ref=${CI_COMMIT_REF_NAME}" --form "yaml_file=@scan_job.yml" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/trigger/pipeline"
  after_script:
    - rm -f scan_job.yml

# 原模板名称不变
.build_kaniko:
  extends: .build_kaniko_base

注意事项

  • 需确保CI_JOB_TOKEN具备触发流水线的权限,可在项目设置中调整权限配置
  • 扫描工具可替换为Clair、Anchore等,只需修改扫描作业的image和script内容

内容的提问来源于stack exchange,提问作者Diogo Guerra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 07:19:55