news 2026/9/26 9:29:24

OpenShift Builds 构建体系详解:Docker、S2I 与自定义构建策略实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenShift Builds 构建体系详解:Docker、S2I 与自定义构建策略实战指南
  • 测试
  • 云原生
  • 质量保障

【免费下载链接】origin

Conformance test suite for OpenShift

项目地址:https://gitcode.com/gh_mirrors/or/origin
点击查看免费下载

本文以 docs/builds.md 为核心脉络,系统讲解 OpenShift(即 origin 项目)中镜像构建 API 的设计动机、三种默认构建策略(Docker、Source-to-Image、Custom)的原理与配置方法,并结合本仓库的 e2e 测试与真实 YAML/JSON 配置样例,帮助读者掌握如何通过构建 API 让 OpenShift 成为可调度、可限制资源、可被第三方 CI 编排的容器镜像构建后端。

背景与动机:为什么 Kubernetes 需要"构建"能力

Kubernetes 本身只负责"运行容器":它从镜像仓库拉取已经构建好的镜像,再以 Pod 的形式调度运行。镜像的构建环节并不在 Kubernetes 的核心能力范围内——按照原文档 docs/builds.md 的论述,在没有构建支持的情况下,系统管理员若想获得镜像构建能力,只能自行挑选一套既有构建系统,或从零编写一套,并自行解决如何在 Kubernetes 之上或之外部署、维护它。

然而,大多数运维人员更希望复用 Kubernetes 的任务调度能力:把构建任务作为可调度的任务塞进现有的资源池中,而不是另起炉灶。这正是 OpenShift 构建 API 存在的根本理由:

  • 构建 API 让 OpenShift 成为第三方容器镜像构建系统的可用后端,这类系统通常需要资源约束与调度能力;
  • 组织可以从既有的持续集成(CI)流程中编排 Docker 构建,形成围绕容器镜像的 CI/CD 流水线;
  • 绝大多数构建任务都具有共同特征:一组构建输入、一个必须运行到完成的构建过程、构建过程日志的捕获、成功构建产物的发布,以及最终的构建状态;
  • Kubernetes 倡导的"镜像驱动部署"(image-driven deployment)流程,也依赖镜像的持续可用。

原文档特别强调两个设计原则:构建应利用资源限制机制(如 CPU 用量、内存用量、构建 Pod 执行时间上限,待 Kubernetes 原生支持后即可生效),并且构建应当可重复、结果一致(相同的输入 = 相同的输出)。

典型用户场景

原文档给出了四类核心场景,构成了构建 API 的验收视角:

  1. 从源码 URL 构建镜像并推送至仓库(最终在 OpenShift 中部署);
  2. 从二进制输入(Docker context、产物)构建镜像并推送至仓库;
  3. 作为提供镜像构建服务的厂商,把资源分配、调度、垃圾回收等负担转嫁给 OpenShift,而不是自己解决;
  4. 作为构建系统开发者,借助 OpenShift 执行构建,但仍从现有 CI 侧编排,以契合组织的 DevOps SOP。

两个示例用例

  • 云 IDE 场景(Company X):一家提供 Docker 化云 IDE 服务的公司,需要为客户托管项目大规模构建镜像,希望获得一套开箱即用的方案,能处理调度、资源分配与垃圾回收。通过构建 API,Company X 可以将构建工作交给 OpenShift,集中精力解决核心业务问题。
  • 企业 DevOps 场景(Company Y):Company Y 希望用 OpenShift 构建镜像,但其 SOP 强制要求使用第三方 CI 服务器来触发构建(如上游项目构建成功后触发)和推进构建(CI 中签收通过后晋升)。借助构建 API,Company Y 在 CI 服务器中实现编排 OpenShift 构建的工作流,从而与其组织 SOP 集成。

构建策略总览

OpenShift 构建系统基于构建 API 中可选类型(type)提供可扩展的构建策略支持。默认提供三种策略:

