Mongodb in Kubernetes Timeouts beim Einfügen großer Datenmengen

Mongodb in Kubernetes Timeouts beim Einfügen großer Datenmengen

Wir haben eine API im Einsatz, die einmal am Tag mehrere Batches großer Datenmengen empfängt, die in eine MongoDB eingefügt werden. Wir verwenden die cvallance/mongo-k8s-sidecarfür die Replikationsset-Konfiguration

Dies funktioniert perfekt auf einer lokalen Mongo-Datenbank.

es gibt auch keinen Produktionsverkehr auf der Datenbank, der zu erhöhten Bedingungen oder ähnlichem führen könnte.

Nun haben wir es in einer Google Container Engine bereitgestellt. Dort funktioniert der Import im Allgemeinen auch. Aber von Zeit zu Zeit erhalten wir TimeoutExceptions wie diese:

replSetReconfig kann nicht ausgeführt werden, da der Knoten derzeit seine Konfiguration aktualisiert

oder

MongoDB.Driver.MongoCommandException: Befehlseinfügung fehlgeschlagen: BSONObj-Größe: 16793637 (0x1004025) ist ungültig. Größe muss zwischen 0 und 16793600 (16 MB) liegen. Erstes Element: einfügen: „LandingPageConnectionSet_Stage“.

oder

Fehler in Arbeitsschleife { MongoError: Verbindung 0 zu 127.0.0.1:27017 ist bei Function.MongoError.create (/opt/cvallance/mongo-k8s-sidecar/node_modules/mongodb-core/lib/error.js:29:11) bei Socket abgelaufen. (/opt/cvallance/mongo-k8s-sidecar/node_modules/mongodb-core/lib/connection/connection.js:198:20) bei Object.onceWrapper (events.js:254:19) bei Socket.emit (events.js:159:13) bei Socket._onTimeout (net.js:411:8) bei ontimeout (timers.js:478:11) bei tryOnTimeout (timers.js:302:5) bei Timer.listOnTimeout (timers.js:262:5)

Ich sehe, dass die CPU offenbar nicht am Limit ist.

Kubernetes-Konfiguration für 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

Wir haben auch die Konfiguration leicht geändert, indem wir die Wiretiger-Cachegröße begrenzt und die Smallfiles-Optionen entfernt haben, sodass der Teil in der Konfiguration folgendermaßen aussah:

   - mongod
    - "--replSet"
    - rs0
    - "--bind_ip"
    - 0.0.0.0
    - "--noprealloc"
    - "--wiredTigerCacheSizeGB"
    - "1.5"

Antwort1

Ich habe die Protokolle und das Kubernetes-Dashboard mit Boas Enkler überprüft.

Im Kubernetes Dashboard zum Status der PODs gab es folgende Hinweise:

Pod Name: kube-lego-*****-***     
Status: Evicted 
Reason: The node was low on resource: memory.

Sie hätten die gleichen Informationen erhalten können überkubectl describe pod [podname]

Beachten Sie, dass das Zitieren derDokumentation: „Wenn der Kubelet nicht genügend Ressourcen auf dem Knoten zurückfordern kann, beginnt er mit der Räumung von Pods.“

Daher ging ich davon aus, dass der Fehler bei Mongodb lag, da es vor Ort ohne Probleme funktionierte. Zur Überprüfung gingen wir die Kernel-Protokolle durch, die in der seriellen Konsolenausgabe angezeigt wurden, und fanden:

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

Uns fiel auch auf, dass in der YAML-Datei des Deployments kein Feld für Speicheranforderungen vorhanden war. Dies ist ein Problem, da es passieren kann, dass selbst wenn drei Knoten ohne Arbeitslast vorhanden sind, alle PODs auf demselben Knoten gestartet werden, da sie theoretisch passen.

Um dieses Verhalten zu mildern, gibt es einige mögliche Lösungen:

  • Skalieren Sie den Cluster vertikal und führen Sie Speicheranforderungswerte ein

  • AnweisenDer MongoDB-Prozess verbraucht weniger Speicher als angefordert.

  • Die Einführung eines Speicherlimits ist wichtig, wenn Sie mehrere Container auf demselben Knoten ausführen und vermeiden möchten, dass diese dadurch beendet werden. Bedenken Sie, dass sie auf diese Weise manchmal beendet werden, auch wenn auf dem Knoten noch Speicher verfügbar ist.

verwandte Informationen