
Temos uma API em execução que recebe uma vez por dia vários lotes de grandes dados que são inseridos em um mongodb. Usamos o cvallance/mongo-k8s-sidecar
para a configuração do replicationset
Isso funciona perfeitamente em um banco de dados mongo local.
também não há tráfego de produção no banco de dados que possa gerar condições de aumento ou algo assim.
Agora nós o implantamos em um mecanismo de contêiner do Google. Lá a importação funciona em geral também. Mas de vez em quando obtemos exceções de tempo limite como esta:
Não é possível executar replSetReconfig porque o nó está atualizando sua configuração
ou
MongoDB.Driver.MongoCommandException: Falha na inserção do comando: tamanho do BSONObj: 16793637 (0x1004025) é inválido. O tamanho deve estar entre 0 e 16793600(16MB) Primeiro elemento: insira: "LandingPageConnectionSet_Stage".
ou
Erro no workloop { MongoError: conexão 0 a 127.0.0.1:27017 expirou em Function.MongoError.create (/opt/cvallance/mongo-k8s-sidecar/node_modules/mongodb-core/lib/error.js:29:11) na Soquete. (/opt/cvallance/mongo-k8s-sidecar/node_modules/mongodb-core/lib/connection/connection.js:198:20) em Object.onceWrapper (events.js:254:19) em Socket.emit (events. js:159:13) em Socket._onTimeout (net.js:411:8) em ontimeout (timers.js:478:11) em tryOnTimeout (timers.js:302:5) em Timer.listOnTimeout (timers.js: 262:5)
Posso ver que a CPU parece não estar no limite.
Configuração do Kubernetes para 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
também alteramos pouco a configuração, limitando o tamanho do cache do wiretiger e removendo as opções de smallfiles para que a parte da configuração ficasse assim:
- mongod
- "--replSet"
- rs0
- "--bind_ip"
- 0.0.0.0
- "--noprealloc"
- "--wiredTigerCacheSizeGB"
- "1.5"
Responder1
Verifiquei os logs e o Dashboard do Kubernetes com Boas Enkler.
No painel do Kubernetes sobre o status dos PODs havia as seguintes dicas:
Pod Name: kube-lego-*****-***
Status: Evicted
Reason: The node was low on resource: memory.
Você poderia ter recuperado as mesmas informações atravéskubectl describe pod [podname]
Observe que citando odocumentação: "Se o kubelet não conseguir recuperar recursos suficientes no nó, o kubelet começará a despejar os pods."
Portanto acreditei que o erro com o Mongodb já que estava funcionando no local sem nenhum problema, para verificar novamente passamos pelos logs do Kernel mostrados pela saída serial do console e encontramos:
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
Percebemos também que não havia campo Memory Request no arquivo YAML da implantação. Isso é um problema, pois pode acontecer que mesmo que haja três nós sem carga de trabalho, todos os PODs sejam iniciados no mesmo nó, pois eles teoricamente se encaixam.
Para mitigar este comportamento existem algumas soluções possíveis:
Dimensione verticalmente o cluster e introduza valores de solicitação de memória
Instruiro processo mongodb consome uma quantidade de memória menor que a solicitada.
A introdução do limite de memória é essencial se você tiver mais contêineres rodando no mesmo nó e quiser evitar que eles sejam eliminados por isso. Considere que desta forma ele será eliminado algumas vezes, mesmo que ainda haja memória disponível no nó.