策略类型用途
Docker(DockerStrategy)基于 Docker context / Dockerfile 执行docker build
Source / S2I(SourceStrategy)基于 Source-to-Image 工具,将源码注入基础镜像并组装新镜像
Custom(CustomStrategy)使用用户自定义的 builder 镜像来执行构建,扩展构建过程

Docker 构建策略

使用 Docker 策略时,用户可以提供一个 Docker context 的 URL 作为 Docker 构建的基础。

工作原理:OpenShift 让构建容器直接访问节点上的 Docker daemon。构建期间会创建一个只含单个容器(build container)的 Pod,节点上的 Docker socket 以 bind mount 方式挂载进构建容器;构建容器随后执行docker build,所有与 Docker 的交互都经由节点的 Docker daemon 完成。

优势:

  1. 允许在非特权容器中执行 Docker 构建;
  2. 最小化镜像存储需求;
  3. 减少所需 Docker daemon 的数量。

劣势:

  1. 按用户约束资源变得更困难;
  2. 构建期间创建的容器处于 kubelet 管理范围之外;
  3. 构建期间创建的容器进程是远端 Docker 进程的子进程,使容器清理更加困难。

原文档指出这些问题都有可行的缓解路径,该机制被认定为 work in progress。

为什么不用 Docker-in-Docker?

理论上可以用容器内嵌套 Docker daemon(Docker-in-Docker)实现构建,表面上有诱人优势:构建进程资源可自然地被限制在用户可接受范围内(cgroups),且构建期间创建的容器以构建容器为父进程、清理简单。但实践中存在无法接受的严重问题:

  1. 需要特权容器——这是无法解决的、一票否决的安全问题;同时它也抵消了 cgroups 隔离的理论收益,因为进程可能逃逸出容器;
  2. 使用 devicemapper 时极易在宿主机上泄漏 loopback 设备与存储;
  3. 构建容器之间难以共享镜像/层存储,每个 Docker-in-Docker 实例都必须保存构建期间下载镜像的完整独立副本;节点上的缓存代理至多能减少从远端仓库拉取镜像的次数,无法消除每容器独立副本的需求。

因此,Docker-in-Docker 不被视为安全多租户生产环境下的可行构建策略。

S2I(Source-to-Image)构建策略

S2I 是一个用于构建可复现容器镜像的工具:通过把用户源码注入容器镜像并组装出新的镜像,产生可直接docker run的即用镜像。S2I 支持增量构建,可复用之前下载的依赖、之前构建的产物等。

从本仓库的 e2e 测试可以看到 S2I 策略的完整落地验证:

  • test/extended/builds/s2i_incremental.go 验证了"增量 s2i 构建":连续两次构建同一 BuildConfig,第二次构建复用第一次构建产物,随后用生成镜像实例化 Pod 与服务,并curl验证容器内保存了上次构建的 artifacts(响应包含artifacts exist);
  • test/extended/builds/s2i_env.go 验证源码中的环境文件(.s2i/environment)能正确注入应用(响应包含success);
  • test/extended/testdata/builds/test-build.yaml 中的sample-build展示了 Source 策略的标准写法:source.type: Git指向https://github.com/openshift/ruby-hello-world.git,strategy.type: Source,并在sourceStrategy.env中注入FOO、BAR、BUILD_LOGLEVEL等环境变量,from指向image-registry.openshift-image-registry.svc:5000/openshift/ruby:3.3-ubi8作为 s2i 基础镜像。
结合 CLI 的 S2I 实操路径(来自 test/extended/builds/start.go)
  • oc new-app https://github.com/openshift/ruby-hello-world#config:从带分支引用的仓库创建应用并触发 s2i 构建,测试验证会正确检出config分支而不是同名目录;
  • oc start-build sample-build --wait:启动构建并等待完成;配合--commit=fffffff等错误引用时,--wait会检测到status is "Failed";
  • oc start-build sample-build -e FOO=bar -e VAR=test:覆盖环境变量,构建日志中会同时出现新增变量与 BuildConfig 中继承的变量(如BAR=test);
  • oc start-build sample-verbose-build --build-loglevel=1:可覆盖 BuildConfig 中的BUILD_LOGLEVEL。

