Fundamentos do Armazenamento em Bloco RBD
O armazenamento em bloco é fundamentado em sequências de bytes de tamanho fixo, geralmente organizados em setores de 512 bytes. Interfaces baseadas em blocos são amplamente utilizadas em mídias tradicionais e modernas, como HDDs, SSDs e soluções de nuvem como EBS e CBS. No ecossistema Ceph, o RBD (RADOS Block Device) oferece uma solução robusta com características avançadas:
- Provisionamento Dinâmico (Thin-provisioning): O espaço é alocado conforme a demanda real.
- Escalabilidade Massiva: Suporte a imagens de até 16 exabytes.
- Snapshots e Clones: Capacidade de criar pontos de restauração e clonagem via Copy-on-write.
- Alta Disponibilidade: Replicação assíncrona multissite e recuperação de desastres.
- Integração Nativa: Suporte direto via driver de kernel e compatibilidade total com KVM/libvirt.
Estratégias de Integração com Kubernetes
A conexão entre o Ceph e o Kubernetes pode ser realizada através de três abstrações principais:
- Volumes: Definição direta no manifesto do Pod, referenciando o driver específico.
- PV/PVC (Persistent Volume / Claim): Abstração que separa a requisição de armazenamento da sua implementação física.
- StorageClass: Automatiza o provisionamento. O administrador define as classes e o usuário solicita via PVC, permitindo o provisionamento dinâmico.
Provisionamento Dinâmico com Rook
O Rook atua como um operador cloud-native que simplifica a implantação e o gerenciamento do Ceph dentro do Kubernetes. Ele gerencia automaticamente drivers CSI (Contanier Storage Interface) para RBD e CephFS. Abaixo, definimos uma classe de armazenamento utilizando o driver CSI do Rook:
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: pool-replicado-dados
namespace: rook-ceph
spec:
failureDomain: host
replicated:
size: 3
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-rbd-sc
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph
pool: pool-replicado-dados
imageFormat: "2"
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
csi.storage.k8s.io/fstype: xfs
allowVolumeExpansion: true
reclaimPolicy: Delete
Após a aplicação deste manifesto, é possível verificar a criação do pool e da classe de armazenamento:
# Verificação do Pool no Ceph
ceph osd lspools
# Resultado esperado: 1 device_health_metrics, 2 pool-replicado-dados
# Verificação da StorageClass no Kubernetes
kubectl get sc ceph-rbd-sc
Implementação Prática: Aplicação WordPress e MySQL
Para demonstrar o uso do armazenamento RBD, utilizaremos uma arquitetura clássica de WordPress com banco de dados MySQL, onde ambos utilizam PVCs vinculados à nossa StorageClass.
Configuração do Banco de Dados (MySQL)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-mysql-dados
spec:
storageClassName: ceph-rbd-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 15Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: db-mysql
spec:
selector:
matchLabels:
app: blog-storage
tier: db
template:
metadata:
labels:
app: blog-storage
tier: db
spec:
containers:
- image: mysql:5.7
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: senha_forte_123
volumeMounts:
- name: mysql-vol
mountPath: /var/lib/mysql
volumes:
- name: mysql-vol
persistentVolumeClaim:
claimName: pvc-mysql-dados
Configuração da Camada de Aplicação (WordPress)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-wp-html
spec:
storageClassName: ceph-rbd-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-wordpress
spec:
selector:
matchLabels:
app: blog-storage
tier: frontend
template:
metadata:
labels:
app: blog-storage
tier: frontend
spec:
containers:
- image: wordpress:latest
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: db-mysql-service
- name: WORDPRESS_DB_PASSWORD
value: senha_forte_123
volumeMounts:
- name: wp-vol
mountPath: /var/www/html
volumes:
- name: wp-vol
persistentVolumeClaim:
claimName: pvc-wp-html
Fluxo de Provisionamento e Persistência
O ciclo de vida do provisionamento segue uma lógica automatizada pelo driver CSI:
- O usuário submete um PersistentVolumeClaim (PVC).
- A StorageClass identifica o provisioner (Rook-Ceph).
- O provisioner solicita ao Ceph a criação de uma imagem RBD no pool correspondente.
- Um PersistentVolume (PV) é criado dinamicamante e vinculado (Bound) ao PVC.
- O driver mapeia o dispositivo de bloco no nó onde o Pod está agendado e monta o sistema de arquivos solicitado.
Para validar o mapeamanto no nível do sistema operacional, pode-se executar o comando rbd showmapped nos nós do cluster, revelando os dispositivos /dev/rbd* ativos.
Escalabilidade com StatefulSets
Para aplicações que exigem armazenamento persistente individual por réplica, como clusters de bancos de dados ou sistemas distribuídos, utilizamos o volumeClaimTemplates em um StatefulSet:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: srv-web-escalavel
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: web-node
template:
metadata:
labels:
app: web-node
spec:
containers:
- name: nginx
image: nginx:alpine
volumeMounts:
- name: data-storage
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: data-storage
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "ceph-rbd-sc"
resources:
requests:
storage: 5Gi
Neste modelo, cada Pod gerado (ex: srv-web-escalavel-0, srv-web-escalavel-1) receberá seu próprio volume RBD exclusivo e persistente.