写点什么

Step by Step!Kubernetes 持续部署指南

  • 2020-05-18
  • 本文字数:6936 字

    阅读完需:约 23 分钟

Step by Step!Kubernetes持续部署指南

在很久很久以前的一份工作中,我的任务是将老式的 LAMP 堆栈切换到 Kubernetes 上。那会儿我的老板总是追逐新技术,认为只需要几天时间就能够完成新旧技术的迭代——鉴于那时我们甚至对容器的工作机制一无所知,所以不得不说老板的想法真的很大胆。


在阅读了官方文档并且搜索了很多信息之后,我们开始感到不知所措——有许多新的概念需要学习:pod、容器以及 replica 等。对我而言,Kubernetes 似乎只是为一群聪明的开发者而设计的。


然后我做了我在这一状况下常做的事:通过实践来学习。通过一个简单的例子可以很好地理解错综复杂的问题,所以我自己一步一步完成了整个部署过程。


最后,我们做到了,虽然远未达到规定的一周时间——我们花了将近一个月的时间来创建三个集群,包括它们的开发、测试和生产。


本文我将详细介绍如何将应用程序部署到 Kubernetes。阅读完本文之后,你将拥有一个高效的 Kubernetes 部署和持续交付工作流程。

持续集成与交付

持续集成是在每次应用程序更新时构建和测试的实践。通过以少量的工作,更早地检测到错误并立即解决。


集成完成并且所有测试都通过之后,我们就能够添加持续交付到自动化发布和部署的流程中。使用 CI/CD 的项目可以更频繁、更可靠地发布。


我们将使用 Semaphore,这是一个快速、强大且易用地持续集成和交付(CI/CD)平台,它能够自动执行所有流程:


1、 安装项目依赖项


2、 运行单元测试


3、 构建一个 Docker 镜像


4、 Push 镜像到 Docker Hub


5、 一键 Kubernetes 部署


对于应用程序,我们有一个 Ruby Sinatra 微服务,它暴露一些 HTTP 端点。该项目已包含部署所需的所有内容,但仍需要一些组件。

准备工作

在开始操作之前,你需要登录 Github 和 Semaphore 账号。此外,为后续方便拉取或 push Docker 镜像,你需要登录 Docker Hub。


接下来,你需要在计算机上安装一些工具:


  • Git:处理代码

  • curl:网络的“瑞士军刀”

  • kubectl:远程控制你的集群


当然,千万不要忘了 Kubernetes。大部分的云供应商都以各种形式提供此服务,选择适合你的需求的即可。最低端的机器配置和集群大小足以运行我们示例的 app。我喜欢从 3 个节点的集群开始,但你可以只用 1 个节点的集群。


集群准备好之后,从你的供应商中下载 kubeconfig 文件。有些允许你直接从其 web 控制台下载,有些则需要帮助程序。我们需要此文件才能连接到集群。


有了这个,我们已经可以开始了。首先要做的是 fork 存储库。

Fork 存储库

在这篇文章中 fork 我们将使用的演示应用程序。


  1. 访问 semaphore-demo-ruby-kubernetes 存储库,并且点击右上方的 Fork 按钮

  2. 点击 Clone or download 按钮并且复制地址

  3. 复制存储库:


$ git clone https://github.com/your_repository_path…
复制代码


使用 Semaphore 连接新的存储库


1、 登录到你的 Semaphore


2、 点击侧边栏的链接,创建一个新项目


3、 点击你的存储库旁【 Add Repository 】按钮

使用 Semaphore 测试

持续集成让测试变得有趣并且高效。一个完善的 CI 流水线能够创建一个快速反馈回路以在造成任何损失之前发现错误。我们的项目附带一些现成的测试。


打开位于.semaphore/semaphore.yml 的初始流水线文件,并快速查看。这个流水线描述了 Semaphore 构建和测试应用程序所应遵循的所有步骤。它从版本和名称开始。


version: v1.0name: CI
复制代码


接下来是 agent,它是为 job 提供动力的虚拟机。我们可以从 3 种类型中选择:


agent:  machine:    type: e1-standard-2    os_image: ubuntu1804
复制代码


Block(块)、任务以及 job 定义了在流水线的每个步骤中要执行的操作。在 Semaphore,block 按照顺序运行,与此同时,在 block 中的 job 也会并行运行。流水线包含 2 个 block,一个是用于库安装,一个用于运行测试。



第一个 block 下载并安装了 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 里的代码。既然每个 job 都在完全隔离的机器里运行,那么我们必须依赖缓存(cache)来在 job 运行之间存储和检索文件。


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
复制代码


第二个 block 进行测试。请注意我们重复使用了 checkout 和 cache 的代码以将初始文件放入 job 中。最后一个命令用于启动 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
复制代码


最后一个部分我们来看看 Promotion。Promotion 能够在一定条件下连接流水线以创建复杂的工作流程。所有 job 完成之后,我们使用 auto_promote_on 来启动下一个流水线。


promotions:  - name: Dockerize    pipeline_file: docker-build.yml    auto_promote_on:      - result: passed
复制代码


工作流程继续执行下一个流水线。

构建 Docker 镜像

我们可以在 Kubernetes 上运行任何东西,只要它打包在 Docker 镜像中。在这一部分,我们将学习如何构建镜像。


我们的 Docker 镜像将包含应用程序的代码、Ruby 以及所有的库。让我们先来看一下 Dockerfile:


FROM ruby:2.5 RUN apt-get update -qq && apt-get install -y build-essential ENV APP_HOME /appRUN mkdir $APP_HOMEWORKDIR $APP_HOME ADD Gemfile* $APP_HOME/RUN bundle install --without development test ADD . $APP_HOME EXPOSE 4567 CMD ["bundle", "exec", "rackup", "--host", "0.0.0.0", "-p", "4567"]
复制代码


Dockerfile 就像一个详细的菜谱,包含所有构建容器镜像所需要的步骤和命令:


1、 从预构建的 ruby 镜像开始


2、 使用 apt-get 安装构建工具


3、 复制 Gemfile,因为它具有所有的依赖项


4、 用 bundle 安装它们


5、 复制 app 的源代码


6、 定义监听端口和启动命令


我们将在 Semaphore 环境中 bake 我们的生产镜像。然而,如果你想要在计算机上进行一个快速的测试,那么请输入:


$ docker build . -t test-image
复制代码


使用 Docker 运行和暴露内部端口 4567 以在本地启动服务器:


$ docker run -p 4567:4567 test-image
复制代码


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


$ curl -w "\n" localhost:4567hello world :))
复制代码

添加 Docker Hub 账户到 Semaphore

Semaphore 有一个安全的机制以存储敏感信息,如密码、令牌或密钥等。为了能够 push 镜像到你的 Docker Hub 镜像仓库中,你需要使用你的用户名和密码来创建一个 Secret:


  1. 打开你的 Semaphore

  2. 在左侧导航栏中,点击【 Secret

  3. 点击【 Creat New Secret

  4. Secret 的名字应该是 Dockerhub,键入登录信息(如下图所示),并保存。


构建 Docker 流水线

这个流水线开始构建并且 push 镜像到 Docker Hub,它仅仅有 1 个 block 和 1 个 job:



这次,我们需要使用更好的性能,因为 Docker 往往更加耗费资源。我们选择具有四个 CPU,8GB RAM 和 35GB 磁盘空间的中端机器 e1-standard-4:


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


构建 block 通过登录到 Docker Hub 启动,用户名和密码可以从我们刚创建的 secret 导入。登录之后,Docker 可以直接访问镜像仓库。


下一个命令是 docker pull,它试图拉取最新镜像。如果找到镜像,那么 Docker 可能能够重新使用其中的一些层,以加速构建过程。如果没有最新镜像,也无需担心,只是需要花费长一点的时间来构建。


最后,我们 push 新的镜像。注意,这里我们使用 SEMAPHORE_WORKFLOW_ID 变量来标记镜像。