自定义(Custom)构建策略

自定义构建策略与 Docker 构建策略非常相似,区别在于用户可以自定义用于执行构建的 builder 镜像。Docker 构建默认使用openshift/origin-docker-builder镜像;使用自定义 builder 镜像则可以完全定制构建过程。

原文档给出的自定义构建策略 JSON 示例:

"strategy": { "type": "Custom", "customStrategy": { "image": "my-custom-builder-image", "exposeDockerSocket": true, "env": [ { "name": "EXPOSE_PORT", "value": "8080" } ] } }
  • exposeDockerSocket:把宿主机 Docker socket 挂载进 builder 容器,允许在其中执行docker build与docker push。原文档特别提示:该能力未来可能被管理员限制。
  • env:向 builder 容器环境传入额外环境变量。
默认注入 builder 容器的环境变量

原文档明确列出以下默认传递的环境变量:

变量含义
$BUILD当前 Build 的 JSON 表示
$OUTPUT_IMAGEBuild 中配置的输出容器镜像名
$OUTPUT_REGISTRYBuild 中配置的输出容器镜像仓库
$SOURCE_URI源代码仓库的 URL
$SOURCE_REF源代码仓库的分支、tag 或 ref
$DOCKER_SOCKETDocker socket 的完整路径
仓库中的 Custom 策略实战样例

本仓库 e2e 测试提供了比文档示例更完整的 Custom 策略 YAML 配置:test/extended/testdata/builds/test-custom-build.yaml:

kind: BuildConfig apiVersion: build.openshift.io/v1 metadata: name: sample-custom-build spec: strategy: type: Custom customStrategy: env: - name: "BUILD_LOGLEVEL" value: "2" forcePull: true from: kind: ImageStreamTag name: custom-builder-image:latest output: to: kind: ImageStreamTag name: sample-custom:latest

可以看到 Custom 策略除env外还支持forcePull(强制每次拉取最新 builder 镜像)与from(通过 ImageStreamTag 指定 builder 镜像来源),构建产物通过output.to写入名为sample-custom:latest的 ImageStreamTag。

配套的 builder 镜像定义位于 test/extended/testdata/builds/custom-build/Dockerfile,它基于registry.redhat.io/rhel8/buildah:latest,将待构建的 Dockerfile 样例(Dockerfile.sample,内容为FROM image-registry.openshift-image-registry.svc:5000/openshift/tools:latest+RUN touch /tmp/built)放入/tmp/input/,并将真正的构建逻辑脚本build.sh设为 ENTRYPOINT——即"builder 镜像运行时执行的就是自定义构建逻辑"。

对应的 e2e 测试见 test/extended/builds/custom_build.go,完整演练了"自定义构建"链路:

# 1. 用二进制方式先构建出自定义 builder 镜像 oc new-build --binary --strategy=docker --name=custom-builder-image oc start-build custom-builder-image --from-dir=test/extended/testdata/builds/custom-build # 2. 应用 Custom 策略的 BuildConfig 并启动构建 oc create -f test/extended/testdata/builds/test-custom-build.yaml oc start-build sample-custom-build # 3. 等待名为 sample-custom-build-1 的构建成功完成

构建输入与 CLI 实操:从仓库测试看完整命令链

原文档把"构建输入"列为构建任务的公共特征之一。结合 test/extended/builds/start.go 与 test/extended/testdata/builds/test-build.yaml,可梳理出 OpenShift 支持的多种输入方式与对应命令:

二进制输入(Binary)构建

对应 BuildConfig 中source.type: Binary的配置,例如sample-build-binary:

source: type: Binary binary: {} strategy: type: Docker dockerStrategy: from: kind: DockerImage name: image-registry.openshift-image-registry.svc:5000/openshift/ruby:3.3-ubi8

oc start-build支持以下二进制输入形态:

命令参数说明测试验证点
--from-file=<file>以单个文件作为构建输入(也支持 HTTPS URL)输出Uploading file ... as binary input for the build
--from-dir=<dir>以目录(Docker context)作为输入输出Uploading directory ... as binary input for the build
--from-repo=<repo>以本地 Git 仓库作为输入,可配合--commit=<sha>指定提交输出at commit "HEAD"
--from-archive=<url>以远程归档(zip)作为输入,配合contextDir处理归档内的顶层目录输出Uploading archive from ... as binary input for the build

此外,构建日志中会出现Build complete表示成功;若 BuildConfig 无有效输入,oc start-build会报错has no valid source inputs。

Git 源码输入与 Dockerfile 输入

  • Git 源码输入:source.type: Git+source.git.uri,如sample-build使用https://github.com/openshift/ruby-hello-world.git;
  • Dockerfile 输入:source.type: Dockerfile+source.dockerfile内联内容,测试 test/extended/builds/dockerfile.go 用oc new-build -D -从 stdin 传入 Dockerfile 创建构建,并验证生成的 BuildConfig 中spec.source.git为空、Dockerfile 内容被完整保存,最终镜像的Config.User为 Dockerfile 中声明的USER 1001;还覆盖了FROM scratch、输出 tag 推断(ruby:latest)、以及非法 Dockerfile 内容导致构建失败并在日志中报no such file or directory等场景。

构建参数(Build Args)

对于 Docker 策略,可在dockerStrategy.buildArgs中预设参数,也可用 CLI 覆盖:

dockerStrategy: buildArgs: - name: foofoo value: default

测试验证(test/extended/builds/start.go):

  • 预设的 build arg 会传入构建,日志输出其值(default);
  • oc start-build ... --build-arg=foofoo=bar可覆盖,日志输出新值(bar);
  • 传入 Dockerfile 未声明的 arg(如--build-arg=bar=foo)构建仍成功,但日志出现警告:one or more build args were not consumed: [bar]。

触发与取消构建

sample-build的触发配置示例:

triggers: - type: ImageChange imageChange: {} - type: Generic generic: secret: "mysecret" secretReference: name: "webhooksecret"

对应 Generic Webhook 的调用端点是POST /apis/build.openshift.io/v1/namespaces/<ns>/buildconfigs/sample-build/webhooks/<secret>/generic,测试验证了:用内联 secret(mysecret)与引用的 Secret(secretvalue1)都能成功触发构建,而错误 secret(invalid)则不会产生任何构建。

取消构建使用oc cancel-build <buildName>,配合oc start-build --wait时,--wait会检测到status is "Cancelled";对于因 nodeSelector 无法匹配而无法调度的构建,系统会自动取消并在事件中记录取消原因(BuildCancelledEventReason)。

构建的运行模型:Pod、调度与资源限制

从构建 API 的设计目标与当前实现看,每次构建都以 Pod 形式承载。以 test/extended/builds/start.go 中的verifyBuildPod为例,可以确认构建 Pod 的实际形态:

  • 构建 Pod 名形如<buildName>-build;
  • Pod 会显式选择 linux 节点(kubernetes.io/os=linuxnodeSelector);
  • 源码克隆通过名为git-clone的 init container 完成;出于 CVE-2024-45496(.gitconfig 可能被利用执行任意命令)的考虑,该 init container 必须是非特权、仅保留CHOWN/DAC_OVERRIDE能力、并 drop ALL 其余能力、使用 runtime-default seccomp profile 的加固配置;
  • 构建容器与 Docker daemon 的交互、日志捕获、产物发布均由 OpenShift 构建控制器协调。

资源限制方面,原文档强调构建应当能够限定 CPU、内存与 Pod 执行时间;在仓库的 BuildConfig 样例中可以通过resources与nodeSelector字段(如sample-build-binary-invalidnodeselector中的nodelabelkey: nodelabelvalue)进行配置,构建系统会根据这些约束调度构建 Pod。

