[关闭]
@levinzhang 2021-10-31T09:57:03.000000Z 字数 16966 阅读 892

借助Tekton实现微服务的Pipeline

by

摘要:

微服务特性(microservicility)指的是除了业务逻辑之外,服务必须要实现的一组横切性的关注点。这些关注点包括调用、弹性(elasticity)和回弹性(resiliency)等。本文描述了如何使用Tekton构建微服务的Pipeline。


核心要点

在微服务架构中,应用程序是由多个相互连接的服务组成的,这些服务协同工作以实现所需的业务功能。所以,一个典型的企业级微服务架构如下所示:

最初,我们可能认为使用微服务架构实现一个应用程序是很容易的事情。但是,要恰当地完成这一点并不容易,因为我们会面临一些新的挑战,而这些挑战是单体架构所未曾遇到的。举例来讲,这样的挑战包括容错、服务发现、扩展性、日志和跟踪等。

为了应对这些挑战,每个微服务都需要实现在Red Hat被称为“微服务特性(microservicility)”的内容。这个术语指的是除了业务逻辑之外,服务必须要实现的一个横切性关注点的列表。

这些关注点总结起来如下图所示:

在本系列的第一部分第二部分中,我们分别讨论了如何使用QuarkusIstio实现这些微服务特性。但是,还有一个微服务特性是我们在这两篇文章中都没有涉及到的,那就是Pipeline

在微服务架构中,我们应该能够独立地部署服务,而不需要任何的部署编排(orchestration)。在服务间没有任何的编排意味着没有必要在每次部署的时候都部署和发布整个应用程序,只需要其中的很小一部分就可以了。

如果我们能够发布应用中各个小的组成部分的话,那么这会带来一些好处:

出于这样的原因,每个服务应该都有自己部署Pipeline,这样的话,我们就可以随时部署它,只需要遵循它自己的规则或流程即可。

但是,为每个服务都创建一个部署Pipeline会带来一些挑战,这是我们需要解决的:

大多数问题的答案就是Pipeline即代码(pipeline-as-code)。这种技术能够允许我们以代码或可视为代码的文件(YAML)的形式创建持续交付Pipeline。

因为Pipeline是以代码的形式定义的,所以它们应该置于源码控制之下,这意味着它们是可以重用、可以建立分支也可以创建tag。更重要的是,我们能够将服务代码和交付Pipeline添加到相同的仓库中。

Kubernetes正在成为部署微服务的事实标准工具。它是一个开源的系统,用来自动化、编排、扩展和管理容器。

正如我们在前面的两篇文章中所讲到的那样,在我们提到的十个微服务特性中,通过使用 Kubernetes 能够覆盖其中的三个。

如果我们使用Istio,可以实现另外五个微服务特性,即服务发现、回弹性、认证、监控和跟踪。

使用Kubernetes和Istio是个好主意,但是Pipeline该怎么实现呢?我们该如何实现一个Kubernetes原生的持续交付Pipeline呢?引入Tekton是一个可行的解决方案。

Tekton

Tekton是一个Kubernetes原生的构建CI/CD Pipeline的解决方案,能够以Kubernetes扩展的方式安装和运行。它提供了一组Kubernetes自定义资源(custom resource),借助这些自定义资源,我们可以为Pipeline创建和重用构建块。

实体

Tekton定义了如下的基本Kubernetes自定义资源定义(Kubernetes Custom Resource Definition,CRD)来构建Pipeline:

PipelineResource能够定义可引用的资源,比如源码仓库或容器镜像。

Task定义了一个按顺序执行的step列表。每个step会在容器中执行命令。每个task都是一个Kubernetes Pod,Pod中包含了与step同等数量的容器。

TaskRun会实例化一个要执行的Task,并且会带有具体的输入、输出和参数。

Pipeline会定义一个task的列表,这些task会按照特定的顺序来执行。

PipelineRun会实例化一个要执行的Pipeline,并且会带有具体的输入、输出和参数。它会自动为每个Task创建TaskRun实例。

