
No início deste mês, 3 de maio, foi anunciada uma grande versão do "sistema de gerenciamento para data warehouses distribuídos em Kubernetes" -
Rook 1.0.0 . Mais de um ano atrás, já
publicamos uma visão geral do Rook. Depois, fomos convidados a conversar sobre a experiência de seu
uso na prática - e agora, a tempo de um marco tão significativo na história do projeto, temos o prazer de compartilhar nossas impressões acumuladas.
Em resumo, o Rook é um conjunto de
operadores para o Kubernetes que assumem o controle completo da implantação, gerenciamento e recuperação automática de soluções de armazenamento, como Ceph, EdgeFS, Minio, Cassandra, CockroachDB.
No momento, a solução mais desenvolvida (e
apenas em um estágio
estável ) é o
operador de torre-ceph .
Nota : Entre as mudanças significativas no release da Rook 1.0.0 relacionadas ao Ceph, é possível notar o suporte ao Ceph Nautilus e a capacidade de usar o NFS para bucket do CephFS ou RGW. Entre outros, destaca-se o "amadurecimento" do suporte do EdgeFS ao nível beta.Então, neste artigo, nós:
- responda à pergunta de quais vantagens vemos ao usar o Rook para implantar o Ceph no cluster Kubernetes;
- compartilhar experiências e impressões sobre o uso da torre na produção;
- Vamos dizer por que dizemos "Sim!" Para Rook e nossos planos para ele.
Vamos começar com conceitos e teoria gerais.
"Eu tenho uma vantagem em uma torre!" (jogador de xadrez desconhecido)

