开源技术 * IBM 微讲堂:Kubeflow 系列(观看回放 | 下载讲义) 了解详情

使用 Tekton Pipeline 在 Kubernetes 上构建和部署 Hello World 应用程序

基于容器的软件开发技术已日渐成熟。由于复制环境很容易,因此开发者通常会在其桌面上创建应用程序,并在本地调试和测试这些应用程序。随后,他们将构建应用程序并将其部署到 Kubernetes 集群中。

在本教程中,我将展示如何使用两种方式将应用程序部署到 IBM Cloud 上的 Kubernetes 集群中:

  • 在不使用 DevOps 管道的情况下使用 kubectl CLI
  • 使用 Tekton Pipeline(这是 Kubernetes 样式的持续集成和持续交付 (CI/CD) 管道)

前提条件

要完成本教程,您需要:

  • 创建一个 IBM Cloud 帐户。
  • 获取一个 Kubernetes Service on IBM Cloud 实例(完成此过程大约需要 20 分钟)。
  • 通过 kubectl CLI 访问 Kubernetes 集群。要访问相关说明,请转到 IBM Cloud 仪表板 > [您的集群] > Access
  • 在 IBM Cloud 容器注册表上创建一个名称空间。要执行此操作,请转到 IBM Cloud 仪表板,然后单击 Navigation > Kubernetes > Registry > Namespaces
  • 配置 Git CLI。使用以下命令来将代码库克隆到您的工作站中:

    git clone https://github.com/IBM/deploy-app-using-tekton-on-kubernetes.git
    

预估时间

在满足前提条件后,本教程大约需要 40 分钟。

使用 kubectl 在 IBM Cloud Kubernetes Service 上构建和部署应用程序

要在 Kubernetes 集群上构建和部署应用程序,请执行以下步骤:

  1. 为应用程序编写一个 Dockerfile,并使用 Dockerfile 来构建容器镜像。
  2. 将所构建的容器镜像上传到可访问的容器注册表。
  3. 使用容器镜像创建 Kubernetes 部署,然后使用配置 (YAML) 文件将应用程序部署到 IBM Cloud Kubernetes Service 集群中。

在本教程中,我们选择将一个简单的 Hello World! Node.js 应用程序部署到 Kubernetes 中,如下所示。以下代码来自我们的样本应用程序(也可以使用您现有的样本应用程序)。

  const app = require('express')()

  app.get('/', (req, res) => {
    res.send("Hello from Appsody!");
  });

  var port = 3300;

  var server = app.listen(port, function () {
    console.log("Server listening on " + port);
  })

  module.exports.app = app;

Dockerfile 和部署配置 deploy.yaml 都位于您先前克隆的 GitHub 代码库中。本部分中所述的步骤可帮助您使用 CLI 将应用程序部署到集群中。

1. 设置部署目标

第一步,您需要为容器镜像设置正确的部署目标,以将其上传到可访问的容器注册表。根据集群的创建地区,镜像 URL 将采用以下格式:

  <REGION_ABBREVIATION>.icr.io/<YOUR_NAMESPACE>/<YOUR_IMAGE_NAME>:<VERSION>

以下命令将告知集群的 Registry API 端点。您可以从输出中获取地区缩写。

   ibmcloud cr api

要获取名称空间,请使用以下命令:

    ibmcloud cr namespaces

例如,美国南部地区的部署目标为:

       us.icr.io/test_namespace/sampleapp:1.0

2. 部署应用程序

运行以下命令以在 Kubernetes 集群上部署应用程序:

  cd ~/deploy-app-using-tekton-on-kubernetes/src

  # Build and push it to IBM Cloud Container registry.Following command takes care of build and push to container registry and eliminates the overhead to run docker commands individually.
  ibmcloud cr build -t us.icr.io/test_namespace/sampleapp:1.0 .

  # Verify whether the image is uploaded to the container registry
  ibmcloud cr images

  # Update deploy target in deploy.yaml
  sed -i '' s#IMAGE#us.icr.io/test_namespace/sampleapp:1.0# deploy.yaml

  # Run deploy configuration
  kubectl create -f deploy.yaml

  # Verify output - pod and service should be up and running
  kubectl get pods
  kubectl get service

在成功部署之后,可通过 http://<public-ip-of-kubernetes-cluster>:32426/ 来访问您的应用程序,您可以从 IBM Cloud 仪表板中检索 Kubernetes 集群的公共 IP,并在 deploy.yaml 中将端口 32426 定义为 nodePort

上面的步骤展示了如何使用 CLI 将应用程序部署到 Kubernetes 集群中。如果在部署后更改了应用程序,则需要重新运行这些步骤。

为了更快更可靠地构建、测试和部署应用程序,您需要自动执行这整个工作流程。采用 CI/CD 方法,可以减少开发和手动部署过程的开销,从而节省大量的时间和精力。

本教程的下一部分将说明如何使用 Tekton Pipeline 进行构建和部署。

使用 Tekton Pipeline 在 IBM Cloud Kubernetes Service 上构建和部署应用程序

Tekton 是一个 Kubernetes 原生开源框架,功能强大且十分灵活,可用于创建 CI/CD 系统。通过抽去底层实现细节,Tekton 可帮助您在多个云提供商或本地系统中构建、测试和部署应用程序。

在我展示如何使用 Tekton Pipeline 之前,您需要了解下面几个高级概念:

Tekton Pipeline 项目通过提供五个用于定义管道的额外自定义资源定义 (CRD) 扩展了 Kubernetes API:

  • 任务是一项作业,用于定义一组构建步骤(例如,编译代码、运行测试、构建和部署镜像)。
  • 任务运行用于运行您定义的任务。通过任务运行,可以执行一个任务以将任务的输入和输出绑定在一起。
  • 管道用于描述构成管道的任务列表。
  • 管道运行用于定义管道的执行。它将引用要运行的管道以及要用作输入和输出的管道资源。
  • 管道资源用于定义一个对象,该对象可以是管道的输入(例如 Git 代码库)或输出(例如 Docker 镜像)。

要使用 Tekton Pipeline 自动执行应用程序的构建和部署工作流程,请执行以下步骤:

1. 将 Tekton Pipeline 组件添加到 Kubernetes 集群中

第一步,使用以下命令来将 Tekton Pipeline 添加到 Kubernetes 集群中:

  kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

安装将创建两个 pod,您可以使用以下命令来检查这一情况。确保等到这些 pod 都处于运行状态。

  kubectl get pods --namespace tekton-pipelines

有关更多信息,请参阅 Tekton 文档。在完成这些步骤后,Kubernetes 集群即可运行 Tekton Pipeline。首先,我们来创建自定义资源的定义。

2. 创建管道资源

在本教程的示例中,应用程序、Dockerfile 和部署配置的源代码都位于您先前克隆的 GitHub 代码库中。

要创建用于访问 Git 代码库的输入管道资源,请执行以下操作:

git.yaml 文件中,通过执行以下操作来为 Git 代码库定义 PipelineResource

  • 将资源的 type 指定为 Git。
  • 提供 Git 代码库 URL 作为 url
  • 提供 revision 作为要使用的 Git 代码库分支的名称。

~/tekton-pipeline/resources/git.yaml 中提供了完整的 YAML 文件。将该文件应用于集群,如下所示。

  cd ~/tekton-pipeline
  kubectl apply -f resources/git.yaml

3. 创建任务

任务用于定义管道的步骤。为了使用 Git 代码库中的源代码将应用程序部署到集群中,我们定义了以下两个任务:build-image-from-sourcedeploy-to-cluster在任务定义中,将用作自变量 (args) 的参数称为 $(inputs.params.<var_name>)

定义 build-image-from-source

此任务包含以下两个步骤:

  1. list-src 步骤将列出所克隆的代码库中的源代码。这样做是为了验证是否正确克隆了源代码。
  2. build-and-push 步骤将使用 Dockerfile 构建容器镜像,并将所构建的镜像推送到容器注册表。在此示例中,我们使用 Kaniko 来构建并推送镜像。您可以使用 Kaniko、buildah、podman 等。Kaniko 使用 Dockerfile 名称、其位置和目标来将容器镜像作为自变量进行上传。

所有必需参数都是通过参数来传递的。使用以下命令来将该文件应用于集群:

  kubectl apply -f task/build-src-code.yaml

定义 deploy-to-cluster

现在,我们来使用所构建的容器镜像将应用程序部署到 pod 中,并使其成为一项服务,以便可以从任何地方进行访问。此任务将使用 ~/src/deploy.yaml 中的部署配置。

此任务包含以下两个步骤:

  1. update-yaml 步骤将更新容器镜像 URL,而不是 deploy.yaml 中的 IMAGE
  2. Deploy-app 步骤将应用程序部署到 Kubernetes pod 中,并使用 ~/src/deploy.yaml 将其作为一项服务公开。此步骤使用 kubectl 在 Kubernetes 集群上创建部署配置。

所有必需参数都是通过参数来传递的。

将该文件应用于集群,如下所示:

  kubectl apply -f task/deploy-to-cluster.yaml

4. 创建管道

管道将列出要执行的任务。它将提供每个任务所需的输入、输出资源和输入参数。如果任务之间存在任何依赖关系,也可以一并解决。

tekton-pipeline/resources/pipeline.yaml 中:

  • 管道使用了上述任务 build-image-from-sourcedeploy-to-cluster
  • 此处使用了 runAfter 关键字,因为必须逐个执行这些任务。
  • 通过 resources 关键字提供了管道资源(Git 代码库)。

所有必需参数都是通过参数来传递的。参数值在管道中定义为 $(params.imageUrl),这与任务定义中的 args 不同。按如下所示应用此配置:

  kubectl apply -f pipeline/pipeline.yaml

5. 创建管道运行

要执行管道,您需要一个 PipelineRun 资源定义,以用于传递所有必需参数。PipelineRun 将触发管道,而管道又会创建 TaskRuns,以此类推。以类似的方式,所有参数都会代入任务中。

如果在 PipelineRun 中未定义某个参数,那么将从资源定义本身的 spec 下的 params 中选取该参数的 默认值。例如,在任务 build-image-from-source 中使用了 pathToDockerfile 参数,但未在 pipeline-run.yaml 中提供该参数的值。因此,在执行任务期间,将使用 ~/tekton-pipeline/build-src-code.yaml 中定义的默认值。

PipelineRun 定义 tekton-pipeline/pipeline/pipeline-run.yaml 中:

  • 引用通过 pipeline.yaml 创建的管道 application-pipeline
  • 引用管道资源 git 作为输入。
  • params 下提供在执行管道和任务期间必需的参数值。
  • 指定服务帐户。

请注意,通过管道,可以将镜像推送到注册表并将其部署到集群中。您需要确保它具有足够的权限来访问容器注册表和集群。服务帐户将提供注册表的凭证。在执行 PipelineRun 之前,您需要定义一个服务帐户。

注意:暂时不要应用 PipelineRun 文件,因为您还需要为它定义服务帐户。

6. 创建服务帐户

要访问受保护的资源,请设置一个服务帐户,该帐户将使用密钥来创建或修改 Kubernetes 资源。将 IBM Cloud Kubernetes Service 配置为使用 IBM Cloud 身份和访问管理 (IAM) 角色。这些角色将决定用户可在 IBM Cloud Kubernetes 上执行的操作。

生成 API 密钥

要使用 IBM Cloud 仪表板生成 API 密钥,请遵照 IBM Cloud 文档中的说明进行操作。您还可以使用以下 CLI 命令来创建 API 密钥:

  ibmcloud iam api-key-create MyKey -d "this is my API key" --file key_file.json
  cat key_file.json | grep apikey

复制 apikey。您将在下一步中使用此密钥。

创建密钥

要创建密钥,请使用以下代码。APIKEY 是您创建的密钥,REGISTRY 是用于您的集群的注册表 API 端点。例如:us.icr.io

  kubectl create secret generic ibm-cr-secret --type="kubernetes.io/basic-auth" --from-literal=username=iamapikey --from-literal=password=<APIKEY>

  kubectl annotate secret ibm-cr-secret tekton.dev/docker-0=<REGISTRY>

这将创建一个名为 ibm-cr-secret 的密钥,然后便可以在服务帐户的配置文件中使用该密钥。

在配置文件 tekton-pipeline/pipeline/service-account.yaml 中:

  • ServiceAccount 资源使用了 ibm-cr-secret 密钥。
  • 根据密钥资源的定义,将使用服务帐户的 API 令牌来填充新构建的密钥。

下一步是定义角色。角色只能用于授予对单个名称空间内资源的访问权限。您必须在规则中包含相应的资源和 apiGroup,否则此操作将由于访问问题而失败。角色绑定可向一个或一组用户授予角色中定义的权限。它包含主题(用户、组或服务帐户)的列表以及对所授予角色的引用。

按如下所示应用此配置:

  kubectl apply -f pipeline/service-account.yaml