Task可以通过创建TaskRun对象单独运行,也可以作为Pipeline的一部分运行。

安装

执行如下的命令来启动集群:

  1. minikube start -p tekton --kubernetes-version='v1.19.0' --vm-driver='virtualbox' --memory=4096
  2. [istio] minikube v1.17.1 on Darwin 11.3
  3. Kubernetes 1.20.2 is now available. If you would like to upgrade, specify: --kubernetes-version=v1.20.2
  4. minikube 1.19.0 is available! Download it: https://github.com/kubernetes/minikube/releases/tag/v1.19.0
  5. To disable this notice, run: 'minikube config set WantUpdateNotification false'
  6. Using the virtualbox driver based on existing profile
  7. You cannot change the memory size for an exiting minikube cluster. Please first delete the cluster.
  8. Starting control plane node istio in cluster istio
  9. Restarting existing virtualbox VM for "istio" ...
  10. Preparing Kubernetes v1.19.0 on Docker 19.03.12 ...
  11. Verifying Kubernetes components...
  12. Enabled addons: storage-provisioner, default-storageclass
  13. Done! kubectl is now configured to use "tekton" cluster and "" namespace by default

Kubernetes启动就绪之后,我们可以下载tkn CLI工具来与Tekton Pipeline进行交互。在本例中,我们从发布页面下载tkn 0.18.0。

现在,我们通过执行如下的命令安装Tekton控制器:

  1. kubectl apply -f
  2. https://storage.googleapis.com/tekton-releases/pipeline/previous/v0.24.0/release.yaml
  3. namespace/tekton-pipelines created
  4. podsecuritypolicy.policy/tekton-pipelines created
  5. clusterrole.rbac.authorization.k8s.io/tekton-pipelines-controller-cluster-access created
  6. clusterrole.rbac.authorization.k8s.io/tekton-pipelines-controller-tenant-access created
  7. clusterrole.rbac.authorization.k8s.io/tekton-pipelines-webhook-cluster-access created
  8. role.rbac.authorization.k8s.io/tekton-pipelines-controller created
  9. deployment.apps/tekton-pipelines-controller created
  10. service/tekton-pipelines-controller created
  11. horizontalpodautoscaler.autoscaling/tekton-pipelines-webhook created
  12. deployment.apps/tekton-pipelines-webhook created
  13. service/tekton-pipelines-webhook created

定义Pipeline

接下来,我们看一下该如何在Tekton中定义持续交付的Pipeline。这个pipeline由两个task组成。第一个task从GitHub上clone项目,使用Maven(可以是其他任意的构建工具甚至是不同的语言)构建Java项目,创建容器镜像并将其推送至一个容器registry。第二个任务会将服务部署至一个Kubernetes集群。

但是,在开发pipeline之前,我们先通过一个简单的“Hello World”来理解Tekton的概念。

第一个Task

我们创建一个只包含单个step的task,该task会启动一个busybox容器并在容器中执行echo命令。创建名为hello-world-task.yml的文件:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: helloworld
  5. spec:
  6. steps:
  7. - name: sayhello
  8. image: busybox
  9. command:
  10. - echo
  11. args: ['Hello World']
  12. kubectl apply -f src/main/tekton/hello-world-task.yml -n default
  13. task.tekton.dev/helloworld created

使用tkn列出当前注册的所有task:

  1. tkn task list
  2. NAME DESCRIPTION AGE
  3. helloworld 1 minute ago

此时只是注册了这个task,现在我们需要初始化一个task来执行它。我们可以通过使用tkn CLI或应用一个TaskRun来实现这一点。在这里,我们创建一个名为 hello-world-taskrun.ymlTaskRun文件,它会在name字段中注册前文所述的task

  1. apiVersion: tekton.dev/v1beta1
  2. kind: TaskRun
  3. metadata:
  4. name: helloworld-run
  5. spec:
  6. taskRef:
  7. name: helloworld

然后,我们应用这个文件,task就会被触发。

  1. kubectl apply -f src/main/tekton/hello-world-taskrun.yml
  2. taskrun.tekton.dev/helloworld-run created

我们可以使用tkn列出当前所有的task:

  1. tkn tr list
  2. NAME STARTED DURATION STATUS
  3. helloworld-run 8 seconds ago --- Running(Pending)

归根到底,Task只是运行在Kubernetes集群中的一个Kubernetes Pod,而每个step则是Pod中的一个容器。执行如下的命令获取当前的Pod:

  1. kubectl get pods
  2. NAME READY STATUS RESTARTS AGE
  3. helloworld-run-pod-75dwt 0/1 Completed 0 45s

Pod的状态是已完成,因为task已经执行完毕了。它会运行一个容器,容器的名字会符合TaskRunmetadata部分name字段所定义的值。

我们可以描述一下Pod,请关注containers区域,以获取task启动的容器的概况:

  1. kubectl describe pod helloworld-run-pod-75dwt
  2. Containers:
  3. step-sayhello:
  4. Container ID: docker://e3bb6b747e6cbb76829e7658b7bf2976f3f09861775a4584eccfba0c143996a6
  5. Image: busybox
  6. ...

最后,我们可以使用tkn的logs命令查看TaskRun的日志:

  1. tkn tr logs helloworld-run
  2. [sayhello] Hello World

现在,我们对Tekton的task已经有了基本的了解,接下来我们更进一步,实现一个具备了所需step的真正pipeline。

Pipeline资源

PipelineResource定义了输入/输出资源的位置,这些资源会被Task中的step所用到。这些参数通常会遵循Git URL或者容器镜像全限定名的形式。

我们创建一个新的PipelineResource文件来配置项目的仓库:

  1. apiVersion: tekton.dev/v1alpha1
  2. kind: PipelineResource
  3. metadata:
  4. name: git-source
  5. spec:
  6. type: git
  7. params:
  8. - name: url
  9. value: https://github.com/lordofthejars/hello-world-tekton.git
  10. kubectl apply -f src/main/tekton/git-pipeline-resource.yml -n default
  11. pipelineresource.tekton.dev/git-source created

然后,创建另外一个PipelineResource来设置容器镜像:

  1. apiVersion: tekton.dev/v1alpha1
  2. kind: PipelineResource
  3. metadata:
  4. name: hello-world-image
  5. spec:
  6. type: image
  7. params:
  8. - name: url
  9. value: quay.io/lordofthejars/hello-world-quarkus-tekton:1.0.0
  10. kubectl apply -f src/main/tekton/container-image-resource.yml
  11. pipelineresource.tekton.dev/hello-world-image created
  12. tkn resource list
  13. NAME TYPE DETAILS
  14. git-source git url: https://github.com/lordofthejars/hello-world-tekton.git
  15. hello-world-image image url: quay.io/lordofthejars/hello-world-quarkus-tekton:1.0.0

Task

在创建task之前,我们先创建一个Kubernetes Secret,它包含了两个用于Quay访问凭证的键/值对,分别是Quay的用户名和Quay的密码。请将username和password的值替换成正确的值。

  1. kubectl create secret generic quay-credentials --from-literal=quay-username='yyy' --from-literal=quay-password='xxx'
  2. secret/quay-credentials created

接下来,我们创建一个Task来构建项目,创建Linux容器镜像并将其推送至容器registry上(在本例中,我们使用Quay,但是可以切换成任意的其他方案)。

因为这是一个使用Quarkus实现的Java项目,所以我们会通过集成Jib实现以Dockerless的方式创建容器镜像。在一个容器运行时(Tekton就是这种情况)中构建容器镜像时,我们可能会遇到一些在容器中运行task容器的问题(构建新的容器)。这也是为何采用Dockerless技术创建容器的重要原因。对于Java项目来说,Jib是一个可行的方案,但是也有其他通用的、不针对特定语言的方案,比如BuildahKaniko

我们创建一个task,它会执行执行Maven package goal,设置构建所需的Quarkus选项并将容器镜像推送至Quay。当然,我们还需要以输入和输出(PipelineResource)的方式设置Git仓库和容器镜像名,并以参数(Kubernetes Secrets)的形式设置Quay的用户名和密码。

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: build-app
  5. spec:
  6. params:
  7. - name: quay-credentials-secret
  8. type: string
  9. description: name of the secret holding the quay credentials
  10. default: quay-credentials
  11. resources:
  12. inputs:
  13. - name: source
  14. type: git
  15. outputs:
  16. - name: builtImage
  17. type: image
  18. steps:
  19. - name: maven-build
  20. image: docker.io/maven:3.6-jdk-11-slim
  21. command:
  22. - mvn
  23. args:
  24. - clean
  25. - package
  26. - -Dquarkus.container-image.push=true
  27. env:
  28. - name: QUARKUS_CONTAINER_IMAGE_IMAGE
  29. value: $(outputs.resources.builtImage.url)
  30. - name: QUARKUS_CONTAINER_IMAGE_USERNAME
  31. valueFrom:
  32. secretKeyRef:
  33. name: $(params.quay-credentials-secret)
  34. key: quay-username
  35. - name: QUARKUS_CONTAINER_IMAGE_PASSWORD
  36. valueFrom:
  37. secretKeyRef:
  38. name: $(params.quay-credentials-secret)
  39. key: quay-password
  40. workingDir: "/workspace/source/"

在前面的文件中,我们看到Quay凭证的secret名被设置为参数。参数quay-credentials有一个默认值,它的值与kubectl creates secret命令中所用的值是相同的。

输入参数被命名为source,类型为git

输出参数是容器镜像的名称。

env部分中,我们定义了一些环境变量,用来配置Quarkus容器镜像扩展如何构建和推送容器镜像:

在Kubernetes集群中注册task:

  1. kubectl apply -f src/main/tekton/build-push-task.yml
  2. tkn task list
  3. NAME DESCRIPTION AGE
  4. build-app 3 hours ago

最后我们通过创建一个TaskRun来初始化这个task,此时我们需要链接在前文中通过PipelineResource创建的输入/输出资源并将secret名称设置为参数。

  1. apiVersion: tekton.dev/v1beta1
  2. kind: TaskRun
  3. metadata:
  4. name: build-app-run
  5. spec:
  6. params:
  7. - name: quay-credentials-secret
  8. value: quay-credentials
  9. resources:
  10. inputs:
  11. - name: source
  12. resourceRef:
  13. name: git-source
  14. outputs:
  15. - name: builtImage
  16. resourceRef:
  17. name: hello-world-image
  18. taskRef:
  19. name: build-app

注意,resourceRef字段指向了在前文中定义的PipelineResource的名称。

