<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          在 Kubernetes 上編排 MongoDB 集群

          共 6496字,需瀏覽 13分鐘

           ·

          2020-09-02 10:32

          無(wú)狀態(tài)應(yīng)用在 Kubernetes 中的使用非常方便,但是對(duì)于一些有狀態(tài)應(yīng)用部署還是相對(duì)較麻煩,雖然也有單獨(dú)的 StatefulSets 資源對(duì)象來(lái)處理有狀態(tài)應(yīng)用,但是畢竟不具有通用性,有狀態(tài)應(yīng)用的編排和具體的應(yīng)用息息相關(guān),比如 MongoDB、ElasticSearch、Redis、Zookeeper 等應(yīng)用。我們這里不再對(duì) StatefulSets 的具體使用展開介紹了,將通過(guò)部署一個(gè)可擴(kuò)展的 MongoDB 集群為例進(jìn)行說(shuō)明。

          首先我們運(yùn)行一個(gè) DaemonSet 的控制器來(lái)管理節(jié)點(diǎn),禁用巨頁(yè),因?yàn)?MongoDB 是建議關(guān)閉掉 Transparent Hugepage 的,否則可能導(dǎo)致性能下降,內(nèi)存鎖,甚至系統(tǒng)重啟等問(wèn)題,當(dāng)然最好的還是只調(diào)整 MongoDB 的 Pod 所在的節(jié)點(diǎn):

          # hostvm-ds.yamlapiVersion: apps/v1kind: DaemonSetmetadata:name: hostvm-configurerlabels:app: startup-scriptspec:selector:matchLabels:app: startup-scripttemplate:metadata:labels:app: startup-scriptspec:hostPID: truecontainers:- name: hostvm-configurerimage: cnych/startup-script:v1securityContext:privileged: trueenv:- name: STARTUP_SCRIPTvalue: |            #! /bin/bashset -o errexitset -o pipefailset -o nounset
          # Disable hugepagesecho 'never' > /sys/kernel/mm/transparent_hugepage/enabledecho 'never' > /sys/kernel/mm/transparent_hugepage/defrag

          然后配置 ServiceAccount、Headless SVC 和 StatefulSet,資源清單文件如下所示:

          # mongo.yamlapiVersion: v1kind: Namespacemetadata:name: mongo---apiVersion: v1kind: ServiceAccountmetadata:name: mongonamespace: mongo---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata:name: mongosubjects:- kind: ServiceAccountname: mongonamespace: mongoroleRef:kind: ClusterRolename: cluster-adminapiGroup: rbac.authorization.k8s.io---apiVersion: v1kind: Servicemetadata:name: mongonamespace: mongolabels:name: mongospec:ports:- port: 27017targetPort: 27017clusterIP: Noneselector:role: mongo---apiVersion: apps/v1kind: StatefulSetmetadata:name: mongonamespace: mongospec:serviceName: mongoreplicas: 3selector:matchLabels:role: mongoenvironment: stagingtemplate:metadata:labels:role: mongoenvironment: stagingreplicaset: MainRepSetspec:affinity:podAntiAffinity:  # 添加 Pod 反親和性,將副本打散在不同的節(jié)點(diǎn)preferredDuringSchedulingIgnoredDuringExecution:  # 軟策略- weight: 100podAffinityTerm:labelSelector:matchExpressions:- key: replicasetoperator: Invalues:- MainRepSettopologyKey: kubernetes.io/hostnameterminationGracePeriodSeconds: 10serviceAccountName: mongocontainers:- name: mongoimage: mongo:4.0command:- mongod- "--wiredTigerCacheSizeGB"- "0.25"- "--bind_ip"- "0.0.0.0"- "--replSet"- MainRepSet- "--smallfiles"- "--noprealloc"ports:- containerPort: 27017volumeMounts:- name: mongo-datamountPath: /data/dbresources:requests:cpu: 1memory: 2Gi- name: mongo-sidecarimage: cvallance/mongo-k8s-sidecarenv:- name: MONGO_SIDECAR_POD_LABELSvalue: "role=mongo,environment=staging"- name: KUBE_NAMESPACEvalue: "mongo"- name: KUBERNETES_MONGO_SERVICE_NAMEvalue: "mongo"volumeClaimTemplates:- metadata:name: mongo-dataspec:accessModes: [ "ReadWriteOnce" ]storageClassName: rook-ceph-block  # 提供一個(gè)可用的 Storageclassresources:requests:storage: 10Gi

          這里我們給 Mongo 的 Pod 添加了一個(gè) sidecar 容器,主要用于副本集的配置,該 sidecar 會(huì)每5s檢查一次新成員。通過(guò)幾個(gè)環(huán)境變量配置指定了 Pod 的標(biāo)簽、命名空間和 Service。

          為了保證應(yīng)用的穩(wěn)定性,我們通過(guò) podAntiAffinity 指定了 Pod 的反親和性,這樣可以保證不會(huì)有兩個(gè)副本出現(xiàn)在同一個(gè)節(jié)點(diǎn)上。

          此外需要提供一個(gè)可用的 StorageClass,這樣可以保證不同的副本數(shù)據(jù)持久化到不同的 PV。

          直接運(yùn)行上面的兩個(gè)資源清單文件即可:

          $ kubectl apply -f hostvm-ds.yaml$ kubectl apply -f mongo.yaml

          部署完成后可以通過(guò)如下命令檢查應(yīng)用運(yùn)行狀態(tài):

          $ kubectl -n mongo get allkubectl -n mongo get allNAME          READY   STATUS              RESTARTS   AGEpod/mongo-0   2/2     Running             0          28mpod/mongo-1   2/2     Running             0          23mpod/mongo-2   2/2     Running             0          16m
          NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEservice/mongo ClusterIP None 27017/TCP 51m
          NAME READY AGEstatefulset.apps/mongo 3/3 28m

          由于我們這里的 Service 是無(wú)頭服務(wù),沒(méi)有 ClusterIP,也沒(méi)有 ExternalIP,這個(gè) Service 會(huì)直接解析到 Pod 的 IP 列表,當(dāng)應(yīng)用完全部署到 Kubernetes 集群上后,我們就可以按照不同的節(jié)點(diǎn)來(lái)進(jìn)行訪問(wèn)了:

          Node-0: mongo-0.mongo.mongo.svc.cluster.local:27017Node-1: mongo-1.mongo.mongo.svc.cluster.local:27017Node-2: mongo-2.mongo.mongo.svc.cluster.local:27017

          當(dāng)然如果想從集群外部訪問(wèn) mongo,可以為這些 Pod 部署一些內(nèi)部的負(fù)載均衡器,或者使用 nginx-ingress、traefik 這些 Ingress 控制器來(lái)創(chuàng)建 Ingress 暴露出去。

          我們集群中部署了 Traefik v2.2 版本,該版本是支持 TCP 服務(wù)的,我們可以通過(guò)創(chuàng)建一個(gè)如下所示的 IngressRoute 對(duì)象來(lái)暴露 mongo 服務(wù):

          # ingressroute-tcp.yamlapiVersion: traefik.containo.us/v1alpha1kind: IngressRouteTCPmetadata:name: mongonamespapce: mongospec:entryPoints:- mongo  # 需要通過(guò)靜態(tài)方式開啟 mongo 的入口點(diǎn)routes:- match: HostSNI(`*`)services:- name: mongoport: 27017

          由于 Traefik 暴露 TCP 服務(wù)需要 SNI 的支持,我們這里沒(méi)有指定特定的域名,所以需要通過(guò)一個(gè)專門的入口點(diǎn) mongo 來(lái)暴露,需要在 Traefik 中聲明并開啟這個(gè)入口點(diǎn),類似于下面的這樣靜態(tài)配置:

          ......- name: mongocontainerPort: 27017hostPort: 27017args:- --entryPoints.mongo.address=:27017......

          直接運(yùn)行上面的 IngressRouteTCP 對(duì)象即可:

          $ kubectl apply -f ingressroute-tcp.yaml -n mongo

          需要注意的是,應(yīng)用程序至少要知道一個(gè)當(dāng)前正在運(yùn)行的 mongo 節(jié)點(diǎn),這樣才可以發(fā)現(xiàn)所有其他節(jié)點(diǎn)。

          我這里本地是 Mac 系統(tǒng),使用的是 Robo 3T 作為 mongo 客戶端,連接到其中一個(gè)節(jié)點(diǎn)并運(yùn)行 rs.status() 后,我們可以查看到副本集的詳細(xì)信息,并檢查其他兩個(gè) Pod 是否被配置并自動(dòng)連接到副本集上。

          rs.status() 顯示副本集名稱和成員數(shù)量

          在成員列表中也可以看到每個(gè)成員的 FQDN 名稱和狀態(tài),不過(guò)需要注意的是 FQDN 只能在 Kubernetes 集群內(nèi)部訪問(wèn):

          FQDN 名稱和狀態(tài)

          現(xiàn)在我們可以對(duì) Mongo 進(jìn)行擴(kuò)容,以檢查新的 Pod 是否被添加到副本集中去:

          $ kubectl -n mongo scale statefulsets mongo --replicas=4statefulset.apps/mongo scaled$ kubectl -n mongo get pods -o wideNAME      READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATESmongo-0   2/2     Running   0          32m     10.244.8.29    ydzs-node6              mongo-1   2/2     Running   0          27m     10.244.7.175   ydzs-node5              mongo-2   2/2     Running   0          20m     10.244.2.175   ydzs-node2              mongo-3   2/2     Running   0          4m29s   10.244.3.95    ydzs-node3              

          由于上面我們配置了 Pod 的反親和性,但是是軟策略,所以4個(gè) Pod 會(huì)經(jīng)量分散到不同的節(jié)點(diǎn)上。擴(kuò)容后同樣新的 Pod 也會(huì)自動(dòng)提供一個(gè)持久券:

          $ kubectl -n mongo get pvcNAME                 STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGEmongo-data-mongo-0   Bound    pvc-ac306842-f6a9-413c-bf92-576dd6a3b092   10Gi       RWO            rook-ceph-block   56mmongo-data-mongo-1   Bound    pvc-d319e5d2-ac99-4a2b-898c-feb4bdf0f256   10Gi       RWO            rook-ceph-block   27mmongo-data-mongo-2   Bound    pvc-fc8ded1d-0649-4b64-963e-0b9e2fc1f27d   10Gi       RWO            rook-ceph-block   21mmongo-data-mongo-3   Bound    pvc-762b4b91-432e-4409-8d8f-e3e809d6a159   10Gi       RWO            rook-ceph-block   4m51s

          現(xiàn)在我們?cè)偃?/span>Robo 3T 客戶端重新執(zhí)行 rs.status() 檢查新的 Pod ?是否被添加到副本集中了:

          已經(jīng)變成4個(gè)成員了

          新增的 Pod 與之前的成員都采用相同的 FQDN 方案,并同步到同一個(gè) Primary 節(jié)點(diǎn)去。

          到這里我們就成功地將 MongoDB 部署到了 Kubernetes 集群,而且還是可伸縮的。后續(xù)我們還可以考慮針對(duì)應(yīng)用部署 VPA,或者增加一些網(wǎng)絡(luò)策略或 Istio 來(lái)控制應(yīng)用,當(dāng)然這種方式整體來(lái)說(shuō)是可行的,但是可維護(hù)性還不是非常高,如果可以,我們應(yīng)該去根據(jù)自己的業(yè)務(wù)需求開發(fā)對(duì)應(yīng)的 Operator,或者使用第三方高質(zhì)量的 Operator 來(lái)編排 MongoDB。

          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一本道精品在线 | 免费69成人无码无遮又大 | 人人摸人人插 | 中国性爱在线 | 色色色大香蕉 |