Uma das principais vantagens do Rook é que a interação com os data warehouses é realizada através dos mecanismos do Kubernetes. Isso significa que você não precisa mais copiar os comandos para configurar o Ceph do folheto para o console.
- Deseja implantar em um cluster CephFS? Basta escrever um arquivo yaml!
- o que? Deseja implantar um armazenamento de objetos com a API S3? Basta escrever um segundo arquivo yaml!Rook é criado por todas as regras de um operador típico. A interação ocorre com a ajuda de
CRD (Custom Resource Definitions) , na qual descrevemos as características das entidades Ceph de que precisamos
(uma vez que esta é a única implementação estável, por padrão, o artigo falará sobre Ceph, a menos que seja explicitamente indicado o contrário) . De acordo com os parâmetros definidos, o operador executará automaticamente os comandos necessários para a configuração.
Vejamos os detalhes usando o exemplo da criação de um Object Store, ou melhor,
CephObjectStoreUser
.
apiVersion: ceph.rook.io/v1 kind: CephObjectStore metadata: name: {{ .Values.s3.crdName }} namespace: kube-rook spec: metadataPool: failureDomain: host replicated: size: 3 dataPool: failureDomain: host erasureCoded: dataChunks: 2 codingChunks: 1 gateway: type: s3 sslCertificateRef: port: 80 securePort: instances: 1 allNodes: false --- apiVersion: ceph.rook.io/v1 kind: CephObjectStoreUser metadata: name: {{ .Values.s3.crdName }} namespace: kube-rook spec: store: {{ .Values.s3.crdName }} displayName: {{ .Values.s3.username }}
Os parâmetros indicados na listagem são bastante padrão e dificilmente precisarão de comentários, mas você deve prestar atenção especial aos que são destacados nas variáveis de modelo.
O esquema geral de trabalho se resume ao fato de que, através do arquivo YAML, "ordenamos" recursos, para os quais o operador executa os comandos necessários e nos retorna o segredo "não real", com o qual podemos continuar trabalhando
(veja abaixo) . E a partir das variáveis indicadas acima, o comando e o nome do segredo serão compostos.
Que tipo de equipe é essa? Ao criar um usuário para armazenamento de objetos, a instrução Rook dentro do pod fará o seguinte:
radosgw-admin user create --uid="rook-user" --display-name="{{ .Values.s3.username }}"
O resultado deste comando será uma estrutura JSON:
{ "user_id": "rook-user", "display_name": "{{ .Values.s3.username }}", "keys": [ { "user": "rook-user", "access_key": "NRWGT19TWMYOB1YDBV1Y", "secret_key": "gr1VEGIV7rxcP3xvXDFCo4UDwwl2YoNrmtRlIAty" } ], ... }
Keys
é o que aplicativos futuros precisarão acessar o armazenamento de objetos por meio da API S3. O operador Rook os seleciona e os coloca em seu namespace como um segredo com o nome
rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}
.
Para usar dados desse segredo, basta adicioná-los ao contêiner como variáveis de ambiente. Como exemplo, darei um modelo para Job, no qual criamos automaticamente buckets para cada ambiente de usuário:
{{- range $bucket := $.Values.s3.bucketNames }} apiVersion: batch/v1 kind: Job metadata: name: create-{{ $bucket }}-bucket-job annotations: "helm.sh/hook": post-install "helm.sh/hook-weight": "2" spec: template: metadata: name: create-{{ $bucket }}-bucket-job spec: restartPolicy: Never initContainers: - name: waitdns image: alpine:3.6 command: ["/bin/sh", "-c", "while ! getent ahostsv4 rook-ceph-rgw-{{ $.Values.s3.crdName }}; do sleep 1; done" ] - name: config image: rook/ceph:v1.0.0 command: ["/bin/sh", "-c"] args: ["s3cmd --configure --access_key=$(ACCESS-KEY) --secret_key=$(SECRET-KEY) -s --no-ssl --dump-config | tee /config/.s3cfg"] volumeMounts: - name: config mountPath: /config env: - name: ACCESS-KEY valueFrom: secretKeyRef: name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }} key: AccessKey - name: SECRET-KEY valueFrom: secretKeyRef: name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }} key: SecretKey containers: - name: create-bucket image: rook/ceph:v1.0.0 command: - "s3cmd" - "mb" - "--host=rook-ceph-rgw-{{ $.Values.s3.crdName }}" - "--host-bucket= " - "s3://{{ $bucket }}" ports: - name: s3-no-sll containerPort: 80 volumeMounts: - name: config mountPath: /root volumes: - name: config emptyDir: {} --- {{- end }}
Todas as atividades listadas neste trabalho foram realizadas sem ir além do Kubernetes. As estruturas descritas nos arquivos YAML são dobradas no repositório Git e reutilizadas repetidamente. Nisto vemos uma enorme vantagem para os engenheiros de DevOps e o processo de CI / CD como um todo.
Com Rook e Rados para Joy
O uso de um monte de Ceph + RBD impõe certas restrições na montagem de volumes nos pods.
Em particular, o espaço para nome deve ter um segredo para acessar o Ceph, para que os aplicativos com estado possam funcionar. Tudo bem se você tiver 2-3 ambientes em seus namespaces: você pode copiar o segredo manualmente. Mas e se cada recurso de desenvolvedor criar um ambiente separado com seu próprio espaço para nome?
Resolvemos esse problema com a ajuda de um
operador de shell , que copiava automaticamente segredos para o novo espaço para nome (um exemplo desse gancho é descrito
neste artigo ).
No entanto, ao usar o Rook, esse problema simplesmente não existe. O processo de montagem ocorre usando seus próprios drivers baseados em
Flexvolume ou
CSI (ainda em beta) e, portanto, não requer segredos.
Rook resolve automaticamente muitos problemas, o que nos encoraja a usá-lo em novos projetos.
Cerco da Torre
Concluímos a parte prática com a implantação de Rook e Ceph para a possibilidade de realizar nossos próprios experimentos. Para invadir esta torre inexpugnável, foi mais fácil, os desenvolvedores prepararam um pacote Helm. Vamos fazer o download:
$ helm fetch rook-master/rook-ceph --untar --version 1.0.0
rook-ceph/values.yaml
pode encontrar muitas configurações diferentes no arquivo
rook-ceph/values.yaml
. Mais importante, especifique tolerâncias para agentes e pesquisa. Por que você pode usar o mecanismo de tolerâncias / tolerâncias, descrevemos em detalhes
neste artigo .
Em resumo, não queremos que os pods com o aplicativo cliente estejam localizados nos mesmos nós em que os discos para armazenamento de dados estão localizados. O motivo é simples: dessa forma, o trabalho dos agentes da Rook não afetará o aplicativo em si.
Portanto, abra o arquivo
rook-ceph/values.yaml
editor favorito e adicione o seguinte bloco ao final:
discover: toleration: NoExecute tolerationKey: node-role/storage agent: toleration: NoExecute tolerationKey: node-role/storage mountSecurityMode: Any
Para cada nó reservado para armazenamento de dados, adicione a mancha correspondente:
$ kubectl taint node ${NODE_NAME} node-role/storage="":NoExecute
Em seguida, instale o Helm-chart com o comando:
$ helm install --namespace ${ROOK_NAMESPACE} ./rook-ceph
Agora você precisa criar um cluster e indicar a localização do
OSD :
apiVersion: ceph.rook.io/v1 kind: CephCluster metadata: clusterName: "ceph" finalizers: - cephcluster.ceph.rook.io generation: 1 name: rook-ceph spec: cephVersion: image: ceph/ceph:v13 dashboard: enabled: true dataDirHostPath: /var/lib/rook/osd mon: allowMultiplePerNode: false count: 3 network: hostNetwork: true rbdMirroring: workers: 1 placement: all: tolerations: - key: node-role/storage operator: Exists storage: useAllNodes: false useAllDevices: false config: osdsPerDevice: "1" storeType: filestore resources: limits: memory: "1024Mi" requests: memory: "1024Mi" nodes: - name: host-1 directories: - path: "/mnt/osd" - name: host-2 directories: - path: "/mnt/osd" - name: host-3 directories: - path: "/mnt/osd"
Verifique o status do Ceph - espere ver
HEALTH_OK
:
$ kubectl -n ${ROOK_NAMESPACE} exec $(kubectl -n ${ROOK_NAMESPACE} get pod -l app=rook-ceph-operator -o name -o jsonpath='{.items[0].metadata.name}') -- ceph -s
Ao mesmo tempo, verifique se os pods com o aplicativo cliente não chegam aos nós reservados para Ceph:
$ kubectl -n ${APPLICATION_NAMESPACE} get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName
Outros componentes opcionais estão configurados. Mais informações sobre eles são indicadas na
documentação . Para administração, é altamente recomendável instalar o painel e a caixa de ferramentas.
Torres e ganchos: a torre é suficiente para tudo?
Como você pode ver, o desenvolvimento do Rook está em pleno andamento. Mas ainda existem problemas que não nos permitem abandonar completamente a configuração manual do Ceph:
- Nenhum driver Rook pode exportar métricas no uso de blocos montados, o que nos impede de monitorar.
- O Flexvolume e o CSI não sabem como redimensionar volumes (diferentemente do mesmo RBD); portanto, o Rook perde uma ferramenta útil (e às vezes extremamente necessária!).
- Rook ainda não é tão flexível quanto o Ceph comum. Se quisermos configurar o pool para que os metadados do CephFS sejam armazenados no SSD e os próprios dados no HDD, precisaremos registrar manualmente grupos de dispositivos separados nos mapas CRUSH.
- Apesar de o operador rook-ceph ser considerado estável, no momento existem alguns problemas ao atualizar o Ceph da versão 13 para 14.
Conclusões
"Agora Rook está fechada do mundo exterior por peões, mas acreditamos que um dia ela desempenhará um papel decisivo na festa!" (uma cotação foi inventada especificamente para este artigo)O projeto Rook, sem dúvida, conquistou nossos corações - acreditamos que [com todos os seus prós e contras] definitivamente merece sua atenção.
Nossos planos adicionais se resumem em tornar o rook-ceph um módulo para
addon-operator , que tornará seu uso em nossos muitos clusters Kubernetes ainda mais simples e conveniente.
PS
Leia também em nosso blog: