为了运行构建过程和管理构建,OpenShift利用了两种内部工具:BuildConfig和Build。

BuildConfig

BuildConfig是用来定义构建策略的工具,即定义做什么以及怎么做。
BuildConfig支持以下四种构建策略:

1. Dockerfile - 即直策应用Dockerfile构建出镜像。

openshiftphpOpenShift 4 HOL 4  BuildTriggerWebhook和镜像更新 Webpack

2. S2I - 利用S2I工具从运用源码或运用包构建出镜像。
S2I的根本镜像一样平常也称为Builder Image,OpenShift为目前主流的开拓措辞(例如Java、PHP、GO、NodeJS、Python、Ruby、HTML等)都供应了对应的Builder Image。
S2I会根据要支配运用源码的特点自动找到对应的Builder Image,然后将其和运用源码构建成目标容器镜像。

3. Pipeline - 利用Jenkins或Tekon(Kubernetes原生的CI/CD功能,在OpenShift 4已经是默认CI/CD环境)的Pipeline构建出镜像。

4. Custom - 可以定义特定的Builder Image,而不是用缺省的Builder Image。

在OpenShift中除了可以利用YAML定义BuildConfig外还可以利用"oc new-build"命令创建一个构建的配置。

Build

还记得我们在《OpenShift 4 Hands-on Lab (1) - 支配运用》中的“支配运用代码”一节中,在利用S2I命令后用查看build的日志么?Build是用来记录每次构建运行情形的工具,每运行一次构建,OpenShift都会天生一个Build工具与之对应。
在OpenShift中用以下命令可以对Build过程进行操作:

1. oc start-build:启动一次构建过程。

2. oc cancel-build:暂时停滞一个构建运行。

OpenShift是在一个专门的Pod中运行构建过程的。
当构建过程完成后,该Pod即变成Completed的状态。
实在,当我们查看Build日志的时候,看的便是这个Pod的日志。

Builder Image

运行一次构建过程的输入是BuildConfig和原始的根本镜像(即Builder Image),构建过程的输出是结果镜像。
OpenShift缺省为紧张的措辞开拓的运用供应了Builder Image,同时用户还可根据须要定制自己的Builder Image。

Build Trigger和Build Chain

我们除了可以利用上述命令手动触发运行Build外,Build还支持基于事宜自动触发构建过程。
OpenShift支持以下三种构建触发器(Build Trigger):

1. Webhook:将构建对应的Webhook地址注册到Code Repository上,例如最常用的Github。
当Github上的代码发生变革后,Github可以利用Webhook从远程触发启动一次构建过程。

2. Builder Image变革:当一个Builder Image发生变革后,OpenShift可以触发构建过程,以便更新所有依赖这个Builder Image的镜像。

3. BuildConfig:当BuildConfig被创建后,OpenShift自动触发一次构建过程,从而完成S2I过程。

在OpenShift中,由Build Trigger实现确当根本镜像变革后自动触发构建依赖它的镜像,于是在这两个镜像之间就形成了Build Chain(构建链)的关系。

触发Build,创建或更新镜像

由于在Pipeline中除了能实现Build外还可实现其它各种CI/CD功能,因此我们放不才面章节单独Pipeline先容,而在本节我们先先容如何配置Webhook和Build Trigger。

基于Webhook的Build Trigger

在开始之前须要确保在Github上有一个账户“MY_GITHUB”。

1. 将https://github.com/liuxiaoyu-git/php-helloworld复制到自己的Github账号中。

2. 在OpenShift中新建一个项目webhook-USER-ID。

$ oc new-project USER-IDwebhook

3. 实行以下命令,创建基于PHP的php-helloworld运用

$ oc new-app php~https://github.com/MY_GITHUB/php-helloworld

4. 查看buildconifg,找到最下面,确认基于该buildconfig中只有一个build,即php-helloworld-1。
然后复制“Webhook GitHub”的URL后面地址,我们把这个地址称为“WEBHOOK_URL”。

$ oc describe bc/php-helloworldName: php-helloworldNamespace: user-1-webhookCreated: 38 seconds agoLabels: app=php-helloworld app.kubernetes.io/component=php-helloworld app.kubernetes.io/instance=php-helloworldAnnotations: openshift.io/generated-by=OpenShiftNewAppLatest Version: 1 Strategy: SourceURL: https://github.com/liuxiaoyu-git/php-helloworldFrom Image: ImageStreamTag openshift/php:7.2Output to: ImageStreamTag php-helloworld:latest Build Run Policy: SerialTriggered by: Config, ImageChangeWebhook GitHub: URL: https://api.cluster-beijing-4af7.beijing-4af7.example.opentlc.com:6443/apis/build.openshift.io/v1/namespaces/user-1-webhook/buildconfigs/php-helloworld/webhooks/<secret>/githubWebhook Generic: URL: https://api.cluster-beijing-4af7.beijing-4af7.example.opentlc.com:6443/apis/build.openshift.io/v1/namespaces/user-1-webhook/buildconfigs/php-helloworld/webhooks/<secret>/generic AllowEnv: falseBuilds History Limit: Successful: 5 Failed: 5 Build Status Duration Creation Timephp-helloworld-1 running running for 38s 2020-02-11 15:36:59 +0000 UTC Events: <none>

