预告:12月22日,ACOUG联合创始人及多位核心专家将欢聚一堂,为“关键词解析2018技术圈的那些事儿”为主题的分享讨论,欢迎大家踊跃报名参会。
详情:【感恩,回馈,展望】2018ACOUG年会盛大来袭!
Kubernetes主要用于无状态应用程序。但是,在1.3版本中引入了PetSets,之后它们演变为StatefulSets。官方文档将StatefulSets描述为“StatefulSets旨在与有状态应用程序和分布式系统一起使用”。
对此最好的用例之一是对数据存储服务进行编排,例如MongoDB,ElasticSearch,Redis,ZooKeeper等。
我们可以把StatefulSets的特性归纳如下:
有序索引Pod
稳定的网络ID
有序并行的Pod管理
滚动更新
这些细节可以在这里[1]找到。
StatefulSets的一个非常明显的特征是提供稳定网络ID,与HeadlessServices[2]一起使用时,功能可以更加强大。
我们在Kubernetes文档中随时可以查看的信息上不会花费很多时间,让我们专注于运行和扩展MongoDB集群。
你需要一个可以运行的Kubernetes群集并启用RBAC(推荐)。在本教程中,我将使用GKE集群,但是,AWSEKS或Microsoft的AKS或Kops管理的Kubernetes也是可行的替代方案。
我们将为MongoDB集群部署以下组件:
配置HostVM的DaemonSet
MongoPod的ServiceAccount和ClusterRoleBinding
为Pod提供永久性存储SSDs的StorageClass
访问Mongo容器的HeadlessService
MongoPodsStatefulSet
GCPInternalLB:从Kubernetes集群外部访问MongoDB(可选)
使用Ingress访问Pod(可选)
值得注意的是,每个MongoDBPod都会运行一个Sidecar,以便动态配置副本集。Sidecar每5秒检查一次新成员。
DaemonSetforHostVMConfiguration
kind:DaemonSet
apiVersion:extensions/v1beta1
metadata:
name:hostvm-configurer
labels:
app:startup-script
spec:
template:
metadata:
labels:
app:startup-script
spec:
hostPID:true
containers:
-name:hostvm-configurer-container
image:gcr.io/google-containers/startup-script:v1
securityContext:
privileged:true
env:
-name:STARTUP_SCRIPT
value:|
#!/bin/bash
set-oerrexit
set-opipefail
set-onounset
#Disablehugepages
echo'never'>/sys/kernel/mm/transparent_hugepage/enabled
echo'never'>/sys/kernel/mm/transparent_hugepage/defrag
ConfigurationforServiceAccount,StorageClass,HeadlessSVCandStatefulSet
apiVersion:v1
kind:Namespace
metadata:
name:mongo
---
apiVersion:v1
kind:ServiceAccount
metadata:
name:mongo
namespace:mongo
---
apiVersion:rbac.authorization.k8s.io/v1beta1
kind:ClusterRoleBinding
metadata:
name:mongo
subjects:
-kind:ServiceAccount
name:mongo
namespace:mongo
roleRef:
kind:ClusterRole
name:cluster-admin
apiGroup:rbac.authorization.k8s.io
---
apiVersion:storage.k8s.io/v1beta1
kind:StorageClass
metadata:
name:fast
provisioner:kubernetes.io/gce-pd
parameters:
type:pd-ssd
fsType:xfs
allowVolumeExpansion:true
---
apiVersion:v1
kind:Service
metadata:
name:mongo
namespace:mongo
labels:
name:mongo
spec:
ports:
-port:27017
targetPort:27017
clusterIP:None
selector:
role:mongo
---
apiVersion:apps/v1beta1
kind:StatefulSet
metadata:
name:mongo
namespace:mongo
spec:
serviceName:mongo
replicas:3
template:
metadata:
labels:
role:mongo
environment:staging
replicaset:MainRepSet
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
-weight:100
podAffinityTerm:
labelSelector:
matchExpressions:
-key:replicaset
operator:In
values:
-MainRepSet
topologyKey:kubernetes.io/hostname
terminationGracePeriodSeconds:10
serviceAccountName:mongo
containers:
-name:mongo
image:mongo
command:
-mongod
-"--wiredTigerCacheSizeGB"
-"0.25"
-"--bind_ip"
-"0.0.0.0"
-"--replSet"
-MainRepSet
-"--smallfiles"
-"--noprealloc"
ports:
-containerPort:27017
volumeMounts:
-name:mongo-persistent-storage
mountPath:/data/db
resources:
requests:
cpu:1
memory:2Gi
-name:mongo-sidecar
image:cvallance/mongo-k8s-sidecar
env:
-name:MONGO_SIDECAR_POD_LABELS
value:"role=mongo,environment=staging"
-name:KUBE_NAMESPACE
value:"mongo"
-name:KUBERNETES_MONGO_SERVICE_NAME
value:"mongo"
volumeClaimTemplates:
-metadata:
name:mongo-persistent-storage
annotations:
volume.beta.kubernetes.io/storage-class:"fast"
spec:
accessModes:["ReadWriteOnce"]
storageClassName:fast
resources:
requests:
storage:10Gi
关键点:
应该使用适当的环境变量仔细配置Mongo的Sidecar,以及为Pod提供的标签,和为deployment和service的命名空间。有关Sidecar容器的详细信息,请点击此处[3]。
默认缓存大小的指导值是:“50%的RAM减去1GB,或256MB”。鉴于所请求的内存量为2GB,此处的WiredTiger缓存大小已设置为256MB。
Inter-PodAnti-Affinity确保在同一个工作节点上不会安排2个MongoPod,从而使其能够适应节点故障。此外,建议将节点保留在不同的可用区中,以便集群能够抵御区域故障。
当前部署的ServiceAccount具有管理员权限。但是,它应该仅限于DB的命名空间。
上面提到的两个配置文件也可以在这里[4]找到。
部署MongoDB集群
kubectlapply-fconfigure-node.yml
kubectlapply-fmongo.yml
你可以通过以下命令查看所有组件状况:
root$kubectl-nmongogetall
NAMEDESIREDCURRENTAGE
statefulsets/mongo333m
NAMEREADYSTATUSRESTARTSAGE
po/mongo-02/2Running03m
po/mongo-12/2Running02m
po/mongo-22/2Running01m
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
svc/mongoClusterIPNone<none>27017/TCP3m/<none>
如你所见,该服务没有Cluster-IP,也没有External-IP,它是Headless服务。此服务将直接解析为StatefulSets的Pod-IP。
让我们来验证一下DNS解析。我们在集群中启动了一个交互式shell:
kubectlrunmy-shell--rm-i--tty--imageubuntu--bash
root@my-shell-68974bb7f7-cs4l9:/#digmongo.mongo+search+noall+answer
;<<>>DiG9.11.3-1ubuntu1.1-Ubuntu<<>>mongo.mongo+search+noall+answer
;;globaloptions:+cmd
mongo.mongo.svc.cluster.local.30INA10.56.7.10
mongo.mongo.svc.cluster.local.30INA10.56.8.11
mongo.mongo.svc.cluster.local.30INA10.56.1.4
服务的DNS规则是.,因此,在我们的例子中看到的是mongo.mongo。
IPs(10.56.6.17,10.56.7.10,10.56.8.11)是我们的MongoStatefulSets的PodIPs。这可以通过在集群内部运行nslookup来测试。
root@my-shell-68974bb7f7-cs4l9:/#nslookup10.56.6.17
17.6.56.10.in-addr.arpaname=mongo-0.mongo.mongo.svc.cluster.local.
root@my-shell-68974bb7f7-cs4l9:/#nslookup10.56.7.10
10.7.56.10.in-addr.arpaname=mongo-1.mongo.mongo.svc.cluster.local.
root@my-shell-68974bb7f7-cs4l9:/#nslookup10.56.8.11
11.8.56.10.in-addr.arpaname=mongo-2.mongo.mongo.svc.cluster.local.
如果你的应用程序部署在Kubernetes的群集中,那么它可以通过以下方式访问节点:
Node-0:mongo-0.mongo.mongo.svc.cluster.local:27017
Node-1:mongo-1.mongo.mongo.svc.cluster.local:27017
Node-2:mongo-2.mongo.mongo.svc.cluster.local:27017
如果要从集群外部访问Mongo节点,你可以为每个Pod部署内部负载平衡或使用IngressController(如NGINX或Traefik)创建一个内部Ingress。
GCPInternalLBSVCConfiguration(可选)
apiVersion:v1
kind:Service
metadata:
annotations:
cloud.google.com/load-balancer-type:Internal
name:mongo-0
namespace:mongo
spec:
ports:
-
port:27017
targetPort:27017
selector:
statefulset.kubernetes.io/pod-name:mongo-0
type:LoadBalancer
为mongo-1和mongo-2也部署2个此类服务。
你可以将内部负载均衡的IP提供给MongoClientURI。
root$kubectl-nmongogetsvc
NAMETYPECLUSTER-IPEXTERNAL-IPPORT(S)AGE
mongoClusterIPNone<none>27017/TCP15m/<none>
mongo-0LoadBalancer10.59.252.15710.20.20.227017:30184/TCP9m
mongo-1LoadBalancer10.59.252.23510.20.20.327017:30343/TCP9m
mongo-2LoadBalancer10.59.254.19910.20.20.427017:31298/TCP9m
mongo-0/1/2的外部IP是新创建的TCP负载均衡器的IP。这些是您的子网或对等网络,如果有的话。
通过Ingress访问Pod(可选)
也可以使用诸如Nginx之类的IngressController来定向到MongoStatefulSets的流量。确保Ingress服务是内部服务,而不是通过PublicIP公开。Ingress对象的配置看起来像这样:
...
spec:
rules:
-host:mongo.example.com
http:
paths:
-path:'/mongo-0'
backend:
hostNames:
-mongo-0
serviceName:mongo#Thereisnoextraservice.Thisistheheadlessservice.
servicePort:'27017'
请务必注意,您的应用程序至少应该知道一个当前处于启动状态的Mongo节点,这样可以发现所有其他节点。
我在本地mac上使用Robo3T作为mongo客户端。连接到其中一个节点后并运行rs.status(),您可以查看副本集的详细信息,并检查是否已配置其他2个Pod并自动连接到副本集。
rs.status()查看副本集名称和成员个数
每个成员都可以看到FQDN和状态。此FQDN只能从群集内部访问。
每个secondary成员正在同步到mongo-0,mongo-0是当前的primary。
现在我们扩展mongoPods的StatefulSet以检查新的Mongo容器是否被添加到ReplicaSet。
root$kubectl-nmongoscalestatefulsetsmongo--replicas=4
statefulset"mongo"scaled
root$kubectl-nmongogetpods-owide
NAMEREADYSTATUSRESTARTSAGEIPNODE
mongo-02/2Running025m10.56.6.17gke-k8-demo-demo-k8-pool-1-45712bb7-vfqs
mongo-12/2Running024m10.56.7.10gke-k8-demo-demo-k8-pool-1-c6901f2e-trv5
mongo-22/2Running023m10.56.8.11gke-k8-demo-demo-k8-pool-1-c7622fba-qayt
mongo-32/2Running03m10.56.1.4gke-k8-demo-demo-k8-pool-1-85308bb7-89a4
可以看出,所有四个Pod都部署到不同的GKE节点,因此我们的Pod-AntiAffinity策略工作正常。
扩展操作还将自动提供持久卷,该卷将充当新Pod的数据目录。
root$kubectl-nmongogetpvc
NAMESTATUSVOLUMECAPACITYACCESSMODESSTORAGECLASSAGE
mongo-persistent-storage-mongo-0Boundpvc-337fb7d6-9f8f-11e8-bcd6-42010a94002411GRWOfast49m
mongo-persistent-storage-mongo-1Boundpvc-53375e31-9f8f-11e8-bcd6-42010a94002411GRWOfast49m
mongo-persistent-storage-mongo-2Boundpvc-6cee0f97-9f8f-11e8-bcd6-42010a94002411GRWOfast48m
mongo-persistent-storage-mongo-3Boundpvc-3e89573f-9f92-11e8-bcd6-42010a94002411GRWOfast28m
要检查名为mongo-3的Pod是否已添加到副本集,我们将在同一节点上再次运行rs.status()并观察其差异。
对于同一个的Replicaset,成员数现在为4。
新添加的成员遵循与先前成员相同的FQDN方案,并且还与同一主节点同步。
进一步的考虑
给MongoPod的NodePool打上合适的label并确保在StatefulSets和HostVM配置的DaemonSets的Spec中指定适当的NodeAffinity会很有帮助。这是因为DaemonSet将调整主机操作系统的一些参数,并且这些设置应仅限于MongoDBPod。没有这些设置,对其他应用程序可能会更好。
在GKE中给NodePool打Label非常容易,可以直接从GCP控制台进行。
虽然我们在Pod的Spec中指定了CPU和内存限制,但我们也可以考虑部署VPA(VerticalPodAutoscaler)。
可以通过实施网络策略或服务网格(如Istio)来控制从集群内部到我们的数据库的流量。
如果你已经看到这里,我相信你已经浏览了整个博文。我试图整理很多分散的信息并将其作为一个整体呈现。我的目标是为您提供足够的信息,以便开始使用Kubernetes上的StatefulSets,并希望你们中的许多人觉得它很有用。我们非常欢迎您提出反馈、意见或建议。:)
相关链接:
https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/
https://kubernetes.io/docs/concepts/services-networking/service/#headless-services
https://github.com/cvallance/mongo-k8s-sidecar
https://github.com/Thakurvaibhav/k8s/tree/master/databases/mongodb
原文链接:https://medium.com/@thakur.vaibhav23/scaling-mongodb-on-kubernetes-32e446c16b82
资源下载
2018DTCC
,数据库大会PPT
2018DTC
,2018DTC大会PPT
DBALIFE
,“DBA的一天”海报
DBA04
,DBA手记4电子书
122ARCH
,Oracle12.2体系结构图
2018OOW
,OracleOpenWorld资料
PRELECTION
,大讲堂讲师课程资料
近期文章
企业数据架构的云化智能重构和变革(含大会PPT)
Oracle研发总裁ThomasKurian加盟GoogleCloud
变与不变:Undo构造一致性读的例外情况
Oracle18c新特性:动态ContainerMap增强ApplicationContainer灵活性
Oracle18c新特性:Schema-Only帐号提升应用管理安全性
Oracle18c新特性:多租户舰队CDBFleet(含PPT)
为什么看了那么多灾难,还是过不好备份这一关?
閱讀更多 大地在小腳下 的文章