Estudo de caso: Sistema de arquivos CEPH
Ceph é um sistema de armazenamento que pode ser implantado em grandes clusters de servidores com discos anexados. O vídeo a seguir aborda os conceitos básicos por trás do Ceph.
Os objetivos de design para Ceph2 incluem o seguinte:
- Um cluster de armazenamento de uso geral que é flexível para ser compatível com uma ampla variedade de aplicativos.
- Uma arquitetura que pode ser dimensionada de maneira direta para centenas de milhares de nós e petabytes de armazenamento.
- Um sistema altamente confiável sem nenhum ponto único de falha que é autogerenciado e robusto.
- O sistema deve ser executado em um hardware de commodities com disponibilidade imediata. O Ceph foi projetado para ser acessível por meio de três abstrações diferentes, conforme mostrado na figura a seguir.
O cluster de armazenamento Ceph é um repositório de objetos distribuído. Diferentes serviços de armazenamento voltados para o cliente estão em camadas sobre o cluster de armazenamento. O serviço do gateway de objeto do Ceph permite que os clientes acessem um cluster de armazenamento Ceph usando uma interface HTTP baseada em REST que no momento é compatível com os protocolos S3 da Amazon e Swift do Openstack. O serviço de dispositivo de blocos do Ceph permite que os clientes acessem o cluster de armazenamento como dispositivos de blocos, que podem ser formatados com um sistema de arquivos local e montados em um sistema operacional ou usados como um disco virtual para operar máquinas virtuais em Xen, KVM, VMWare ou QEMU. Por fim, o Ceph FS (sistema de arquivos Ceph) fornece uma abstração de arquivos e diretórios em todo o cluster de armazenamento como um sistema de arquivos em conformidade com o POSIX.
Figura 6: ecossistema Ceph
A arquitetura do Ceph será ilustrada abaixo com uma análise mais detalhada:
Figura 7: arquitetura Ceph
A base do Ceph é um sistema de armazenamento de objetos distribuído chamado RADOS. Os clientes podem interagir com o RADOS diretamente usando uma API de nível baixo chamada librados, que é baseada em soquetes e compatível com várias linguagens de programação. Como alternativa, os clientes podem interagir com as três APIs de nível superior que fornecem três abstrações separadas no RADOS.
RADOS Gateway ou radosgw permite que os clientes acessem o RADOS por meio de um gateway baseado em REST sobre HTTP. Isso emula o serviço de objeto do Amazon S3 e é compatível com aplicativos que usam a API do Amazon S3 ou a API do Openstack SWIFT.
O Dispositivo de Blocos RADOS ou RBD expõe o repositório de objetos do RADOS como um dispositivo de blocos distribuído de uso geral, muito parecido com uma SAN. O RBD permite que os dispositivos de blocos sejam gravados do RADOS e montados em sistemas Linux usando um driver de kernel. Os RBDs também podem ser usados como imagens de disco virtual para sistemas de virtualização populares, como Xen, VMWare, KVM e QEMU.
O Ceph FS é um sistema de arquivos distribuído em conformidade com o POSIX que está em camadas sobre o RADOS e que pode ser montado diretamente nos sistemas de arquivos de clientes Linux. O Ceph FS será discutido em detalhes posteriormente nesta página.
Arquitetura do cluster de armazenamento Ceph (RADOS)
A base do Ceph é o RADOS (Repositório Confiável e Autônomo de Objetos Distribuído). No RADOS, os dados são armazenados como objetos distribuídos sobre um cluster de computadores. Os clientes interagem com um cluster RADOS ao armazenar e recuperar objetos. Um objeto é composto por um nome de objeto, que é a chave usada para identificar um objeto, bem como por conteúdos binários do objeto, o valor associado a uma chave de objeto específica. A função do RADOS é armazenar objetos de maneira distribuída em um cluster de modo escalonável, confiável e tolerante a falhas.
Há dois tipos de nós em um cluster RADOS: OSDs (daemons de armazenamento de objetos) e nós de monitoramento (Figura 8). Um OSD armazena objetos e responde a solicitações de objetos. Os OSDs armazenam esses objetos em nós usando o sistema de arquivos local em cada nó e mantém um cache de buffer para aprimorar o desempenho. Os nós de monitoramento inspecionam o status do cluster para manter o controle dos OSDs que entram e saem do cluster.
Figura 8: Arquitetura RADOS. Os OSDs são responsáveis pelos dados em um nó. Um OSD normalmente é implantado por disco físico. Os nós marcados com M são os nós de monitoramento.
Estado do cluster e monitores no RADOS
O estado de um cluster RADOS é encapsulado em um objeto conhecido como mapa de cluster que é compartilhado por todos os nós em um cluster. O mapa de cluster contém informações sobre o estado de um cluster em um determinado momento, incluindo o número de OSDs presentes, uma representação compacta de como os dados são distribuídos entre os OSDs, que será discutida em detalhes na próxima seção, e um carimbo de data/hora lógico que indica a hora em que esse mapa de cluster foi criado. As atualizações para o mapa de cluster são feitas de maneira incremental e ponto a ponto pelos nós de monitoramento. Isso significa que somente as alterações no mapa de cluster de um carimbo de data/hora são comunicadas entre os nós em um cluster, a fim de manter pequena a quantidade de dados transferidos entre os nós.
Os monitores no RADOS são coletivamente responsáveis pelo gerenciamento do sistema de armazenamento ao armazenar a cópia mestra do mapa de cluster e enviar atualizações periódicas, caso haja uma alteração no estado dos OSDs. Os monitores são organizados com base no algoritmo paxos e exigem que a maioria dos monitores leia ou atualize o mapa de cluster. Os monitores garantem que as atualizações de mapa sejam serializadas e consistentes. Um cluster RADOS foi projetado para ter um pequeno número de monitores (>3) que normalmente é um número ímpar para garantir que as ligações não sejam interrompidas quando os monitores individuais precisarem chegar a um consenso.
Posicionamento de dados no RADOS
Para que um armazenamento de objeto distribuído funcione corretamente, o cliente deverá ser capaz de entrar em contato com o OSD correto para interagir com um objeto. O cliente primeiro entrará em contato com um monitor a fim de recuperar o mapa de cluster para o cluster de armazenamento fornecido. As informações contidas no mapa de cluster poderão ser usadas para determinar o OSD exato que é responsável por um determinado objeto no cluster.
A primeira etapa será determinar o grupo de posicionamento de um objeto específico (Figura 9). Um grupo de posicionamento poderá ser considerado o bucket no qual um objeto reside. Isso será feito usando uma função de hash. A função de hash mais recente a ser usada sempre será obtida do mapa de cluster. Depois que o grupo de posicionamento do objeto fornecido for determinado, o cliente precisará localizar o OSD responsável por esse grupo de posicionamento.
Figura 9: como localizar um objeto em um grupo de posicionamento e em um OSD usando o algoritmo CRUSH.
O algoritmo usado para atribuir grupos de posicionamento aos OSDs é conhecido como o algoritmo Controlled Replication Under Scalable Hashing (CRUSH)1 (Figura 9). O CRUSH atribui grupos de posicionamento em um cluster de maneira pseudoaleatória, porém determinística. O CRUSH é mais estável do que uma função de hash já que quando os OSDs entram ou saem do cluster, o CRUSH garante que a maioria dos grupos de posicionamento permaneça onde está e desloca somente uma pequena quantidade de dados para manter uma distribuição balanceada. Uma função de hash simples, por outro lado, exigiria a redistribuição da maioria das chaves quando os buckets fossem adicionados ou removidos. A descrição completa do algoritmo CRUSH está além do escopo desta discussão. Leitores interessados podem consultar CRUSH: Controlled, scalable, decentralized placement of replicated data.
Quando um nome de objeto for transformado em hash em um grupo de posicionamento, o CRUSH produzirá uma lista de exatamente r OSDs que serão responsáveis pelo grupo de posicionamento. Neste exemplo, r será o número de réplicas de um determinado objeto. Com base nas informações do mapa de cluster, os OSDs ativos que estão nesse mapeamento são identificadas e o OSD pode ser contatado para interagir (operações como criar, ler, atualizar, excluir) com o objeto especificado.
Replicação no RADOS
No RADOS, um objeto é replicado entre vários OSDs associados ao grupo de posicionamento desse objeto. Isso garante que haja várias cópias de um objeto específico no caso de falha de um determinado OSD. O RADOS tem vários esquemas disponíveis nos quais a replicação é realmente executada. Estes são os esquemas de replicação de cópia primária, em cadeia e de abertura (Figura 10).
Figura 10: Modos de replicação compatíveis com o RADOS. (Fonte 2)
Replicação de cópia primária: No esquema de replicação de cópia primária um cliente interage com o primeiro OSD disponível (OSD de réplica primária) para interagir com um objeto. O OSD de réplica primária processará a solicitação e responderá ao cliente. No caso de uma gravação, o OSD de réplica primária encaminhará a solicitação de gravação para r-1 réplicas que atualizarão as cópias locais do objeto e responderão ao mestre. A operação de gravação no mestre será atrasada até que todas as gravações sejam confirmadas por outros OSDs para esse objeto. O mestre reconhecerá a gravação para o cliente. A gravação não será concluída até que todas as réplicas tenham respondido à cópia primária do OSD. O mesmo processo se aplicará às leituras, pois a cópia primária responderá a uma leitura somente depois que todas as réplicas tiverem sido contatadas e o valor do objeto for o mesmo em todas as réplicas.
Replicação em cadeia: As solicitações de um objeto serão encaminhadas pela cadeia até que a rª réplica (final) seja encontrada. Caso a operação seja uma gravação, ela será confirmada em cada uma das réplicas e enviada para a última réplica. O último OSD com a réplica final reconhecerá a gravação no cliente. Todas as operações de leitura serão direcionadas diretamente para a parte final, a fim de reduzir o número de saltos necessários para ler os dados de um cluster.
Replicação de abertura: A replicação de abertura combina elementos da replicação de cópia primária e a replicação em cadeia. As solicitações de leitura são direcionadas para o último OSD na cadeia de réplicas, enquanto as gravações são enviadas primeiro para o cabeçalho. Diferentemente da cadeia, as atualizações para os OSDs intermediários são feitas em paralelo, semelhante ao esquema de replicação de cópia primária.
Além desses esquemas de replicação, a persistência no RADOS é manipulada usando duas mensagens de confirmação separadas (Figura 11). Cada OSD tem um cache do buffer dos dados servidos por ele. As atualizações são gravadas no cache do buffer e reconhecidas imediatamente por meio de uma mensagem de confirmação. Esse cache do buffer é periodicamente liberado para o disco e quando a última réplica confirmar os dados no disco, uma mensagem de confirmação será enviada ao cliente, indicando que os dados foram persistentes.
Figura 11: Confirmação versus mensagens de confirmação no RADOS (Source 2)
Modelo de consistência no RADOS
Todas as mensagens no RADOS, do cliente e as mensagens ponto a ponto entre os nós, são marcadas com o carimbo de data/hora para garantir que elas sejam ordenadas e aplicadas de maneira consistente. Caso os OSDs detectem uma mensagem incorreta devido a um mapa de cluster desatualizado do solicitante da mensagem, eles enviarão as atualizações do mapa incremental para atualizar o solicitante.
Há casos incomuns nos quais as garantias estritas de consistência oferecidas pelo RADOS deverão ser tratadas com cuidado. Caso os mapeamentos do grupo de posicionamento de um determinado OSD sejam alterados, no caso de uma alteração no mapa de cluster, o sistema deverá garantir que a entrega dos grupos de posicionamento entre os OSDs antigos e novos deverá ser feita de maneira direta e consistente. Durante a alteração do grupo de posicionamento, os OSDs novos deverão contatar os antigos para obter uma transferência de estado, durante a qual os OSDs antigos saberão sobre a alteração e interromperão a resposta a consultas para esses grupos de posicionamento específicos.
Outra situação em que pode ser difícil obter garantias estritas de consistência é no caso de uma falha de rede provocar uma partição de rede. Nesse caso, alguns clientes que têm um mapa de cluster antigo poderão continuar executando operações de leitura nesse OSD enquanto um mapa atualizado poderá alterar o OSD responsável por esse grupo de posicionamento. Lembre-se de que esse é um cenário de falha que foi destacado anteriormente em nossa discussão sobre o teorema CAP. Nesse caso, a janela de inconsistência sempre existirá. O RADOS busca reduzir o efeito desse cenário, exigindo que todos os OSDs pulsem com outras réplicas em um intervalo padrão de 2 segundos. Caso um OSD específico não possa alcançar os outros grupos de réplicas em um determinado limite, ele bloqueará as leituras. Além disso, os OSDs atribuídos para serem o novo primário de um grupo de posicionamento específico deverão receber uma confirmação de transferência do antigo grupo de posicionamento primário ou aguardar até que o intervalo de pulsação pressuponha que esse grupo está inoperante. Dessa forma, uma possível janela de inconsistência em um cluster RADOS será reduzida na presença de partições de rede.
Detecção de falha e tolerância a falhas no RADOS
Serão detectadas falhas de nó no RADOS durante uma falha de comunicação entre os OSDs atribuídos a um grupo de posicionamento ou entre OSDs e nós de monitoramento. Caso um nó falhe em responder dentro de um número limitado de tentativas de reconexão, ele será declarado como inativo. Os OSDs que fazem parte de um grupo de posicionamento trocarão mensagens de pulsação para garantir que as falhas sejam detectadas. Isso resultará em nós de monitoramento assumindo a liderança na atualização do mapa de cluster e na notificação de todos os nós por meio de uma mensagem de atualização de mapa incremental. Após uma atualização de mapa de cluster, os OSDs trocarão objetos entre si para garantir que o número desejado de réplicas seja mantido para cada grupo de posicionamento. Caso um OSD descubra uma mensagem que foi declarada inativa, ele simplesmente sincronizará o buffer no disco e eliminará a si mesmo para garantir que o comportamento seja consistente.
Sistema de arquivos Ceph
Conforme indicado na figura anterior, o Ceph FS é uma camada de abstração sobre o sistema de armazenamento do RADOS. O RADOS não tem nenhuma noção dos metadados de um objeto além do nome do objeto. O sistema de arquivos Ceph permite que os metadados do arquivo sejam colocados em camadas sobre os objetos de arquivos individuais armazenados no RADOS. O vídeo a seguir explicará o conceito de CephFS.
Além das funções de nó de cluster dos OSDs e monitores, o Ceph FS apresenta os servidores de MDS (metadados) (Figura 12). Esses servidores armazenam os metadados do sistema de arquivos: a árvore de diretórios, bem como as listas de controle de acesso e as permissões, o modo, as informações de propriedade e os carimbos de data/hora de cada arquivo.
Figura 12: servidores de metadados no sistema de arquivos Ceph
Os metadados usados pelo Ceph FS são diferem dos metadados usados pelo sistema de arquivos local de várias maneiras. Lembre-se de que em um sistema de arquivos local um arquivo é descrito por um inode, que contém uma lista de ponteiros apontando para os blocos de dados de um arquivo. Os diretórios em um sistema de arquivos local são simplesmente arquivos especiais com links para outros inodes que podem ser outros diretórios ou arquivos. No Ceph FS, um objeto do directory no servidor de metadados contém todos os inodes incorporados dentro dele.
Partição dinâmica de subárvore
Um servidor de metadados será inicialmente responsável por todos os metadados do cluster. À medida que os servidores de metadados forem adicionados ao cluster, a árvore de diretório do sistema de arquivos será particionada e atribuída ao grupo resultante dos servidores de metadados (Figura 13). Cada MDS mede a popularidade dos metadados na própria hierarquia de diretório usando contadores. Um esquema ponderado3 é usado não apenas para atualizar o contador de um nó folha específico no diretório, mas também para os ancestrais desse elemento de diretório até a raiz. Portanto, cada MDS será capaz de manter uma lista de pontos de acesso nos metadados que poderão ser migrados para um novo MDS quando ele for adicionado ao cluster.
Figura 13: partição dinâmica de subárvore no sistema de arquivos Ceph
Cache e tolerância a falhas em servidores de metadados
Os servidores de metadados no Ceph FS normalmente armazenam informações de metadados em cache na memória e atendem a maioria das solicitações sem memória. Além disso, os servidores do MDS usam uma forma de registro em diário em que as atualizações são enviadas por downstream para o RADOS como objetos de diário e são gravadas por servidor de metadados. No caso de falha de um servidor de metadados, o diário poderá ser reproduzido para recompilar a parte do servidor MDS com falha da árvore em um novo MDS ou em um MDS existente.
Referências
- Weil, S. A., Brandt, S. A., Miller, E. L. e Maltzahn, C. (2006). CRUSH: Controlled, scalable, decentralized placement of replicated data In Proceedings of the 2006 ACM/IEEE conference on Supercomputing 122
- Weil, S. A., Brandt, S. A., Miller, E. L. e Maltzahn, C. (2006). Ceph: A scalable, high-performance distributed file system Proceedings of the 7th symposium on Operating systems design and implementation (OSDI) 307-320
- Weil, S. A., Pollack, K. T., Brandt, S. A. e Miller, E. L. (2004). Dynamic metadata management for petabyte-scale file systems Anais da Conferência da ACM/IEEE de 2004 sobre Supercomputação 4