Docker – Introdução a contêineres
Views: 24
Contêineres podem ser utilizados não só para a gestão de ambientes de desenvolvimento mas também na computação em nuvem, isso permite a exportação de configurações e ambientes inteiros entre as diferentes etapas do desenvolvimento. Este artigo apresenta uma introdução aos contêineres, com ênfase em ambientes Linux, e suas funcionalidades, aplicabilidades e comparação com máquinas virtuais. Foi utilizado a implementação do Docker para estas comparações, pois apresenta grande aderência pela comunidade e serviços baseados em computação em nuvem (Iaas, SaaS, PaaS).
O que são contêineres
Contêineres, em sistemas operacionais (SO), é um método de rodar múltiplos ambientes, para aplicações ou sistemas, de maneira isolada em um único host. Isso é obtido através da criação de user spaces (isolamento do kernel), cgroups (“control groups”, isolamento de recursos do hardware, para Linux: CPU, memória, IO de disco, network, etc) e namespaces (isolamento do SO host: árvores de processos, sistema de arquivos, user ID, etc).
Os contêineres têm, em seus ambientes, seus próprios processos, assim aplicações ou sistemas empacotadas em contêineres podem rodar com suas dependências satisfeitas, de maneira agnóstica ao host em que rodam.
Além disso, os contêineres permitem empacotar aplicações e sistemas inteiros, com todas suas dependências, de um ambiente para outro – como o ambiente de desenvolvimento para o ambiente de produção.
Algumas implementações de contêineres são:
- LXC;
- Docker;
- OpenVZ;
- Solaris Conteiners;
- lmctfy;
- WPAR;
Contêineres e o SO
Contêineres são implementações de virtualização ao nível de sistema operacional que provém um ambiente virtual onde é possível rodar um sistema e suas dependências (banco de dados, bibliotecas, binários, etc), mas compartilhando o kernel do hospedeiro.
Além da virtualização (abstração ao SO), contêineres também criam um user space próprio, o que permite o isolamento do uso de CPU, memória, I/O e network.
Contêineres baseados em Linux, podem implementar isolamento por namespaces, o que garante a isolação da visão que o contêiner do host (árvore de processos, usuários, network, sistemas de arquivos montados).
Assim sendo, os contêineres são capazes de criar ambientes verdadeiramente isolados do host, possuindo, dentro do contêiner ou acessando os recursos do host, tudo o que é necessário para rodar uma aplicação ou sistema.
Contêineres e a nuvem
Uma das grandes inovações para os desenvolvedores nos últimos anos, foi o crescimento e a adoção de infraestrutura em nuvem (IaaS), softwares em nuvem (SaaS) e plataformas em nuvem (PaaS). Isso garante controle, métricas, deploy e provisionamento de infraestrutura maneira automatizada e em tempo real.
Contudo, ainda temos problemas em manter diversos ambientes (desenvolvimento, teste, homologação, produção, alfa, beta, ambientes de diferentes funções) de maneira isomórfica.
Os contêineres oferecem uma maneira prática de manter diversos ambientes iguais. Empacotando o ambiente de desenvolvimento e distribuindo esse nos ambientes subsequentes, tiramos a preocupação dos desenvolvedores em produzir uma aplicação de deploy simples e que funcione em diferentes ambientes, e acabamos com a desculpa “funciona na minha máquina”.
Além disso, com a maior adesão de desenvolvedores pelo uso de contêineres, muitos serviços de nuvem têm suporte a Contêineres (criar, realizar deploy e manter).
Máquinas virtuais
Os contêineres parecem muito com a virtualização, mas os dois conceitos estão longe de serem a mesma coisa.
Ambos os casos são implementações de virtualização ao nível de sistema operacional (operating-system-level virtualization), essas implementações permitem criar contêineres, virtualizações e jaulas (jails).
Enquanto os Contêineres se preocupam em apenas em ter as bibliotecas e binários suficientes para rodar a aplicação (tudo isso gerenciado pela contêiner engine (abstração do SO), compartilhando o kernel do hospedeiro), a virtualização se preocupa em levantar um sistema operacional (guest OS, abstração de hardware) com as bibliotecas e binários para rodar a aplicação (tudo isso gerenciado pelo hypervisor, não compartilhando).
Contêineres e VMs
Tanto contêineres quanto máquinas virtuais provêm isolação para ambientes e aplicações. Contudo, ambos funcionam de maneira diferente, pois os contêineres são capazes de visualizar o sistema operacional do hospedeiro ao invés do hardware, enquanto máquinas virtuais não; isso torna contêineres mais portáveis que máquinas virtuais.
Comparativo entre contêineres e máquinas virtuais
Contêineres
Contêineres oferecem uma camada onde é possível empacotar sistemas e aplicações com suas dependências juntos. Inúmeros contêineres podem rodar ao mesmo tempo, em uma mesma máquina, todos compartilhando o kernel do hospedeiro como processos isolados.
Contêineres precisam de pouco espaço (disco e RAM) e processamento do hospedeiro, pois apenas têm o sistema ou aplicativo e algumas dependências satisfeitas, o restante necessário (bibliotecas, binários, softwares e até mesmo o kernel) é compartilhando com o hospedeiro. Tudo isso tomará o corpo de alguns megabytes.
Figura 1 – Exemplo de Dockerfile, responsável por criar um contêiner. O Docker irá copiar uma imagem do WordPress e mudar o dono do arquivo /var/www/html.
Além disso, a escalabilidade é mais simples com contêineres, já que é necessário alocar megabytes para criar instâncias, e temos ferramentas para a automação desse serviço.
Quebrar deploys em várias partes distintas, menores e com responsabilidades únicas, é uma maneira mais elegante de manter grandes sistemas. Ao mesmo tempo, a equipe que mantêm o sistema irá terminar com VÁRIAS PARTES para manter.
Figura 2 – Camadas de um conteiner Docker: da aplicação a infraestrutura. Fonte: What is a Conteiner? , 2017
Um dos grandes problemas que vêm com a abordagem dos contêineres é a gestão desses.
A boa prática diz que um contêiner carrega uma única aplicação, isso acarreta um ambiente com vários contêineres o que gera responsabilidades a respeito da provisão de todos esses. Ter um contêiner rodando um sistema e outro rodando o banco de dados implica a criação de uma rede para comunicação entre as instâncias (e o conhecimento de criação e manutenção de uma rede ip); uma rede de contêineres gera a responsabilidade de criar e manter estas redes.
Ter um servidor ou nuvem com vários contêineres não implica apenas em ter conhecimento em criar e subir contêineres, e manter redes de contêineres, mas também em conhecer a tecnologia utilizada pelo provedor da infraestrutura (seja IaaS, SaaS ou PaaS).
Os principais players de cloud (AWS, Azure, Google Cloud Platform, IBM Cloud, GoDaddy, DigitalOcean, Vultr, Heroku, entre tantos outros) têm cada qual APIs próprias para realizar o deploy e manter os contêineres. Além das APIs, cada qual possui painéis de controle, sistemas, rotinas e termos de uso de serviços próprios. O profissional responsável por manter os sistemas online, utilizando contêineres e nuvem, precisa saber muito além que o tradicional deploy por FTP ou SSH.
VMs
VMs (máquinas virtuais) oferecem uma camada de abstração para o hardware, transformando um servidor em vários servidores. O hypervisor permite que inúmeras VMs rodem em um único hospedeiro.
Uma VM é uma cópia integral de um SO: todas as bibliotecas, software, binários, etc. Tudo isso tomará o corpo de alguns gigabytes.
Figura 3 – Camadas de uma VM: da aplicação a infraestrutura. Fonte: What is a Conteiner? , 2017
Para conseguir rodar uma VM é necessário iniciar o boot de um SO por completo (isso inclui várias rotinas, subir vários processos em memória e alocar recursos), todo esse processo pode levar segundos ou até minutos para se realizar. Além disso, criar o processo de uma máquina virtual pode causar sobrecarga no hospedeiro.
Contudo, se uma alteração em um contêiner implica derrubar uma instância e criar uma nova (com as alterações), uma VM apenas pode receber as alterações e manter a instância intacta. Isso gera maior conforto para os desenvolvedores durante o desenvolvimento, e assim mesmo manter a isonomia dos ambientes. Apesar de representar um processo grande para levantar e manter no SO hospedeiro, uma VM possui maior simplicidade em criar processos auxiliares ao sistema ou aplicação (como banco de dados ou acesso a hardware, por exemplo). Uma VM para desenvolvimento não implica uma VM com GUI, ou a instalação de software utilitários (navegadores, players ou readers, por exemplo), pois essa VM precisa apenas o necessário para rodar alguns sistemas e auxiliares ou utilitários. Um mesmo SO para servidores pode, e muito bem, ser utilizado para a criação de uma VM; por seu tamanho, manutenção e segurança.
O Docker
Existem diversas implementações de contêineres no mercado, tais como o Docker, LXC e o OpenVZ. Uma implementação que têm crescido em uso é o Docker.
A plataforma Docker oferece uma maneira amigável ao desenvolvedor de criar e manter contêineres com tudo o que as aplicações e sistemas precisam. Isso é possível graças a automatização de tarefas repetitivas, como: a criação do ambiente de desenvolvimento (crie uma vez, utilize sempre), permissões de acesso, compartilhar aplicações, rollback de versões e deploy e controle de overhead do hospedeiro.
Além disso, a plataforma oferece meios de manter contêineres e realizar a comunicação entre contêineres de maneira simples e prática (sem se preocupar com detalhes de configuração ao nível do SO do hospedeiro), oferecendo uma API de alto nível para manter e orquestrar vários contêineres.
Arquitetura
A arquitetura do Docker utiliza vários recursos do kernel GNU/Linux.
São utilizados, para fins de conteinerização, recursos como: cgroups, namespaces, capabilities, AppArmor. Tudo isso comunicando, com o contêiner, via interfaces como: libvirt, LXC, systemd-nspawn e libconteiner.
Figura 4 – As interfaces utilizadas para comunicação com o Kernel. Fonte: Docker 0.9: introducing execution drivers and libcontainer, 2014.
O ambiente de execução do Docker, atualmente, é o libconteiner: uma biblioteca escrita em Go e que substituiu o LXC como padrão.
A libconteiner é provê uma API para criação de contêineres com: namespaces, cgroups, capabilities e controle de acesso ao sistema de arquivos. Isso permite ao usuário (desenvolvedor ou aplicação) gerenciar todo o ciclo de vida de um contêiner e realizar operações adicionais depois de criado.
Considerações Finais
A adoção de contêineres pode aumentar a produtividade de desenvolvedores, principalmente com o Docker, sem a necessidade de instalar, configurar e manter vários ambientes ao mesmo tempo, sem falar quando, em uma mesma máquina, existem 2 ou 3 versões do framework, linguagem ou biblioteca ao mesmo tempo.
Até mesmo garantir que, em uma equipe, todos estão trabalhando usando as mesmas configurações. Quando for necessário mudar alguma configuração do sistema, apenas o Dockerfile será alterado e distribuído aos membros da equipe.
A pesquisa mostrou que a adoção e utilização por empresas e equipes de desenvolvimento, não é apenas aprender a empacotar aplicações e sistemas em contêineres. Mas sim, entender que, ao adotar essa abordagem, é necessário entender conteúdos pertinentes a rede de computadores, administração de sistemas, o entendimento e utilização de ferramentas do serviço escolhido para abrigar estes contêineres (como AWS, Heroku, Azure entre outros).
Contudo, quando a quantidade do contêineres cresce, será necessário configurar redes ip virtuais (no caso do Docker, a própria ferramenta pode criar automaticamente, de acordo com a configuração criada). Assim a complexidade irá aumentando, até mesmo em casos onde um software de orquestração será necessário, como o Kubernetes.
Referências
ITWorld. Containers vs. virtual machines: How to tell which is the right choice for your enterprise. Disponível em http://www.itworld.com/article/2915530/virtualization/containers-vs-virtual-machines-how-to-tell-which-is-the-right-choice-for-your-enterprise.html
Clutch. Best Cloud Service Providers. Disponível em https://clutch.co/cloud
Docker. Comparing Containers and Virtual Machines. Disponível em https://www.docker.com/what-container
Linux conteiners. What’s LXC?. Disponível em https://linuxcontainers.org/lxc/introduction/
CATD. Userland. Disponível em http://www.catb.org/jargon/html/U/userland.html
Archive. The powered world. Disponível em https://web.archive.org/web/20011215052223/http://uuu.sourceforge.net/si.php#SEC6
Networkworld. Software Containers: Used More Frequently than Most Realize. Disponível em http://www.networkworld.com/article/2226996/cisco-subnet/software-containers–used-more-frequently-than-most-realize.html
LWN. Process containers. Disponível em https://lwn.net/Articles/236038/
Doker. Kernel namespaces. Disponível em https://docs.docker.com/engine/security/security/#kernel-namespaces
Open Conteiners. Libcontainer. Disponível em https://github.com/opencontainers/runc/blob/master/libcontainer/README.md
Docker. Docker 0.9: introducing execution drivers and libcontainer. Disponível em http://blog.docker.com/2014/03/docker-0-9-introducing-execution-drivers-and-libcontainer/
Viva o Linux. Docker – Infraestrutura simples e rápida. Disponível em https://www.vivaolinux.com.br/artigo/Docker-Infraestrutura-simples-e-rapida
Digital Ocean. O Ecossistema do Docker: Uma Visão geral da Conteinerização. Disponível em https://www.digitalocean.com/community/tutorials/o-ecossistema-do-docker-uma-visao-geral-da-conteinerizacao-pt