插入大量數據時 Kubernetes 中的 Mongodb 超時
我們有一個正在執行的 api,它每天接收一次插入到 mongodb 中的多批大數據。我們使用
cvallance/mongo-k8s-sidecar
複制集配置這在本地 mongodatabase 上完美執行。
數據庫上也沒有可能提高條件的生產流量。
現在我們將它部署到Google容器引擎。那裡的進口一般也有效。但有時我們會遇到這樣的超時異常:
無法執行 replSetReconfig,因為節點目前正在更新其配置
或者
MongoDB.Driver.MongoCommandException:命令插入失敗:BSONObj 大小:16793637 (0x1004025) 無效。大小必須介於 0 和 16793600(16MB) 第一個元素:插入:“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) 處超時在套接字。(/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"
我和 Boas Enkler 一起檢查了日誌和 kubernetes 儀表板。
在關於 POD 狀態的 Kubernetes 儀表板中,有以下提示:
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 程序消耗的記憶體量小於請求的記憶體量。
- 如果您有更多容器在同一個節點上執行並且您希望避免它們被它殺死,那麼引入記憶體限制是必不可少的。考慮一下,即使節點上仍有可用記憶體,有時也會以這種方式殺死它。