作者 | 阿里云智能事业群技术专家 冬岛

Build 模块提供了一套 Pipeline 机制。Pipeline 的每一个步骤都可以执行一个动作,这个动作可以是把源码编译成二进制、可以是编译镜像也可以是其他的任何事情。Knative Build 执行编译的时候并不需要我们提前准备编译环境,所有这些都是直接在 Pod 中执行的。当有任务需要执行的时候 Build 模块就自动创建 Pod 进行相应的处理。所以这一系列的动作都是 Kubernetes 原生的。
Knative Build 的几个关键特性
- 一个完整的 Build 是由多个 Builder 构成的 Pipeline,每一个 Builder 可以执行一个或多个操作
- 一个 Builder 在执行的时候就是一个 container,而且容器的镜像是声明 Builder 的时候用户自己指定的,所以可以在 container 里面执行任何指令
- 基于 Kaniko 可以在 Builder 中编译镜像以及把镜像推送到镜像仓库等操作
- BuildTemplate 提供了可以重复使用的模板
- Build 过程可以从 git 仓库 clone 代码、向镜像仓库 push 镜像。所有这些动作使用到的鉴权信息都可以通过 serviceAccount 进行关联。直接使用 Kubernetes 原生的能力即可实现
Build 示例
既然是 Hello World 我们就从一个具体的例子谈起。
1apiVersion: build.knative.dev/v1alpha1 2kind: Build 3metadata: 4 name: example-build-name 5spec: 6 serviceAccountName: build-auth-example 7 source: 8 git: 9 url: https://github.com/example/build-example.git 10 revision: master 11 steps: 12 - name: ubuntu-example 13 image: ubuntu 14 args: ["ubuntu-build-example", "SECRETS-example.md"] 15 - image: gcr.io/example-builders/build-example 16 args: ["echo", "hello-example", "build"] 17 - name: dockerfile-pushexample 18 image: gcr.io/example-builders/push-example 19 args: ["push", "${IMAGE}"] 20 volumeMounts: 21 - name: docker-socket-example 22 mountPath: /var/run/docker.sock 23 volumes: 24 - name: example-volume 25 emptyDir: {}
关键字段解释:
- steps
steps 字段和 template 字段互斥。如果未指定 template 就需要设置 steps 字段。此字段用于指定 Pipeline 的步骤。也可以把 steps 定义在 BuildTemplate 中,这样就能通过模板来复用 Pipeline 的能力了。
每一个 step 就是制定一个镜像,在真正执行的时候启动一个容器去做当前 step 的动作。
- Template
如果未设置 steps 就需要指定此字段。此字段通过引用 BuildTemplate 来设置 steps。
- Source
常用的 Source 就是 git repo,通过此字段指定引用的 git repo ,repo 的授权信息通过关联的 ServiceAccount 进行设定。
- ServiceAccount
从 git repe 克隆代码和向镜像仓库 push 镜像都需要鉴权信息。这些鉴权信息可以通过 Kubernetes 的 ServiceAccount 进行关联。
- Volumes
可以通过挂载 volume 的形式挂载 secret 或者 emptyDir 在多个 step 之间共享数据
- Timeout
整个 Build 过程默认超时时间是 10 分钟,也就是如果在 10 分钟内没有还有 step 没有执行完成就会超时退出。但有可以通过 Timeout 字段自定义超时时间。
接下来分别对每一个关键字段进行详细的解读。
steps
下面这是一个设置 steps 的例子,这个例子中有三个 step。每一个 step 都通过一个镜像执行一个容器完成自己的动作。
1spec: 2 steps: 3 - name: ubuntu-example 4 image: ubuntu 5 args: ["ubuntu-build-example", "SECRETS-example.md"] 6 - image: gcr.io/example-builders/build-example 7 args: ["echo", "hello-example", "build"] 8 - name: dockerfile-pushexample 9 image: gcr.io/example-builders/push-example 10 args: ["push", "${IMAGE}"] 11 volumeMounts: 12 - name: docker-socket-example 13 mountPath: /var/run/docker.sock
Template
通过 BuildTemplate 来定义可以重复使用的 steps,主要是对 steps 的复用。BuildTemplate 本身是 Kubernetes 中的一个 CRD。CRD 的好处就是可以在用户之间共享,只要是在同一个 Kubernetes 集群内就可以相互共享,这样效率更高。
BuildTemplate 除了定义 steps 以外还可以指定 parameters,用户在使用 BuildTemplate 的时候可以基于 parameters 对 steps 做个性化的设置。而 BuildTemplate 的编写者也可以通过 parameters 来共享变量。
1spec: 2 parameters: 3 # This has no default, and is therefore required. 4 - name: IMAGE 5 description: Where to publish the resulting image. 6 7 # These may be overridden, but provide sensible defaults. 8 - name: DIRECTORY 9 description: The directory containing the build context. 10 default: /workspace 11 - name: DOCKERFILE_NAME 12 description: The name of the Dockerfile 13 default: Dockerfile 14 15 steps: 16 - name: dockerfile-build 17 image: gcr.io/cloud-builders/docker 18 workingDir: "${DIRECTORY}" 19 args: 20 [ 21 "build", 22 "--no-cache", 23 "--tag", 24 "${IMAGE}", 25 "--file", 26 "${DOCKERFILE_NAME}", 27 ".", 28 ] 29 volumeMounts: 30 - name: docker-socket 31 mountPath: /var/run/docker.sock 32 33 - name: dockerfile-push 34 image: gcr.io/cloud-builders/docker 35 args: ["push", "${IMAGE}"] 36 volumeMounts: 37 - name: docker-socket 38 mountPath: /var/run/docker.sock 39 40 # As an implementation detail, this template mounts the host's daemon socket. 41 volumes: 42 - name: docker-socket 43 hostPath: 44 path: /var/run/docker.sock 45 type: Socket
Source
常见的 source 就是指定一个 git repo 或者 emptyDir 共享数据,下面我们分别对这两种场景进行说明。
- git repo 的例子
下面这个例子的意思是从 https://github.com/knative/build.git clone 代码,并且指定一个 step 是 cat README.md
1spec: 2 source: 3 git: 4 url: https://github.com/knative/build.git 5 revision: master 6 steps: 7 - image: ubuntu 8 args: ["cat", "README.md"]
- volume 共享数据
下面这个例子是两个 step,第一个 step 下载文件并保存到 /var/my-volume 中,第二个 step 是使用 /var/my-volume 的内容。
1spec: 2 steps: 3 - image: ubuntu 4 entrypoint: ["bash"] 5 args: ["-c", "curl https://foo.com > /var/my-volume"] 6 volumeMounts: 7 - name: my-volume 8 mountPath: /var/my-volume 9 10 - image: ubuntu 11 args: ["cat", "/etc/my-volume"] 12 volumeMounts: 13 - name: my-volume 14 mountPath: /etc/my-volume 15 16 volumes: 17 - name: my-volume 18 emptyDir: {}
ServiceAccount
下面这个例子是使用了 test-build-robot-git-ssh 这个 ServiceAccount 去关联 clone 代码需要的 git ssh 认证信息。通过 ServiceAccount 和 secret 保存认证信息也可以做到在多个用户之间共享相同的数据,而且可以通过 RBAC 控制不同资源的可见范围,比较灵活。
-
Build 配置如下
apiVersion: build.knative.dev/v1alpha1 kind: Build metadata: name: test-build-with-serviceaccount-git-ssh labels: expect: succeeded spec: serviceAccountName: test-build-robot-git-ssh source: git: url: git@github.com:knative/build.git revision: master
steps: - name: config image: ubuntu command: ["/bin/bash"] args: ["-c", "cat README.md"]
-
test-build-robot-git-ssh ServiceAccount 配置如下
apiVersion: v1 kind: ServiceAccount metadata: name: test-build-robot-git-ssh secrets:
- name: test-git-ssh
-
ServiceAccount 关联的 secret 如下
apiVersion: v1 kind: Secret metadata: name: test-git-ssh annotations: build.knative.dev/git-0: github.com type: kubernetes.io/ssh-auth data:
Generated by:
cat id_rsa | base64 -w 0
ssh-privatekey: LS0tLS1CRUdJTiBSU0EgUFJJVk.....[example]
Generated by:
ssh-keyscan github.com | base64 -w 0
known_hosts: Z2l0aHViLmNvbSBzc2g.....[example]
Timeout
下面这个是自定义 Build 超时时间的例子。
1spec: 2 timeout: 20m 3 source: 4 git: 5 url: https://github.com/knative/build.git 6 revision: master 7 steps: 8 - image: ubuntu 9 args: ["cat", "README.md"]