5. 实行命令查看buildconfig的配置,找到“triggers”部分中的“github”,然后用“secret”后面的字符串更换“WEBHOOK_URL”字符串中的“\<secret>”区域。

$ oc get bc/php-helloworld -o yaml。


triggers: -- github: secret: bhZIQnufyQZ3246OhM9Q type: GitHub -- generic: secret: -4UndTQhFrASVoqgNNUt type: Generic -- type: ConfigChange -- imageChange: lastTriggeredImageID: image-registry.openshift-image-registry.svc:5000/openshift/php@sha256:a5aaaae5baf98cb674ac2352429e0450591b45d3674e44c516612a9ee67282d5 type: ImageChange

6. 实行命令查看build,确认php-helloworld-1的“STATUS”是已经“Complate”状态。

$ oc get buildNAME TYPE FROM STATUS STARTED DURATIONphp-helloworld-1 Source Git@8cb7578 Complete About an hour ago 1m49s

7. 实行命令查看pod,可以看到除了一个正在运行运用的Pod外,专门卖力Build的Pod(php-helloworld-1-build)已经是Completed状态。

$ oc get podNAME READY STATUS RESTARTS AGEphp-helloworld-1-build 0/1 Completed 0 9hphp-helloworld-1-deploy 0/1 Completed 0 9hphp-helloworld-2-z4r4l 1/1 Running 1 7h53m

8. 天生route,然后访问页面。

$ oc expose svc/php-helloworldroute.route.openshift.io/php-helloworld exposed$ curl http://$(oc get route php-helloworld -o template='{{.spec.host}}')

9. 进入github的php-helloworld的repository,点击“Setting”标签。

10. 在设置中进入Webhooks,然后点击“Add webhook”按钮。
将WEBHOOK_URL复制到Payload URL中,并选择Content type为application/json,然后将SSL verification选为Disable,末了点击Add webhook按钮。
可以看到这个webhook显示为下图“绿色”状态。

11. 在github上修正php-helloworld的index.php页面,然后提交修正。
提交后,github会通过webhook在OpenShift上触发一次新的build运行。

12. 实行以下命令,确认php-helloworld-2的“STATUS”为“Complete”状态。

$ oc get buildNAME TYPE FROM STATUS STARTED DURATIONphp-helloworld-1 Source Git@8cb7578 Complete About an hour ago 1m32sphp-helloworld-2 Source Git@e78c498 Complete About an hour ago 1m18s

13. 再次访问route,确认页面已经更新。

$ curl http://$(oc get route php-helloworld -o template='{{.spec.host}}')

14. 查看名为php-helloworld-2的build,确认“Build trigger cause”是“GitHub WebHook”。

$ oc describe build/php-helloworld-2。

Build trigger cause: GitHub WebHookCommit: e78c498 (change)Author/Committer: liuxiaoyu-git / GitHub
利用Build Trigger自动更新Image

设想你的容器镜像是多层的(如下图),实在每个相邻的下层镜像都是上层镜像的根本镜像(即Builder Image)。
那么当下层的镜像发生更新后,依赖它的上层镜像须要重新构建才能使得全体镜像是最新状态,这种自动化触发构建的过程须要利用OpenShift中Builder Image类型的Build Trigger实现。

1. 新建一个项目,然后实行以下命令,基于一个Docker新建一个Build。
把稳:我们可以从返回结果看到当运行new-build命令后,OpenShift会自动创建BuildConfig,然后在以此运行一次构建过程。
在构建过程中,OpenShift先根据https://github.com/liuxiaoyu-git/welcome/blob/master/sh/Dockerfile识别出这次构建的Buider Image是名为busybox的镜像,通过“Every time "busybox:latest" changes a new build will be triggered”的解释我们可以知道OpenShift会自动在构建的Builder Image和目标镜像之间建立起Build Trigger以实现自动更新。
其余,OpenShift还会创建Buider Image(即busybox)和构建的输出镜像(即ops)对应的ImageStream工具。

$ oc new-project USER-ID-build-trigger$ oc new-build --name=ops https://github.com/liuxiaoyu-git/welcome --context-dir=sh--> Found container image 6d5fcfe (6 weeks old) from docker.io for "docker.io/busybox" An image stream tag will be created as "busybox:latest" that will track the source image A Docker build using source code from https://github.com/liuxiaoyu-git/welcome will be created The resulting image will be pushed to image stream tag "ops:latest" Every time "busybox:latest" changes a new build will be triggered --> Creating resources with label build=ops ... imagestream.image.openshift.io "busybox" created imagestream.image.openshift.io "ops" created buildconfig.build.openshift.io "ops" created--> Success

