Docker + Cluster DRBD + SQL Server – Database as a Service utilizando volumes replicados

AGRADEÇA AO AUTOR COMPARTILHE!

Este artigo abordará como configurar dois nós em um Cluster Ativo/Passivo através da ferramenta DRBD Manage.

Entretanto, teremos um volume DRBD em modo primário/primário em ambos os hosts.

Deste modo, todos os dados gravados no nó Ativo serão replicados para o nó Passivo, dados esses que irão compor um volume de dados que poderá ser utilizado por um ou mais containers que serão provisionados através da tecnologia Docker.

O container que iremos provisionar utilizará a imagem oficial da Microsoft para disponibilizar o serviço de Banco de Dados Microsoft SQL Server.

Para a criação do volume de dados replicado no Docker utilizaremos o plugin drbdmanage.

Realizaremos operações no container em execução no primeiro nó do cluster e em seguida, pararemos a execução do container no primeiro nó e inicializaremos ele no segundo nó, permitindo demonstrar que os dados não só irão persistir após a finalização do container como será replicado para o segundo nó do Cluster.

Um pouco de história

Docker

Docker é um projeto open source que permite automatizar o desenvolvimento, distribuição e execução de aplicações em Linux containers.

Um Linux container é um método para executar isoladamente um ou mais binários em um único host (hospedeiro), sem a necessidade de um hipervisor (que demandaria a instalação de um sistema operacional convidado).

projeto Docker pode ser instalado e configurado com facilidade não apenas em sistemas GNU/Linux, mas também em sistemas como Windows e Mac OS/X.

Diferentemente de uma tecnologia de virtualização como Linux KVM, VMWare vSphere, Xen e Hyper-V que demandam a instalação de um sistema operacional convidado, compartilham apenas o Kernel do host no qual estão sendo executados, onde binários e bibliotecas dentro de cada container são a priori restritos ao ambiente de execução de cada container.

Deste modo, cada aplicação/serviço em execução dentro de um container poderá ter seus binários e bibliotecas atualizados sem a preocupação de prejudicar outros containers.

Docker é baseado na tecnologia LXC (Linux Containers), mas temos outras tecnologias de containers como o Jails de sistemas BSD, assim como, temos tecnologias muito mais simples para criação de sandbox (que é base para a idéia empregada em Linux Containers), por exemplo, chroot, onde é possível isolar serviços como o Web Service Apache e o DNS Service Bind.

O Docker foi desenvolvido inicialmente como uma API de alto nível que complementaria o LXC , mas a partir da versão 0.9 introduziu sua própria biblioteca, desenvolvida utlizando a linguagem GO.

Através do Docker é possível executar aplicações diversas como, por exemplo, servidores de banco de dados, web application service, servidores de banco de dados (alvo deste artigo).

Supondo que temos um host com Debian, é possível executarmos containers que disponibilize um sistema/distribuição Ubuntu, Suse ou CentOS, pois toda a árvore de filesystem contendo binários, arquivos de configuração, bibliotecas (dinâmicas e estáticas) particulares para cada distribuição estarão isoladas em cada container, onde o único elemento utilizado em comum por cada container é o kernel.

DRBD

DRBD é um software compatível com o Sistema Operacional Linux desenvolvido pela empresa Linbit que permite estabelecer um sistema de armazenamento distribuído e replicado.

Ele foi implementado como módulo do Kernel Linux, bem como, oferece diversas ferramentas e scripts para gerenciamento dos volumes replicados.

DRBD é  tradicionalmente utilizado em Cluster de Computador com finalidade de complementar sistemas de Alta Disponibilidade. Entretanto, desde a versão 9 ele também vem sendo utilizado para criação de grande estruturas para armazenamento de dados baseados no conceito de SDS (Software Defined Storage), bem como, vem evoluindo com grande foco na integração com tecnologias de Cloud Computing.

É possível utilizar dois modos de operação: Ativo/Passivo (modo que iremos utilizar neste artigo) e o modo Ativo/Ativo, que permite que tanto o primeiro nó do Cluster como o segundo possar ler e gravar dados no volume replicado. Entretanto, o uso do modo Ativo/Ativo demanda tecnologias complementares para gerenciamento do acesso concorrente aos dados, neste caso, sistemas de arquivos para clusters, como por exemplo, GFS2 e OCFS, bem como, é possível utilizar uma variação da tecnologia LVM, o Cluster LVM (CLVM), que permite alocar volumes lógicos de dados (que representam partições de disco) de maneira simultânea em ambos os nós do Cluster.

