У нас есть запущенный api, который получает один раз в день несколько пакетов больших данных, которые вставляются в mongodb. Мы используем cvallance/mongo-k8s-sidecar
для конфигурации набора репликации
Это отлично работает в локальной базе монгоданных.
в базе данных также нет производственного трафика, который мог бы повысить условия или около того.
Теперь мы развернули его на движке контейнеров Google. Там вообще импорт работает. Но время от времени бывали такие исключения:
Невозможно запустить replSetReconfig, потому что узел в настоящее время обновляет свою конфигурацию
или
MongoDB.Driver.MongoCommandException: Ошибка при вставке команды: BSONObj size: 16793637 (0x1004025) недействителен. Размер должен быть от 0 до 16793600 (16 МБ). Первый элемент: вставить: «LandingPageConnectionSet_Stage».
или
Ошибка в рабочем цикле {MongoError: время ожидания подключения 0 к 127.0.0.1:27017 истекло в Function.MongoError.create (/opt/cvallance/mongo-k8s-sidecar/node_modules/mongodb-core/lib/error.js:29:11) в Socket. (/opt/cvallance/mongo-k8s-sidecar/node_modules/mongodb-core/lib/connection/connection.js:198:20) в Object.onceWrapper (events.js: 254: 19) в Socket.emit (events. js: 159: 13) в Socket._onTimeout (net.js: 411: 8) в ontimeout (timers.js: 478: 11) в tryOnTimeout (timers.js: 302: 5) в Timer.listOnTimeout (timers.js: 262: 5)
Я вижу, что процессор, похоже, не на пределе своих возможностей.
Конфигурация Kubernetes для mongodb
---
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: fast
provisioner: kubernetes.io/gce-pd
parameters:
type: pd-ssd
---
apiVersion: v1
kind: Service
metadata:
name: mongo
labels:
name: mongo
spec:
ports:
- port: 27017
targetPort: 27017
clusterIP: None
selector:
role: mongo
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: mongo
spec:
serviceName: "mongo"
replicas: 3
template:
metadata:
labels:
role: mongo
environment: test
spec:
terminationGracePeriodSeconds: 10
containers:
- name: mongo
image: mongo:3.6
command:
- mongod
- "--replSet"
- rs0
- "--bind_ip"
- 0.0.0.0
- "--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
annotations:
volume.beta.kubernetes.io/storage-class: "fast"
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 32Gi
мы также немного изменили конфигурацию, ограничив размер кеша Wiretiger и удалив опции smallfiles, чтобы часть в конфигурации выглядела так:
- mongod
- "--replSet"
- rs0
- "--bind_ip"
- 0.0.0.0
- "--noprealloc"
- "--wiredTigerCacheSizeGB"
- "1.5"
Я проверил журналы и панель управления kubernetes с Боасом Энклером.
В панели управления Kubernetes относительно статуса POD были следующие подсказки:
Pod Name: kube-lego-*****-***
Status: Evicted
Reason: The node was low on resource: memory.
Вы могли бы получить ту же информацию через kubectl describe pod [podname]
Обратите внимание, что цитируя документация: "Если kubelet не может освободить достаточно ресурсов на узле, kubelet начинает выселение Pod'ов."
Поэтому я считал, что это ошибка Mongodb, поскольку он работал в помещении без каких-либо проблем, чтобы дважды проверить, мы просмотрели журналы ядра, показанные последовательным выводом консоли, и обнаружили:
Memory cgroup out of memory: Kill process 4**7 (mongod) score 1494 or sacrifice child
...
Memory cgroup out of memory: Kill process 1**8 (mongod) score 1538 or sacrifice child
Мы также заметили, что в YAML-файле развертывания нет поля запроса памяти. Это проблема, поскольку может случиться так, что даже при наличии трех узлов без нагрузки может случиться так, что все POD будут запущены на одном узле, поскольку они теоретически подходят.
Чтобы смягчить это поведение, есть несколько возможных решений:
Вертикальное масштабирование кластера и введение значений запросов к памяти
Инструктировать процесс mongodb потребляет меньше памяти, чем запрошенная.
Введение ограничения памяти необходимо, если на одном узле работает больше контейнеров, и вы хотите избежать их гибели. Учтите, что таким образом он иногда будет отключен, даже если на узле все еще есть доступная память.