在本文中,我们将使用示例微服务应用程序VotingApp来说明可在Kubernetes集群中部署应用程序的几种方式:
- 使用Yaml规范
- 通过Helm chart
- 使用Kustomize
VotingApp
VotingApp是由Docker创建的应用程序,它主要是用来说明docker和Kubernetes的功能。该应用程序遵循微服务架构,由五个服务组成,如下图所示。
VotingApp的整体架构
该应用程序通常用于演示和演示,这是一个很好的示例,因为它使用了多种语言和数据库技术:
- vote:使用Python开发的前端,允许用户在猫和狗之间进行选择
- redis:存储投票的数据库
- worker:从Redis获得投票并将结果存储在Postgres数据库中的服务。该服务存在Java和.NET两个版本
- db:Postgres数据库,worker在该数据库中合并票数
- result:Node.js开发的前端,用于显示结果
原始应用程序托管在GitHub中,本文所用到的,使用3种不同的方式定义该应用程序 的配置在公众号云原生的github代码库里:
- 使用Yaml规范
- 通过helm chart
- 通过kustomize结构
在下文中,我们将使用这三种方式来部署VotingApp,并说明它们之间的区别。
设置演示集群
首先,我们将在本地计算机上快速设置一个Kubernetes集群。在本地运行Kubernetes真的很容易,因为那里有许多可用的解决方案。仅举几个:
- k0s
- k3s
- microK8s
- miniKube
- kind
在本文中,我们使用最新版本的k0s(2021年4月为0.12),并使用vagrant和VirtualBox进行安装。
首先,我们创建一个新文件夹,并Vagrantfile
在其中添加以下内容。
Vagrant.configure("2") do |config| config.vm.box = "hashicorp/bionic64" config.vm.network "private_network", ip: "192.168.33.11" config.vm.provision "shell", inline: <<-SHELL curl -sSLf https://get.k0s.sh | sudo sh sudo k0s install controller --single sudo systemctl start k0scontroller.service SHELL end
接下来,在该文件夹中,运行以下命令,以创建一个VM并在其中安装k0s:
$ vagrant up
接下来,我们在这个新创建的VM中运行一个root shell:
$ vagrant ssh
vagrant @ vagrant:〜$ sudo su- root @ vagrant:〜#
使用k0s附带的客户端kubectl
,我们可以使用以下命令查看我们的单节点集群(节点进入“Ready ”状态大约需要一分钟):
# k0s kubectl get nodes
NAME STATUS ROLES AGE VERSION
vagrant Ready <none> 40s v1.20.5-k0s1
然后,在公众号云原生的github代码库里找到配置文件,在20210403
目录下
下一步,我们将使用原始Yaml规范部署VotingApp。
Yaml规格
该清单文件夹中包含了每个微服务的yaml:
# tree manifests/ manifests/ ├── db-deployment.yaml ├── db-service.yaml ├── redis-deployment.yaml ├── redis-service.yaml ├── result-deployment.yaml ├── result-service.yaml ├── vote-deployment.yaml ├── vote-service.yaml └── worker-deployment.yaml
vote
,result
,redis
和db
都有一个Deployment
和Service
资源worker
仅具有一种Deployment
资源,因为它不需要公开:worker
是一种连接redis
和db
的启动服务
以下命令使用yaml所有创建应用程序:
#k0s kubectl apply -f manifests/
注意:该命令kubectl apply -f
会作用于该文件夹的所有yaml
同样我们需要确保一切正常:
# k0s kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/worker 1/1 1 1 102s deployment.apps/db 1/1 1 1 103s deployment.apps/result 1/1 1 1 102s deployment.apps/vote 1/1 1 1 102s deployment.apps/redis 1/1 1 1 102s
然后,我们可以使用VM的IP以及在vote-service.yaml和result-service.yaml中指定的nodePort来访问Web界面:vote
可在端口31001,端口31001result
上访问。我们可以对项目进行投票并查看结果,确认整个应用程序运行良好。
使用原始 manifests部署VotingApp
然后可以使用以下命令删除该应用程序:
# k0s kubectl delete -f manifests
使用yaml清单直接部署应用程序很简单,但是它不提供方便的功能来完全管理应用程序的生命周期或动态配置应用程序(Helm真正发挥作用的领域)。
Helm
通过Helm,我们可以管理(定义,安装,升级)复杂的Kubernetes应用程序。通过Chart的概念,该工具可以轻松地创建,版本控制,共享和发布整个应用程序,Chart是一个包含整个应用程序规范的软件包。Helm还提供了一种模板语言来动态配置应用程序。
在配置库中,helm文件夹包含VotingApp的最简单图表。
# tree helm helm ├── Chart.yaml ├── templates │ ├── db-deployment.yaml │ ├── db-service.yaml │ ├── _helpers.tpl │ ├── redis-deployment.yaml │ ├── redis-service.yaml │ ├── result-deployment.yaml │ ├── result-service.yaml │ ├── vote-deployment.yaml │ ├── vote-service.yaml │ └── worker-deployment.yaml └── values.yaml
该模板文件夹中包含相当多,我们在上一步中使用(当我们部署了从应用程序的同一规格清单文件夹),除了几件事情:
vote
和result
服务使用heml模板语言来定义nodePort而不是使用文本值。每个值都是对values.yaml中定义的值的引用(稍后会对此进行详细介绍):
# cat templates/vote-service.yaml apiVersion: v1 kind: Service metadata: labels: app: vote name: vote spec: type: NodePort ports: - name: "vote-service" port: 5000 targetPort: 80 nodePort: {{ .Values.vote.port }} selector: app: vote # cat templates/result-service.yaml apiVersion: v1 kind: Service metadata: labels: app: result name: result spec: type: NodePort ports: - name: "result-service" port: 5001 targetPort: 80 nodePort: {{ .Values.result.port }} selector: app: result
- heml模板还用于
worker
指定用于此特定服务的图像(版本Java
和.NET
版本均可用):
# cat templates/worker-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: worker name: worker spec: replicas: 1 selector: matchLabels: app: worker template: metadata: labels: app: worker spec: containers: - image: {{ .Values.worker.image }} name: worker
- 在以上模板中引用的值在values.yaml中定义:
# cat values.yaml vote: port: 31002 result: port: 31003 worker: image: lucj/voting:worker.java
现在让我们使用Helm部署VotingApp。
首先,我们需要helm
按照以下说明安装二进制文件
接下来,我们voting
在helm
文件夹中运行以下命令来创建发行版的第一个修订版:
# helm upgrade voting --install --values values.yaml .
我们得到的结果类似于以下内容:
Release "voting" does not exist. Installing it now. NAME: voting LAST DEPLOYED: Wed Mar 31 21:02:07 2021 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None
在后台,helm读取templates
文件夹中的规范,使用来自values.yaml的值创建真实的Yaml清单(Kubernetes可以执行),并要求API服务器创建相应的资源。
创建发行版的第一个修订版后,我们确保所有Pod都处于“运行”状态,以确保一切运行良好:
# k0s kubectl get deploy,pod NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/worker 1/1 1 1 24s deployment.apps/vote 1/1 1 1 24s deployment.apps/db 1/1 1 1 24s deployment.apps/redis 1/1 1 1 24s deployment.apps/result 1/1 1 1 24s NAME READY STATUS RESTARTS AGE pod/db-684b9b49fd-t7k74 1/1 Running 0 23s pod/vote-767f6d6d79-5qlhd 1/1 Running 0 23s pod/worker-79bb99bfc6-jhn5r 1/1 Running 0 23s pod/redis-67db9bd79b-99vs2 1/1 Running 0 23s pod/result-8cfbc4889-c4z8c 1/1 Running 0 23s
然后,我们可以使用VM的IP和values.yaml中指定的nodePort(用于的31002,用于的31003 )访问vote
andresult
接口vote``result
使用Helm部署VotingApp
默认情况下worker使用java版本,我们可以通过查看worker规范来验证这一点:
# k0s kubectl get deploy/worker \
-o jsonpath="{ .spec.template.spec.containers[0].image }"
lucj/voting:worker.java
如果我们想尝试一下dotnet
版本,我们只需要升级发行版以提供我们想要更改的值,此操作将创建一个新的修订版:
# helm upgrade voting --set worker.image=lucj/voting:worker.dotnet .
然后,我们确保已正确更新部署,并且现在使用dotnet
映像的版本:
# k0s kubectl get deploy/worker \
-o jsonpath="{ .spec.template.spec.containers[0].image }"
lucj/voting:worker.dotnet
通过访问vote
和result
Web界面,我们可以轻松地验证此新修订版本是否按预期工作。
如果我们想回到以前的版本,Helm也可以通过rollback
使用以前的值创建该发行版的新修订的命令来提供帮助:
# helm rollback voting Rollback was a success! Happy Helming!
再一次,我们可以验证worker的java
镜像已经被使用,并且该应用程序可以正常工作。
然后,我们可以删除该应用程序:
# helm uninstall voting
我们仅通过一个简单的示例对Helm进行了说明,并使用了模板语言定义了几个属性,但是Helm确实具有更多功能,如您在文档中所看到的。在下一步中,我们将说明如何使用Kustomize部署应用程序。
Kustomize
Kustomize引入了一种无模板的方式来定制应用程序配置。它既可以作为独立二进制文件,也可以作为native功能使用kubectl
。它基本上从yaml规范列表中定义了一个基准,并允许我们使用其他资源来重载该基准。让我们看看在VotingApp的上下文中这是如何工作的。
在配置库中,kustomize文件夹包含2个子文件夹:
# tree kustomize kustomize/ ├── base │ ├── db-deployment.yaml │ ├── db-service.yaml │ ├── kustomization.yaml │ ├── redis-deployment.yaml │ ├── redis-service.yaml │ ├── result-deployment.yaml │ ├── result-service.yaml │ ├── vote-deployment.yaml │ ├── vote-service.yaml │ └── worker-deployment.yaml └── overlays └── demo ├── front-services.yaml ├── kustomization.yaml └── vote-ns.yaml
- 该
base
子文件夹包含我们部署原始heml应用时我们所使用的那些YAML规范。该文件夹还包含kustomization.yaml
基本上列出了构成基线的规范的文件夹。
# cat base/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - db-deployment.yaml - db-service.yaml - redis-deployment.yaml - redis-service.yaml - result-deployment.yaml - result-service.yaml - vote-deployment.yaml - vote-service.yaml - worker-deployment.yaml
以下命令使用标准来部署此基准,kubectl apply
但使用的是-k
标志:
#k0s kubectl apply -k base /
在这里,我们可以检查所有Pod是否运行良好并可以与VotingApp一起运行:为我们最喜欢的动物投票并查看结果。
然后,我们可以使用相同的-k
标志删除该应用程序:
#k0s kubectl delete -k base /
base
文件夹旁边是overlays
文件夹,其中包含一个demo
子文件夹。最后一个包含几个文件,这些文件用于使base
文件夹中现有的内容超载。基本上,从overlays/demo
文件夹中部署应用程序就像使用来自基线的资源,对其进行修改,然后根据这些更改运行新版本的应用程序
该demo
文件夹包含一个定义vote
名称空间的规范,
# cat overlays/demo/vote-ns.yaml apiVersion: v1 kind: Namespace metadata: name: vote
另一个规范front-services.yaml用于重载vote
和result
服务,以重新定义nodePort的值,
# cat overlays/demo/front-services.yaml apiVersion: v1 kind: Service metadata: name: vote spec: ports: - name: "vote-service" port: 5000 targetPort: 80 nodePort: 31010 --- apiVersion: v1 kind: Service metadata: name: result spec: ports: - name: "result-service" port: 5001 targetPort: 80 nodePort: 31011
最后,该kustomization.yaml
文件定义了从demo
文件夹部署应用程序时要考虑的资源:使用了基本清单,将投票清单添加到此列表,应用了战略合并来修改端口号,并且整个应用程序是进入vote
命名空间。
# cat overlays/demo/kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization bases: - ../../base resources: - vote-ns.yaml namespace: vote patchesStrategicMerge: - front-services.yaml
以下命令从overlays / demo部署VotingApp folder
:
#k0s kubectl apply -k overlays / demo /
然后,我们可以访问VotingApp并再次投票选出我们最喜欢的动物。该vote
接口在端口31010上可用,而在端口31011上则可用result
。
通过Kustomize通过overlays/demo部署VotingApp
完成后,我们可以-k
使用用于创建的相同标志删除应用程序。
#k0s kubectl delete -k base /
关键要点
在本文中,我们概述了可以在Kubernetes中部署应用程序的主要方式:
- 使用原始Yaml specifications是管理应用程序的最简单但配置更少的方法
- Heml是一种更可配置的方法。它使用模板语言,动态值,并简化了管理应用程序整个生命周期的过程。除了可以轻松分发Helm chart外,通过Helm chart还可以使用许多应用程序
- Kustomize是另一种方法,它允许通过基本文件夹定义同一应用程序的多个版本,而该基本文件夹可以通过使用其他资源来重载。Kustomize使通过多个覆盖子文件夹轻松管理应用程序的多个版本