Mão na massa

Atualmente o Docker tem suporte a plugins, o que permite estender suas funcionalidades, e no caso deste artigo, iremos utilizar um plugin para volume de dados, o que permitirá especificamente armazenar o conteúdo de volumes Docker sob um backend storage DRBD.

A vantagem é que todas as operações que um ou mais containers realizar sob seus volumes de dados, não serão simplesmente gravadas em um filesystem local, mas gravados em um dispositivo virtual de blocos replicados gerenciado pelo módulo de kernel do DRBD, replicando os dados para um ou mais hosts (nós) do nosso Cluster.

A abordagem deste artigo será simplemente permitir que quando um container for ser executado em dos nós do Cluster, ele terá acesso aos dados mais recentes existentes no volume, pois este volume é proveniente de uma estrutura de replicação estabelecida pelo DRBD.

Em outros artigos estaremos explorando ambientes mais complexos com o DRBD atuando em um modo Ativo/Ativo.

Para criação de nosso container que proverá o serviço de banco de dados baseado no Microsoft SQL Server, estaremos utilizando uma imagem de container Docker disponibilizada pela Microsoft denominada microsoft/mssql-server-linux

Para este artigo utilizaremos o Docker Hub para realizar o pull da imagem acima mencionada.

A seguir temos os requisitos mínimos para poder utilizar a imagem de container Docker disponibilizada pela Microsoft:

  • Docker Engine 1.8 ou superior
  • Mínimo de 4 GB de espaço em disco
  • Mínimo de 4 GB de RAM (apesar que para a finalidade de testes, uma máquina virtual 2.5 GB atenderá o mínimo de 2 GB exigido pelo SQL Server sobre container).
  • Configurar uma senha forte para a conta de administrador do serviço do SQL Server, senha essa contendo pelo menos 8 caracteres utilizando letras maiúsculas e minúsculas, números e/ou símbolos não alfanuméricos.

Para este artigo utilizamos a distribuição CentOS Linux 7 (7.4.1708), e a instalação do Docker pode ser realizada de maneira simples através da etapas abaixo descritas.

Todas as etapas abaixo serão realizadas em ambos os nós do nosso Cluster, que para este artigo os nós serão referenciados como:

– containernode01  – Endereço IP: 192.168.0.161
– containernode02 – Endereço IP: 192.168.0.162

Para atividades de configuração especificas em um determinado nó do Cluster, estaremos informando previamente.

Portanto, em ambos os nós:

– Instale os pacotes que serão dependências no restante do processo de instalação do Docker Engine:

Neste caso, o pacote yum-utils permitirá utilizarmos a ferramenta yum-config-manager para adicionar o repositório Docker Comunity Edition.

– Adicione o repositório ao sistema:

– Instale o pacote do Docker Engine:

– Execute os daemons do Docker e ative o serviço na inicialização do sistema:

– Adicione o atual usuário logado no grupo de usuário Docker. Essa ação fará com que não seja necessária a utilização do comando sudo para utilização docker.

– Reinicie o sistema para testar a inicialização do serviço do Docker:

– Para testar o serviço Docker Engine, execute uma consulta simples através do docker cliente, por exemplo, se existe algum container em execução:

Certamente a listagem estará vazia, o que indica que o docker client conseguiu estabelecer a conexão com o serviço Docker Engine.

– Instale o pacote para adicionar e configurar o repositório EPEL, pois a versão 9 do DRBD que será utilizada neste artigo, encontra-se neste repositório:

– Instale os pacotes do DRBD:

– Ative o carregamento do módulo do kernel durante o boot:

– Instale os pacotes a seguir pois serão necessários para podermos realizar o download e compilar a ferramenta drbdmanage. Em seguida, descompacte o arquivo e proceda com as etapas de build e instalação:

– Realize um teste com a ferramenta drbdmanage. O retorno deverá ser a palavra “pong”, indicando que a ferramenta está funcional:

A grande vantagem da ferramenta drbdmanage é que ela facilita o gerenciamento de Clusters utilizando a tecnologia DRBD. Através dela podemos gerenciar dispositivos de bloco baseados em LVM ou ZFS, onde o mesmo estejam sob um dispositivos de replicação DRBD.