TaskRun被应用的时候,构建过程就开始执行了,它会clone项目,使用Maven进行构建,然后创建并推送镜像。通过使用tkn CLI,我们可以看到当前task的实时日志:

  1. tkn tr logs -f
  2. ? Select taskrun: [Use arrows to move, type to filter]
  3. > build-app-run started 38 minutes ago
  4. helloworld-run started 1 day ago
  5. [git-source-source-w2ck5] {"level":"info","ts":1620922474.2565205,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/lordofthejars/hello-world-tekton.git @ ee3edc414c47f2bdeda9cc7c47ac54427d35a9dc (grafted, HEAD) in path /workspace/source"}
  6. [git-source-source-w2ck5] {"level":"info","ts":1620922474.276228,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/source"}
  7. ...
  8. [maven-build] Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/maven-plugin-parameter-documenter/2.0.6/maven-plugin-parameter-documenter-2.0.6.pom
  9. Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/maven-plugin-parameter-documenter/2.0.6/maven-plugin-parameter-documenter-2.0.6.pom (1.9 kB at 58 kB/s)
  10. [maven-build] Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/reporting/maven-reporting-api/2.0.6/maven-reporting-api-2.0.6.pom
  11. [maven-build] [INFO] [io.quarkus.container.image.jib.deployment.JibProcessor] Pushed container image quay.io/lordofthejars/hello-world-quarkus-tekton:1.0.0 (sha256:e71b0808af36ce3b9b980b2fb83886be2e06439ee454813052a115829e1e727c)
  12. [maven-build] [INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 24202ms
  13. [maven-build] [INFO] ------------------------------------------------------------------------
  14. [maven-build] [INFO] BUILD SUCCESS
  15. [maven-build] [INFO] ------------------------------------------------------------------------
  16. [maven-build] [INFO] Total time: 01:16 min
  17. [maven-build] [INFO] Finished at: 2021-05-13T16:15:52Z
  18. [maven-build] [INFO] ------------------------------------------------------------------------
  19. [image-digest-exporter-88mpr] {"severity":"INFO","timestamp":"2021-05-13T16:15:53.025263494Z","caller":"logging/config.go:116","message":"Successfully created the logger."}
  20. [image-digest-exporter-88mpr] {"severity":"INFO","timestamp":"2021-05-13T16:15:53.025374882Z","caller":"logging/config.go:117","message":"Logging level set to: info"}
  21. [image-digest-exporter-88mpr] {"severity":"INFO","timestamp":"2021-05-13T16:15:53.025508459Z","caller":"imagedigestexporter/main.go:59","message":"No index.json found for: builtImage","commit":"b86a9a2"}

Pipeline

现在,我们已经创建了一个简单的task。但是,实际的持续交付/部署pipeline应该是由多个task组成的:构建并推送容器镜像,然后将其部署到Kubernetes集群中。

接下来我们创建具有两个step的task:

创建名为deploy-task.yml的文件,内容如下所示:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Task
  3. metadata:
  4. name: kubectl-deploy
  5. spec:
  6. params:
  7. - name: deploymentFile
  8. type: string
  9. description: deployment file location
  10. resources:
  11. inputs:
  12. - name: source
  13. type: git
  14. - name: builtImage
  15. type: image
  16. steps:
  17. - name: update-deployment-file
  18. image: quay.io/lordofthejars/image-updater:1.0.0
  19. script: |
  20. #!/usr/bin/env ash
  21. yq eval -i '.spec.template.spec.containers[0].image = env(DESTINATION_IMAGE)' $DEPLOYMENT_FILE
  22. env:
  23. - name: DESTINATION_IMAGE
  24. value: "$(inputs.resources.builtImage.url)"
  25. - name: DEPLOYMENT_FILE
  26. value: "/workspace/source/$(inputs.params.deploymentFile)"
  27. - name: kubeconfig
  28. image: quay.io/rhdevelopers/tutorial-tools:0.0.3
  29. command: ["kubectl"]
  30. args:
  31. - apply
  32. - -f
  33. - /workspace/source/$(inputs.params.deploymentFile)

注意,在第一个step中,我们使用script来代替command。要传递Tekton参数到script区域,我们需要通过环境变量来实现。

  1. kubectl apply -f src/main/tekton/deploy-task.yml
  2. task.tekton.dev/kubectl-deploy created
  3. tkn task ls
  4. NAME DESCRIPTION AGE
  5. build-app 18 hours ago
  6. helloworld 1 day ago
  7. kubectl-deploy 11 minutes ago

要部署服务,我们需要在Kubernetes集群中执行kubectl命令。为了实现这一点,我们需要设置一个Kubernetes Role以允许default服务账号(因为这是在我们的样例中运行Tekton Pipeline所使用的服务账号)具备相应的权限。这个角色必须要允许在运行的容器中应用Kubernetes资源。

创建名为pipeline-sa-role.yml的文件,内容如下:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: Role
  3. metadata:
  4. name: pipeline-extra-role
  5. rules:
  6. - apiGroups:
  7. - ""
  8. resources:
  9. - pods
  10. - services
  11. - endpoints
  12. - configmaps
  13. - secrets
  14. verbs:
  15. - "*"
  16. - apiGroups:
  17. - apps
  18. resources:
  19. - deployments
  20. - daemonsets
  21. - replicasets
  22. - statefulsets
  23. verbs:
  24. - "*"
  25. - apiGroups:
  26. - ""
  27. resources:
  28. - pods
  29. verbs:
  30. - get
  31. - apiGroups:
  32. - apps
  33. resources:
  34. - replicasets
  35. verbs:
  36. - get
  37. ---
  38. apiVersion: rbac.authorization.k8s.io/v1
  39. kind: RoleBinding
  40. metadata:
  41. name: pipeline-exta-role-binding
  42. roleRef:
  43. kind: Role
  44. name: pipeline-extra-role
  45. apiGroup: rbac.authorization.k8s.io
  46. subjects:
  47. - kind: ServiceAccount
  48. name: default

注册角色:

  1. kubectl apply -f src/main/tekton/pipeline-sa-role.yml
  2. role.rbac.authorization.k8s.io/pipeline-extra-role created
  3. rolebinding.rbac.authorization.k8s.io/pipeline-exta-role-binding created

现在,我们已经可以创建Tekton Pipeline将这两个task组合在一起了。在这里,定义pipeline参数至关重要,因为在pipeline定义中引用Tekton Task的时候,要设置这些参数。在这两个task中,我们都定义了params值(quay-credentials-secretdeploymentFile),并引用pipelineresource作为输入/输出。

创建pipeline.yml文件:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: Pipeline
  3. metadata:
  4. name: hello-world-pipeline
  5. spec:
  6. resources:
  7. - name: appSource
  8. type: git
  9. - name: containerImage
  10. type: image
  11. tasks:
  12. - name: build-app
  13. taskRef:
  14. name: build-app
  15. params:
  16. - name: quay-credentials-secret
  17. value: quay-credentials
  18. resources:
  19. inputs:
  20. - name: source
  21. resource: appSource
  22. outputs:
  23. - name: builtImage
  24. resource: containerImage
  25. - name: kube-deploy
  26. taskRef:
  27. name: kubectl-deploy
  28. params:
  29. - name: deploymentFile
  30. value: src/main/kubernetes/kubernetes.yml
  31. runAfter:
  32. - build-app
  33. resources:
  34. inputs:
  35. - name: source
  36. resource: appSource
  37. - name: builtImage
  38. resource: containerImage
  39. kubectl apply -f src/main/tekton/pipeline.yml
  40. pipeline.tekton.dev/hello-world-pipeline created

我们可以使用tkn CLI列出pipeline:

  1. tkn pipeline list
  2. NAME AGE LAST RUN STARTED DURATION STATUS
  3. hello-world-pipeline 5 seconds ago --- --- --- ---

通过命令描述pipeline,能够让我们看到pipeline的概述以及在运行它的时候,必须要定义哪些内容:

  1. tkn pipeline describe hello-world-pipeline
  2. Name: hello-world-pipeline
  3. Namespace: default
  4. Resources
  5. NAME TYPE
  6. appSource git
  7. containerImage image
  8. Params
  9. No params
  10. Results
  11. No results
  12. Workspaces
  13. No workspaces
  14. Tasks
  15. NAME TASKREF RUNAFTER TIMEOUT CONDITIONS PARAMS
  16. build-app build-app --- --- quay-credentials-secret: quay-credentials
  17. kube-deploy kubectl-deploy build-app --- --- deploymentFile: src/main/kubernetes/deployment.yml
  18. PipelineRuns
  19. No pipelineruns

现在,我们不需要任何的TaskRun了,因为它们会在应用PipelineRun的时候自动创建:

  1. apiVersion: tekton.dev/v1beta1
  2. kind: PipelineRun
  3. metadata:
  4. name: hello-world-pipeline-run
  5. spec:
  6. resources:
  7. - name: appSource
  8. resourceRef:
  9. name: git-source
  10. - name: containerImage
  11. resourceRef:
  12. name: hello-world-image
  13. pipelineRef:
  14. name: hello-world-pipeline

PipelineRun中,我们设置了PipelineResourcesPipeline之间的链接,因为它是由TaskRun执行的。

  1. kubectl apply -f src/main/tekton/pipeline-run.yml
  2. pipelinerun.tekton.dev/hello-world-pipeline-run created

与TaskRun类似,我们可以通过如下的命令将一个pipeline的日志以流的方式链接起来:

  1. tkn pipeline logs -f
  2. [kube-deploy : git-source-source-sdgld] {"level":"info","ts":1620978300.0659564,"caller":"git/git.go:169","msg":"Successfully cloned https://github.com/lordofthejars/hello-world-tekton.git @ b954dbc68e0aa7e4cfb6defeff00b1e4ded2889c (grafted, HEAD) in path /workspace/source"}
  3. [kube-deploy : git-source-source-sdgld] {"level":"info","ts":1620978300.0972755,"caller":"git/git.go:207","msg":"Successfully initialized and updated submodules in path /workspace/source"}
  4. [kube-deploy : kubeconfig] deployment.apps/hello-world created

如果构建成功的话,服务将会部署到当前的Kubernetes集群中。我们可以获取所有的Pod以查看集群中发生了什么:

  1. kubectl get pods
  2. NAME READY STATUS RESTARTS AGE
  3. hello-world-59d47597c-qm9nr 1/1 Running 0 36m
  4. hello-world-pipeline-run-build-app-xmvg2-pod-v4vps 0/4 Completed 0 37m
  5. hello-world-pipeline-run-kube-deploy-bfqhd-pod-x68xh 0/3 Completed 0 36m

我们可以看到有两个已完成的Pod。hello-world-pipeline-run-build-app Pod对应的是build-app task,它会clone、构建和测试服务,并且最终会创建和推送容器镜像。hello-world-pipeline-run-kube-deploy Pod对应kube-deploy task,它负责部署应用。

除了task之外,这里还有一个正在运行的Pod。这就是pipeline执行期间所部署的应用Pod。

结论

开发和实现微服务架构要比开发单体应用更具挑战性。我们相信,微服务特性能够促使你在应用基础设施方面正确地开发服务。

在本系列的第一篇第二篇文章中,我们分别学习了如何使用Quarkus或Istio实现微服务特性,但是我们还没有介绍Pipeline这项微服务特性。本文阐述了如何使用Tekton实现一个基本的持续交付pipeline,Tekton是一个Kubernetes原生的解决方案,用于构建CI/CD pipeline。

Tekton一个很重要的优势是能够在容器最终要部署的同一个集群中创建容器镜像。这减少了容器在某些机器上构建而在其他机器上部署时可能出现的差异。另一个优势是使用YAML文件来定义pipeline的方式。通过这种方式,pipeline能够与源代码一起存储,使其可创建分支、可创建tag或版本化。

有时候,没有必要从头开始定义task,在Tekton Catalog上,我们可以看到很多可以直接使用的task。除此之外,如果你需要开发自定义的task的话,要借助参数和输入/输出资源将它们设计的尽可能比较开放。通过这种方式,task有可能实现在你的组织内的重用,从而解决类似的问题。

本文只是Tekton的一个简介。我们可以看到当一个PipelineRun对象在集群中创建的时候,pipeline就会运行,但是触发器/事件也可以触发Pipeline。举例来讲,事件可能是对GitHub仓库中特性分支的推送。触发器是一个更高级的话题,你可以通过该地址学习关于触发器的更多知识。

用于阐述本文的源码可以在GitHub仓库中找到。第一篇第二篇文章的源码也分别可以在这里这里获取。

关于作者

Alex Soto是红帽公司的开发者体验总监。他对Java领域、软件自动化充满热情,他相信开源软件模式。Soto是Manning的《Testing Java Microservices》O’Reilly的《Quarkus Cookbook》两本书的共同作者,他还是多个开源项目的贡献者。自2017年以来,他一直是Java Champion,是国际演讲者和Salle URL大学的教师。你可以在Twitter上关注他(Alex Soto ⚛️),随时了解Kubernetes和Java领域的动态。

查看英文原文:Implementing Pipeline Microservicilities with Tekton

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注