Рубрики
Uncategorized

Орхестируя mongodb над Kubernetes

Kubernetes в основном использовался для приложений без сохранения состояния. Однако в версии были введены домашние животные … Помечено Kubernetes, DevOps, Docker, MongoDB.

Kubernetes в основном использовался для приложений без сохранения состояния. Однако в версии 1.3 были введены домашние зоны, а позже они превратились в наборы состояния. Официальная документация описывает государственные наборы как

Statefulsets предназначены для использования с приложениями Stateful и распределенными системами

Одним из лучших вариантов использования для этого является организация услуг по предоставлению данных, такие как MongoDB, Elasticsearch, Redis, Zookeeper и так далее.

Некоторые Особенности Это может быть приписано Statefulsets:

  1. Стручки с порядковыми индексами
  2. Стабильные сетевые идентификации
  3. Заказано и параллельное управление стручками
  4. Обновления

Одной из очень четкой особенности наборов Stateful является предоставление идентификаторов StablenetWork, которые при использовании с Безголовые службы , может быть еще более мощным.

Не тратя много времени на информацию, легко доступную в документации Kubernetes, давайте сосредоточимся на запуске и масштабировании кластера MongoDB.

Вам нужно иметь бег Kubernetes Cluster с RBAC включен (рекомендуемые). В этом уроке мы будем использовать GKE Cluster Тем не менее, AWS EKS или Microsoft AKS или KOPS, управляемые K8, также являются жизнеспособными альтернативами.

Мы развернем следующие компоненты для нашего кластера MongoDB

1. Демон установил для настройки hostvm 2. Сервисная учетная запись и привязку кластерола для монго 5. Mongo Pods Stateful Set 6.GCP Внутренний LB для доступа к MongoDB извне кластера Kuberntes (необязательно) 7. Доступ к стручкам с использованием Ingress (необязательно)

Важно отметить, что у каждого стручка MongoDB будет работать коляска, чтобы настроить реплику, установленную на лету. Коляска проверяет новые участники каждые 5 секунд.

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 -o errexit
            set -o pipefail
            set -o nounset

            # Disable hugepages
            echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled
            echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag
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

Важные точки:

  1. Коляска для Mongo должна быть тщательно настроена с помощью надлежащих переменных среды, указав этикетки, приведенные POD, пространство имен для развертывания и обслуживания.
  2. Руководство по размеру кеша по умолчанию: «50% ОЗУ минус 1 ГБ, или 256 МБ» Анкет Учитывая, что количество запрошенной памяти составляет 2 ГБ, размер кэша WiredTiger здесь был установлен на 256 МБ
  3. Межпод анти-аффинность Обеспечивает, чтобы на одном и том же рабочем узле запланировано 2 монго -капсула, что делает его устойчивым к сбоям узлов. Кроме того, рекомендуется сохранить узлы в разных AZ, чтобы кластер был устойчив к сбою зон.
  4. В настоящее время развернутая учетная запись имеет привилегии администратора. Тем не менее, это должно быть ограничено пространством имен БД.

После того, как мы развертываем оба манифеста, указанные выше, мы можем проверить компоненты, когда следующие

root$ kubectl -n mongo get all
NAME                 DESIRED   CURRENT   AGE
statefulsets/mongo   3         3         3m
NAME         READY     STATUS    RESTARTS   AGE
po/mongo-0   2/2       Running   0          3m
po/mongo-1   2/2       Running   0          2m
po/mongo-2   2/2       Running   0          1m
NAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)     AGE
svc/mongo   ClusterIP   None                 27017/TCP   3m

Как вы можете видеть, у сервиса нет кластерного IP, и нет внешнего IP, это Безголовный сервис . Эта услуга будет напрямую разрешаться в Pod-Ips для наших государственных наборов.

Чтобы проверить разрешение DNS, мы запустим интерактивную оболочку в нашем кластере

kubectl run my-shell --rm -i --tty --image ubuntu -- bash
root@my-shell-68974bb7f7-cs4l9:/# dig mongo.mongo +search +noall +answer
; <<>> DiG 9.11.3-1ubuntu1.1-Ubuntu <<>> mongo.mongo +search +noall +answer
;; global options: +cmd
mongo.mongo.svc.cluster.local. 30 IN A 10.56.7.10
mongo.mongo.svc.cluster.local. 30 IN A 10.56.8.11
mongo.mongo.svc.cluster.local. 30 IN A 10.56.1.4

DNS для обслуживания будет Анкет Следовательно, в нашем случае это будет Mongo.mongo .

IPS (10.56.6.17, 10.56.7.10, 10.56.8.11) являются IPS нашего Mongo Stateful Set. Это можно проверить, запустив nslookup над ними изнутри кластера.

root@my-shell-68974bb7f7-cs4l9:/# nslookup 10.56.6.17
17.6.56.10.in-addr.arpa name = mongo-0.mongo.mongo.svc.cluster.local.

root@my-shell-68974bb7f7-cs4l9:/# nslookup 10.56.7.10
10.7.56.10.in-addr.arpa name = mongo-1.mongo.mongo.svc.cluster.local.

root@my-shell-68974bb7f7-cs4l9:/# nslookup 10.56.8.11
11.8.56.10.in-addr.arpa name = mongo-2.mongo.mongo.svc.cluster.local.

