网络研讨会系列:在Kubernetes中部署有状态服务

来自菜鸟教程
跳转至:导航、​搜索

本文补充了关于在云中部署和管理容器化工作负载的 网络研讨会系列 。 该系列涵盖了容器的基本知识,包括管理容器生命周期、部署多容器应用程序、扩展工作负载以及使用 Kubernetes。 它还强调了运行有状态应用程序的最佳实践。

本教程包含本系列第五节“在 Kubernetes 中部署有状态服务”中的概念和命令。


观看 YouTube 视频

###介绍

Kubernetes 是一个用于管理容器化应用的开源容器编排工具。 在本系列的前几部分中,您学习了 Kubernetes 的构建块以及将容器打包为 Kubernetes ReplicaSet。 虽然 ReplicaSet 确保了无状态 Pod 的可用性,但它们不能用于数据库集群等有状态工作负载。

虽然在 Kubernetes 中打包、部署、管理和扩展现代云原生应用程序可能很容易,但在容器化环境中部署和管理数据库和内容管理系统等传统工作负载需要不同的方法。 StatefulSets 为有状态工作负载带来 Kubernetes ReplicaSet 的灵活性。

在本教程系列的最后一部分中,您将使用 Helm(一种流行的 Kubernetes 开源包管理器)在 Kubernetes 中将高可用性 MongoDB ReplicaSet 部署为 StatefulSet。

先决条件

要完成本教程,您需要:

第 1 步 – 在开发机器上安装 Helm 客户端

使用 Helm,管理员可以使用单个命令部署复杂的 Kubernetes 应用程序。 应用程序被打包为定义、安装和升级 Kubernetes 应用程序的 Charts。 图表提供了对 Kubernetes 对象(例如 Pod、部署和服务)的抽象。

Helm 有两个组件——服务器和客户端。 Helm 的服务器端作为称为 Tiller 的服务在 Kubernetes 中运行。 客户端是一个与 Tiller 交互的命令行工具。

由于您要部署 MongoDB ReplicaSet Helm Chart,因此您需要与 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 ReplicaSet。

第 2 步 – 在 Kubernetes 中部署 MongoDB ReplicaSet

Kubernetes 中的 StorageClass 为管理员提供了一种描述他们提供的存储“类别”的方法。 例如,当用户请求存储卷时,StorageClass 将确定从他们那里提供的存储后端类别。 这些类可能包括标准 HDD 和更快的 SSD。 在幕后,StorageClass 与底层基础设施(例如云提供商的 API)交互以提供存储。

由于您需要持久化存储来存储 MongoDB 数据,您可能希望将 DigitalOcean Block Storage 卷附加到工作节点,并将 MongoDB Pod 指向使用存储卷进行持久化。

在这种情况下,StorageClass 充当 Pod 和 DigitalOcean 块存储服务之间的接口。 当您请求块存储卷时,StorageClass 会与知道如何分配块存储卷的预配置驱动程序进行对话。

StackPointCloud 安装 DigitalOcean 存储驱动程序,并在设置期间向 Kubernetes 注册 StorageClass。 这使我们免于安装和配置驱动程序和 StorageClass 的步骤。

在我们部署 MongoDB 集群之前,让我们确保为 DigitalOcean 卷配置了 StorageClass:

kubectl get storageclass

输出确认 StorageClass 已配置并准备就绪。

[secondary_label Output
NAME                     PROVISIONER                            AGE
digitalocean (default)   digitalocean/flex-volume-provisioner   1d

接下来,您将基于 DigitalOcean StorageClass 配置和部署 MongoDB ReplicaSet。

为您的项目创建一个新目录并切换到新目录:

mkdir ~/mongo-rs
cd ~/mongo-rs

从 GitHub 克隆 Helm Chart 存储库:

git clone https://github.com/kubernetes/charts.git

导航到 MongoDB ReplicaSet 目录 (charts/stable/mongodb-replicaset/) 并验证文件 values.yaml 是否存在。

cd charts/stable/mongodb-replicaset/
ls values.yaml
Outputvalues.yaml

此文件包含图表的参数和配置。 您需要修改此文件以将 MongoDB ReplicaSet 配置为使用 DigitalOcean StorageClass。

编辑values.yaml

nano values.yaml

查找并取消注释以下部分:

值.yaml

...
# storageClass: "-" 
...

"-" 替换为 "digitalocean",如下所示:

值.yaml

...
storageClass: "digitalocean"
...

保存文件并退出编辑器。

现在导航到 ~/mongo-rs 文件夹。

cd ~/mongo-rs

您现在已准备好将 MongoDB ReplicaSet 部署到由 DigitalOcean 块存储提供支持的 Kubernetes 集群。 运行以下命令以启动数据库集群。

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 ReplicaSet 已创建为 Kubernetes StatefulSet。

OutputNAME                      DESIRED   CURRENT   AGE
todo-mongodb-replicaset   3         2         2m

现在探索 Pod:

kubectl get pods

Pod 的数量及其命名约定表明 MongoDB ReplicaSet 配置成功:

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 都有一个以序列号结尾的后缀,这是 StatefulSet 的一个显着特征。

现在让我们检查一下 MongoDB 实例是否正在相互通信。 我们将通过在其中一个 Pod 中的 MongoDB shell 中运行命令来完成此操作。

使用 kubectl 在其中一台主机上启动 mongo 控制台:

kubectl exec -it todo-mongodb-replicaset-0 mongo

连接后,您会发现自己在 MongoDB shell 中:

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]

使用以下命令检查 ReplicaSet 的配置:

rs.conf()

输出确认有三个 MongoDB 实例作为 ReplicaSet 运行。

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 帐户并选择 Volumes 选项卡:

您可以看到三个 10GB 的卷都附加到 Kubernetes 工作节点。 MongoDB StatefulSet 的每个 Pod 都将数据存储在一个块存储卷中。 10GB 的大小在 persistentVolume 部分下的 values.yaml 中定义。

值.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 部分。

web-rs-ss.yaml

      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

这会在运行时将数据库连接字符串作为环境变量传递给应用程序。 这个版本的应用程序没有将应用程序指向一个简单的 MongoDB Pod,而是使用您创建的 StatefulSet。 value 部分中的每个条目都引用 MongoDB StatefulSet 的 Pod 之一。

使用 kubectl 部署 web ReplicaSet 以及 web 服务

kubectl create -f web-rs-ss.yaml -f web-service.yaml

您会看到两者都已创建:

Outputreplicaset "web" created
service "web" created

再次列出 pod:

kubectl get pods

您现在可以看到属于 MongoDB 和 Web 应用程序的所有 Pod。

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 服务与 MongoDB 集群通信。 Web 应用程序可通过 NodePort 31201 上的 web 服务获得。

在任何工作节点上访问此端口都会显示 Web 应用程序。

您可以通过增加 ReplicaSet 中的 Pod 数量来扩展 Web 应用程序。

kubectl scale rs/web --replicas=10
Outputreplicaset "web" scaled

然后,您可以将应用程序扩展回两个 Pod。

kubectl scale rs/web --replicas=2
Outputreplicaset "web" scaled

现在让我们运行一些可用性测试。

第 4 步 – 测试 MongoDB ReplicaSet 的高可用性

运行 StatefulSet 的优势之一是工作负载的高可用性。 让我们通过删除 MongoDB StatefulSet 中的一个 Pod 来测试一下。

kubectl delete pod todo-mongodb-replicaset-2
Outputpod "todo-mongodb-replicaset-2" deleted

检查 Pod 的数量:

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。