Para este artigo teremos em cada nó do Cluster dois discos, sendo um para uso exclusivo do sistema operacional e demais serviços e um dele para criação do volume de dados replicados pelo DRBD, e que será utilizado para o armazenamento de dados de forma persistente em nossos containers.

Por padrão o drbdmanage possui uma referência a um volume group chamado drbdpool, referência essa existente no arquivo /etc/drbdmanaged.cfg

Podemos manter esse nome padrão ou altera-lo no arquivo de configuração anteriormente citado. Para este artigo iremos utilizar o nome, containersData, portanto, execute o comando abaixo para realizar a alteração:

Para este artigo, vamos supor que a segunda unidade de disco seja /dev/sdb, portanto, criaremos um volume group chamado containersData nesta unidade de disco.

– Crie uma partição primária na segunda unidade de disco e em seguida crie um volume físico e depois o volume lógico chamado containersData

No host containernode01 (192.168.0.161) e containernode02 (192.168.0.162) criaremos pares de chaves, para permitir que a partir de um host possamos acessar o outro via SSH, sem a necessidade de informarmos senha e vice-versa. Esta etapa é importante, pois iremos utilizar a ferramenta drbdmanage para provisionar nossa infraestrutura de Cluster, etapa essa que pode ser simplificada devido a autenticação entre hosts poderem ser realizadas por meio de chaves RSA.

– No host containernode01 (192.168.0.161) execute:

– No host containernode02 (192.168.0.162) execute:

– No host containernode01 (192.168.0.161) execute:

– No hosts containernode01 e containernode02 edite o arquivo /etc/hosts, deixando o final dele da seguinte forma para não dependermos de uma infraestrutura DNS para a resolução.

– No host containernode01 (192.168.0.161) execute:

Em ambos os comandos deverá ser exibido o hostname do host 192.168.0.162. Esta etapa é importante, para testarmos a comunicação entre ambos hosts via SSH sem uso autenticação baseada em senha, pois conforme exposto, isto permitirá que a ferramenta drbdmanage estabeleça a conexão via SSH entre os hosts e procedimentos, como por exemplo, criação de volumes lógicos sob o dispositivo de bloco replicado DRBD seja realizado durante a criação de volumes docker.

– No host containernode02 (192.168.0.162) execute:

Os testes de conexão via SSH sem senha em um primeiro momento, permitirá que os hosts que estão sofrendo conexão sejam inseridos na lista de hosts conhecidos em  (/root/.ssh/know_hosts).

Os volumes de dados que criaremos a partir do docker utilizará um plugin chamado drbdmanage, onde todas as chamadas realizadas a esse plugin serão direcionadas ao serviço docker-drbdmanage-plugin, e o mesmo utilizará a atual estrutura de cluster provisionada, permitindo transparência durante a criação de volumes no docker, criação essa que utilizará do mecanismo de replicação do DRBD.

Provisionando o Cluster

– No host containernode01, execute:

Confirme a operação informando “yes”.

– Verifique que dois volumes DRBD foram criados:

– Verifique o status do Cluster que até o momento possui um nó:

– No host containernode01, execute o comando abaixo para associar o segundo nó ao Cluster:

Confirme a operação informando “yes”.

Esta etapa será executada baseando-se no uso do SSH, portanto, a criação dos pares de chaves que realizamos anteriormente (para permitir autenticação sem depender de senha) é fundamental para o funcionamento desta etapa.

– No host c0ntainernode01, verifique o status do Cluster que agora possuirá dois nós:

– No host containernode02, execute o comando abaixo para verificar o status da replicação:

Observe que o Status indicado é Secundário para o containernode02 e Primário para o containernode01, bem como, os dois volumes criados estão em estado UpToDate entre os volumes 0 e 1 de ambos os nós do Cluster.

Instalando o serviço DRBD Manage Docker Volume Plugin

Em ambos os nós do Cluster:

– Realize o download o arquivo e proceda com a: descompactação, build e instalação dos arquivos e ativação do serviço:

No último comando é necessário que o status do serviços esteja em running para podermos proceder com as próximas etapas.

Criando um volume de dados no Docker para persistência de dados.

Neste etapa utilizaremos o plugin/driver drbdmanage para criar nosso volume de dados, para permitir a persistência de dados após a finalização do container.

Todas as etapas a seguir serão realizadas no primeiro nó do Cluster (containernode01) execute:

Os dois últimos comandos poderão ser executados também no segundo do Cluster (containernode02), para elucidar que as operações de gravação no primeiro nó, são replicadas para o segundo nó, bem como, o volume criado no docker automaticamente teve um volume lógico LVM criado para armazenar as informações.

Lembrando que todas as operações de leitura e escrita no container são direcionadas ao driver drbdmanage, que faz com que as informações sejam armazenadas em um volume lógico LVM, volume este que está sob um device virtual (que representa um dispositivo de bloco replicado do DRBD, que por si só replicada as informações para o segundo nó do Cluster).

Criando um container para execução do Microsoft SQL Server.

Vamos realizar o pull da imagem de container do SQL Server e utiliza-la para criar e executar o container que proverá um serviço de banco de dados da Microsoft sob o host atual.

Lembrando que, a configuração a seguir utilizará a persistência de dados, pois ao finalizar o container, por padrão os dados serão perdidos, e em muitas situações a perda dos dados gerados durante a execução do container não é aceitável.

Entretanto, tudo dependerá da finalidade do container, afinal, podemos executar um container, gerar informações nele, mas tais informações poderem ser descartadas ou as mesmas já terem sido armazenadas em outro host ou container que utiliza persistência de dados.

– No host containernode01 (192.168.0.161) execute:

Aguarde o pull da imagem para que o container seja criado e entre em execução

O comando acima pode ser entendido da seguinte maneira:

run – esta opção realiza três ações: pull da imagem, criação do container e em seguida execução do container criado.

-e – permite a criação de variáveis de ambiente sob o ambiente de execução do container. No caso acima, foram criadas duas variáveis de ambiente: ACCEPT_EULA recebendo o valor Y e SA_PASSWORD recebendo o valor #AdminSQLServer2017 (que será a senha da conta System Administrator do SQL Server). Deste modo, durante a execução do binário existente na imagem que sofreu o pull, este binário irá verificar a existências destas variáveis e utilizar os valores setados nelas.
A variável ACCEPT_EULA permite que definir se os termos da licença de uso serão aceitos.

-p – permite realizar o mapeamento de portas. No caso acima, qualquer conexão a porta 1433 (  valor numérico a esquerda dos :  ) será redirecionada para a porta 1433 (  valor numérico a direita dos :  ) em listening no container.

-d – executará o container em modo background.

-v – anexará um volume externo a um volume dentro do container, no caso, teremos o mapeamento do volume criado e gerenciado pelo serviço DRBD (volumeDatabase) existente no host físico para o diretório /var/opt/mssql existente no container.

Portanto, a ação de criação, exclusão e alteração ocorrida em /var/opt/mssql dentro do container também ocorrerá em no volume volumeDatabase, que por sua vez realizará o armazenamento no host físico onde o container é executado e os blocos de dados serão replicado para o segundo nó do Cluster.

–name – Define o nome que o container terá ao ser criado.

Em seguida verifique se o container está em execução:

Caso o container não seja listado, então execute novamente o comando docker run sem a opção -d

Para podermos visualizar no console qualquer mensagem de erro durante a inicialização dos binários do container.
Um erro muito comum é a falta de memória no host, lembrando que a recomendação mínima são 4 GB.

Outra opção muito importante para verificar a inicialização de serviços/binários dentro de um container é a opção logs, portanto, você pode verificar da seguinte maneira:

Verificada a existência de algum erro (por exemplo, quantidade de memória insuficiente), abra outro terminal e pare o container com o comando:

Para executar novamente o container, basta executar:

Verifique novamente se o container está em execução:

Inspecione as propriedades do volume que criamos anteriormente. Esta etapa permite verificar por exemplo, onde nosso volume está montado atualmente, bem como, verificar que o mesmo trata-se de um volume de dados replicado via DRBD:

No ambiente em que estamos utilizando, as seguintes informações foram expostas:

“Driver”: “drbdmanage”,
“Labels”: {},
“Mountpoint”: “/run/docker/drbdmanage/mnt/volumeDatabase”,
“Name”: “volumeDatabase”,
“Options”: {
“fs”: “ext4”,
“size”: “400”
},
“Scope”: “local”

Execute o comando mount para confirmar que o volume está sob um device de replicação em bloco DRBD:

A indicação do device /dev/drbdXXX indica que o volume está sob DRBD, onde XXX indica o valor atribuído no momento para o nome do dispositivo DRBD.

