Build是什么
Build是Openshift容器平台上将输入转化为输出的过程,通常情况下是将代码转化为镜像的过程。
Build的配置叫BuildConfig,它将定义构建策略及构建参数。设置的构建策略和参数确定了Build的构建过程。
Openshift构建有四种主要策略
- Docker 构建
- 源代码构建(S2i)
- 自定义构建
- Pipeline构建可以实现复杂的工作流
Docker构建、S2i构建、Pipeline构建是默认支持的。
不同的构建有六种源
- Git
- Dockerfile
- Binary
- Image
- Input secrets
- External artifacts
其中Binary和Git不能同时使用。 Dockerfile和Image可以单独使用,也可以与Git或Binary一起使用。 如果使用Binary作为BuildConfig.spec.source.type,只能通过命令行工具oc start-build
来构建。
BuildConfig实例
kind: "BuildConfig"
apiVersion: "v1"
metadata:
name: "ruby-sample-build"
spec:
runPolicy: "Serial"
triggers:
-
type: "GitHub"
github:
secret: "secret101"
- type: "Generic"
generic:
secret: "secret101"
-
type: "ImageChange"
source:
git:
uri: "https://github.com/openshift/ruby-hello-world"
strategy:
sourceStrategy:
from:
kind: "ImageStreamTag"
name: "ruby-20-centos7:latest"
output:
to:
kind: "ImageStreamTag"
name: "origin-ruby-sample:latest"
postCommit:
script: "bundle exec rake test"
属性 | 说明 |
---|---|
metadata.name | BuildConfig名 |
spec.runPolicy | 运行策略,默认是顺序运行 |
spec.triggers | 触发器,这个可以触发新的构建 |
spec.source | 定义了构建的源。 源类型确定输入的主要来源,可以是Git,指向代码存储库位置,Dockerfile,从内联Dockerfile构建,或Binary,以接受二进制有效负载。 可以同时拥有多个源,有关详细信息,请参阅每种源类型的文档。 |
spec.strategy | 策略部分描述了用于执行构建的构建策略。 您可以在此处指定Source,Docker或Custom策略。 |
spec.output | 成功构建容器映像后,它将被推送到输出部分中描述的存储库中。 |
spec.postCommit | postCommit部分定义了一个可选的构建钩子。 |
postCommit支持多种不同方式的配置
script: 默认会使用/bin/sh -ic来运行内容
command: 如果镜像没有/bin/sh,则使用command
args: 给Entrypoint传递参数,镜像必须支持传入参数
例子:
postCommit:
script: "bundle exec rake test --verbose"
postCommit:
command: ["/bin/bash", "-c", "bundle exec rake test --verbose"]
postCommit:
args: ["bundle", "exec", "rake", "test", "--verbose"]
postCommit:
script: "bundle exec rake test $1"
args: ["--verbose"]
postCommit:
command: ["bundle", "exec", "rake", "test"]
args: ["--verbose"]
通过命令行设置
$ oc set build-hook bc/mybc \
--post-commit \
--command \
-- bundle exec rake test --verbose
$ oc set build-hook bc/mybc --post-commit --script="bundle exec rake test --verbose"
基础的构建操作
启动一个Build
$ oc start-build
$ #使用--from-build启动
$ oc start-build --from-build=
$ #添加--follow参数,在终端输出日志
$ oc start-build --follow
$ #给构建传入环境变量
$ oc start-build --env==
您可以通过直接推送源代码来启动构建,而不是依赖于Git源代码拉取或Dockerfile构建构建,这可能是Git或SVN工作目录的内容,也就是您想要的一组预构建二进制工件。 部署或单个文件。 这可以通过为start-build命令指定以下选项之一来完成:
参数 | 说明 |
---|---|
--from-dir= |
指定将归档并用作构建的二进制输入的目录。 |
--from-file= |
指定将成为构建源中唯一文件的单个文件。 该文件放在空目录的根目录中,其文件名与提供的原始文件相同。 |
--from-repo= |
指定本地存储库的路径,以用作构建的二进制输入。 添加--commit选项以控制用于构建的分支,标记或提交。 |
将任何这些选项直接传递给构建时,内容将流式传输到构建并覆盖当前构建源设置。
$ # 将本地Git仓库的v2分支/tag的内容作为存档并启动构建
$ oc start-build hello-world --from-repo=../hello-world --commit=v2
取消一个构建
$ oc cancel-build
$ #取消多个构建
$ oc cancel-build
$ #取消通过buildconfig构建的所有构建
$ oc cancel-build bc/
$ #取消指定状态的构建
$ oc cancel-build bc/ --state=
删除构建
$ #删除BuildConfig,同时删除之前的Build
$ oc delete bc
$ #删除BuildConfig,但保留之前的Build
$ oc delete --cascade=false bc
查看Build的详情
$ oc describe build
查看Build的日志
$ oc logs -f build/
$ #查看最新的一个Build的日志
$ oc logs -f bc/
$ #查看指定版本的Build日志
$ oc logs --version= bc/
设置Build的日志级别
要启用更详细的输出,请在BuildConfig中将BUILD_LOGLEVEL环境变量作为sourceStrategy或dockerStrategy的一部分传递:
sourceStrategy:
...
env:
- name: "BUILD_LOGLEVEL"
value: "2"
Build的输入
构建输入需要提供输入源
- 内联Dockerfile定义
- 从现有图像中提取的内容
- Git仓库
- 本地输入
- 输入Secret和ConfigMaps
- 额外的文件
不同的输入可以组合成一个构建。 由于内联Dockerfile优先,它可以覆盖另一个输入提供的名为Dockerfile的任何其他文件。 二进制(本地)输入和Git仓库是不能同时使用。
当您不希望构建期间使用的某些资源或凭据在构建生成的最终应用程序映像中可用时,或者想要使用在Secret资源中定义的值时,输入机密很有用。 外部工件可用于提取其他文件,这些文件不可用作其他构建输入类型之一。
构造工作目录,并将所有输入内容放在工作目录中。 例如,输入Git存储库被克隆到工作目录中,并且使用目标路径将从输入镜像指定的文件复制到工作目录中。
构建过程将目录更改为contextDir(如果已定义)。
内联Dockerfile(如果有)将写入当前目录。
来自当前目录的内容将提供给构建过程,以供Dockerfile。 这意味着构建将忽略驻留在contextDir之外的任何输入内容。
以下例子中设置了多个输入源
source:
git:
uri: https://github.com/openshift/ruby-hello-world.git
images:
- from:
kind: ImageStreamTag
name: myinputimage:latest
namespace: mynamespace
paths:
- destinationDir: app/dir/injected/dir
sourcePath: /usr/lib/somefile.jar
contextDir: "app/dir"
dockerfile: "FROM centos:7\nRUN yum install -y httpd"
- git仓库将会被clone到构建的工作目录中。
- myinputimage:latest镜像中的/usr/lib/somefile.jar文件,将会被拷贝到工作目录中的app/dir/injected/dir文件夹下
- 构建的工作目录将变为原工作目录下的/app/dir
- 具有此内容的Dockerfile将在
/ app / dir中创建,覆盖具有该名称的任何现有文件。
Dockerfile源
当提供dockerfile值时,该字段的内容将作为名为Dockerfile的文件写入磁盘。 这是在处理完其他输入源之后完成的,因此如果输入源存储库在根目录中包含Dockerfile,则它将被此内容覆盖。
该字段的典型用途是为Docker策略提供Dockerfile
该字段是定义在BuildConfig中的spec下
source:
dockerfile: "FROM centos:7\nRUN yum install -y httpd"
镜像源
可以通过图像向构建过程提供其他文件。 输入图像的引用方式与定义From和To图像目标的方式相同。 这意味着可以引用容器图像和图像流标记。 与映像一起使用时,必须提供一个或多个路径对,以指示要复制映像的文件或目录的路径以及将它们放置在构建上下文中的目标。
源路径可以是指定图像中的任何绝对路径。 目标必须是相对目录路径。 在构建时,将加载映像,并将指示的文件和目录复制到构建过程的上下文目录中。 这是克隆源存储库内容(如果有)的目录。 如果源路径以/结尾。 然后将复制目录的内容,但不会在目标上创建目录本身。
该字段是定义在BuildConfig中的spec下
source:
git:
uri: https://github.com/openshift/ruby-hello-world.git
images:
- from:
kind: ImageStreamTag
name: myinputimage:latest
namespace: mynamespace
paths:
- destinationDir: injected/dir
sourcePath: /usr/lib/somefile.jar
- from:
kind: ImageStreamTag
name: myotherinputimage:latest
namespace: myothernamespace
pullSecret: mysecret
paths:
- destinationDir: injected/dir
sourcePath: /usr/lib/somefile.jar
Git源
设置了Git源后,将从指定的Git源clone下代码
如果设置了dockerfile源,那么它将会覆盖掉代码中目录下的Dockerfile文件
git源字段也是BuildConfig中的spec下
source:
git:
uri: "https://github.com/openshift/ruby-hello-world"
ref: "master"
contextDir: "app/dir"
dockerfile: "FROM openshift/ruby-22-centos7\nUSER example"
Git源设置中还可以指定代码
source:
git:
uri: "https://github.com/openshift/ruby-hello-world"
httpProxy: http://proxy.example.com
httpsProxy: https://proxy.example.com
noProxy: somedomain.com, otherdomain.com
Git源设置下载的用户及密码
Builder pods需要访问定义为构建源的任何Git存储库。 源克隆密钥用于为构建器窗格提供通常无法访问的访问权限,例如具有自签名或不可信SSL证书的私有存储库或存储库。
- .gitconfig配置文件
- Basic Authentication
- SSH Key Authentication
- Trusted Certificate Authorities
使用builder服务帐户运行构建,该帐户必须能够访问所使用的任何源克隆密钥。 使用以下命令授予访问权限:
$ oc secrets link builder mysecret
说明:默认情况下是不需要主动绑定builder与secret的,除非在masterconfig中的serviceAccountConfig.limitSecretReferences设置为true。
自动将源克隆密码添加到构建配置中
apiVersion: "v1"
kind: "BuildConfig"
metadata:
name: "sample-build"
spec:
output:
to:
kind: "ImageStreamTag"
name: "sample-image:latest"
source:
git:
uri: "https://github.com/user/app.git"
sourceSecret:
name: "basicsecret"
strategy:
sourceStrategy:
from:
kind: "ImageStreamTag"
name: "python-33-centos7:latest"
secret构建
$ oc create secret generic \
--from-literal=username= \
--from-literal=password= \
--type=kubernetes.io/basic-auth
$ oc create secret generic \
--from-literal=password= \
--type=kubernetes.io/basic-auth
$ oc create secret generic \
--from-file=ssh-privatekey= \
--type=kubernetes.io/ssh-auth
本地源
从本地文件系统到构建器的流内容称为二进制类型构建。 对于此类构建,BuildConfig.spec.source.type的对应值为Binary。
此源类型的独特之处在于它仅基于您对oc start-build的使用而被利用。
在star-build构建时需要指定以下参数之一
参数 | 说明 |
---|---|
--from-dir= |
指定将归档并用作构建的二进制输入的目录。 |
--from-file= |
指定将成为构建源中唯一文件的单个文件。 该文件放在空目录的根目录中,其文件名与提供的原始文件相同。 |
--from-repo= |
指定本地存储库的路径,以用作构建的二进制输入。 添加--commit选项以控制用于构建的分支,标记或提交。 |
--from-archive | 指定的压缩包文件将发送到构建器,在构建器上下文目录中将其解压缩。 此选项与--from-dir的行为相同; 只要这些选项的参数是目录,就会首先在主机上创建压缩文件。 |
如果您的BuildConfig已经定义为binary类型,那它将会被客户端发送的内容给替代。
如果您的BuildConfig定义了Git源类型,则会动态禁用Git源类型,因为Binary和Git是互斥的,并且提供给构建器的二进制流中的数据优先。
您可以将带有HTTP或HTTPS架构的URL传递给--from-file和--from-archive,而不是文件名。 将-from-file与URL一起使用时,构建器映像中文件的名称由Web服务器发送的Content-Disposition标头确定,如果标头不存在,则由URL路径的最后一个组件确定。 不支持任何形式的身份验证,也无法使用自定义TLS证书或禁用证书验证。
使用oc new-build --binary = true
时,该命令可确保强制执行与二进制构建关联的限制。 生成的BuildConfig将具有Binary的源类型,这意味着为此BuildConfig运行构建的唯一有效方法是使用oc start-build和其中一个--from选项来提供必需的二进制数据。
dockerfile和contextDir源选项对二进制构建具有特殊含义。
dockerfile可以与任何二进制构建源一起使用。 如果使用dockerfile且二进制流是存档,则其内容将作为存档中任何Dockerfile的替换Dockerfile。 如果dockerfile与--from-file参数一起使用,并且file参数名为dockerfile,则dockerfile中的值将替换二进制流中的值。
在二进制流封装提取的存档内容的情况下,contextDir字段的值被解释为存档中的子目录,并且如果有效,则构建器在执行构建之前更改为该子目录。
本地源构建的一个实例:
-
创建本地文件夹,存放代码
$ mkdir myapp $ cd myapp
-
在目录下创建一个Dockerfile文件
FROM centos:centos7 EXPOSE 8080 COPY index.html /var/run/web/index.html CMD cd /var/run/web && python -m SimpleHTTPServer 8080
-
在目录下添加一个index.html文件
My local app Hello World
This is my local application
-
创建一个buildConfig
$ oc new-build --strategy docker --binary --docker-image centos:centos7 --name myapp
-
开始一个构建,使用当前文件夹
$ oc start-build myapp --from-dir . --follow
-
根据生成的镜像部署应用
$ oc new-app myapp $ oc expose svc/myapp
-
查看当前应用
$ oc get route myapp
https://docs.openshift.com/dedicated/dev_guide/dev_tutorials/binary_builds.html#binary-builds-local-code-changes
导入Secret与ConfigMap
在某些情况下,构建操作需要凭据或其他配置数据来访问相关资源,但不希望将该信息放置在源代码管理中。 您可以为此目的定义输入密钥并输入ConfigMaps。
例如:
$ #创建configmap
$ oc create configmap settings-mvn --from-file=settings.xml=
$ # 创建Secret
$ oc create secret generic secret-mvn --from-file=id_rsa=
将ConfigMap与Secret加入到构建目录
source:
git:
uri: https://github.com/wildfly/quickstart.git
contextDir: helloworld
configMaps:
- configMap:
name: settings-mvn
secrets:
- secret:
name: secret-mvn
要在新的构建中添加
$ oc new-build \
openshift/wildfly-101-centos7~https://github.com/wildfly/quickstart.git \
--context-dir helloworld --build-secret “secret-mvn” \
--build-config-map "settings-mvn"
指定文件保存的工作目录下的子目录
source:
git:
uri: https://github.com/wildfly/quickstart.git
contextDir: helloworld
configMaps:
- configMap:
name: settings-mvn
destinationDir: ".m2"
secrets:
- secret:
name: secret-mvn
destinationDir: ".ssh"
在新建构建时指定
$ oc new-build \
openshift/wildfly-101-centos7~https://github.com/wildfly/quickstart.git \
--context-dir helloworld --build-secret “secret-mvn:.ssh” \
--build-config-map "settings-mvn:.m2"
setting.xml将会被放在./.m2目录下
id_rsa文件将会放在./.ssh目录下
Build输出
Build构建好的镜像输出可以是ImageStreamTag,也可以是外部的镜像仓库
spec:
output:
to:
kind: "ImageStreamTag"
name: "sample-image:latest"
或者
spec:
output:
to:
kind: "DockerImage"
name: "my-registry.mycompany.com:5000/myimages/myimage:tag"
Docker和Source策略,在构建好的镜像中会写入以下环境变量
名称 | 说明 |
---|---|
OPENSHIFT_BUILD_NAME | 构建名 |
OPENSHIFT_BUILD_NAMESPACE | 构建的namespace |
OPENSHIFT_BUILD_SOURCE | 构建的代码地址 |
OPENSHIFT_BUILD_REFERENCE | 构建的代码所在的分支 |
OPENSHIFT_BUILD_COMMIT | 构建的代码的Commit |
输出的镜像ImageStreamTag有以下label
名称 | 说明 |
---|---|
io.openshift.build.commit.author | 代码提交的作者 |
io.openshift.build.commit.date | 代码提交的时间 |
io.openshift.build.commit.id | 代码提交的Commit ID |
io.openshift.build.commit.message | 代码提交的Message |
io.openshift.build.commit.ref | 代码构建所在的分支 |
io.openshift.build.source-location | 构建的地址 |
也可以通过设置imageLabels给镜像添加新的lable
spec:
output:
to:
kind: "ImageStreamTag"
name: "my-image:latest"
imageLabels:
- name: "vendor"
value: "MyCompany"
- name: "authoritative-source-url"
value: "registry.mycompany.com"
镜像输出到外部的镜像仓库,需要添加外部镜像仓库的权限
您可以使用.docker / config.json文件为私有容器注册表提供有效凭据。 这允许您将输出图像推送到私有容器映像注册表,或从需要身份验证的私有容器映像注册表中提取构建器映像。
默认情况下,.docker/config.json文件位于主目录中,格式如下:
auths:
https://index.docker.io/v1/:
auth: "YWRfbGzhcGU6R2labnRib21ifTE="
email: "[email protected]"
在Openshift平台上,可以将它保存在Secret中,供build时调用
-
根据本地的.docker/config.json文件创建Secret
$ oc create secret generic dockerhub \ --from-file=.dockerconfigjson=
\ --type=kubernetes.io/dockerconfigjson -
将该secret授权给builder,一般这一步不需要,默认是已经授过权的
$ oc secrets link builder dockerhub
-
将pushSecret字段添加到BuildConfig的输出部分,并将其设置为您创建的秘密的名称,在上面的示例中为dockerhub:
spec: output: to: kind: "DockerImage" name: "private.registry.com/org/private-image:latest" pushSecret: name: "dockerhub"
或者使用oc命令
$ oc set build-secret --push bc/sample-build dockerhub
-
通过指定pullSecret字段从私有容器映像注册表中提取构建器容器映像,该字段是构建策略定义的一部分:
strategy: sourceStrategy: from: kind: "DockerImage" name: "docker.io/user/private_repository" pullSecret: name: "dockerhub"
或者使用oc命令
$ oc set build-secret --pull bc/sample-build dockerhub
Build策略
s2i策略
强制更新镜像
默认情况下,通过ImageStreamTag构建时,如果构建容器所在的主机上已存在镜像,就会直接使用该镜像,除非添加forcePull:true
属性
strategy:
sourceStrategy:
from:
kind: "ImageStreamTag"
name: "builder-image:latest"
forcePull: true
增量构建
S2I可以执行增量构建,这意味着它可以重用先前构建的图像中的工件。 要创建增量构建,请创建一个BuildConfig,并对策略定义进行以下修改
strategy:
sourceStrategy:
from:
kind: "ImageStreamTag"
name: "incremental-image:latest"
incremental: true
替换默认的构建脚本
strategy:
sourceStrategy:
from:
kind: "ImageStreamTag"
name: "builder-image:latest"
scripts: "http://somehost.com/scripts_directory"
Docker策略
Dockerfile的FROM指令将替换为BuildConfig的from:
strategy:
dockerStrategy:
from:
kind: "ImageStreamTag"
name: "debian:latest"
默认情况下,Docker构建使用位于BuildConfig.spec.source.contextDir字段中指定的上下文根的Dockerfile(名为Dockerfile)。
dockerfilePath字段允许构建使用不同的路径来定位Dockerfile,相对于BuildConfig.spec.source.contextDir字段。 它可以是除默认Dockerfile之外的其他文件名(例如,MyDockerfile),或者是子目录中Dockerfile的路径(例如,dockerfiles / app1 / Dockerfile)
strategy:
dockerStrategy:
dockerfilePath: dockerfiles/app1/Dockerfile
Docker构建通常重用在执行构建的主机上找到的缓存层。 将noCache选项设置为true会强制构建忽略缓存层并重新运行Dockerfile的所有步骤:
strategy:
dockerStrategy:
noCache: true
默认情况下,通过ImageStreamTag构建时,如果构建容器所在的主机上已存在镜像,就会直接使用该镜像,除非添加forcePull:true
属性
strategy:
dockerStrategy:
from:
kind: "ImageStreamTag"
name: "debian:latest"
forcePull: true
构建添加环境变量
dockerStrategy:
...
env:
- name: "HTTP_PROXY"
value: "http://myproxy.net:5187/"
构建参数
dockerStrategy:
...
buildArgs:
- name: "foo"
value: "bar"
自定义策略
根据镜像构建
strategy:
customStrategy:
from:
kind: "DockerImage"
name: "openshift/sti-image-builder"
为了允许从容器内部运行Docker命令和构建容器映像,必须将构建容器绑定到可访问的套接字。 为此,请将exposeDockerSocket选项设置为true:
strategy:
customStrategy:
exposeDockerSocket: true
强制更新镜像
strategy:
customStrategy:
forcePull: true
构建添加环境变量
customStrategy:
...
env:
- name: "HTTP_PROXY"
value: "http://myproxy.net:5187/"
Pipeline流水线策略
通过两种方式提供jenkinsfile文件
-
在BuildConfig配置文件中写
kind: "BuildConfig" apiVersion: "v1" metadata: name: "sample-pipeline" spec: strategy: jenkinsPipelineStrategy: jenkinsfile: |- node('agent') { stage 'build' openshiftBuild(buildConfig: 'ruby-sample-build', showBuildLogs: 'true') stage 'deploy' openshiftDeploy(deploymentConfig: 'frontend') }
-
在git代码文件中添加jenkinsfile文件
kind: "BuildConfig" apiVersion: "v1" metadata: name: "sample-pipeline" spec: source: git: uri: "https://github.com/openshift/ruby-hello-world" strategy: jenkinsPipelineStrategy: jenkinsfilePath: some/repo/dir/filename
可选的jenkinsfilePath字段指定要使用的文件的名称,相对于源contextDir。 如果省略了contextDir,则默认为存储库的根。 如果省略jenkinsfilePath,则默认为Jenkinsfile。
环境变量
jenkinsPipelineStrategy:
...
env:
- name: "FOO"
value: "BAR"
Build构建的高级用法
设置构建时对资源进行限制(cpu/memory)
apiVersion: "v1"
kind: "BuildConfig"
metadata:
name: "sample-build"
spec:
resources:
limits:
cpu: "100m"
memory: "256Mi"
设置构建的超时时间
spec:
completionDeadlineSeconds: 1800
构建pod与Node绑定,只在指定的Node上执行构建
apiVersion: "v1"
kind: "BuildConfig"
metadata:
name: "sample-build"
spec:
nodeSelector:
key1: value1
key2: value2
Build链
有一些构建,比如说Java应用,在构建的过程中会产生大量的中间文件与缓存,及一些构建的工具包,这些资源在运行时是不需要的,但它们会导致最终的镜像包很大。所以运行时的镜像中只需要存在构建的结果,而不需要构建过程中的文件与工作包。这就需要将构建拆分成两部分,第一部分执行构建,生成最终的制品文件,第二部分将制品文件放在可运行环境中进行运行。
apiVersion: v1
kind: BuildConfig
metadata:
name: artifact-build
spec:
output:
to:
kind: ImageStreamTag
name: artifact-image:latest
source:
git:
uri: https://github.com/openshift/openshift-jee-sample.git
type: Git
strategy:
sourceStrategy:
from:
kind: ImageStreamTag
name: wildfly:10.1
namespace: openshift
type: Source
将上一个构建的输出,作为新的构建的输入
apiVersion: v1
kind: BuildConfig
metadata:
name: image-build
spec:
output:
to:
kind: ImageStreamTag
name: image-build:latest
source:
type: Dockerfile
dockerfile: |-
FROM jee-runtime:latest
COPY ROOT.war /deployments/ROOT.war
images:
- from:
kind: ImageStreamTag
name: artifact-image:latest
paths:
- sourcePath: /wildfly/standalone/deployments/ROOT.war
destinationDir: "."
strategy:
dockerStrategy:
from:
kind: ImageStreamTag
name: jee-runtime:latest
type: Docker
triggers:
- imageChange: {}
type: ImageChange
Build清理
只保留构建成功的2个历史构建,和2个失败的历史构建
apiVersion: "v1"
kind: "BuildConfig"
metadata:
name: "sample-build"
spec:
successfulBuildsHistoryLimit: 2
failedBuildsHistoryLimit: 2
参考文章
二进制文件构建
Pipeline流水线构建
BuildConfig