Если ваше приложение развернуто в кластере K8, то оно может получить доступ к узлам —

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

Если вы хотите получить доступ к узлам монго извне кластера, вы можете развернуть балансировщики внутренней нагрузки для каждой из этих стручков или создать внутренний вход, используя контроллер входа, такой как Nginx или Traefik

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

Развернуть еще 2 аналогичные услуги для Mongo-1 и Mongo-2.

Вы можете предоставить IPS внутренней балансировщика нагрузки для мочеиспускания URI.

root$ kubectl -n mongo get svc
NAME      TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
mongo     ClusterIP      None                    27017/TCP         15m
mongo-0   LoadBalancer   10.59.252.157   10.20.20.2    27017:30184/TCP   9m
mongo-1   LoadBalancer   10.59.252.235   10.20.20.3    27017:30343/TCP   9m
mongo-2   LoadBalancer   10.59.254.199   10.20.20.4    27017:31298/TCP   9m

Внешние IPS для Mongo-0/1/2 являются IPS недавно созданных балансировщиков нагрузки TCP. Они локальные для ваших подсети или заглядываемых сетей, если таковые имеются.

Трафик в Mongo Stateful Set Pods также может быть направлен с использованием контроллера Ingress, такого как Nginx. Убедитесь, что услуга Ingress является внутренней и не выявлена над публичным IP. Объект Ingress будет выглядеть примерно так:

...
spec:
  rules:
  - host: mongo.example.com
    http:
      paths:
      - path: '/'
        backend:
          serviceName: mongo # There is no extra service. This is 
          servicePort: '27017' # the headless service

Важно отметить, что ваше приложение осведомлено как по крайней мере один узел Mongo, который в настоящее время растет, чтобы оно могло обнаружить все остальные.

Вы можете использовать Robo 3T в качестве клиента Mongo на вашем местном Mac. После подключения к одному из узлов и запуска rs.status () , вы можете просмотреть детали набора реплик и проверить, были ли настроены другие 2 стручки и подключены к набору реплик автоматически.

Теперь мы масштабируем набор Stateful для монго, чтобы проверить, добавляются ли новые стручки Mongo в репликат или нет.

root$ kubectl -n mongo scale statefulsets mongo --replicas=4
statefulset "mongo" scaled
root$ kubectl -n mongo get pods -o wide
NAME      READY     STATUS    RESTARTS   AGE       IP           NODE
mongo-0   2/2       Running   0          25m       10.56.6.17   gke-k8-demo-demo-k8-pool-1-45712bb7-vfqs
mongo-1   2/2       Running   0          24m       10.56.7.10   gke-k8-demo-demo-k8-pool-1-c6901f2e-trv5
mongo-2   2/2       Running   0          23m       10.56.8.11   gke-k8-demo-demo-k8-pool-1-c7622fba-qayt
mongo-3   2/2       Running   0          3m        10.56.1.4    gke-k8-demo-demo-k8-pool-1-85308bb7-89a4

Видно, что Все четыре стручки развернуты в разных узлах GKE и, таким образом, наша аффинная политика Pod-Anti работает правильно.

Действие масштабирования также автоматически обеспечит постоянный том, который будет действовать как каталог данных для нового стручка.

root$ kubectl -n mongo get pvc
NAME                               STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mongo-persistent-storage-mongo-0   Bound     pvc-337fb7d6-9f8f-11e8-bcd6-42010a940024   11G        RWO            fast           49m
mongo-persistent-storage-mongo-1   Bound     pvc-53375e31-9f8f-11e8-bcd6-42010a940024   11G        RWO            fast           49m
mongo-persistent-storage-mongo-2   Bound     pvc-6cee0f97-9f8f-11e8-bcd6-42010a940024   11G        RWO            fast           48m
mongo-persistent-storage-mongo-3   Bound     pvc-3e89573f-9f92-11e8-bcd6-42010a940024   11G        RWO            fast           28m

Чтобы проверить, добавляется ли POD с именем Mongo-3 в набор реплики или нет, мы запускаем rs.status () Еще раз на том же узле и наблюдайте за разницей.

Дальнейшие соображения:

  1. Это может быть полезно для МАРЕКА НАЗОНА Pool который будет использоваться для стручков Mongo и обеспечить, чтобы соответствующая аффинность узла упоминается в спецификации для набора Date Daemon Configure и конфигурации HostVM. Это связано с тем, что набор демона изменит некоторые параметры ОС хоста, и эти настройки должны быть ограничены только для стручков MongoDB. Другие приложения могут работать лучше без этих настроек.
  2. Маркировка пула узлов чрезвычайно проста в GKE, может быть непосредственно из консоли GCP.
  3. Хотя мы указали ограничения процессора и памяти в спецификации POD, мы также можем рассмотреть возможность развертывания VPA (Вертикальный POD Autoscaler).
  4. Трафик в наш БД изнутри кластера может контролироваться путем реализации сетевых политик или сервисной сетки, такой как Istio Анкет

Цель этого блога — дать вам достаточно информации, чтобы начать работу с наборами Stateful на Kubernetes и надеемся, что вы найдете это полезным.

Оригинал: «https://dev.to/appfleet/orchestrating-mongodb-over-kubernetes-1o5d»