Kubernetes の Mongodb 大量のデータを挿入するとタイムアウトが発生する

Kubernetes の Mongodb 大量のデータを挿入するとタイムアウトが発生する

実行中のAPIがあり、これは1日に1回、MongoDBに挿入される大量のデータの複数のバッチを受け取ります。cvallance/mongo-k8s-sidecarレプリケーションセット構成に使用します。

これはローカルの mongodatabase では完璧に動作します。

また、条件などを発生させる可能性のあるデータベース上の運用トラフィックもありません。

今、私たちはそれを Google コンテナ エンジンにデプロイしました。そこでもインポートは一般的に機能します。しかし、時々次のようなタイムアウト例外が発生しました:

ノードが現在構成を更新中のため、replSetReconfig を実行できません

または

MongoDB.Driver.MongoCommandException: コマンドの挿入に失敗しました: BSONObj サイズ: 16793637 (0x1004025) が無効です。サイズは 0 から 16793600 (16MB) の範囲でなければなりません。最初の要素: 挿入: "LandingPageConnectionSet_Stage"。

または

ワークループでエラーが発生しました { MongoError: ソケットの Function.MongoError.create (/opt/cvallance/mongo-k8s-sidecar/node_modules/mongodb-core/lib/error.js:29:11) で、0 から 127.0.0.1:27017 への接続がタイムアウトしました。 (/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)

CPU が限界に達していないことがわかります。

mongodb の Kubernetes 構成

---
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"

答え1

Boas Enkler と一緒にログと 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 ファイルにメモリ要求フィールドがないことに気付きました。これは問題です。ワークロードのないノードが 3 つある場合でも、理論的には適合するため、すべての POD がまったく同じノードで開始される可能性があるからです。

この動作を軽減するために、いくつかの解決策が考えられます。

  • クラスターを垂直にスケールし、メモリ要求値を導入する

  • 指導するmongodb プロセスが要求された量よりも少ないメモリ量を消費するようにします。

  • 同じノードで複数のコンテナが実行されていて、それらのコンテナがメモリ制限によって強制終了されるのを避けたい場合は、メモリ制限の導入が不可欠です。この方法では、ノードに使用可能なメモリがまだある場合でも、コンテナが強制終了される場合があることに注意してください。

関連情報