anúncios

quarta-feira, 16 de agosto de 2023

Entendendo o funcionando do Docker por debaixo dos panos

Por baixo dos panos, o Docker é construído sobre várias tecnologias do kernel do Linux, incluindo namespaces, cgroups, UnionFS e outras ferramentas para permitir o isolamento e gerenciamento eficiente de containers.

Namespaces:

Os namespaces permitem isolar recursos do sistema, como processos, rede, sistema de arquivos, entre outros. Cada container Docker é criado em um conjunto de namespaces, o que garante que os processos em um container não possam ver nem interagir com processos fora dele.

Os principais namespaces usados pelo Docker são: PID (para isolar processos), NET (para isolar a rede), MNT (para isolar o sistema de arquivos), UTS (para isolar o hostname), IPC (para isolar a comunicação interprocesso) e USER (para isolar os IDs de usuário).

Cgroups (Control Groups):

Os cgroups permitem limitar, contabilizar e isolar o uso de recursos, como CPU, memória, E/S de disco e rede, para grupos de processos. O Docker usa cgroups para garantir que os containers tenham uma cota de recursos definida, evitando que um container consuma todos os recursos do sistema.

Com cgroups, o Docker pode controlar e distribuir recursos entre diferentes containers de forma justa e previsível.

UnionFS:

O UnionFS é usado para criar um sistema de arquivos em camadas dentro de um container Docker. Ele permite que diferentes camadas (imagens) sejam empilhadas para formar o sistema de arquivos completo do container.

Cada camada representa alterações ou adições ao sistema de arquivos. Isso permite que múltiplos containers compartilhem camadas de imagem idênticas, economizando espaço em disco e facilitando o gerenciamento de imagens.

Docker Daemon e Cliente:

O Docker funciona em um modelo cliente-servidor, onde o Docker Daemon é o servidor e o Docker Cliente é a interface pela qual os usuários interagem com o Docker.

O Docker Daemon é responsável por gerenciar os containers, imagens, volumes e redes. Ele é responsável por criar, iniciar, parar e destruir containers, bem como gerenciar o ciclo de vida das imagens.

O Docker Cliente é uma CLI (Interface de Linha de Comando) que permite aos usuários enviar comandos para o Docker Daemon. O Cliente envia as solicitações para o Daemon, que as processa e executa as ações necessárias.

Docker Image e Container:

Uma Docker Image é uma estrutura de arquivos somente leitura usada para criar containers. Uma imagem contém o sistema de arquivos raiz e as configurações necessárias para executar um aplicativo. Ela é composta por uma ou mais camadas de UnionFS, onde cada camada é uma modificação ou adição em relação à camada anterior.

Um Docker Container é uma instância em execução de uma imagem. É um ambiente isolado que contém um sistema de arquivos que deriva da imagem, juntamente com um conjunto de processos que estão sendo executados.

Quando você executa um container Docker, o Docker Daemon utiliza as tecnologias do kernel mencionadas (namespaces, cgroups e UnionFS) para criar o ambiente isolado para o container. A partir da imagem base, ele cria uma camada de sistema de arquivos (layer) somente leitura e, em seguida, adiciona uma camada somente leitura para os arquivos do sistema de arquivos do container. A partir daí, ele cria uma camada de escrita para quaisquer alterações feitas no sistema de arquivos durante a execução do container.

Esse modelo de camadas permite que os containers sejam leves e eficientes, compartilhando recursos sempre que possível e tornando o processo de criação e distribuição de containers mais rápido e fácil.

Criando um container sem o Docker, utilizando apenas os recursos de namespaces, cgroups e o utilitário chroot.

Após entendermos a teoria do funcionamento do Docker, agora vamos criar um container sem Docker, utilizando os recursos de namespaces, cgroups e o chroot.

No GNU/Linux Debian ou Ubuntu, segue:

sudo apt update

sudo apt install debootstrap -y

mkdir /mnt/debian

sudo debootstrap stable /mnt/debian http://deb.debian.org/debian

Para visualizar os arquivos da imagem Debian que foi criado pelo pacote debootstrap.

ls -la /mnt/debian

chroot /mnt/debian /bin/bash

A partir desse momento está no outro SO que foi instalado com a imagem do Debian com debootstrap

cat /etc/debian_version

cat /etc/issue

exit

Agora vamos fazer o isolamento de processos da imagem minialista do Debian criada com debootstrap com o comando seguinte:

unshare --mount --uts --ipc --net --pid --user --map-root-user --fork --uts --ipc chroot /mnt/debian /bin/bash

mount -t proc proc /proc

ps -ef

Outra aba do terminal

ps aux | grep bash

Identificar o PID do bash

sudo chroot debian bash

apt update

apt install stress

exit

unshare --mount --uts --ipc --net --pid --user --map-root-user --fork --uts --ipc chroot /mnt/debian /bin/bash

mount -t proc proc /proc

mount -t sysfs sys /sys

mount -t tmpfs tmp /tmp

ps -ef

Na máquina física

sudo apt install cgroup-tools

sudo cgcreate -g memory,cpu,blkio,freezer,devices:/nome-grupo

cat /sys/fs/cgroup/memory/nome-grupo

cgclassify -g memory,cpu,blkio,freezer,devices:nome-grupo PID(bash-criado-pelo-unshare)

cat /sys/fs/cgroup/cpu/nome-grupo/tasks

sudo cgset -r memory.limit_in_bytes=128M nome-grupo

sudo cgget -r memory.stat nome-grupo

cat /sys/fs/cgroup/memory/nome-grupo/memory.limit_in_bytes

sudo cgset -r cpu.cfs_periodo_us=100000 -r cpu.cfs_quota_us=$[ 10000 * 32] nome-grupo

stress --cpu 1 --vm-bytes 120M --VM 1

Com esses procedimentos executados você pode observar o funcionamento por debaixos dos panos do Docker, a criação de um container sem Docker, por meio da imagem minialista do Debian e o isolamento de processos com namespaces, cgroups, chroot, unshare e teste de stress do container puro criado.

Feito!

Nenhum comentário:

Postar um comentário