构建 API 的定位:面向第三方构建系统与 CI/CD 编排

回到原文档的核心理念:为构建提供 API,使 OpenShift 成为任意第三方容器镜像构建系统的可行后端。这意味着:

  • 资源约束与调度能力由 OpenShift 统一提供,第三方系统无需自行解决资源分配、调度与垃圾回收(对应云 IDE 场景);
  • 组织现有的 CI 流程(Jenkins 等)可以通过构建 API 触发、监控、晋升构建,将 OpenShift 构建无缝嵌入既有 DevOps SOP(对应企业 DevOps 场景);
  • 构建输出进入 ImageStream/ImageStreamTag(如sample-custom:latest),为后续"镜像驱动部署"提供输入。

本仓库 test/extended/builds/ 下的数十个 e2e 测试(涵盖构建触发、Webhook、二进制输入、增量构建、环境变量、配额 s2i_quota.go、机密注入 secrets.go、构建清理 build_pruning.go 等)从实践层面印证了构建 API 的完整能力面,可作为深入理解构建系统行为与边界条件的参考起点。

  • 测试
  • 云原生
  • 质量保障

【免费下载链接】origin

Conformance test suite for OpenShift

项目地址:https://gitcode.com/gh_mirrors/or/origin
点击查看免费下载

相关推荐

上一篇:Imba样式修饰符:为什么你需要掌握这3类核心功能?
下一篇:PowerInfer终极指南:嵌入式设备上实现快速LLM推理的完整解决方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 8:42:39

Atlas 300V 24G上跑通YOLO:昇腾推理部署全流程解析

搞AI算法工程的朋友&#xff0c;这两年应该没少被“国产算力”“昇腾生态”“Atlas”这几个词刷屏。尤其是做边缘视频分析、工业质检、智慧园区这类项目的团队&#xff0c;经常会在选型阶段卡在同一个问题上&#xff1a;手里的YOLO模型&#xff0c;到底怎么跑到华为Atlas上&…

作者头像 李华
网站建设 2026/9/26 10:06:54

大模型广告营销实践:货拉拉文案素材生成与智能投放全解析

大模型这阵风刮到营销广告领域&#xff0c;其实是早晚的事。货拉拉的广告业务和常规电商广告不太一样&#xff0c;它同时连接货运司机和货主两端&#xff0c;营销场景既要覆盖C端用户拉新&#xff0c;又要服务B端货主促活&#xff0c;还得配合一次次大促节点做集中爆发。这种多…

作者头像 李华
网站建设 2026/9/26 9:04:44

护网行动实战指南:红蓝紫队角色与应急处置全流程

1. 护网行动到底是什么&#xff1a;一场高强度的网络安全实战演练护网行动&#xff0c;圈内人习惯直接叫“护网”&#xff0c;本质是一场由国家或大型机构组织的、针对真实业务系统的网络安全实战攻防演练。简单说&#xff0c;就是组织方请来专业的攻击队伍&#xff08;红队&am…

作者头像 李华
网站建设 2026/9/26 9:50:36

Atlas 300V 24G部署YOLO推理实战:从环境配置到性能调优

不用绕弯子&#xff0c;直接说结论&#xff1a;Atlas 300V 24G这块卡&#xff0c;在AI推理圈子里最近讨论度确实高。很多人第一眼看到“300V”“24G”这种参数&#xff0c;第一反应是“这不就是个运算加速卡吗”&#xff0c;然后拿着它去跑YOLO训练&#xff0c;结果环境装到一半…

作者头像 李华
网站建设 2026/9/25 8:36:51

treg 思路解析:CLI AI 工具链的密钥管理与多模型路由实战

1. 从"treg"这个标题说起&#xff1a;一个被低估的CLI工具链入口第一次看到"treg"这个标题&#xff0c;很多人会一头雾水——它既不像一个完整的产品名&#xff0c;也不像某个技术栈的缩写。但如果你最近在折腾OpenRouter、Codex CLI、Claude CLI这类命令行…

作者头像 李华