7. 执行管道

在执行 PipelineRun 之前,修改 tekton-pipeline/pipeline/pipelinerun.yaml 中的 imageUrlimageTag。请参考上面的“设置部署目标”部分,以确定镜像 URL 和镜像标记。如果镜像 URL 为 us.icr.io/test_namespace/sampleapp 并且镜像标记为 1.0,请将配置文件更新为:

  sed -i '' s#IMAGE_URL#us.icr.io/test_namespace/sampleapp# pipeline/pipelinerun.yaml
  sed -i '' s#IMAGE_TAG#1.0# pipeline/pipelinerun.yaml

现在,创建 PipelineRun 配置,如下所示:

  kubectl create -f pipeline/pipeline-run.yaml

这将创建一个管道并在终端上返回以下消息:

  pipelinerun.tekton.dev/application-pipeline-run created

检查新管道的状态:

  kubectl describe pipelinerun application-pipeline-run

您可能需要根据该状态来重新运行此命令。下面显示了中间状态:

Status:
  Conditions:
    Last Transition Time:  2020-07-09T08:43:53Z
    Message:               Tasks Completed: 0 (Failed: 0, Cancelled 0), Incomplete: 2, Skipped: 0
    Reason:                Running
    Status:                Unknown
    Type:                  Succeeded

   ...
   ...
Events:
   Type     Reason     Age     From     Message
   ----     ------     ---     ----     -------
   Normal Started 33s PipelineRun
   Normal Running 33s PipelineRun Tasks Completed: 0 (Failed: 0, Cancelled 0), Incomplete: 2, Skipped: 0

请注意消息“Tasks Completed: 0”。

在完成管道执行后,您应该会看到 describe 命令的输出,如下所示。

Events:
   Type     Reason     Age     From     Message
   ----     ------     ---     ----     -------
   Normal Started 2m33s PipelineRun
   Normal Running 2m33s PipelineRun Tasks Completed: 0 (Failed: 0, Cancelled 0), Incomplete: 2, Skipped: 0
   Normal Running 57s   PipelineRun Tasks Completed: 1 (Failed: 0, Cancelled 0), Incomplete: 1, Skipped: 0
   Normal Succeeded 43s PipelineRun Tasks Completed: 2 (Failed: 0, Cancelled 0), Skipped: 0

如果管道执行失败,那么将显示失败的任务。它还为您提供了可用于查看日志的其他详细信息。有关资源(例如,管道)的详细信息,请使用 kubectl describe 命令来获取更多信息。

  kubectl describe <resource> <resource-name>

8. 验证结果

要验证 pod 和服务是否按预期运行,请查看以下命令的输出:

  kubectl get pods
  # Output should be something like this
    NAME                                                                READY   STATUS      RESTARTS   AGE
    app-59dff7b655-7ggbt                                                1/1     Running     0          81s
    application-pipeline-run-build-image-from-source-2m62g-pod-f4eb96   0/3     Completed   0          119s
    application-pipeline-run-deploy-application-kg2jm-pod-89f884        0/3     Completed   0          89s

  kubectl get service
  # Output
    NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
    app          NodePort    xxx.xx.xx.xxx   <none>        3300:32426/TCP   4m51s

在成功执行 PipelineRun 之后,可通过 http://<public-ip-of-kubernetes-cluster>:32426/ 来访问该应用程序,您可以从 IBM Cloud 仪表板中检索 Kubernetes 集群的公共 IP,并在 deploy.yaml 中将端口 32426 定义为 nodePort

恭喜!您已使用 Tekton Pipeline 成功部署了该应用程序。您现在应该已掌握 Tekton Pipeline 的基础知识,并了解了如何开始构建自己的管道。另外还提供了其他功能,包括 Webhook 和基于 Web 的仪表板。我建议通过 IBM Cloud Kubernetes Service 来试用一下。

后续步骤

本教程展示了如何以及为何要使用 Tekton Pipeline 将应用程序部署到 Kubernetes 中。Tekton 包含在 IBM Cloud Pak for Applications 中,后者提供了一种更快更安全的方法来将业务应用程序迁移到云上支持容器的环境中。Cloud Pak for Applications 基于 Red Hat OpenShift 构建并受其支持。借助此开发者指南,探索并试用其他功能。

本文翻译自:Build and deploy a Hello World application on Kubernetes using a Tekton pipeline(2020-07-10)