2. 实行命令查看由Builder Trigger形成的和名为busybox的ImageStream干系的build-chain(构建链)。
下面解释当"busybox:latest"镜像变革后会触发“bc/ops”来更新镜像“ops:latest”。

$ oc adm build-chain busyboxistag/busybox:latest bc/ops istag/ops:latest

3. 实行以下命令基于另一个Docker新建另一个名为foo的Build。

$ oc new-build --name=foo https://github.com/liuxiaoyu-git/welcome --context-dir=foo

4. 查看BuildConfig和Build的情形,当前运行了2个构建,它们分别是根据对应的BuildConfig运行的。

$ oc get bcNAME TYPE FROM LATESTfoo Docker Git 1ops Docker Git 1$ oc get buildNAME TYPE FROM STATUS STARTED DURATIONops-1 Docker Git@359ea3d Complete 2 minutes ago 27sfoo-1 Docker Git@359ea3d Complete About a minute ago 23s

5. 实行命令查看由Builder Trigger形成的和名为busybox的ImageStream干系的build-chain。
和上一次查看比较,在“ops:latest”镜像和“foo:latest”镜像之间又形成了新的build-chain关系。

$ oc adm build-chain busybox -n build-triggeristag/busybox:latest bc/ops istag/ops:latest bc/foo istag/foo:latest

6. 实行以下命令分别查看和名为ops、foo的ImageStream干系的build-chain。

$ oc adm build-chain ops -n build-triggeristag/ops:latest bc/foo istag/foo:latest$ oc adm build-chain foo -n build-triggeristag/foo:latest

7. 查看BuildConfig中的Trigger。
可以看到每个BuildConfig包括4种Trigger,个中目前只有“TYPE”为“image”的有对应的Trigger。

$ oc set triggers bc/foo -n build-triggerNAME TYPE VALUE AUTObuildconfigs/foo config truebuildconfigs/foo image ops:latest truebuildconfigs/foo webhook <secret>buildconfigs/foo github <secret>$ oc set triggers bc/ops -n build-triggerNAME TYPE VALUE AUTObuildconfigs/ops config truebuildconfigs/ops image busybox:latest truebuildconfigs/ops webhook <secret>buildconfigs/ops github <secret>

8. 针对ops,再运行一次新的build。

$ oc start-build bc/opsbuild.build.openshift.io/ops-2 started

9. 实行以下命令会创造有4个构建的记录,这是由于在ops-2完成构建后会根据build-chain自动触发实行foo-2的构建。

$ oc get build -wNAME TYPE FROM STATUS STARTED DURATIONops-1 Docker Git@359ea3d Complete 12 minutes ago 27sfoo-1 Docker Git@359ea3d Complete 11 minutes ago 23sops-2 Docker Git@359ea3d Complete 4 minutes ago 27sfoo-2 Docker Git@359ea3d Complete 3 minutes ago 23s

10. 实行以下命令,删除build-chain在foo和ops之间的Trigger。

$ oc set triggers bc/foo --from-image=ops:latest --removebuildconfig.build.openshift.io/foo triggers updated

11. 再次查看Build Chain,创造ops:latest后不再有foo的BuildConfig过程

oc adm build-chain busyboxistag/busybox:latest bc/ops istag/ops:latest

12. 再次新运行一次ops的build,然后查看确认只有5个build记录。
这是由于我们在上一步删除foo和ops之间的Build Trigger,因此新构建ops-3不会自动触发foo-3的构建了。

$ oc start-build bc/opsbuild.build.openshift.io/ops-3 started$ oc get buildNAME TYPE FROM STATUS STARTED DURATIONops-1 Docker Git@359ea3d Complete 29 minutes ago 27sfoo-1 Docker Git@359ea3d Complete 27 minutes ago 23sops-2 Docker Git@359ea3d Complete 20 minutes ago 27sfoo-2 Docker Git@359ea3d Complete 20 minutes ago 23sops-3 Docker Git@359ea3d Complete 47 seconds ago 27s

13. 实行以下命令,重新规复foo和ops之间的Build Chain。

$ oc set triggers bc/foo --from-image=ops:latest --remove=falsebuildconfig.build.openshift.io/foo triggers updated

14. 再次新运行一次ops的build,然后查看确认有8个build记录。
不但有ops-4和foo-4,还有上面由于Build Chain断掉后短缺的foo-3。

$ oc start-build bc/opsbuild.build.openshift.io/ops-4 started$ oc get buildNAME TYPE FROM STATUS STARTED DURATIONops-1 Docker Git@359ea3d Complete 43 minutes ago 27sfoo-1 Docker Git@359ea3d Complete 42 minutes ago 23sops-2 Docker Git@359ea3d Complete 35 minutes ago 27sfoo-2 Docker Git@359ea3d Complete 34 minutes ago 23sops-3 Docker Git@359ea3d Complete 15 minutes ago 27sfoo-3 Docker Git@359ea3d Complete 9 minutes ago 19sops-4 Docker Git@359ea3d Complete About a minute ago 28sfoo-4 Docker Git@359ea3d Complete 51 seconds ago 24s