Container Storage Interface (CSI) é uma interface unificada entre Kubernetes e sistemas de armazenamento. Já falamos sobre isso brevemente , e hoje veremos mais de perto a combinação de CSI e Ceph: mostraremos como para o cluster Kubernetes.
O artigo fornece exemplos reais, embora um pouco simplificados, para facilitar a percepção. Não consideramos instalar e configurar clusters Ceph e Kubernetes.
Você está se perguntando como isso funciona?

Então você tem um cluster Kubernetes ao seu alcance, implantado, por exemplo, . Há um cluster Ceph funcionando próximo - você também pode instalá-lo, por exemplo, com este . Espero que não seja necessário mencionar que para produção entre eles deve haver uma rede com largura de banda de pelo menos 10 Gbit/s.
Se você tem tudo isso, vamos lá!
Primeiro, vamos até um dos nós do cluster Ceph e verificamos se está tudo em ordem:
ceph health
ceph -s
A seguir, criaremos imediatamente um pool para discos RBD:
ceph osd pool create kube 32
ceph osd pool application enable kube rbd
Vamos passar para o cluster Kubernetes. Lá, em primeiro lugar, instalaremos o driver Ceph CSI para RBD. Instalaremos, conforme esperado, através do Helm.
Adicionamos um repositório com um gráfico, obtemos um conjunto de variáveis para o gráfico ceph-csi-rbd:
helm repo add ceph-csi https://ceph.github.io/csi-charts
helm inspect values ceph-csi/ceph-csi-rbd > cephrbd.yml
Agora você precisa preencher o arquivo cephrbd.yml. Para fazer isso, descubra o ID do cluster e os endereços IP dos monitores no Ceph:
ceph fsid # так мы узнаем clusterID
ceph mon dump # а так увидим IP-адреса мониторов
Inserimos os valores obtidos no arquivo cephrbd.yml. Ao mesmo tempo, possibilitamos a criação de políticas PSP (Pod Security Policies). Opções em seções plug-in de nó и provedor já no arquivo, eles podem ser corrigidos conforme mostrado abaixo:
csiConfig:
- clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
monitors:
- "v2:172.18.8.5:3300/0,v1:172.18.8.5:6789/0"
- "v2:172.18.8.6:3300/0,v1:172.18.8.6:6789/0"
- "v2:172.18.8.7:3300/0,v1:172.18.8.7:6789/0"
nodeplugin:
podSecurityPolicy:
enabled: true
provisioner:
podSecurityPolicy:
enabled: true
A seguir, só nos resta instalar o gráfico no cluster Kubernetes.
helm upgrade -i ceph-csi-rbd ceph-csi/ceph-csi-rbd -f cephrbd.yml -n ceph-csi-rbd --create-namespace
Ótimo, o driver RBD funciona!
Vamos criar um novo StorageClass no Kubernetes. Novamente, isso requer alguns ajustes no Ceph.
Criamos um novo usuário no Ceph e damos a ele direitos para gravar no pool Kube:
ceph auth get-or-create client.rbdkube mon 'profile rbd' osd 'profile rbd pool=kube'
Agora vamos ver se a chave de acesso ainda está lá:
ceph auth get-key client.rbdkube
O comando produzirá algo assim:
AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==
Vamos adicionar esse valor ao Secret no cluster Kubernetes – onde precisarmos dele chave do usuário:
---
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: ceph-csi-rbd
stringData:
# Значения ключей соответствуют имени пользователя и его ключу, как указано в
# кластере Ceph. ID юзера должен иметь доступ к пулу,
# указанному в storage class
userID: rbdkube
userKey: <user-key>
E criamos nosso segredo:
kubectl apply -f secret.yaml
A seguir, precisamos de um manifesto StorageClass mais ou menos assim:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: <cluster-id>
pool: kube
imageFeatures: layering
# Эти секреты должны содержать данные для авторизации
# в ваш пул.
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-rbd
csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-rbd
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-rbd
csi.storage.k8s.io/fstype: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard
Precisa ser preenchido ID do cluster, o que já aprendemos pela equipe ceph-fside aplique este manifesto ao cluster Kubernetes:
kubectl apply -f storageclass.yaml
Para verificar como os clusters funcionam juntos, vamos criar o seguinte PVC (Persistent Volume Claim):
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
Vamos ver imediatamente como o Kubernetes criou o volume solicitado no Ceph:
kubectl get pvc
kubectl get pv
Tudo parece estar ótimo! Como é isso no lado do Ceph?
Obtemos uma lista de volumes no pool e visualizamos informações sobre nosso volume:
rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653 # тут, конечно же, будет другой ID тома, который выдала предыдущая команда
Agora vamos ver como funciona o redimensionamento de um volume RBD.
Altere o tamanho do volume no manifesto pvc.yaml para 2Gi e aplique-o:
kubectl apply -f pvc.yaml
Vamos esperar que as alterações tenham efeito e observar novamente o tamanho do volume.
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653
kubectl get pv
kubectl get pvc
Vemos que o tamanho do PVC não mudou. Para descobrir o porquê, você pode consultar o Kubernetes para obter uma descrição YAML do PVC:
kubectl get pvc rbd-pvc -o yaml
Aqui está o problema:
mensagem: Aguardando que o usuário (re) inicie um pod para concluir o redimensionamento do volume do sistema de arquivos no nó. tipo: FileSystemResizePending
Ou seja, o disco cresceu, mas o sistema de arquivos nele não.
Para aumentar o sistema de arquivos, você precisa montar o volume. Em nosso país, o PVC/PV criado atualmente não é utilizado de forma alguma.
Podemos criar um pod de teste, por exemplo assim:
---
apiVersion: v1
kind: Pod
metadata:
name: csi-rbd-demo-pod
spec:
containers:
- name: web-server
image: nginx:1.17.6
volumeMounts:
- name: mypvc
mountPath: /data
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: rbd-pvc
readOnly: false
E agora vamos dar uma olhada no PVC:
kubectl get pvc
O tamanho mudou, está tudo bem.
Na primeira parte trabalhamos com o dispositivo de bloco RBD (significa Rados Block Device), mas isso não pode ser feito se diferentes microsserviços precisarem trabalhar com este disco simultaneamente. CephFS é muito mais adequado para trabalhar com arquivos do que com imagens de disco.
Usando o exemplo dos clusters Ceph e Kubernetes, configuraremos o CSI e outras entidades necessárias para trabalhar com o CephFS.
Vamos obter os valores do novo gráfico Helm que precisamos:
helm inspect values ceph-csi/ceph-csi-cephfs > cephfs.yml
Novamente você precisa preencher o arquivo cephfs.yml. Como antes, os comandos do Ceph ajudarão:
ceph fsid
ceph mon dump
Preencha o arquivo com valores como este:
csiConfig:
- clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
monitors:
- "172.18.8.5:6789"
- "172.18.8.6:6789"
- "172.18.8.7:6789"
nodeplugin:
httpMetrics:
enabled: true
containerPort: 8091
podSecurityPolicy:
enabled: true
provisioner:
replicaCount: 1
podSecurityPolicy:
enabled: true
Observe que os endereços dos monitores são especificados no formato simples endereço:porta. Para montar cephfs em um nó, esses endereços são transferidos para o módulo do kernel, que ainda não sabe trabalhar com o protocolo monitor v2.
Alteramos a porta para httpMetrics (o Prometheus irá lá para monitorar métricas) para que não entre em conflito com o nginx-proxy, que é instalado pelo Kubespray. Você pode não precisar disso.
Instale o gráfico Helm no cluster Kubernetes:
helm upgrade -i ceph-csi-cephfs ceph-csi/ceph-csi-cephfs -f cephfs.yml -n ceph-csi-cephfs --create-namespace
Vamos ao armazenamento de dados do Ceph para criar um usuário separado. A documentação afirma que o provisionador CephFS requer direitos de acesso de administrador de cluster. Mas criaremos um usuário separado fs com direitos limitados:
ceph auth get-or-create client.fs mon 'allow r' mgr 'allow rw' mds 'allow rws' osd 'allow rw pool=cephfs_data, allow rw pool=cephfs_metadata'
E vamos dar uma olhada imediata em sua chave de acesso, precisaremos dela mais tarde:
ceph auth get-key client.fs
Vamos criar Secret e StorageClass separados.
Nada de novo, já vimos isso no exemplo do RBD:
---
apiVersion: v1
kind: Secret
metadata:
name: csi-cephfs-secret
namespace: ceph-csi-cephfs
stringData:
# Необходимо для динамически создаваемых томов
adminID: fs
adminKey: <вывод предыдущей команды>
Aplicando o manifesto:
kubectl apply -f secret.yaml
E agora - um StorageClass separado:
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
clusterID: <cluster-id>
# Имя файловой системы CephFS, в которой будет создан том
fsName: cephfs
# (необязательно) Пул Ceph, в котором будут храниться данные тома
# pool: cephfs_data
# (необязательно) Разделенные запятыми опции монтирования для Ceph-fuse
# например:
# fuseMountOptions: debug
# (необязательно) Разделенные запятыми опции монтирования CephFS для ядра
# См. man mount.ceph чтобы узнать список этих опций. Например:
# kernelMountOptions: readdir_max_bytes=1048576,norbytes
# Секреты должны содержать доступы для админа и/или юзера Ceph.
csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret
csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-cephfs
csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret
csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-cephfs
csi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secret
csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-cephfs
# (необязательно) Драйвер может использовать либо ceph-fuse (fuse),
# либо ceph kernelclient (kernel).
# Если не указано, будет использоваться монтирование томов по умолчанию,
# это определяется поиском ceph-fuse и mount.ceph
# mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- debug
Vamos preencher aqui ID do cluster e aplicável no Kubernetes:
kubectl apply -f storageclass.yaml
Проверка
Para verificar, como no exemplo anterior, vamos criar um PVC:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: csi-cephfs-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
storageClassName: csi-cephfs-sc
E verifique a presença de PVC/PV:
kubectl get pvc
kubectl get pv
Se quiser ver arquivos e diretórios no CephFS, você pode montar esse sistema de arquivos em algum lugar. Por exemplo, conforme mostrado abaixo.
Vamos para um dos nós do cluster Ceph e realizar as seguintes ações:
# Точка монтирования
mkdir -p /mnt/cephfs
# Создаём файл с ключом администратора
ceph auth get-key client.admin >/etc/ceph/secret.key
# Добавляем запись в /etc/fstab
# !! Изменяем ip адрес на адрес нашего узла
echo "172.18.8.6:6789:/ /mnt/cephfs ceph name=admin,secretfile=/etc/ceph/secret.key,noatime,_netdev 0 2" >> /etc/fstab
mount /mnt/cephfs
Obviamente, montar o FS em um nó Ceph como esse só é adequado para fins de treinamento, que é o que fazemos em nosso . Não acho que alguém faria isso na produção; há um alto risco de apagar acidentalmente arquivos importantes.
E por fim, vamos verificar como funciona o redimensionamento de volumes no caso do CephFS. Vamos voltar ao Kubernetes e editar nosso manifesto para PVC - aumente o tamanho lá, por exemplo, para 7Gi.
Vamos aplicar o arquivo editado:
kubectl apply -f pvc.yaml
Vejamos o diretório montado para ver como a cota mudou:
getfattr -n ceph.quota.max_bytes <каталог-с-данными>
Para que este comando funcione, pode ser necessário instalar o pacote em seu sistema atr.
Os olhos estão com medo e as mãos estão fazendo
Todos esses feitiços e longos manifestos YAML parecem complicados superficialmente, mas na prática, os alunos do Slurm pegam o jeito rapidamente.
Neste artigo não nos aprofundamos na selva - existe documentação oficial para isso. Se você estiver interessado nos detalhes de configuração do armazenamento Ceph com um cluster Kubernetes, estes links o ajudarão:
No curso Slurm você pode ir um pouco mais longe e implantar um aplicativo real no Kubernetes que usará o CephFS como armazenamento de arquivos. Por meio de solicitações GET/POST, você poderá transferir arquivos e recebê-los do Ceph.
E se você estiver mais interessado em armazenamento de dados, inscreva-se no . Enquanto o teste beta estiver em andamento, o curso pode ser obtido com desconto e você pode influenciar seu conteúdo.
Autor do artigo: Alexander Shvalov, engenheiro praticante , Administrador certificado do Kubernetes, autor e desenvolvedor de cursos Slurm.
Fonte: habr.com
