使用StatefulSet在Kubernetes上运行MongoDB
编者注:今天的帖子由Google Cloud Platform开发人员倡导者Sandeep Dinesh撰写,展示了如何在容器中运行数据库。
警告: 这个帖子已经有好几年了。这些代码示例需要更改才能在当前的Kubernetes集群上工作。
传统观点认为,您不能在容器中运行数据库。 “容器是无状态的!”他们说,“没有状态的数据库毫无意义!”
当然,这根本不是真的。在Google,一切都在包含数据库的容器中运行。您只需要正确的工具。 Kubernetes 1.5 包括新 有状态集 API对象(在以前的版本中,StatefulSet被称为PetSet)。借助StatefulSets,Kubernetes使运行有状态工作负载(例如数据库)变得更加容易。
如果您按照我以前的帖子进行操作,就会知道如何创建一个 带有Docker的MEAN Stack应用, 然后 迁移到Kubernetes 提供更轻松的管理和可靠性,以及 创建一个MongoDB副本集 提供冗余和高可用性。
在我上一篇博客文章中设置的副本有效的同时,您需要执行一些令人讨厌的步骤。您必须手动为每个副本创建磁盘,ReplicationController和服务。缩放设置意味着要手动管理所有这些资源,这是一个出错的机会,并且会使您的状态应用程序处于风险中。在前面的示例中,我们创建了一个Makefile来简化对这些资源的管理,但是如果Kubernetes能够为我们解决所有这些问题,那就太好了。
使用StatefulSets,这些头痛终于消失了。您可以在Kubernetes中本地创建和管理MongoDB副本集,而无需脚本和Makefile。让我们看看如何。
注意:StatefulSets当前是一个beta资源。的 边柜 用于自动配置的也不支持。
先决条件和设置
在开始之前,您需要安装Kubernetes 1.5+和 Kubernetes命令行工具。如果您想按照本教程进行操作并使用Google Cloud Platform,则还需要 谷歌云 SDK.
一旦你有一个 谷歌云项目已创建 并设置好您的Google Cloud SDK(提示:gcloud init),我们可以创建集群。
要创建Kubernetes 1.5集群,请运行以下命令:
gcloud container clusters create "test-cluster"
这将构成一个三节点的Kubernetes集群。随意地 自定义命令 如您所见。
然后,对集群进行身份验证:
gcloud container clusters get-credentials test-cluster
设置MongoDB副本集
要设置MongoDB副本集,您需要三件事:A 存储类, 一种 无头服务和 有状态集.
我已经为它们创建了配置文件,您可以从GitHub克隆示例:
git clone //github.com/thesandlord/mongo-k8s-sidecar.git
cd /mongo-k8s-sidecar/example/StatefulSet/
要创建MongoDB副本集,请运行以下两个命令:
kubectl apply -f googlecloud\_ssd.yaml
kubectl apply -f mongo-statefulset.yaml
而已!使用这两个命令,您已经启动了运行高可用性和冗余MongoDB副本集所需的所有组件。
从高层次看,它看起来像这样:
让我们更详细地研究每件作品。
存储类
存储类告诉Kubernetes用于数据库节点的存储类型。您可以在大量不同的环境中设置许多不同类型的StorageClass。例如,如果您在自己的数据中心中运行Kubernetes,则可以使用 GlusterFS。在GCP上,您的 存储选择 是SSD和硬盘。当前有驱动程序 AWS, 蔚蓝, 谷歌云, GlusterFS, OpenStack煤渣, 的vSphere, Ceph RBD和 兆字节.
存储类的配置如下所示:
kind: 存储类
apiVersion: storage.k8s.io/v1beta1
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
此配置将创建一个称为“快速”的新StorageClass,该类由SSD卷支持。 有状态集现在可以请求一个卷,并且StorageClass将自动创建它!
部署此StorageClass:
kubectl apply -f googlecloud\_ssd.yaml
无头服务
现在,您已经创建了存储类,您需要进行无头服务。这些就像普通的Kubernetes服务一样,除了它们不为您做任何负载平衡。与StatefulSets结合使用时,它们可以为您提供唯一的DNS地址,使您可以直接访问吊舱!这对于创建MongoDB副本集非常理想,因为我们的应用程序需要单独连接到所有MongoDB节点。
无头服务的配置如下所示:
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
name: mongo
spec:
ports:
- port: 27017
targetPort: 27017
clusterIP: None
selector:
role: mongo
您可以说这是无头服务,因为clusterIP设置为“无”。除此之外,它看起来与任何普通的Kubernetes服务完全相同。
有状态集
抵抗之城。 有状态集实际上运行MongoDB并将所有内容编排在一起。状态集不同于Kubernetes 副本集 (不要与MongoDB副本集混淆!),使它们更适合有状态应用程序。与Kubernetes 副本集不同,在StatefulSet下创建的Pod具有一些唯一的属性。吊舱的名称不是随机的,而是每个吊舱都有一个序数名称。结合无头服务,可以使吊舱具有稳定的标识。此外,可以一次创建一个Pod,而不是一次创建一个Pod,这对引导有状态系统很有帮助。您可以在中阅读有关StatefulSet的更多信息。 文件资料.
就像从前一样, 这个“边车”的容器 将自动配置MongoDB副本集。 “边车”是一个辅助容器,可以帮助主容器完成其工作。
有状态集的配置如下所示:
apiVersion: apps/v1beta1
kind: 有状态集
metadata:
name: mongo
spec:
selector:
matchLabels:
role: mongo
environment: test
serviceName: "mongo"
replicas: 3
template:
metadata:
labels:
role: mongo
environment: test
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mongo
image: mongo
command:
- mongod
- "--replSet"
- rs0
- "--smallfiles"
- "--noprealloc"
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
- name: mongo-sidecar
image: cvallance/mongo-k8s-sidecar
env:
- name: MONGO_SIDECAR_POD_LABELS
value: "role=mongo,environment=test"
volumeClaimTemplates:
- metadata:
name: mongo-persistent-storage
spec:
storageClassName: "fast"
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
有点长,但是相当简单。
第一个描述了StatefulSet对象。然后,我们进入“元数据”部分,您可以在其中指定标签和副本数。
接下来是Pod规格。当缩小副本数量时,可以使用TerminationGracePeriodSeconds正常关闭Pod,这对于数据库很重要!然后显示了两个容器的配置。第一个运行带有配置复制集名称的命令行标志的MongoDB。它还会将持久性存储卷安装到/ data / db(MongoDB保存其数据的位置)。第二个容器运行边车。
最后,还有volumeClaimTemplates。这是与我们在配置卷之前创建的StorageClass有关的内容。它将为每个MongoDB副本提供100 GB磁盘。
使用MongoDB副本集
此时,您应该在集群中创建了三个Pod。这些对应于您的MongoDB副本集中的三个节点。您可以使用以下命令查看它们:
kubectl get pods
NAME READY STATUS RESTARTS AGE
mongo-0 2/2 Running 0 3m
mongo-1 2/2 Running 0 3m
mongo-2 2/2 Running 0 3m
Each pod in a 有状态集 backed by a 无头服务 will have a stable DNS name. The template follows this format: <pod-name>.<service-name>
这意味着MongoDB副本集的DNS名称为:
mongo-0.mongo
mongo-1.mongo
mongo-2.mongo
您可以直接在 连接字符串URI 您的应用程序。
在这种情况下,连接字符串URI将为:
mongodb://mongo-0.mongo,mongo-1.mongo,mongo-2.mongo:27017/dbname\_?
而已!
扩展MongoDB副本集
有状态集s的一个巨大优势是您可以像Kubernetes 副本集一样扩展它们。如果要使用5个MongoDB节点而不是3个,只需运行scale命令:
kubectl scale --replicas=5 statefulset mongo
sidecar容器将自动配置新的MongoDB节点以加入副本集。
在您的连接字符串URI中包含两个新节点(mongo-3.mongo和mongo-4.mongo),您很高兴。太容易了!
打扫干净
要清理已部署的资源,请删除StatefulSet,Headless Service和预配置的卷。
删除StatefulSet:
kubectl delete statefulset mongo
删除服务:
kubectl delete svc mongo
删除卷:
kubectl delete pvc -l role=mongo
最后,您可以删除测试集群:
gcloud container clusters delete "test-cluster"
快乐黑客!
有关更酷的Kubernetes和Container博客文章,请关注我 推特 和 中.
-Google Cloud Platform开发倡导者Sandeep Dinesh。