Podemos verificar que durante o carregamento do serviço o Microsoft SQL Server dentro do container, diversos arquivos, incluindo os datafiles foram criados, simplemente listando os arquivos do ponto de montagem verificado anteriormente.

Para listar os datafiles do serviço do SQL Server, execute:

Com o container em execução iremos estabelecer uma sessão de usuário com o serviço em execução sob o Container.

Dentro das das vantagens clássicas de container temos isolamento, portabilidade e flexibilidade, e graças a isso podemos não apenas executar binários e  bibliotecas existentes em uma imagem na forma de um container que atuará como serviço, mas também podemos simplesmente realizar a chamada a outros binários existentes no container já em execução, por exemplo, um binário que represente uma ferramenta de linha de comando que faz parte da solução empacotada dentro da imagem.

Iremos iniciar o binário bastante conhecido por DBAs que trabalham com SQL Server, o sqlcmd para estabelecermos uma sessão de usuário com o serviço do SQL Server.

A opção exec realiza a chamada a binários existentes dentro de um container em execução, ou seja, sem precisar criar um novo container apenas para executar um binário já existente na imagem que foi utilizada de base para a criação do container anterior.

Já as opções -it permitem que durante a execução do binário sqlcmd seja possível estabelecer a interação entre entre o shell e o binário em execução no momento.

Após a execução do binário sqlcmd será exibido o prompt

Execute a instrução SQL select a seguir acompanhada da instrução GO:

Serão exibidos os databases padrão do SQL Server, no caso:

  • master
  • tempdb
  • model
  • msdb

Realizaremos a seguir algumas operações simples em SQL:

  • Criação de um database;
  • Abertura do database;
  • Criação de uma tabela;
  • Inserção de registros nesta tabela;
  • Consulta de registros;

Com a sessão finalizada com a instrução exit, iremos parar o container e inicia-lo novamente para comprovar que a persistência de dados está sendo realizada corretamente.

Verifique se o container não encontra-se mais em execução:

Inicie o container novamente e verifique que o binário do serviço do SQL Server em execução sob o container irá obter acesso aos datafiles:

Execute o binário do cliente sqlcmd novamente:

Liste os databases existentes:

Verificando a replicação de dados para o segundo nó do Cluster

Iremos parar o container no primeiro nó do Cluster (containernode01):

Verifique também que ao finalizar a execução do Container, o volume é desmontado, verificando o atributo MountPoint que antes referenciava /run/docker/drbdmanage/mnt/volumeDatabase e agora referencia somente /

Acesse o segundo nó do Cluster (containerhost02), e crie o container utilizando o comando a seguir:

Aguarde o pull da imagem para que o container seja criado e entre em execução.

Execute o binário do cliente sqlcmd novamente:

Liste os databases existentes:

O último select comprova que todos os database do SQL Server, inclusive o que database que criamos (empresa) foi replicado para o segundo nó do Cluster.

Esta abordagem permite definir um host de containers que atuará em modo stand by, permitindo que na ocorrência de falhas do primeiro nó, o segundo nó inicie os containers e os mesmo acesse a réplica realizada dos volumes.

Conforme pode ser verificado, com a replicação de dados garantimos a alta disponibilidade de dados persistentes para containers, bem como, com o uso do plugin e da ferramenta drbdmanage, podemos rapidamente não só provisionar um Cluster, mas realizar a criação de volumes no Docker com grande facilidade.

AGRADEÇA AO AUTOR COMPARTILHE!

Waldemar Dibiazi Junior

Mais artigos deste autor »

Analista de Infraestrutura de Redes da Prorede Telecom - Ribeirão Preto - SP, trabalhou em dezenas de projetos de virtualização, reestruturação, implantação, bem como, projetos envolvendo clusters fail over, Segregação de Redes, VPNs, Load Balance, File Servers sob Clusters, Monitoramento de Infraestrutura e Nuvens Privadas sob Amazon AWS e Openstack.

Engenheiro de Computação, Pós Graduação em Banco de Dados, MBA em Gestão de Infraestrutura como Serviço, certificado Red Hat RHCSA, RHCE e RHCSA-OSP, estando entre os 20 primeiros certificados da América da Latina na plataforma Openstack da Red Hat.


Deixe seu comentário

Seu endereço de e-mail não será publicado. Campos com * são obrigatórios!

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">