Como usar o systemd-nspawn para containers leves no Linux

1. Introdução ao systemd-nspawn e seus fundamentos

O systemd-nspawn é uma ferramenta nativa do ecossistema systemd que permite criar e gerenciar containers leves no Linux. Diferente de soluções como Docker e Podman, que focam em containers de aplicação, o systemd-nspawn opera no conceito de container de sistema — ou seja, ele simula um ambiente completo de sistema operacional dentro de um namespace isolado, permitindo rodar um init system (como o próprio systemd) e múltiplos serviços simultaneamente.

As principais diferenças entre systemd-nspawn e outras ferramentas incluem:

  • Simplicidade: não requer daemon centralizado, repositórios de imagens ou camadas de abstração complexas
  • Integração nativa com systemd: utiliza journald, cgroups e units do systemd para gerenciamento
  • Leveza: consome menos recursos que máquinas virtuais e não exige overhead de runtime como o Docker
  • Segurança: suporte nativo a namespaces de usuário, seccomp e restrições de capabilities

Pré-requisitos básicos incluem um kernel Linux com suporte a namespaces (PID, network, mount, UTS, IPC, user) e cgroups v2 (habilitados por padrão na maioria das distribuições modernas).

2. Instalação e configuração inicial do ambiente

A instalação do systemd-nspawn varia conforme a distribuição:

# Ubuntu/Debian
sudo apt install systemd-container

# Fedora
sudo dnf install systemd-container

# Arch Linux
sudo pacman -S systemd

Após a instalação, verifique se os módulos do kernel necessários estão ativos:

# Verificar namespaces disponíveis
ls /proc/self/ns/

# Verificar cgroups v2
mount | grep cgroup

O diretório padrão para armazenar containers é /var/lib/machines. Você pode alterar isso editando /etc/systemd/nspawn/ ou usando caminhos personalizados com machinectl.

3. Criação e gerenciamento de containers com systemd-nspawn

Para criar um container, utilize o debootstrap (no Debian/Ubuntu) ou ferramentas equivalentes:

# Criar um container Debian mínimo
sudo debootstrap --include=systemd,systemd-sysv,dbus bookworm /var/lib/machines/meu-container http://deb.debian.org/debian

Gerenciamento básico com machinectl:

# Iniciar o container
sudo machinectl start meu-container

# Acessar o shell
sudo machinectl login meu-container

# Executar comando diretamente
sudo machinectl shell meu-container /bin/bash

# Listar containers ativos
machinectl list

# Parar o container
sudo machinectl poweroff meu-container

Para criar containers a partir de outras distribuições:

# Fedora
sudo dnf --releasever=38 --installroot=/var/lib/machines/fedora-container install systemd passwd dnf

# OpenSUSE
sudo zypper --root=/var/lib/machines/opensuse-container install systemd patterns-base-minimal

4. Configuração de rede e volumes compartilhados

O systemd-nspawn oferece múltiplos modos de rede:

# Rede em modo host (container compartilha a rede do host)
sudo systemd-nspawn -D /var/lib/machines/meu-container --network-host

# Rede com bridge virtual (veth)
sudo systemd-nspawn -D /var/lib/machines/meu-container --network-veth

# Rede isolada (sem acesso externo)
sudo systemd-nspawn -D /var/lib/machines/meu-container --network-none

Para compartilhar diretórios entre host e container (bind mounts):

# Montar diretório /dados do host em /mnt/dados no container
sudo systemd-nspawn -D /var/lib/machines/meu-container \
  --bind=/dados:/mnt/dados \
  --network-veth

Para expor portas do container para a rede externa, combine bind mounts com configuração de roteamento no host:

# Criar bridge e configurar NAT
sudo ip link add br0 type bridge
sudo ip addr add 10.0.0.1/24 dev br0
sudo ip link set br0 up
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

5. Gerenciamento de recursos e isolamento avançado

Limitação de recursos com cgroups via opções do systemd-nspawn:

# Limitar CPU (50% de um core)
sudo systemd-nspawn -D /var/lib/machines/meu-container \
  --cpu-quota=50%

# Limitar memória (512 MB)
sudo systemd-nspawn -D /var/lib/machines/meu-container \
  --memory-high=512M --memory-max=768M

# Limitar I/O de disco (10 MB/s leitura, 20 MB/s escrita)
sudo systemd-nspawn -D /var/lib/machines/meu-container \
  --read-write --property="IOReadBandwidthMax=/dev/sda 10M" \
  --property="IOWriteBandwidthMax=/dev/sda 20M"

Isolamento de segurança com namespaces de usuário:

# Mapear usuário root do container para UID 100000 no host
sudo systemd-nspawn -D /var/lib/machines/meu-container \
  --private-users=100000:65536 \
  --private-users-chown

Sistema de arquivos read-only e tmpfs:

# Montar /var como tmpfs e /usr como read-only
sudo systemd-nspawn -D /var/lib/machines/meu-container \
  --read-only \
  --tmpfs=/var:size=512M

6. Integração com systemd e boot de containers

Para iniciar containers automaticamente como serviços systemd:

# Criar arquivo de configuração do container
sudo mkdir -p /etc/systemd/nspawn
sudo tee /etc/systemd/nspawn/meu-container.nspawn <<EOF
[Exec]
Boot=yes
PrivateUsers=100000:65536

[Network]
VirtualEthernet=yes
EOF

# Habilitar o serviço
sudo systemctl enable systemd-nspawn@meu-container.service
sudo systemctl start systemd-nspawn@meu-container.service

Para containers com suporte completo ao systemd (init):

# Iniciar com boot completo
sudo systemd-nspawn -b -D /var/lib/machines/meu-container

Logs do container ficam disponíveis via journald:

# Ver logs do container
journalctl -u systemd-nspawn@meu-container.service

# Ver logs dentro do container
sudo machinectl shell meu-container /bin/journalctl

7. Casos de uso práticos e boas práticas

Rodando serviços legados: isole aplicações antigas que exigem bibliotecas específicas em containers dedicados:

# Container para aplicação PHP 5.6
sudo debootstrap --include=php5.6,apache2 stretch /var/lib/machines/legado-php
sudo machinectl start legado-php
sudo machinectl shell legado-php /etc/init.d/apache2 start

Ambientes de desenvolvimento reproduzíveis: crie containers com ferramentas específicas para cada projeto:

# Container para desenvolvimento Python 3.11
sudo debootstrap bookworm /var/lib/machines/dev-python
sudo machinectl shell dev-python /bin/bash -c "apt install python3.11 python3-pip"

Backup e migração: containers systemd-nspawn são portáteis:

# Backup do container
sudo tar -czf meu-container-backup.tar.gz -C /var/lib/machines meu-container

# Migrar para outro host
scp meu-container-backup.tar.gz usuario@outro-host:/tmp/
ssh usuario@outro-host "sudo tar -xzf /tmp/meu-container-backup.tar.gz -C /var/lib/machines"

8. Troubleshooting e limitações comuns

Problemas de DNS: configure manualmente o resolv.conf:

# Dentro do container
echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 1.1.1.1" >> /etc/resolv.conf

Erros de permissão: verifique mapeamento de UIDs:

# Verificar UIDs mapeados
sudo cat /proc/$(machinectl show meu-container -p Leader)/uid_map

Limitações conhecidas:
- Não suporta orquestração nativa (como Kubernetes)
- Gerenciamento de rede manual comparado ao Docker
- Sem registro centralizado de imagens (como Docker Hub)
- Performance de I/O inferior a máquinas virtuais em alguns cenários

Referências