3. 应用构建基础

在 OpenShift 中,构建(Build)是把源代码、Dockerfile 或流水线定义转换成可运行镜像的过程。理解三种构建策略的差异,是选择合适构建方式的前提。它们并不是互相替代的关系,而是分别面向不同的输入形态和团队能力。

Source-to-Image(S2I)的核心思想是“镜像即构建环境”。S2I 使用一个包含语言运行时和构建脚本的 builder 镜像,把源代码注入其中,执行 assemble 脚本完成依赖安装与编译,再通过 run 脚本定义容器启动方式。开发者只需提供源码仓库地址,无需编写 Dockerfile。它适合标准化的语言栈,例如 Java、Node.js、Python、PHP,团队希望统一构建规范、减少镜像维护成本时优先选择 S2I。

Docker 构建直接使用仓库中的 Dockerfile,由 OpenShift 调用构建器执行 docker build 等价流程。它适合需要精细控制镜像层、基础镜像、多阶段构建或引入特殊系统依赖的场景。当项目已有成熟 Dockerfile,或需要构建非标准运行时(如自定义 C 库、特定版本编译器)时,Docker 构建更灵活。

Pipeline 构建把构建过程定义为 Jenkins Pipeline 或 OpenShift Pipelines(Tekton)任务。它不局限于“源码到镜像”,而是可以编排测试、代码扫描、镜像推送、部署触发等多个阶段。适合需要多步骤质量门禁、跨仓库协作或复杂发布流程的团队。

三种构建策略的输入与产物路径 S2I 构建 输入:源码仓库 无需 Dockerfile Builder 镜像 assemble 脚本 run 脚本 产物:应用镜像 含运行时与源码 适用场景 标准语言栈 统一构建规范 减少镜像维护 Docker 构建 输入:源码 + Dockerfile 精细控制镜像层 Docker 构建器 多阶段构建 自定义基础镜像 产物:应用镜像 按 Dockerfile 定义 适用场景 已有成熟 Dockerfile 非标准运行时 特殊系统依赖 Pipeline 构建 输入:Pipeline 定义 Jenkins / Tekton 多阶段编排 测试 / 扫描 / 推送 质量门禁 产物:镜像 + 报告 可触发部署 适用场景 多步骤质量门禁 跨仓库协作 复杂发布流程

BuildConfig 关键字段

BuildConfig(BC)是 OpenShift 中定义“如何构建”的核心资源。无论选择哪种策略,都需要通过 BC 描述输入、输出和触发条件。以下字段是实际配置中最常调整的:

  • spec.source:定义构建输入。S2I 和 Docker 构建通常使用 type: Git,指定 git.uri 和 ref;也可以使用 type: Binary 从本地流式上传源码。
  • spec.strategy:决定构建类型。type: Source 表示 S2I,需指定 sourceStrategy.from(builder 镜像);type: Docker 表示 Docker 构建,可指定 dockerStrategy.dockerfilePath;type: JenkinsPipeline 或 type: Custom 用于流水线类构建。
  • spec.output:构建产物推送目标,通常为 ImageStreamTag,例如 myapp:latest。
  • spec.triggers:定义自动触发构建的条件,是持续交付的关键。
  • spec.resources:为构建 Pod 设置 CPU/内存请求与限制,避免构建过程影响集群稳定性。
  • spec.completionDeadlineSeconds:构建超时时间,超时后构建被标记为失败。

下面是一个 S2I 构建的 BuildConfig 示例,使用 Node.js builder 镜像,输出到 web-app:latest:

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: web-app
spec:
  source:
    type: Git
    git:
      uri: https://github.com/example/web-app.git
      ref: main
  strategy:
    type: Source
    sourceStrategy:
      from:
        kind: ImageStreamTag
        name: nodejs:18-ubi8
        namespace: openshift
  output:
    to:
      kind: ImageStreamTag
      name: web-app:latest
  triggers:
    - type: ConfigChange
    - type: ImageChange
      imageChange:
        from:
          kind: ImageStreamTag
          name: nodejs:18-ubi8
    - type: GitHub
      github:
        secret: webhook-secret
  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "1"
      memory: "1Gi"
  completionDeadlineSeconds: 1800

构建触发器:ConfigChange、ImageChange 与 Webhook

触发器让构建从“手动执行”变为“事件驱动”。OpenShift 支持三类主要触发器,理解它们的触发条件和验证方式,才能保证持续交付链路可靠。

ConfigChange:当 BuildConfig 本身被创建或更新时自动触发一次构建。它适合首次创建 BC 后立即验证配置是否正确,也适合在修改构建参数后自动重新构建。注意,它不会因为源码仓库变化而触发。

ImageChange:当指定的 ImageStreamTag 内容发生变化时触发构建。典型场景是 builder 镜像升级:当 nodejs:18-ubi8 标签指向新镜像时,所有引用它的 S2I 构建会自动重新执行,从而把安全补丁或运行时更新带入应用镜像。配置时需要指定 imageChange.from,并确保该 ImageStreamTag 存在。

Webhook:由外部系统通过 HTTP 请求触发,常见类型包括 GitHub、GitLab、Bitbucket 和 Generic。以 GitHub 为例,BC 创建后 OpenShift 会生成一个形如 https://api.example.com:6443/apis/build.openshift.io/v1/namespaces/myproject/buildconfigs/web-app/webhooks/<secret>/github 的 URL。在 GitHub 仓库的 Webhook 设置中填入该 URL,并选择 application/json 内容类型,即可在 push 或 pull request 时自动触发构建。

Webhook 的 secret 可以通过 oc get bc web-app -o jsonpath='{.spec.triggers[?(@.type=="GitHub")].github.secret}' 查看。如果 secret 泄露,应删除并重新生成触发器。

配置与验证流程

实际配置时,建议按以下顺序操作并验证:

  1. 创建或确认 builder ImageStreamTag 可用:oc get is nodejs -n openshift,确认 18-ubi8 标签存在。
  2. 编写 BuildConfig YAML,至少包含 source、strategy、output 和 triggers 四部分。
  3. 应用配置:oc apply -f bc-web-app.yaml。
  4. 观察首次构建:oc get builds 应看到由 ConfigChange 触发的构建记录,状态从 New 变为 Running,最终为 Complete。
  5. 查看构建日志:oc logs -f bc/web-app,确认 assemble 脚本执行成功、依赖安装无报错。
  6. 验证 ImageChange:手动更新 builder 镜像标签指向,例如 oc tag openshift/nodejs:18-ubi8 nodejs:18-ubi8 --source=imagestreamtag,观察是否产生新的构建。
  7. 验证 Webhook:在代码仓库提交一次变更,检查 OpenShift 中是否出现新的构建,并在 GitHub Webhook 的 Recent Deliveries 中确认返回 200。
如果 Webhook 触发后没有构建记录,优先检查三处:secret 是否与 BC 中一致、仓库 Webhook URL 是否包含正确的 namespace 和 BC 名称、OpenShift 路由或 API 地址是否可从外网访问。ImageChange 未触发时,确认 ImageStreamTag 是否真的发生了 digest 变化,仅修改标签名称不会触发。

选择构建策略时,可以用一个简单判断:如果团队希望“只写代码,不写 Dockerfile”,选 S2I;如果已有 Dockerfile 且需要精细控制镜像,选 Docker 构建;如果构建之外还要跑测试、扫描和多环境发布,选 Pipeline 构建。三者也可以组合使用,例如 Pipeline 中调用 S2I 或 Docker 构建作为其中一个阶段,从而兼顾标准化与流程编排能力。