Kubernetes上CD步骤指南

网友投稿 642 2022-11-03

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

Kubernetes上CD步骤指南

在阅读了官方文档和上网搜索之后,我开始感到不知所措。有太多的新概念需要学习:有pods,有容器,有副本集。对我来说,Kubernetes似乎是为一群复杂的开发者存在的。

然后我干了我在这种情况下经常做的事情。“撸起袖子加油实干”。对简单的例子的学习,理解了复杂的主题。最后,我独自成了部署过程。

最终,我们做到了,尽管远没有达到规定的7天内的目标--我们花了将近一个月的时间来创建三个集群(包括开发、测试和上线) 当你认识到我所在的升级团队是由三个彻头彻尾的Kubernetes小白组成的时候,这就不显得那么糟糕了。很难,但值得努力。

这篇文章是我当时希望看到的:一个详细的步骤,说明如何将一个应用程序部署到Kubernetes。在本文结束时,你将学到一个有效的Kubernetes部署和持续交付工作流程。

持续集成和交付

持续集成(CI)是在每次更新时构建和测试应用程序的做法。通过小规模的增量工作,错误会被更早地发现并及时解决。

一旦集成完成,所有测试都通过,我们就可以增加持续交付(CD),使发布和部署过程自动化。一个使用CI/CD的项目可以进行更频繁和可靠的发布。

我们将使用Semaphore,一个快速、强大和易于使用的持续集成和交付(CI/CD)平台来实现整个过程的自动化:

安工程依赖;运行单元测试;构建一个Docker镜像;推送镜像到Docker Hub;提供一键式Kubernetes部署。

对于这个应用程序,我们有一个暴露了一些HTTP端点的Ruby Sinatra微服务。该项目已经包含了部署所需的一切,但还需要编译。

准备工作

在动手之前,你需要注册一个GitHub和Semaphore账户。此外,为你的Docker镜像创建一个Docker Hub账号。

接下来,你应当在你的机器上安装这些工具:

Git:用来存放代码。

curl:网络瑞士军刀。

kubectl:用于远程控制你的集群。

当然,不要忘记Kubernetes。大多数云供应商都以这种或那种形式提供这种那种服务,所以要货比三家,看看什么款式适合你的需求。最低端的机器和集群规模足以运行我们的示例应用程序。我喜欢从一个三节点的集群开始,但你也可以只用一个节点。

集群准备好之后,从你的供应商那里下载kubeconfig文件。有些供应商让你直接从他们的网络控制台下载,而有些则需要辅助程序。我们将需要这个文件来连接到集群。

解决了这个问题,我们就可以开始了。要做的第一件事是fork版本库。

Fork代码仓库

fork我们使用的demo APP。

$ git clone https://github.com/your_repository_path...

用Semaphore连接你的新版本代码库:

使用Semaphore进行测试

持续集成使测试再次变得有趣和有效。一个经过深思熟虑的CI管道创造了一个简短的反馈回路,能够在错误造成任何损害之前及早发现。我们的工程有一些现成的测试。

打开位于.semaphore/semaphore.yml的初始管道文件,快速浏览一下。这个管道描述了Semaphore在构建和测试应用程序时必须遵循的所有步骤。它以名称和版本开始:

1 version:v1.0 2  name: CI

接下来是agent,即运行作业的虚拟机。我们有三种类型可供选择:

1 agent:  2 machine:    3 type:e1-standard-2    4 os_image:ubuntu1804

块、任务和作业定义了在流水线的每一步要做什么。在Semaphore上,区块是按顺序运行的,而区块内的作业是并行运行的。该流水线包含两个块--一个用于安装库,另一个用于运行测试:

第一块是下载和安装Ruby gems:

- name: Install dependencies task: jobs: - name: bundle install commands: - checkout - cache restore gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock),gems-$SEMAPHORE_GIT_BRANCH,gems-master - bundle install --deployment --path .bundle - cache store gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock) .bundle

Checkout从GitHub上克隆代码。由于每个作业都在一个完全隔离的机器中运行,我们必须依靠缓存来存储和检索作业运行之间的共享文件:

blocks: - name: Install dependencies task: jobs: - name: bundle install commands: - checkout - cache restore gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock),gems-$SEMAPHORE_GIT_BRANCH,gems-master - bundle install --deployment --path .bundle - cache store gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock) .bundle

第二块是用于测试。注意,我们重复checkout和cache,以使初始文件进入作业。最后的命令是启动RSpec测试套件:

- name: Tests task: jobs: - name: rspec commands: - checkout - cache restore gems-$SEMAPHORE_GIT_BRANCH-$(checksum Gemfile.lock),gems-$SEMAPHORE_GIT_BRANCH,gems-master - bundle install --deployment --path .bundle - bundle exec rspec

- name: Dockerizepipeline_file: docker-build.ymlauto_promote_on:- result: passed

工作流继续进入下一个管道。

构建Docker镜像

我们可以在Kubernetes中运行任何东西--只要它被打包成了Docker镜像。在本节中,我们将学习如何构建它。

