本文补充了关于在云中部署和管理容器化工作负载的网络研讨会系列 。 该系列涵盖容器的基本要素,包括管理容器生命周期,部署多容器应用程序,扩展工作负载以及使用Kubernetes。 它还突出显示了运行有状态应用程序的最佳实践。
本教程包括系列第5部分中的概念和命令,即在Kubernetes中部署状态服务。
介绍
Kubernetes是一款用于管理容器化应用程序的开源容器编排工具。 在本系列的前几部分中,您学习了Kubernetes和打包容器的构建块,作为Kubernetes ReplicaSets。 虽然ReplicaSets确保无状态Pod的可用性,但它们不能用于数据库集群等有状态工作负载。
虽然在Kubernetes中打包,部署,管理和扩展现代云本地应用程序可能很容易,但在容器化环境中部署和管理传统工作负载(如数据库和内容管理系统)需要采用不同的方法。 StatefulSets将Kubernetes ReplicaSet的灵活性带入有状态的工作负载。
在本教程系列的最后一部分中,您将使用Helm (一种广受欢迎的Kubernetes开放源代码包管理器)作为StatefulSet在Kubernetes中部署高可用性MongoDB副本集。
先决条件
要完成本教程,您需要:
- 在DigitalOcean上运行的活动Kubernetes集群,通过StackPointCloud安装,您可以按照Kubernetes入门教程进行操作 。
- 本教程中介绍的示例Web应用程序在基于Node.js和MongoDB的Kubernetes中部署和扩展微服务得到了扩展,以便为数据库带来高可用性。 有关应用程序设计的详细信息,请参阅Building Containerized Applications教程。
- 活动的Docker Hub帐户,用于存储应用程序的Docker镜像。
- 装有Git的本地机器
- 如果您使用的是macOS,请确保已安装Homebrew 。
第1步 - 在开发机器上安装Helm Client
借助Helm,管理员可以使用单个命令部署复杂的Kubernetes应用程序。 应用程序打包为定义,安装和升级Kubernetes应用程序的图表 。 图表提供了对Kubernetes对象(如Pods,Deployments和Services)的抽象。
Helm有两个组件 - 服务器和客户端。 Helm的服务器端作为名为Tiller的服务在Kubernetes中运行。 客户端是一个与Tiller交互的命令行工具。
由于您要部署MongoDB副本集头盔图表,因此您需要与Helm的服务器端组件Tiller交谈的CLI。 StackPointCloud,您曾用于在DigitalOcean上设置Kubernetes,预装了Tiller。
注意 :这些说明适用于macOS。 如果您正在使用其他操作系统,请参阅Helm安装指南 。
假设你在Mac上安装并配置了Homebrew,运行以下命令安装Helm:
brew install kubernetes-helm
Output==> Downloading https://homebrew.bintray.com/bottles/kubernetes-helm-2.8.2.high_sierra.bottle.tar.gz
...
==> Summary
???? /usr/local/Cellar/kubernetes-helm/2.8.2: 50 files, 121.7MB
一旦安装了Helm,请验证您是否可以通过检查其当前版本来运行它。
helm version
OutputClient: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.8.2", GitCommit:"a80231648a1473929271764b920a8e346f6de844", GitTreeState:"clean"}
这证实客户端已正确安装,并且能够与Tiller交谈。
在下一步中,我们将使用Helm在Kubernetes中部署MongoDB副本集。
第2步 - 在Kubernetes中部署MongoDB副本集
Kubernetes中的StorageClass为管理员提供了描述他们提供的存储“类”的方法。 例如,当用户请求存储卷时,StorageClass将确定从它们供应什么类的存储后端。 这些课程可能包括标准HDD和更快的SSD。 在幕后,StorageClass与基础架构(如云提供商的API)进行交互,以调配存储。
由于需要持久性存储来存储MongoDB数据,因此您可能需要将DigitalOcean块存储卷附加到工作节点,并指向MongoDB Pod以使用存储卷进行持久性存储。
在这种情况下,StorageClass充当Pod和DigitalOcean块存储服务之间的接口。 当您请求一个块存储卷时,StorageClass会与知道如何分配块存储卷的预配置驱动程序通信。
在安装过程中,StackPointCloud安装DigitalOcean存储驱动程序并向Kubernetes注册StorageClass。 这节省了我们从安装和配置驱动程序和StorageClass所涉及的步骤。
在我们部署MongoDB集群之前,让我们确保配置StorageClass for DigitalOcean卷:
kubectl get storageclass
输出确认StorageClass已配置并准备就绪。
[secondary_label Output
NAME PROVISIONER AGE
digitalocean (default) digitalocean/flex-volume-provisioner 1d
接下来,您将配置并部署基于DigitalOcean StorageClass的MongoDB副本集。
为您的项目创建一个新目录并切换到新目录:
mkdir ~/mongo-rs
cd ~/mongo-rs
从GitHub克隆Helm Chart存储库:
git clone https://github.com/kubernetes/charts.git
导航到MongoDB副本集目录( charts/stable/mongodb-replicaset/
)并验证文件values.yaml
存在。
cd charts/stable/mongodb-replicaset/
ls values.yaml
Outputvalues.yaml
该文件包含图表的参数和配置。 您需要修改此文件以配置MongoDB副本集以使用DigitalOcean StorageClass。
编辑values.yaml
:
nano values.yaml
查找并取消注释以下部分:
...
# storageClass: "-"
...
将"-"
替换为"digitalocean"
,如下所示:
...
storageClass: "digitalocean"
...
保存文件并退出编辑器。
现在导航到~/mongo-rs
文件夹。
cd ~/mongo-rs
您现在准备将MongoDB副本集部署到您的Kubernetes集群,由DigitalOcean的块存储提供支持。 运行以下命令启动数据库集群。
helm install --name=todo -f charts/stable/mongodb-replicaset/values.yaml stable/mongodb-replicaset
在前面的命令中,--name指的是Helm图表的名称。 开关-f
指向存储在values.yaml
的配置设置。
您将立即看到输出确认图表创建已经开始。
OutputNAME: todo
LAST DEPLOYED: Sat Mar 31 10:37:06 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
todo-mongodb-replicaset ClusterIP None <none> 27017/TCP 1s
==> v1beta1/StatefulSet
NAME DESIRED CURRENT AGE
todo-mongodb-replicaset 3 1 0s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 0/1 Init:0/2 0 0s
==> v1/ConfigMap
NAME DATA AGE
todo-mongodb-replicaset 1 1s
todo-mongodb-replicaset-tests 1 1s
NOTES:
1. After the statefulset is created completely, one can check which instance is primary by running:
$ for ((i = 0; i < 3; ++i)); do kubectl exec --namespace default todo-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; done
2. One can insert a key into the primary instance of the mongodb replica set by running the following:
MASTER_POD_NAME must be replaced with the name of the master found from the previous step.
$ kubectl exec --namespace default MASTER_POD_NAME -- mongo --eval="printjson(db.test.insert({key1: 'value1'}))"
3. One can fetch the keys stored in the primary or any of the slave nodes in the following manner.
POD_NAME must be replaced by the name of the pod being queried.
$ kubectl exec --namespace default POD_NAME -- mongo --eval="rs.slaveOk(); db.test.find().forEach(printjson)"
现在让我们运行一系列命令来跟踪集群的状态。
首先,看看StatefulSet:
kubectl get statefulset
此命令确认MongoDB副本集是作为Kubernetes StatefulSet创建的。
OutputNAME DESIRED CURRENT AGE
todo-mongodb-replicaset 3 2 2m
现在探索Pods:
kubectl get pods
Pod的数量及其命名约定表明MongoDB副本集已成功配置:
OutputNAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 3m
todo-mongodb-replicaset-1 1/1 Running 0 1m
todo-mongodb-replicaset-2 1/1 Running 0 54s
请注意,每个Pod都有一个以序号结尾的Postfix,这是StatefulSet的一个独特功能。
现在让我们来看看MongoDB实例是否正在相互通信。 我们将通过在其中一个Pod中的MongoDB shell中运行命令来完成此操作。
使用kubectl
在其中一台主机上启动mongo
控制台:
kubectl exec -it todo-mongodb-replicaset-0 mongo
连接之后,您会发现自己在MongoDB外壳中:
OutputMongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
Welcome to the MongoDB shell.
For interactive help, type "help".
...
2018-03-31T05:08:20.239+0000 I CONTROL [initandlisten]
使用以下命令检查副本集的配置:
rs.conf()
输出确认有三个作为副本集运行的MongoDB实例。
Output{
"_id" : "rs0",
"version" : 3,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "todo-mongodb-replicaset-0.todo-mongodb-replicaset.default.svc.cluster.local:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "todo-mongodb-replicaset-1.todo-mongodb-replicaset.default.svc.cluster.local:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "todo-mongodb-replicaset-2.todo-mongodb-replicaset.default.svc.cluster.local:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5abdb4f61d952afc4b0b8218")
}
}
退出MongoDB控制台:
exit
这也会使您与远程主机断开连接。
让我们切换齿轮并检查DigitalOcean控制面板以查找与群集关联的块存储卷。 登录到DigitalOcean帐户并选择卷标签:
您可以看到三个10GB的卷分别连接到Kubernetes工作节点。 MongoDB StatefulSet的每个Pod都将数据存储在一个块存储卷中。 10GB的大小在persistentVolume
部分下的values.yaml
定义。
persistentVolume:
enabled: true
## mongodb-replicaset data Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner. (gp2 on AWS, standard on
## GKE, AWS & OpenStack)
##
storageClass: digitalocean
accessModes:
- ReadWriteOnce
size: 10Gi
annotations: {}
您已经成功配置了在Kubernetes中运行的高可用性MongoDB ReplicaSet。
现在让我们部署与MongoDB集群交谈的Web应用程序。
第3步 - 在Kubernetes中部署和扩展Web应用程序
让我们扩展本教程系列前面部分中使用的ToDo Node.js应用程序,以利用MongoDB集群。
注意 :您也可以从源代码构建容器图像,或者直接在Kubernetes文件中使用YAML文件。 有关构建映像和将应用程序部署到Kubernetes的步骤,请参阅教程在Kubernetes中部署和缩放微服务。
首先创建一个新的工作目录:
mkdir ~/web-app
cd ~/web-app
然后克隆包含代码和Kubernetes构件的ToDo应用程序的存储库。
git clone https://github.com/janakiramm/todo.git
切换到包含Kubernetes配置文件的todo-app/kubernetes
目录。
cd todo-app/kubernetes
在您的编辑器中打开文件web-rs-ss.yaml
。
nano web-rs-ss.yaml
注意YAML文件中的env
部分。
containers:
- name: web
image: janakiramm/todo
env:
- name: "DBHOST"
value: "mongodb://todo-mongodb-replicaset-0.todo-mongodb-replicaset,todo-mongodb-replicaset-1.todo-mongodb-replicaset,todo-mongodb-replicaset-2.todo-mongodb-replicaset:27017"
ports:
- containerPort: 3000
这将数据库连接字符串作为环境变量在运行时传递给应用程序。 这个版本的应用程序使用您创建的StatefulSet,而不是将应用程序指向简单的MongoDB Pod。 value
部分中的每个条目都指向MongoDB StatefulSet的其中一个Pod。
使用kubectl
将web
ReplicaSet与web
Service一起部署
kubectl create -f web-rs-ss.yaml -f web-service.yaml
你会看到两者都被创建:
Outputreplicaset "web" created
service "web" created
再次列出豆荚:
kubectl get pods
您现在可以看到属于MongoDB的所有Pod和Web应用程序。
OutputNAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 26m
todo-mongodb-replicaset-1 1/1 Running 0 24m
todo-mongodb-replicaset-2 1/1 Running 0 23m
web-t5zzk 1/1 Running 0 17s
web-x6dh8 1/1 Running 0 17s
Let’s check out the Kubernetes services
```command
kubectl get svc
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.3.0.1 <none> 443/TCP 1d
todo-mongodb-replicaset ClusterIP None <none> 27017/TCP 27m
web NodePort 10.3.0.167 <none> 3000:31201/TCP 14s
web
Pod通过todo-mongodb-replicaset
Service与MongoDB集群进行通信。 Web应用程序可通过NodePort 31201
上的web
Service 31201
。
在任何工作节点上访问此端口都会显示Web应用程序。
您可以通过增加副本集中的窗格数来扩展Web应用程序。
kubectl scale rs/web --replicas=10
Outputreplicaset "web" scaled
然后,您可以将应用程序缩放到两个Pod。
kubectl scale rs/web --replicas=2
Outputreplicaset "web" scaled
现在让我们运行一些测试的可用性。
第4步 - 测试MongoDB副本集的高可用性
运行StatefulSet的优点之一是工作负载的高可用性。 让我们通过删除MongoDB StatefulSet中的一个Pod来测试它。
kubectl delete pod todo-mongodb-replicaset-2
Outputpod "todo-mongodb-replicaset-2" deleted
检查豆荚的数量:
kubectl get pods
你会看到todo-mongodb-replicaset-2
正在终止:
OutputNAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 33m
todo-mongodb-replicaset-1 1/1 Running 0 32m
todo-mongodb-replicaset-2 0/1 Terminating 0 31m
web-t5zzk 1/1 Running 0 8m
web-x6dh8 1/1 Running 0 8m
在几分钟内,你会看到Kubernetes初始化另一个Pod以替换已删除的Pod。
kubectl get pods
你会看到todo-mongodb-replicaset-2
正在初始化:
NAME READY STATUS RESTARTS AGE
todo-mongodb-replicaset-0 1/1 Running 0 34m
todo-mongodb-replicaset-1 1/1 Running 0 33m
todo-mongodb-replicaset-2 0/1 Init:0/2 0 29s
web-t5zzk 1/1 Running 0 8m
web-x6dh8 1/1 Running 0 8m
既然你知道一切正常,你可以清理干净。
使用以下命令删除在本教程中创建的所有对象:
helm delete --purge todo
kubectl delete -f web-rs-ss.yaml -f web-service.yaml
Outputreplicaset "web" deleted
service "web" deleted
要删除Kubernetes集群本身,请访问StackPointCloud并通过他们的控制面板进行操作。
结论
在本教程中,您将持久,持久,高度可用的MonogDB ReplicaSet部署为Kubernetes StatefulSet。 您还学习了如何从部署在同一个Kubernetes集群中的其他应用程序访问StatefulSet。