O caso
Funcionava na minha máquina. No servidor, não.
O Isaac desenvolveu o sistema de pedidos com uma versão de Python no notebook. No servidor, havia outra versão, e uma biblioteca faltava. Ele passou a tarde instalando dependências à mão, e cada servidor novo repetia o problema.
Uma VM por aplicação resolveria, mas cada uma carregaria um sistema operacional inteiro só para rodar um programa.
Este post parte de Kernel, de Processos e Threads e de Máquinas Virtuais.
O problema
O programa depende do ambiente
Um programa não roda sozinho: ele depende de uma versão de linguagem, de bibliotecas, de configurações do sistema. Quando o ambiente de desenvolvimento e o de produção são diferentes, o mesmo código se comporta de formas diferentes.
A VM resolve a separação, mas com um custo: cada aplicação traz o próprio kernel e o próprio sistema operacional, com memória, disco e tempo de inicialização próprios.
A solução
Container: um processo isolado
Um container é um processo comum, rodando no kernel do próprio servidor, com duas coisas que o isolam: o que ele enxerga e o que ele pode usar. Não há um segundo kernel. Por isso, um container inicia em segundos e ocupa pouca memória extra.
Namespaces (o que ele vê)
Cada container tem a sua visão de processos, rede, pontos de montagem e usuários. Dentro dele, o programa acredita que está sozinho.
Na loja: o sistema de pedidos enxerga apenas os próprios processos e a própria porta de rede.
cgroups (o que ele pode usar)
O kernel limita quanto de CPU e de memória o grupo de processos pode consumir.
Na loja: o relatório não consegue tomar a memória que o sistema de pedidos precisa.
Imagem (o pacote)
Um pacote com o sistema de arquivos e as dependências da aplicação, que roda igual em qualquer servidor.
Na loja: o mesmo pacote roda no notebook do Isaac e no servidor.
Não confunda
Container × VM
Container
“Preciso de outro kernel, ou só de um processo isolado?”
- Exemplo
- Dez instâncias do sistema de pedidos no mesmo servidor, compartilhando o kernel.
- Foco
- Inicia em segundos, ocupa pouca memória extra, mas o kernel é compartilhado.
Máquina virtual
“Preciso de um sistema operacional diferente, ou de isolamento mais forte?”
- Exemplo
- Um sistema Windows rodando num servidor Linux, ou clientes que não podem dividir o kernel.
- Foco
- Cada VM tem o seu kernel. Isolamento mais forte, com mais custo de memória e de inicialização.
Por dentro
Namespaces e cgroups
Os namespaces e os cgroups são recursos do kernel Linux. Um container é, na prática, um processo que o kernel colocou dentro de um conjunto de namespaces e de um cgroup.
- Namespace de processos: o container enxerga só os próprios processos, e o processo principal dele aparece com um número próprio, como o PID 1.
- Namespace de rede: cada container tem as suas interfaces e as suas portas.
- Namespace de montagens: o container vê o próprio sistema de arquivos, montado a partir da imagem.
- cgroup: define limites de CPU e de memória, e conta o que o grupo consome.
Como tudo isso acontece no kernel, um container que estoura a memória é encerrado pelo kernel, do mesmo jeito que um processo comum, e não derruba o servidor.
Empacotar
Imagem e registro
Uma imagem é um pacote imutável: as camadas do sistema de arquivos e a configuração de como iniciar o programa. Cada camada é reaproveitada: duas imagens que partem da mesma base dividem essa base no disco.
Um container é uma instância de uma imagem em execução. Ele recebe uma camada gravável por cima, e tudo o que ele escreve nessa camada some quando o container é removido.
As imagens ficam num registro (registry), de onde os servidores as baixam. Quem quer dados que sobrevivam ao container usa um volume, que é uma área de armazenamento montada nele.
Na prática
Limitar e rodar
Com o Docker, uma das ferramentas mais conhecidas, um comando inicia um container com limites de memória e de CPU:
docker run --memory 512m --cpus 1 nginxO comando baixa a imagem do nginx, cria os namespaces, aplica o cgroup e inicia o processo. Quem consome mais de 512 MB é encerrado, e os outros containers do servidor continuam rodando.
| Situação | Escolha |
|---|---|
| Vários serviços Python com versões diferentes, no mesmo servidor | Containers |
| Um sistema Windows e um Linux no mesmo hardware | VM |
| Dados de um banco que precisam sobreviver ao container | Volume, ou um serviço gerenciado de banco |
| Atualizar a aplicação sem mexer no servidor | Trocar a imagem e reiniciar o container |
Termos-chave
Seis termos para recordar
Toque no cartão para ver a definição.
Teste rápido
Três perguntas, estilo prova
01
Dois containers rodam no mesmo servidor. O que eles compartilham?
02
Um time quer que um banco de dados mantenha os arquivos mesmo depois que o container é removido. O que deve usar?
03
Qual recurso do kernel limita quanta memória um container pode usar?
Container resolve o problema de empacotar e de isolar a aplicação, sem pagar um sistema operacional inteiro por ela. Entender os namespaces e os cgroups mostra o que é isolado e o que não é, e por isso a escolha entre container e VM depende do risco que você aceita e do sistema operacional de que precisa. O próximo passo é ver como essas peças rodam na nuvem.