Este guia detalha a implantação de um cluster MongoDB altamente disponível no Kubernetes usando StatefulSet e GlusterFS para armazenamento persistente. A configuração elimina pontos únicos de falha, oferece escalabilidade dinâmica e garante a integridade dos dados.
Pré-requisitos
- Cluster Kubernetes operacional (consulte guias de instalação anteriores).
- GlusterFS integrado ao Kubernetes com Heketi (consulte guia de implantação do GlusterFS).
Arquitetura da Implantação
Utilizaremos um StatefulSet para gerenciar três réplicas do MongoDB. Cada pod terá seu próprio volume persistente provisionado dinamicamente pelo GlusterFS, garantindo que os dados sobrevivam a reinicializações de pods.
1. Configuração da StorageClass
Primeiro, criamos um Secret parra autenticação com o Heketi e a StorageClass.
# heketi-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: heketi-secret
namespace: heketi
data:
key: YWRtaW4xMjM=
type: kubernetes.io/glusterfs
$ kubectl create -f heketi-secret.yaml
# storageclass-fast.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
parameters:
resturl: "http://10.254.82.26:8080"
clusterid: "d96022e907f82045dcc426a752adc47c"
restauthenabled: "true"
restuser: "admin"
secretName: "heketi-secret"
secretNamespace: "default"
volumetype: "replicate:3"
provisioner: kubernetes.io/glusterfs
reclaimPolicy: Delete
$ kubectl create -f storageclass-fast.yaml
$ kubectl get storageclasses/fast
2. Autorização do ServiceAccount
O container sidecar precisa de permissões para gerenciar outros pods. Criamos um ClusterRoleBinding para a conta de serviço padrão.
# defaultaccount.yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: default-cluster-admin
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
$ kubectl apply -f defaultaccount.yaml
3. Criação do StatefulSet e Headless Service
O StatefulSet gerencia os pods do MongoDB e inclui a definição do service headless.
# statefulset-mongo.yaml
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.4
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"
- name: KUBERNETES_MONGO_SERVICE_NAME
value: "mongo"
volumeClaimTemplates:
- metadata:
name: mongo-persistent-storage
annotations:
volume.beta.kubernetes.io/storage-class: "fast"
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 2Gi
$ kubectl create -f statefulset-mongo.yaml
Nota: Se houver problemas para baixar as imagens, faça pull manualmente e carregue nos nodes.
4. Verificação da Implantação
$ kubectl get pod -l role=mongo
NAME READY STATUS RESTARTS AGE
mongo-0 2/2 Running 0 9m44s
mongo-1 2/2 Running 0 7m51s
mongo-2 2/2 Running 0 6m1s
$ kubectl get pvc
$ kubectl exec -ti mongo-0 -- mongo
rs0:PRIMARY> rs.status()
A saída mostrará os três membros do cluster com seus nomes DNS no formato: mongo-0.mongo.default.svc.cluster.local.
5. Gerenciamento do Cluster
5.1 Escalonamento
Para adicionar um novo nó ao cluster, aumente o número de réplicas do StatefulSet.
$ kubectl scale statefulset mongo --replicas=4
$ kubectl get pod -l role=mongo
NAME READY STATUS RESTARTS AGE
mongo-0 2/2 Running 0 105m
mongo-1 2/2 Running 0 103m
mongo-2 2/2 Running 0 101m
mongo-3 2/2 Running 0 50m
5.2 Recuperação de Falhas
Se um pod falhar, o StatefulSet o recriará automaticamente usando o mesmo PVC, preservando a identidade e os dados.
$ kubectl delete pod mongo-0
$ kubectl exec -ti mongo-0 -- mongo
rs0:PRIMARY> rs.status()
Após a exclusão, o pod é recraido e se junta ao cluster como um membro SECONDARY. Um novo PRIMARY é eleito automaticamente.