blocks:  - name: Build    task:      secrets:        - name: dockerhub      jobs:      - 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
复制代码


当镜像准备完毕,我们进入项目的交付阶段。我们将用手动 promotion 来扩展我们的 Semaphore 流水线。


promotions:  - name: Deploy to Kubernetes    pipeline_file: deploy-k8s.yml
复制代码


要进行第一次自动构建,请进行 push:


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


镜像准备完成之后,我们就可以进入部署阶段。

部署到 Kubernetes

自动部署是 Kubernetes 的强项。我们所需要做的就是告诉集群我们最终的期望状态,剩下的将由它来负责。


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

上传 Kubeconfig 到 Semaphore

我们需要第二个 secret:集群的 kubeconfig。这个文件授予可以对它的管理访问权限。因此,我们不希望将文件签入存储库。


创建一个名为 do-k8s 的 secret 并且将 kubeconfig 文件上传到/home/semaphore/.kube/dok8s.yaml 中:


部署清单

尽管 Kubernetes 已经是容器编排平台,但是我们不直接管理容器。实际上,部署的最小单元是 pod。一个 pod 就好像一群形影不离的朋友,总是一起去同一个地方。因此要保证在 pod 中的容器运行在同一个节点上并且有相同的 IP。它们可以同步启动和停止,并且由于它们在同一台机器上运行,因此它们可以共享资源。


pod 的问题在于它们可以随时启动和停止,我们没办法确定它们会被分配到的 pod IP。要把用户的 http 流量转发,还需要提供一个公共 IP 和一个负载均衡器,它负责跟踪 pod 和转发客户端的流量。


打开位于 deploymente.yml 的文件。这是一个部署我们应用程序的清单,它被 3 个 dash 分离成两个资源。第一个,部署资源:


apiVersion: apps/v1kind: Deploymentmetadata:  name: semaphore-demo-ruby-kubernetesspec:  replicas: 1  selector:    matchLabels:      app: semaphore-demo-ruby-kubernetes  template:    metadata:      labels:        app: semaphore-demo-ruby-kubernetes    spec:      containers:        - name: semaphore-demo-ruby-kubernetes          image: $DOCKER_USERNAME/semaphore-demo-ruby-kubernetes:$SEMAPHORE_WORKFLOW_ID
复制代码


这里有几个概念需要厘清:


  • 资源都有一个名称和几个标签,以便组织

  • Spec 定义了最终期望的状态,template 是用于创建 Pod 的模型。

  • Replica 设置要创建的 pod 的副本数。我们经常将其设置为集群中的节点数。既然我们使用了 3 个节点,我将这一命令行更改为 replicas:3


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


--- apiVersion: v1kind: Servicemetadata:  name: semaphore-demo-ruby-kubernetes-lbspec:  selector:    app: semaphore-demo-ruby-kubernetes  type: LoadBalancer  ports:    - port: 80      targetPort: 4567
复制代码


Kubernetes 将 selector 与标签相匹配以便将服务与 pod 连接起来。因此,我们在同一个集群中有许多服务和部署并且根据需要连接他们。

部署流水线

我们现在进入 CI/CD 配置的最后一个阶段。这时,我们有一个定义在 semaphore.yml 的 CI 流水线,以及定义在 docker-build.yml 的 Docker 流水线。在这一步中,我们将部署到 Kubernetes。


打开位于.semaphore/deploy-k8s.yml 的部署流水线:


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


两个 job 组成最后的流水线:



Job 1 开始部署。导入 kubeconfig 文件之后,envsubst 将 deployment.yaml 中的占位符变量替换为其实际值。然后,kubectl apply 将清单发送到集群。


blocks:  - name: Deploy to Kubernetes    task:      secrets:        - name: do-k8s        - name: dockerhub       env_vars:        - name: KUBECONFIG          value: /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 2 将镜像标记为最新,以让我们能够在下一次运行中将其作为缓存使用。


- name: Tag latest release  task:    secrets:      - name: dockerhub    jobs:    - 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 检查部署状态,初始状态是三个所需的 pod 并且零可用:


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