我们的Docker镜像将包括Ruby、应用程序代码和所有的库。请看一下Dockerfile:

FROM ruby:2.5RUN apt-get update -qq && apt-get install -y build-essentialENV APP_HOME appRUN mkdir $APP_HOMEWORKDIR $APP_HOMEADD Gemfile* $APP_HOME/RUN bundle install --without development testADD . $APP_HOMEEXPOSE 4567 CMD ["bundle", "exec", "rackup", "--host", "0.0.0.0", "-p", "4567"]

Dockerfile,就像食谱一样,有构建容器镜像所需的所有步骤和命令:

从预先构建好的Ruby镜像开始。用apt-get安装构建工具。复制Gemfile,因为它有所有的依赖项。用bundle安装它们。复制应用程序的源代码。定义监听端口和启动命令。

我们将在Semaphore环境下烘烤我们的生产镜像。然而,如果你想在你的机器上做一个快速测试,请输入:

$ docker build . -t test-image

要在本地启动服务器,使用docker run并暴露内部端口4567:

$ docker run -p 4567:4567 test-image

你现在可以测试一个可用的HTTP端点。

$ curl -w "\n" localhost:4567hello world :))

在Semaphore中添加Docker Hub账户

Semaphore提供了一个安全机制来存储敏感信息,如密码、令牌或密钥。为了将镜像推送到你的Docker Hub注册中心,需要用你的用户名和密码创建一个Secret:

Docker管道的构建

这个pipeline构建并将镜像推送到Docker Hub。它只有一个块和一个作业:

这一次,我们可以使用更强的服务器,因为Docker往往更耗费资源。我们将选择中端机器e1-standard-4,有四个CPU,8GB内存和35GB磁盘:

version: v1.0name: Docker buildagent:machine:type: e1-standard-4os_image: ubuntu1804

构建从登录Docker Hub开始。用户名和密码是从我们刚刚创建的秘密中导入的。一旦登录,Docker可以直接访问注册表。

下一个命令是docker pull,尝试拉取镜像的最新版本。如果找到了这个镜像,Docker可能会重用它的一些层,加快构建速度。如果没有最新的镜像,那也没关系。只需要花点时间来构建。

最后,我们将推送新的镜像。注意这里我们使用SEMAPHORE_WORKFLOW_ID变量来唯一地标记图像:

blocks: - name: Build task: secrets: - name: dockerhubjobs: - name: Docker build commands: - echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin - checkout - docker pull "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:latest || true - docker build --cache-from "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:latest -t "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:$SEMAPHORE_WORKFLOW_ID . - docker images - docker push "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:$SEMAPHORE_WORKFLOW_ID

镜像准备好了,下一步进入工程交付阶段。我们将用手动晋级来扩展我们的管道:

Semaphorepromotions:- name: Deploy to Kubernetespipeline_file: deploy-k8s.yml

进行第一次自动构建,做一个推送:

$ touch test-build$ git add test-build$ git commit -m "initial run on Semaphore“$ git push origin master

镜像准备好后,我们可以跳到部署阶段。

部署到Kubernetes

自动部署是Kubernetes的强项。我们只需要告诉集群我们最终想要的状态,它就会处理剩下的事情。

然而,在进行部署之前,你必须将kubeconfig文件上传到Semaphore。

将Kubeconfig添加到Semaphore中

我们需要第二个Secrets:集群的kubeconfig。该文件授予集群管理权限。因此,我们不希望该文件被签出到存代码库中。

创建一个名为do-k8s的Secrets,并将kubeconfig文件上传至/home/semaphore/.kube/dok8s.yaml:

部署清单

尽管Kubernetes是一个容器编排平台,但我们并不直接管理容器。事实上,部署单元是pod。一个pod就像一群快乐的朋友,总是一起去同一个地方。一个pod中的容器被保证运行在同一个节点上,并且拥有相同的IP。它们总是一致地启动和停止,而且,由于它们运行在同一台机器上,它们可以共享资源。

PODS的问题是,它们可以在任何时候启动和停止,而且我们不能确定它们会被分配到什么IP。为了路由来自用户的HTTP流量,我们还需要一个负载平衡服务;它负责跟踪pod并转发传入的连接,因此,从客户的角度来看,总是有一个固定的公共IP。

打开位于deployment.yml的文件。这是用于部署我们的应用程序的清单。它有两个资源,用三个破折号隔开。首先是部署:

apiVersion: apps/v1kind: Deploymentmetadata:name: semaphore-demo-ruby-kubernetesspec:replicas: 1selector:matchLabels:app: semaphore-demo-ruby-kubernetestemplate:metadata:labels:app: semaphore-demo-ruby-kubernetesspec:containers:- name: semaphore-demo-ruby-kubernetesimage: $DOCKER_USERNAME/semaphore-demo-ruby-kubernetes:$SEMAPHORE_WORKFLOW_ID

这里有几个概念需要解读:

资源可以有一个名字和几个标签,这样便于组织和编排。Spec定义了期望的最终状态,模板是用来创建pod的模型。Replicas设置要创建多少个pod的副本。我们通常将其设置为集群中的节点数量。由于我使用的是三个节点,我将把这一行配置为3副本.

第二个资源是service。它绑定到80端口,并将HTTP流量转发到部署的pod中:

---apiVersion: v1kind: Servicemetadata:name: semaphore-demo-ruby-kubernetes-lbspec:selector:app: semaphore-demo-ruby-kubernetestype: LoadBalancerports:- port: 80targetPort: 4567

Kubernetes将选择器与标签进行匹配,以连接服务与pod。因此,我们可以在同一个集群中拥有许多services和deployments,并根据需要连接它们。

Deployment管道

我们正在进入CI/CD配置的最后阶段。此时,我们在semaphore.yml中定义了一个CI管道,在docker-build.yml中定义了Docker管道。现在,我们部署到Kubernetes。

打开位于.semaphore/deploy-k8s.yml的部署管道。如常启动:

version: v1.0name: Deploy to Kubernetesagent:machine:type: e1-standard-2os_image: ubuntu1804

两项工作构成了最后一条管道:

一号job启动部署。在导入kubeconfig文件后,envsubst将deployment.yml中的占位变量替换为其实际值。然后,kubectl apply将清单发送至集群:

blocks: - name: Deploy to Kubernetes task: secrets: - name: do-k8s - name: dockerhub env_vars: - name: KUBECONFIGvalue: home/semaphore/.kube/dok8s.yaml jobs: - name: Deploy commands: - checkout - kubectl get nodes - kubectl get pods - envsubst < deployment.yml | tee deployment.yml - kubectl apply -f deployment.yml

第二项job将镜像标记为最新的,这样我们就可以在下一次运行时将其作为缓存使用:

name: Tag latest release task: secrets: - name: dockerhubjobs: - name: docker tag latest commands: - echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin - docker pull "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:$SEMAPHORE_WORKFLOW_ID - docker tag "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:$SEMAPHORE_WORKFLOW_ID "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:latest - docker push "${DOCKER_USERNAME}"/semaphore-demo-ruby-kubernetes:latest

到这里作业流程就结束了。我们准备好了,可以试一试。

部署应用程序

让我们来教Sinatra应用程序唱歌。在app.rb的App类中添加以下代码:

get "/sing" do"And now, the end is near And so I face the final curtain..."end

推送修改后的文件到GitHub

$ git add .semaphore/*$ git add deployment.yml$ git add app.rb$ git commit -m "test deployment”$ git push origin master

等待docker构建管道执行完成;你可以在Semaphore上查看进度:

现在是部署的时候了。按下 "Promote "按钮。成功了吗?

我们已经有了一个良好的开端。现在就看Kubernetes了。我们可以用kubectl检查部署状态。最初的状态是需要三个pods,但0个可用:

$ kubectl get deploymentsNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEsemaphore-demo-ruby-kubernetes 3 0 0 0 15m

几秒钟后,PODS已经启动,校准完成:

$ kubectl get deploymentsNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEsemaphore-demo-ruby-kubernetes 3 3 3 3 15m

要获得集群的一般状态,使用get all。它显示pods、服务、部署和复本集:

$ kubectl get allNAME READY STATUS RESTARTS AGEpod/semaphore-demo-ruby-kubernetes-7d985f8b7c-454dh 1/1 Running 0 2mpod/semaphore-demo-ruby-kubernetes-7d985f8b7c-4pdqp 1/1 Running 0 119spod/semaphore-demo-ruby-kubernetes-7d985f8b7c-9wsgk 1/1 Running 0 2m34s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/kubernetes ClusterIP 10.12.0.1 443/TCP 24mservice/semaphore-demo-ruby-kubernetes-lb   LoadBalancer   10.12.15.50   35.232.70.45   80:31354/TCP   17m NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEdeployment.apps/semaphore-demo-ruby-kubernetes   3         3         3            3           17mNAME DESIRED CURRENT READY AGEreplicaset.apps/semaphore-demo-ruby-kubernetes-7d985f8b7c 3 3 3 2m36s

服务IP显示在pods之后。这里,负载平衡器被分配了外部IP 35.232.70.45。用你的供应商分配给你的那个来替换它。让我们试试新的服务器。

你会为我们唱歌吗?

$ curl -w "\n" http://YOUR_EXTERNAL_IP/sing

现在,结束了......音乐会落下帷幕......

尾声

部署到Kubernetes并不一定困难或痛苦,如果有正确的CI/CD解决方案的支持,就简单了。现在你拥有了一个到Kubernetes的完全自动化的持续交付管道。

欢迎在你的Kubernetes实例上使用semaphore-demo-ruby-kubernetes。这里有一些想法:

创建一个暂存集群;构建一个开发容器并在其中运行测试;用更多的微服务来扩展这个项目。

上一篇:软件测试培训之手工测试迷茫应该如何调整自己
下一篇:软件测试培训之小谈验收测试
相关文章

 发表评论

暂时没有评论,来抢沙发吧~