🗄️ Armazenamento Compartilhado (RWX) com CephFS
Este guia mostra como instalar o Ceph com o operador Rook em um Cluster Kubernetes no Nuvion da SaveinCloud e criar um CephFS, um sistema de arquivos compartilhado.
Com o CephFS, o cluster passa a oferecer volumes ReadWriteMany (RWX): vários pods, em workers diferentes, montam e gravam no mesmo volume ao mesmo tempo. Isso é útil para aplicações com várias réplicas que precisam dos mesmos arquivos, como uploads de um site, conteúdo estático e arquivos de configuração.
O passo a passo segue a documentação oficial do Rook:
🧩 1. Como Funciona
| Componente | O que faz | Onde roda |
|---|---|---|
| Operador Rook | Instala e gerencia o Ceph dentro do Kubernetes | 1 pod em um worker |
| Monitores (mon) | Guardam o mapa do cluster Ceph; precisam de maioria (quorum) | 3, um em cada worker |
| Managers (mgr) | Métricas e módulos do Ceph | 2 (1 ativo, 1 standby) |
| OSDs | Gravam os dados, um por disco | 1 por worker, no volume extra |
| MDS | Servidor de metadados do CephFS | 2 (1 ativo, 1 standby-replay) |
| Driver CSI | Cria e monta os volumes nos pods | Plugin em cada worker |
Os dados do CephFS são gravados com 3 réplicas, cada uma em um worker diferente. Se um worker cair, os dados continuam disponíveis nos outros dois.
⚠️ 2. Pré-requisitos
- 3 workers (recomendado): o Ceph usa 3 monitores e guarda cada dado em 3 workers diferentes. Com menos de 3 workers, o cluster não chega a
HEALTH_OKe os dados ficam sem redundância. - Recursos dos workers: recomendamos pelo menos 4 vCPU e 8 GiB de RAM em cada worker. Com 1 vCPU e 2 GiB, os pods do Ceph não cabem.
- Um volume extra por worker: veja o próximo passo.
- Ferramentas:
kubectlcom acesso ao cluster (veja Gerenciamento do Cluster) egit.
💽 3. Criando os Volumes para os Workers
O Ceph precisa de discos dedicados. Cada worker deve receber um volume novo, vazio e sem formatação, que vai ser usado só pelo Ceph.
Cada worker do cluster já vem com dois volumes, que não devem ser usados pelo Ceph:
- Volume do nó (
vda): disco do sistema operacional. - Volume dos containers (
vdb): onde ficam as imagens e os dados dos containers, montado em/var/lib/containerd.
O Ceph deve ficar em um terceiro volume (vdc), criado só para ele. Assim, os dados do Ceph não disputam espaço com o sistema nem com as imagens dos containers.
1. No painel do Nuvion, crie um volume para cada worker, todos do mesmo tamanho. Como cada dado é guardado 3 vezes, o espaço útil do CephFS é mais ou menos o tamanho de um volume. Por exemplo, 3 volumes de 10 GiB dão cerca de 10 GiB úteis. Veja como criar um volume em Block Storage.
2. Anexe cada volume a um worker diferente (node-0, node-1 e node-2).
O Rook só usa discos vazios: sem partição e sem sistema de arquivos. Não rode mkfs nem mount nesses volumes. Se o disco tiver um sistema de arquivos, o Rook pula o disco e o OSD não é criado.
3. Confira se o volume aparece vazio em cada worker. Troque <nome-do-worker> pelo nome mostrado em kubectl get nodes:
kubectl debug node/<nome-do-worker> -it --image=busybox:1.36 --profile=sysadmin -- chroot /host lsblk -f
O novo volume deve aparecer como vdc, sem nada nas colunas FSTYPE e MOUNTPOINTS:
NAME FSTYPE ... MOUNTPOINTS
vda ← volume do nó (sistema)
├─vda3 ext4 /boot
└─vda4 xfs /sysroot ...
vdb xfs /var/lib/containerd ← volume dos containers
vdc ← volume novo, para o Ceph
O comando cria um pod node-debugger-... no namespace default. Ao terminar, apague esse pod com kubectl delete pod <nome-do-pod> (o nome aparece em kubectl get pods).
📥 4. Baixando os Manifestos do Rook
Clone o repositório do Rook na versão desejada. Este guia usa a v1.21.0:
git clone --single-branch --branch v1.21.0 https://github.com/rook/rook.git
cd rook/deploy/examples
Todos os arquivos usados daqui em diante estão nesse diretório.
⚙️ 5. Instalando o Operador Rook
Crie os CRDs, as permissões comuns, o operador do CSI e o operador do Rook:
kubectl create -f crds.yaml -f common.yaml -f csi-operator.yaml
kubectl create -f operator.yaml
Espere o pod do operador ficar Running:
kubectl -n rook-ceph get pod -l app=rook-ceph-operator -w
🛠️ 6. Ajustando e Criando o Cluster Ceph
O cluster.yaml de exemplo já vem pronto para este cenário:
useAllNodes: trueeuseAllDevices: true: o Rook procura discos vazios em todos os nós e cria um OSD em cada um. Ele encontra ovdce ignora ovdae ovdb, porque esses já têm sistema de arquivos.security.cephx.csi.keyType: aes: chaves compatíveis com o kernel dos nós. O Ceph 20 gera chaves AES-256 por padrão, e o kernel 6.12 do Fedora CoreOS não aceita esse tipo; o mount falharia comUnknown error 524. Não altere essa opção.
Como o tipo aes é considerado inseguro pelo Ceph 20, o cluster fica em HEALTH_WARN com avisos de insecure key types. Esses avisos são esperados nesse cenário. Para silenciá-los, edite o cluster.yaml:
vi cluster.yaml
Procure a seção healthCheck: e adicione o bloco muteHealthWarning:
healthCheck:
muteHealthWarning:
AUTH_INSECURE_ROTATING_SERVICE_KEY_TYPE:
policy: mute
AUTH_INSECURE_CLIENT_KEY_TYPE:
policy: mute
AUTH_INSECURE_KEYS_ALLOWED:
policy: mute
AUTH_INSECURE_KEYS_CREATABLE:
policy: mute
daemonHealth:
# ... (mantenha o restante como está)
Crie o cluster:
kubectl create -f cluster.yaml
Se você já criou o cluster antes de editar o arquivo, aplique a alteração com kubectl apply -f cluster.yaml.
A criação leva alguns minutos. Acompanhe os pods até aparecerem os mon, mgr e um osd por worker:
kubectl -n rook-ceph get pod -w
🧰 7. Instalando o Toolbox e Verificando o Ceph
O toolbox é um pod com a linha de comando ceph, usado para conferir a saúde do cluster:
kubectl create -f toolbox.yaml
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph status
O resultado esperado:
cluster:
health: HEALTH_OK
(muted: AUTH_INSECURE_CLIENT_KEY_TYPE AUTH_INSECURE_KEYS_ALLOWED ...)
services:
mon: 3 daemons, quorum a,b,c
mgr: b(active), standbys: a
osd: 3 osds: 3 up, 3 in
Confira se cada worker tem um OSD e se os OSDs estão nos volumes novos:
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd tree
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph osd metadata | grep -E '"(hostname|devices)"'
Cada OSD deve aparecer em um worker diferente, com "devices": "vdc".
📂 8. Criando o Sistema de Arquivos (CephFS)
Crie o CephFS myfs, com metadados e dados replicados 3 vezes:
kubectl create -f filesystem.yaml
Espere os pods do MDS ficarem Running e confira o sistema de arquivos:
kubectl -n rook-ceph get pod -l app=rook-ceph-mds
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph fs status myfs
Devem aparecer 1 MDS active e 1 standby-replay, em workers diferentes.
🏷️ 9. Criando a StorageClass
Crie a StorageClass rook-cephfs, que os PVCs vão usar:
kubectl apply -f csi/cephfs/storageclass.yaml
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION
rook-cephfs rook-ceph.cephfs.csi.ceph.com Delete Immediate true
allowVolumeExpansion: true: o volume pode ser aumentado depois.reclaimPolicy: Delete: ao apagar o PVC, os dados do volume são apagados junto.
🧪 10. Testando o Volume Compartilhado
Para testar, crie um PVC RWX e um Deployment com 3 réplicas do nginx usando o mesmo volume. Depois, grave um arquivo em um pod e leia nos outros.
1. Crie o arquivo teste-pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: teste-pvc
spec:
accessModes:
- ReadWriteMany
volumeMode: Filesystem
resources:
requests:
storage: 2Gi
storageClassName: rook-cephfs
kubectl apply -f teste-pvc.yaml
kubectl get pvc teste-pvc
O PVC deve ficar Bound, com ACCESS MODES igual a RWX.
2. Crie o arquivo teste.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-compartilhada
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: web-shared
template:
metadata:
labels:
app: web-shared
spec:
containers:
- name: nginx
image: nginx:alpine
volumeMounts:
- name: dados-compartilhados
mountPath: /usr/share/nginx/html
volumes:
- name: dados-compartilhados
persistentVolumeClaim:
claimName: teste-pvc
kubectl apply -f teste.yaml
kubectl get pods -l app=web-shared -o wide -w
3. Com os 3 pods Running, grave um arquivo pelo primeiro pod (troque <pod-1> pelo nome real):
kubectl exec -it <pod-1> -- sh -c "echo 'Olá do Pod 1 através do CephFS' > /usr/share/nginx/html/index.html"
4. Leia o arquivo pelos outros pods:
kubectl exec -it <pod-2> -- cat /usr/share/nginx/html/index.html
kubectl exec -it <pod-3> -- cat /usr/share/nginx/html/index.html
Todos devem mostrar Olá do Pod 1 através do CephFS. Isso confirma que os pods, mesmo em workers diferentes, estão usando o mesmo volume.
5. Ao terminar, remova o teste:
kubectl delete -f teste.yaml -f teste-pvc.yaml
📌 11. Boas Práticas de Uso
Vários pods podem gravar no mesmo volume sem problema quando cada um grava nos seus próprios arquivos. Quando vários pods gravam no mesmo arquivo, a aplicação precisa usar lock (flock/fcntl), que o CephFS respeita entre os nós. Sem lock, gravações simultâneas no mesmo arquivo podem perder dados sem nenhum erro aparecer. O NFS se comporta da mesma forma.
- Espaço útil: confira o espaço livre com
ceph df. Como os dados são guardados 3 vezes, o espaço útil é cerca de 1/3 da soma dos volumes. - Mais espaço: anexe mais um volume vazio em cada worker. O Rook cria um OSD novo para cada disco vazio na próxima reconciliação. Para forçar a reconciliação na hora, reinicie o operador:
kubectl -n rook-ceph rollout restart deploy/rook-ceph-operator. - Bancos de dados: para volumes usados por um único pod, como os de um banco de dados, prefira um volume
ReadWriteOnce. O CephFS é indicado para dados que vários pods precisam acessar ao mesmo tempo.
🩺 12. Solução de Problemas
| Sintoma | Causa provável | Solução |
|---|---|---|
Nenhum pod rook-ceph-osd-N aparece | O volume tem partição ou sistema de arquivos, ou não foi anexado | Confira com lsblk -f (passo 3). Veja o motivo nos logs: kubectl -n rook-ceph logs -l app=rook-ceph-osd-prepare -c provision |
HEALTH_WARN com PGs undersized | Menos de 3 workers com OSD | Garanta 3 workers, cada um com seu volume |
HEALTH_WARN ... insecure key types | Chaves aes, necessárias para o kernel dos nós | Silencie os avisos com o muteHealthWarning (passo 6) |
Pod preso em ContainerCreating com Unknown error 524 | Chaves AES-256, que o kernel dos nós não aceita | Mantenha security.cephx.csi.keyType: aes no cluster.yaml |
PVC preso em Pending | O CephFS ou a StorageClass não foram criados | Confira com ceph fs status myfs e kubectl get sc rook-cephfs |
🗑️ 13. Remoção
A remoção apaga todos os dados do Ceph. Faça backup do que for importante antes de continuar.
Siga a ordem abaixo, a partir do diretório rook/deploy/examples:
# 1. Apague os workloads e PVCs que usam rook-cephfs, e depois a StorageClass
kubectl get pvc -A | grep rook-cephfs
kubectl delete -f csi/cephfs/storageclass.yaml
# 2. Apague o CephFS
kubectl -n rook-ceph delete cephfilesystem myfs
# 3. Autorize a limpeza dos dados e apague o cluster Ceph
kubectl -n rook-ceph patch cephcluster rook-ceph --type merge \
-p '{"spec":{"cleanupPolicy":{"confirmation":"yes-really-destroy-data"}}}'
kubectl -n rook-ceph delete cephcluster rook-ceph
# 4. Quando o CephCluster sumir, remova o toolbox, o operador e os CRDs
kubectl -n rook-ceph get cephcluster
kubectl delete -f toolbox.yaml
kubectl delete -f operator.yaml
kubectl delete -f common.yaml -f csi-operator.yaml -f crds.yaml
Depois, desanexe e apague os volumes dos workers no painel do Nuvion. Para reaproveitar um volume em uma nova instalação do Ceph, ele precisa estar vazio de novo, sem partição e sem sistema de arquivos.
Mais detalhes em Rook Ceph: Cleanup.