几秒之后,pod 已经启动,reconciliation 已经完成:


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


使用 get all 获得集群的通用状态,它显示了 pod、服务、部署以及 replica:


$ 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           17m NAME                                                        DESIRED   CURRENT   READY   AGEreplicaset.apps/semaphore-demo-ruby-kubernetes-7d985f8b7c   3         3         3       2m3
复制代码


Service IP 在 pod 之后展示。对于我来说,负载均衡器被分配到外部 IP 35.232.70.45。需要将其更改为你的提供商分配给你的那个,然后我们来试试新的服务器。


$ curl -w "\n" http://YOUR_EXTERNAL_IP/sing
复制代码


现在,离结束已经不远了。

胜利近在咫尺

当你使用了正确的 CI/CD 解决方案之后,部署到 Kubernetes 并不是那么困难。你现在拥有一个 Kubernetes 的完全自动的持续交付流水线啦。


这里有几个建议可以让你在 Kubernetes 上随意 fork 并玩转 semaphore-demo-ruby-kubernetes:


  • 创建一个 staging 集群

  • 构建一个部署容器并且在里面运行测试

  • 使用更多微服务扩展项目


2020-05-18 17:59759

评论

发布
暂无评论
发现更多内容

AI在职场:如何通过人工智能提升工作效率

幂简集成

人工智能 API

鸿蒙安全控件之粘贴控件简介

龙儿筝

CST软件如何使用Poser人体摆姿势

思茂信息

cst cst使用教程 CST软件

“老爷机”训不动Lora?一台云电脑就可以让你轻松炼丹

Finovy Cloud

LoRa 云电脑

【JIT/极态云】技术文档--标准组织

武汉万云网络科技有限公司

低代码

荣誉再加码!天翼云揽获SD-WAN & SASE大会两项大奖!

科技热闻

探索 Go 语言中的内存对齐:为什么结构体大小会有所不同?

左诗右码

Go

携手上海证券,共同见证市场活跃背景下交易服务新趋势

非凸科技

上海证券 非凸科技

【GreatSQL优化器-04】贪婪搜索算法浅析

GreatSQL

【等保小知识】信息系统怎么定义?等保测评多久一次?

行云管家

信息系统 等保 等保测评

HyperWorks基于 Shrink Warp Mesh 的零部件网格剖分

智造软件

仿真 仿真软件 Hypermesh

企业采购比价:品牌采购时借用淘宝商品详情接口来采购比价

tbapi

淘宝商品详情接口

工程项目管理系统

深圳亥时科技

【创新视角】解锁淘宝商品详情API:让商品主图与详情图“跃然屏上”,重塑购物体验魅力!

代码忍者

API 接口 pinduoduo API

⭐️ GitHub Star 数量前十的工作流项目

NocoBase

GitHub 开源 工作流 工作流引擎 工作流自动化

山西省等保测评公司名单【2025】

行云管家

网络安全 等保 山西

拼多多商品评价API的获取与应用

科普小能手

拼多多 API API 接口 拼多多商品详情接口 拼多多API

【线上发布会预约中】资源有限,性能无限:GreptimeDB Edge 赋能车端数据处理新高度

Greptime 格睿科技

数据库 汽车 性能报告

如何设置自动化测试断言?

老张

软件测试 自动化测试 接口测试 质量保障

淘宝API接口探索:图片搜索拍立淘与商品评论的深度挖掘

代码忍者

API 接口 pinduoduo API

『OpenCV-Python』视频的读取和保存

德育处主任

OpenCV

智能车间管理系统(源码+文档+部署+讲解)

深圳亥时科技

全球司库 | 科学掌握企业融资债券数据信息,需从这几个维度展开!

用友智能财务

财务 企业数智化 司库

端侧AI,风起移动智能计算

脑极体

芯片

【JIT/极态云】技术文档--钉钉自建组织

武汉万云网络科技有限公司

低代码

Step by Step!Kubernetes持续部署指南_文化 & 方法_Rancher_InfoQ精选文章