前言
Tekton Pipelines是一个开源实现,可为您的Kubernetes应用程序配置和运行CI / CD风格的管道。
Pipelines创建自定义资源作为构建块去声明Pipelines。
自定义资源是Kubernetes API的扩展,可以创建自定义Kubernetes对象。安装自定义资源后,用户可以使用kubectl创建和访问其对象,就像对pod,部署等内置资源一样。这些资源在集群上运行,并由Kubernetes自定义资源定义(CRD)实施。
关于此设计的高级细节:
- Pipelines不知道什么会触发它们,它们可以由事件或手动创建PipelineRun触发。
- Tasks可以单独存在,并且可以完全独立于Pipelines调用。它们具有高内聚低耦合特点。
- Tasks可以取决于其他Tasks创建的工件和参数。
- Tasks可以被TaskRuns调用。
- PipelineResources是用作Tasks输入和输出的工件。
接下来我们将逐一介绍如下构建组件:
Task
TaskRun
Pipeline
PipelineRun
PipelineResource
与特定组件无关的其他参考主题:
- Labels
- Logs
该篇主要介绍Task。
Task
Task(或ClusterTask)是您希望在连续集成流程中运行的顺序步骤的集合。任务将在集群上的pod内运行。
一个 Task 声明包括:
- Inputs
- Outputs
- Steps
Task的作用范围是一个namespace,而ClusterTask的作用范围是整个kubernetes 集群。
ClusterTask
与Task类似,但是作用域是整个集群。
如果使用ClusterTask,则应添加TaskRef类型。默认类型是Task,它代表命名空间的Task。
apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
name: demo-pipeline
namespace: default
spec:
tasks:
- name: build-skaffold-web
taskRef:
name: build-push
kind: ClusterTask
params: ....
ask的功能与ClusterTask完全相同,因此下面对Task的所有引用也描述了ClusterTask.
语法
要为Task资源定义配置文件,可以指定以下字段:
-
必写:
-
apiVersion
- 指定 API 版本, 例如tekton.dev/v1alpha1
. -
kind
- 指定Task
资源对象. -
metadata
- 指定数据以唯一标识Task
资源对象, 例如name
. -
spec
- 为Task
资源对象指定配置信息。必须通过以下任一字段定义Task steps:-
steps
- 指定要在Task中运行的一个或多个容器镜像。
-
-
-
可选:
-
inputs
- 指定你Task
需要用到的参数和PipelineResources
-
outputs
- 指定你Task
产生的PipelineResources
-
volumes
- 指定一个或多个要用于Task
中steps
的 挂载卷. -
stepTemplate
- 指定容器
step 定义,以用作“Task”中所有step
的基础。. -
sidecars
- 指定sidercar容器与steps一起运行.
-
以下示例是一个无效示例,其中使用了大多数可能的配置字段:
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: example-task-name
spec:
inputs:
resources:
- name: workspace
type: git
params:
- name: pathToDockerFile
type: string
description: The path to the dockerfile to build
default: /workspace/workspace/Dockerfile
outputs:
resources:
- name: builtImage
type: image
steps:
- name: ubuntu-example
image: ubuntu
args: ["ubuntu-build-example", "SECRETS-example.md"]
- image: gcr.io/example-builders/build-example
command: ["echo"]
args: ["$(inputs.params.pathToDockerFile)"]
- name: dockerfile-pushexample
image: gcr.io/example-builders/push-example
args: ["push", "$(outputs.resources.builtImage.url)"]
volumeMounts:
- name: docker-socket-example
mountPath: /var/run/docker.sock
volumes:
- name: example-volume
emptyDir: {}
Steps
Steps字段是必填字段。您定义一个或多个Step字段以定义Task主体。
如果定义了多个Step,则由TaskRun调用任务时,将按照定义的顺序执行它们。
Task中的每个Step都必须指定一个遵守容器规约的容器镜像。对于您定义的每个Step字段或容器镜像:
- 按照配置文件,依次运行和评估容器镜像。
- 个容器镜像一直运行到完成或检测到第一个故障为止。
- 如果容器镜像在“Task”中的所有容器镜像中没有最大的资源请求,则CPU,内存和临时存储资源请求将设置为零。这样可以确保执行任务的Pod仅请求执行任务中任何单个容器镜像所需的资源,而不是请求所有容器镜像资源请求的总和。
Inputs
一个Task可以声明其所需的inputs,可以是以下之一或全部:
- 参数
- 输入资源
参数
Task可以声明在TaskRun期间必须提供给任务的输入参数。此的一些示例用例包括:
- 需要知道一个Task构建应用程序时使用什么编译标志。
- 需要知道如何命名已构建工件的Task。
参数名称仅限于字母数字字符-和_,并且只能以字母字符和_开头。例如,fooIs-Bar_是有效的参数名称,barIsBa $或0banana不是。
每个声明的参数都有一个类型字段,如果用户未提供,则假定为字符串。另一个可能的类型是数组-例如,当需要向构建应用程序的任务提供动态数量的编译标志时,此数组很有用。提供实际参数值时,将根据类型字段验证其解析的类型。
用法
以下示例显示如何对Tasks进行参数化,以及如何将这些参数从TaskRun传递给Task。
$(inputs.params.foo)形式的输入参数在步骤内被替换(另请参见变量替换)。
以下Task声明一个名为“ flags”的输入参数,并在steps.args列表中使用它。
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: task-with-parameters
spec:
inputs:
params:
- name: flags
type: array
- name: someURL
type: string
steps:
- name: build
image: my-builder
args: ["build", "$(inputs.params.flags)", "url=$(inputs.params.someURL)"]
以下TaskRun在flags参数中提供了动态数目的字符串:
apiVersion: tekton.dev/v1alpha1
kind: TaskRun
metadata:
name: run-with-parameters
spec:
taskRef:
name: task-with-parameters
inputs:
params:
- name: flags
value:
- "--set"
- "arg1=foo"
- "--randomflag"
- "--someotherflag"
- name: someURL
value: "http://google.com"
Input resources
使用输入的PipelineResources字段为您的任务提供任务所需的数据或上下文。
Outputs
Task定义可以包括输入和输出PipelineResource声明。如果仅在输出中声明了特定的资源集,则预期在下一个任务上载或共享的资源副本位于路径/ workspace / output / resource_name /下。
resources:
outputs:
name: storage-gcs
type: gcs
steps:
- image: objectuser/run-java-jar #https://hub.docker.com/r/objectuser/run-java-jar/
command: [jar]
args:
["-cvf", "-o", "/workspace/output/storage-gcs/", "projectname.war", "*"]
env:
- name: "FOO"
value: "world"
注意:如果任务依赖于输出资源功能,则“任务步骤”字段中的容器无法在路径/ workspace / output中装入任何内容。
在以下示例中,Task tar-artifact
资源同时用作输入和输出,因此将输入资源下载到目录customworkspace(在targetPath中指定)。Step untar
将tar文件提取到tar-scratch-space目录中,edit-tar
添加一个新文件,最后一个步骤tar-it-up
创建一个新的tar文件并将其放置在/ workspace / customworkspace /目录中。执行完任务步骤后,目录/ workspace / customworkspace中的(新)tar文件将被上传到tar-artifact
资源定义中定义的存储桶中.
resources:
inputs:
name: tar-artifact
targetPath: customworkspace
outputs:
name: tar-artifact
steps:
- name: untar
image: ubuntu
command: ["/bin/bash"]
args: ['-c', 'mkdir -p /workspace/tar-scratch-space/ && tar -xvf /workspace/customworkspace/rules_docker-master.tar -C /workspace/tar-scratch-space/']
- name: edit-tar
image: ubuntu
command: ["/bin/bash"]
args: ['-c', 'echo crazy > /workspace/tar-scratch-space/rules_docker-master/crazy.txt']
- name: tar-it-up
image: ubuntu
command: ["/bin/bash"]
args: ['-c', 'cd /workspace/tar-scratch-space/ && tar -cvf /workspace/customworkspace/rules_docker-master.tar rules_docker-master']
Volumes
为你的Task或是所有的step指定一个或多个需要用到volume。
如,使用卷来完成以下常见任务之一:
- 挂载k8s secret。
- 创建一个emptyDir卷以充当缓存,以便在多个构建步骤中使用。考虑使用永久卷进行内部版本缓存。
- 挂载k8s configmap
- 载主机的Docker套接字以使用Dockerfile进行容器映像构建。注意:使用docker build on-cluster构建容器映像是非常不安全的。请改用kaniko。这仅用于演示目的
Step Template
指定一个容器配置,它将用作“任务”中所有步骤的基础。单个步骤中的配置将覆盖或与步骤模板的配置合并。
在下面的示例中,任务指定环境变量FOO设置为bar的stepTemplate。第一步将对该值使用FOO,但是在第二步中,将FOO覆盖并设置为baz。
stepTemplate:
env:
- name: "FOO"
value: "bar"
steps:
- image: ubuntu
command: [echo]
args: ["FOO is ${FOO}"]
- image: ubuntu
command: [echo]
args: ["FOO is ${FOO}"]
env:
- name: "FOO"
value: "baz"
Sidecars
指定要与“步骤”一起运行的“容器”列表。这些容器可以提供辅助功能,例如Docker中的Docker或运行模拟API服务器,以使您的应用在测试过程中命中。
Sidecar在执行Task的步骤之前启动,并在所有步骤完成后销毁。有关Sidecar生命周期的更多信息,请参阅[TaskRun文档]
(https://github.com/tektoncd/p...
以下示例中,运行了docker in docker的 sidecar,以便一个步骤可以使用它来构建docker映像
steps:
- image: docker
name: client
workingDir: /workspace
command:
- /bin/sh
- -c
- |
cat > Dockerfile << EOF
FROM ubuntu
RUN apt-get update
ENTRYPOINT ["echo", "hello"]
EOF
docker build -t hello . && docker run hello
docker images
volumeMounts:
- mountPath: /var/run/
name: dind-socket
sidecars:
- image: docker:18.05-dind
name: server
securityContext:
privileged: true
volumeMounts:
- mountPath: /var/lib/docker
name: dind-storage
- mountPath: /var/run/
name: dind-socket
volumes:
- name: dind-storage
emptyDir: {}
- name: dind-socket
emptyDir: {}
Variable Substitution
任务支持使用所有输入和输出中的值替换字符串。
可以使用以下变量替换语法在任务规范中引用输入参数,其中
$(inputs.params.)
来自资源的参数值也可以使用变量替换来访问。
参数类型为数组的变量替换
类型为array的引用参数将扩展为在引用字符串的位置插入数组元素。
因此,使用以下参数:
inputs:
params:
- name: array-param
value:
- "some"
- "array"
- "elements"
then command: ["first", "$(inputs.params.array-param)", "last"] 将变成 command: ["first", "some", "array", "elements", "last"]
请注意,必须在较大的字符串数组中的完全隔离的字符串中引用数组参数。任何其他尝试引用数组的尝试均无效,并且将引发错误。
例如,如果build-args是array类型的声明参数,那么这是无效的步骤,因为字符串不是隔离的:
- name: build-step
image: gcr.io/cloud-builders/some-image
args: ["build", "additionalArg $(inputs.params.build-args)"]
同样,在非数组字段中引用build-args也无效:
- name: build-step
image: "$(inputs.params.build-args)"
args: ["build", "args"]
对build-args参数的有效引用是隔离的,并且位于合格字段(本例中为args)中:
- name: build-step
image: gcr.io/cloud-builders/some-image
args: ["build", "$(inputs.params.build-args)", "additonalArg"]
Variable Substitution within Volumes
可以设置任务卷名称和不同类型的卷。当前支持包括广泛使用的卷类型,例如configmap,secret和PersistentVolumeClaim。这是有关如何在“任务定义”中使用此示例。
Examples
例如,封装Dockerfile构建的Task可能看起来像这样:
注意:使用docker build on-cluster构建容器映像是非常不安全的。请改用kaniko。这仅用于演示目的。
spec:
inputs:
resources:
- name: workspace
type: git
params:
# These may be overridden, but provide sensible defaults.
- name: directory
type: string
description: The directory containing the build context.
default: /workspace
- name: dockerfileName
type: string
description: The name of the Dockerfile
default: Dockerfile
outputs:
resources:
- name: builtImage
type: image
steps:
- name: dockerfile-build
image: gcr.io/cloud-builders/docker
workingDir: "$(inputs.params.directory)"
args:
[
"build",
"--no-cache",
"--tag",
"$(outputs.resources.image)",
"--file",
"$(inputs.params.dockerfileName)",
".",
]
volumeMounts:
- name: docker-socket
mountPath: /var/run/docker.sock
- name: dockerfile-push
image: gcr.io/cloud-builders/docker
args: ["push", "$(outputs.resources.image)"]
volumeMounts:
- name: docker-socket
mountPath: /var/run/docker.sock
# As an implementation detail, this Task mounts the host's daemon socket.
volumes:
- name: docker-socket
hostPath:
path: /var/run/docker.sock
type: Socket
使用一个外部 volume
挂载多个卷:
spec:
steps:
- image: ubuntu
entrypoint: ["bash"]
args: ["-c", "curl https://foo.com > /var/my-volume"]
volumeMounts:
- name: my-volume
mountPath: /var/my-volume
- image: ubuntu
args: ["cat", "/etc/my-volume"]
volumeMounts:
- name: my-volume
mountPath: /etc/my-volume
volumes:
- name: my-volume
emptyDir: {}
使用 Kubernetes Configmap 作为卷
spec:
inputs:
params:
- name: CFGNAME
type: string
description: Name of config map
- name: volumeName
type: string
description: Name of volume
steps:
- image: ubuntu
entrypoint: ["bash"]
args: ["-c", "cat /var/configmap/test"]
volumeMounts:
- name: "$(inputs.params.volumeName)"
mountPath: /var/configmap
volumes:
- name: "$(inputs.params.volumeName)"
configMap:
name: "$(inputs.params.CFGNAME)"
使用 secret 作为环境变量
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
name: goreleaser
spec:
inputs:
params:
- name: package
type: string
description: base package to build in
- name: github-token-secret
type: string
description: name of the secret holding the github-token
default: github-token
resources:
- name: source
type: git
targetPath: src/$(inputs.params.package)
steps:
- name: release
image: goreleaser/goreleaser
workingdir: /workspace/src/$(inputs.params.package)
command:
- goreleaser
args:
- release
env:
- name: GOPATH
value: /workspace
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: $(inputs.params.github-token-secret)
key: bot-token