2 pontos por GN⁺ 2025-05-06 | 1 comentários | Compartilhar no WhatsApp
  • Em servidores pessoais e VPSs pequenos, a automação declarativa do Kubernetes é atraente, mas a carga de CPU e memória e a complexidade operacional podem superar os ganhos reais
  • O Kubernetes automatiza tarefas como ajustar Pods e renovar certificados TLS mantendo continuamente o estado desejado, mas para isso mantém um runtime consideravelmente grande sempre em execução
  • Em experimentos com Azure Kubernetes Service, Microk8s, K3S e Raspberry Pi, o uso de recursos em idle, o aquecimento e o ruído das ventoinhas se repetiram como problemas
  • O Podman pode transformar contêineres em serviços systemd e detectar e substituir novas imagens com io.containers.autoupdate e podman auto-update
  • A combinação de Podman, systemd e user lingering oferece de forma mais simples a maior parte da automação desejada no Kubernetes, mas a integração com systemd está migrando para a direção do Quadlet

Por que a automação do Kubernetes era pesada para servidores pessoais

  • O Kubernetes é composto por vários componentes, serviços web, sidecars e webhooks, mas seu funcionamento central se aproxima de um loop que compara continuamente o estado atual com o estado desejado e aplica as diferenças
    • Se um Pod deveria existir e não existe, ele o cria
    • Se deveria haver 3 réplicas, mas há 4, ele remove uma
  • Esse modelo foi especialmente útil em extensões como o cert-manager
    • Declara-se que deve existir um certificado TLS válido para um determinado domínio
    • Ao informar como solicitar o certificado, se ele não existir ou estiver perto de expirar, um novo certificado é obtido e instalado no servidor web
  • Para experimentos pessoais, era divertido e tinha valor de aprendizado, mas para operação real ficava mais próximo de uma ferramenta excessiva
  • A carga de recursos se repetiu em vários ambientes
    • Em um NUC, o computador ficava rodando continuamente, esquentava e gerava ruído de ventoinha, dificultando dormir
    • No Azure Kubernetes Service, a implementação do Kubernetes ocupava muita RAM e usava cerca de 7–10% da CPU em idle no worker node
    • Uma instância única do Microk8s em um VPS x86_64 com 2 vCPUs ficava com cerca de 12% de CPU em idle
    • O K3S em uma máquina Ampere A1 com 2 vCPUs é conhecido como uma implementação mais leve, mas usava cerca de 6% de CPU constante
    • Mesmo no Raspberry Pi, não foi encontrada uma implementação que deixasse CPU suficiente para a carga de trabalho sem problemas de aquecimento e ventoinha

O modelo de automação adotado com Podman e systemd

  • O principal motivo para continuar usando Kubernetes era a automação de deploy
    • Com GitOps e Flux, fazer mudanças era fácil
    • Com a automação de imagens de contêiner e os webhooks do Flux v2, ao enviar uma nova imagem, em poucos segundos o servidor a baixava e executava a aplicação em produção
  • As alternativas existentes encontradas fora do Kubernetes não eram satisfatórias
    • A abordagem de lembrar todos os argumentos originais da linha de comando para recriar o contêiner gerava muita carga de gerenciamento
    • Ferramentas que exigiam controle total do docker.sock também não eram preferidas
  • A atualização automática do Podman era próxima do recurso necessário
    • O Podman pode ser visto como uma alternativa à CLI do Docker
    • Depois de criar um contêiner, é possível gerar um arquivo de serviço systemd
    • Ao iniciar o serviço, ele cria ou substitui o contêiner; ao parar o serviço, ele remove o contêiner
  • A atualização automática funciona pela tag io.containers.autoupdate
    • Ela é executada uma vez por dia por um timer, ou podman auto-update é executado diretamente
    • Se houver uma nova imagem, o contêiner é recriado com essa imagem
  • O artigo Auto-updating Podman containers with systemd, da Fedora Magazine, forneceu a maior parte do método de implementação, e foram necessárias mais duas configurações
    • systemctl --user enable mycontainer.service para fazer o contêiner iniciar automaticamente ao fazer login
    • loginctl enable-linger para fazer a sessão do usuário funcionar na inicialização do servidor
  • Com a combinação de Podman, systemd e user lingering, obtêm-se cerca de 99% dos benefícios que o Kubernetes oferecia, com muito menos complexidade e carga de CPU e memória
  • Todos os serviços foram movidos do VPS antigo para um novo VPS com metade da vCPU e da RAM e, com base em algumas horas de execução, ele ficou mais leve, mais rápido e com menor custo computacional
  • No entanto, a integração do Podman com systemd parece já estar descontinuada, e a definição de contêineres está sendo discutida na direção dos arquivos Quadlet

1 comentários

 
GN⁺ 2025-05-06
Opiniões no Hacker News
  • Tenho total empatia pelo sentimento do autor original. No trabalho, gerenciamos com relativa facilidade vários clusters Kubernetes rodando dezenas de microsserviços, mas em projetos de hobby sem receita o orçamento é pequeno, então mesmo querendo usar Kubernetes, não dá
    Em um VPS de US$ 10 por mês com 1 vCPU compartilhada e 2 GB de RAM, Kubernetes é pesado demais. Em vez de Deployments, acabo executando manualmente docker compose up/down via SSH; em vez de Ingress, dependo do recurso de descoberta de contêineres do Traefik; e, por não poder usar CronJobs, até criei um pequeno script para gerenciar o crontab de forma idempotente
    O que eu realmente quero é uma alternativa leve que ofereça uma API compatível com Kubernetes e rode bem até em VPS barato. A lacuna entre orquestração de contêineres de nível corporativo e hospedagem barata para hobby ainda é grande demais

    • Dependendo do escopo da Kube API de que você precisa, o Podman pode cumprir esse papel. Ele consegue criar contêineres e pods a partir de manifestos Kubernetes, então funciona como um docker compose que usa manifestos Kubernetes
      Também pode ser usado junto com units do systemd, como no método descrito no texto. O Podman também oferece suporte à maior parte, ou talvez a toda, a API do Docker, então docker compose funciona, e também é possível trabalhar conectando-se a um socket remoto via SSH
      https://docs.podman.io/en/latest/markdown/podman-kube-play.1...
      https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
    • Fico curioso se você já olhou o k0s ou o k3s. Há bastante gente usando isso bem em pequena escala: https://news.ycombinator.com/item?id=43593269
    • Não quero soar como propaganda da Oracle, mas o Oracle Cloud Free Tier é absurdamente generoso. Dá para rodar bastante coisa, incluindo um pequeno cluster k8s, e o serviço do plano de controle do k8s também é gratuito
      Eles dão gratuitamente 4 cores ARM64 e 24 GB de RAM, que você pode dividir em 1 a 4 nós, dependendo de como quiser
      https://www.oracle.com/cloud/free/
    • Dá para fazer do jeito antigo, usando algo como Ansible. Eu gerencio completamente alguns servidores dedicados com Ansible, e ele pode ser usado como uma espécie de docker compose reforçado
      Use Traefik e labels para generalizar o proxy reverso e os certificados TLS, e adicione Authelia como um provedor simples de autenticação. Há muitos projetos de exemplo no GitHub e, com uma configuração de fim de semana, vira um sistema bem fácil de manter
    • Como você já disse que o custo de usar Kubernetes é alto demais, dependendo do eixo pelo qual você mede eficiência, uma solução feita por você pode acabar sendo mais eficiente
  • O systemd recebe muitas críticas, mas resolve problemas demais para ser descartado facilmente. Grande parte da rejeição quando ele começou a vir por padrão nas distribuições era porque as pessoas precisavam mudar
    Há contêineres, machinectl, nspawn, que é um chroot mais poderoso, vmspawn para quando é necessária virtualização completa, importctl para baixar, importar e exportar máquinas, homed/homectl, que facilita criptografia de diretórios home e controle de permissões, e assim por diante
    Em vez de fstab, ele trata montagens como units, controla a ordem de boot e o início/parada de serviços, e também fornece timers mais poderosos que cron. Por exemplo, é possível saber sobre tarefas que não foram executadas porque a máquina estava desligada, ou executá-las com atraso após o boot sob determinadas condições
    Units de serviço permitem controlar tarefas de forma granular e restringir permissões, e com systemctl edit é possível criar configurações de override sem mexer na configuração original. Aprender no começo é um pouco chato, mas, para fazer coisas complexas, não existe ferramenta que dispense totalmente a leitura da documentação

    • O motivo pelo qual o systemd foi criticado nos primeiros anos, talvez por quase uma década, não era que o projeto em si fosse ruim. Pelo contrário: ele era bom o bastante para ter sucesso apesar de vários problemas
      O problema era a postura dos mantenedores. Eles quebravam coisas que funcionavam bem sem se incomodar muito e sem oferecer correções adequadas. Se você não sentiu dor por causa do systemd, talvez tenha chegado mais tarde, ou suas necessidades tenham coincidido por acaso com as necessidades dos mantenedores principais
    • A única coisa de que não gosto no systemd é que um binário vindo de uma base de código incontavelmente grande assume o papel de PID 1 e, durante upgrades, faz coisas ainda mais complexas ao tentar dar exec em si mesmo no lugar
      Um programa que faça exatamente 100% do que o PID 1 precisa fazer, e nada além disso, poderia ser muito menor. Se o systemd for iniciado a partir daí, algum problema no systemd não levará imediatamente a um kernel panic
      Fonte: https://ewontfix.com/14/
    • É difícil aceitar a ideia de esquecer o cron. Ele funcionou bem por 50 anos, e de repente virou algo terrivelmente errado que obviamente deve ser substituído pelo systemd
    • Se você esquecer o fstab e usar montagens do systemd, as regras de automount são complexas e, mesmo alinhando 1:1 com a documentação, às vezes simplesmente não funcionam, então o sistema de arquivos pode não ser montado a tempo
    • systemd é excelente para Linux moderno de desktop ou servidor, ou usos parecidos. Mas, se você tentar fazer algo fora do modo que o projeto pressupõe, encontrará deboche e resistência. Pergunte à equipe do musl
      Para distribuições ou upstreams, ele facilita muito a vida, mas o preço é adicionar uma complexidade cada vez maior às camadas mais baixas do sistema. Dependendo do ponto de vista, coisas como journalctl, timedatectl, dependência de dbus ou substitutos podem ser vistas como incompatíveis com a filosofia Unix
      Se o objetivo for apenas coordenar processos, executá-los na ordem correta e garantir ativação automática, considero uma ferramenta em um nível mais adequado do que k8s ou Docker
  • Venho mantendo meu homelab há um tempo com podman-systemd, ou seja, Quadlet, e toda vez que olhava uma nova variante de k8s, não parecia valer o trabalho extra. Com playbooks antigos do Ansible, já basta baixar as imagens com antecedência e colocar os arquivos de unit no lugar certo
    Também rodei toda a stack da impressora 3D Voron com podman-systemd, para conseguir atualizar e fazer rollback de todos os componentes de uma vez. Mas agora também estou avaliando atualizar e fazer rollback da imagem de disco inteira de uma vez com mkosi e systemd-sysupdate
    O principal problema é que, em geral, as pessoas só distribuem arquivos docker-compose, então é preciso convertê-los para units do systemd; e algumas imagens Docker têm complexidade desnecessária para o Podman na configuração de usuários e permissões. Em especial, quando o contêiner se recusa a rodar como root ou troca para outro usuário, às vezes é necessário lidar com o incômodo mapeamento de IDs de userns
    Mesmo assim, no geral é muito menos complexo do que qualquer configuração de k8s ou variante de k8s. Também gosto do fato de integrar tanto com systemd quanto com journald, sem ficar dividido em dois lugares

    • Uso uma abordagem parecida há alguns anos: https://github.com/Mati365/hetzner-podman-bunjs-deploy. É baseada em Podman e systemd, e nada quebrou nesse período
      Como basta colocar as units, é muito estável e simples
    • Ao converter arquivos compose em arquivos Quadlet, dá para usar o podlet: https://github.com/containers/podlet
    • No fim, parece ser um único nó, ou um conjunto de nós independentes. Podman/systemd/Quadlet podem ser um detalhe de implementação de como um nó k8s executa contêineres, algo parecido com uma CRI
      Mas isso não substitui a abstração de orquestração e agendamento sobre vários nós que o k8s oferece. Falta a parte de “aqui estão as máquinas capazes de executar arquivos Podman-systemd, aqui está a especificação que quero rodar; distribua isso por conta própria”
    • Experiência parecida. O fluxo de trabalho é subir o contêiner com um comando podman run, verificar se roda corretamente, gerar um arquivo básico de contêiner com podlet e então ajustar esse arquivo separando volumes e redes em outros arquivos Quadlet. E pronto
      O projeto podman-compose também parece ainda ser mantido ativamente e pode ser uma boa alternativa ao docker-compose. Mas a integração entre Podman e systemd é satisfatória demais
  • O próximo passo para simplificar ainda mais isso é gerenciar contêineres dentro do systemd com Quadlet. Há mais detalhes em https://www.redhat.com/en/blog/quadlet-podman

    • Quadlet é exatamente esse caminho. É uma forma realmente boa de executar contêineres e dá aquela sensação de configurar e esquecer. No Fedora ou no Rocky Linux, pelo menos, nem é preciso instalar pacotes adicionais
    • Foi abordado no fim do texto, mas o autor ainda não tinha explorado. Como a integração do Podman com systemd já parece deprecated e agora se fala em definir contêineres por meio de arquivos “Quadlet”, ele deixou isso como algo para aprender depois
    • Vim aos comentários justamente para ver se alguém tinha mencionado Quadlet. Na semana passada migrei meu servidor doméstico de docker compose para Podman Quadlet rootless; a transição foi difícil, mas fiquei muito satisfeito com o resultado
    • Este texto também ajudou bastante a fazer uma transição tranquila do homelab para Quadlet: https://news.ycombinator.com/item?id=43456934
  • Criei o skate: https://github.com/skateco/skate. Basicamente é para esse propósito, mas com suporte a vários hosts e também a manifestos do k8s. Por baixo, usa Podman e systemd

    • Gosto muito dessa abordagem. É realmente frustrante não haver uma forma simples de executar Docker/Podman em vários hosts. Infelizmente, o Docker Swarm está praticamente abandonado desde 2019
      Mas considero que o k8s tem uma API e uma experiência de usuário péssimas. A especificação do Docker Compose é muito mais amigável, então estou experimentando no momento um docker-compose para vários hosts: https://github.com/psviderski/uncloud
  • Voltei a empacotar tudo como pacotes deb e a executar diretamente com systemd em instâncias EC2, sem usar mais contêineres. As instâncias ficam em um Auto Scaling Group ligado a um ALB, e um ansible-pull simples na inicialização instala o deb
    É uma abordagem bem crua, mas cansei do HCL dentro de YAML dentro de JSON sem fim. Agora quero lidar, no máximo, com YAML do Ansible

    • O bom dessa abordagem é que, quando há um bug em uma biblioteca comum, basta executar apt full-upgrade e reiniciar apenas os processos em execução para ficar protegido
      Não é preciso reconstruir nada nem descobrir como atualizar uma biblioteca enterrada nas profundezas de um contêiner que talvez você tenha construído — ou talvez não
    • Segui o mesmo caminho em uma aplicação bem simples. O systemd foi surpreendentemente agradável, e gostei bastante de executar serviços com privilégios mínimos usando contas de usuário atribuídas pelo sistema
      Graças ao suporte a cgroups, também é bom para rodar vários serviços em um único VPS
    • Dá vertigem pensar na quantidade de vida humana desperdiçada no domínio de problema de “gerenciamento de YAML em grande escala”
  • Como o artigo tem mais de um ano, hoje existe até o ParticleOS, uma distribuição de sistema operacional com suporte oficial do systemd para fluxos de trabalho imutáveis
    https://github.com/systemd/particleos
    https://news.ycombinator.com/item?id=43649088

    • O próximo passo lógico seria substituir o kernel Linux por systemd-kernel, e aí estaria completo
  • Pelo que li, parece que tudo isso poderia ser substituído pelo comando docker compose e algo como o Caddy, que obtém certificados automaticamente
    Com apenas um compose.yaml, basicamente basta uma linha: docker compose up -d --pull always. A configuração de CI também se resume a scp compose.yaml user@remote-host:~/ seguido de ssh user@remote-host 'docker compose up -d --pull always'
    A vantagem é que é simples e também funciona na máquina de desenvolvimento. Claro, se o objetivo secundário for experimentar algo interessante e aprender, Quadlet, k8s e systemd também são boas escolhas

    • Basta executar uma única vez docker context create --docker 'host=ssh://user@remote-host' remote-host
      Depois disso, use docker -c remote-host compose -f compose.yaml up -d --pull always, sem precisar copiar o arquivo. Além disso, se você configurar as informações de usuário em ~/.ssh/config, não precisa usar user@ nas chamadas SSH, o que facilita para a equipe copiar e usar a documentação ou os comandos
    • Dá para fazer do jeito mencionado no comentário irmão ou configurar a variável de ambiente DOCKER_HOST. Só é preciso tomar cuidado porque a interpolação do arquivo compose usa variáveis de ambiente locais
  • Eu achava que fazer deploy em um único servidor não deveria ser tão complicado, então criei uma ferramenta para fazer deploy do jeito que eu queria: https://harbormaster.readthedocs.io/
    O Harbormaster encontra repositórios a partir de um arquivo YAML, clona e atualiza periodicamente, e então executa os arquivos Docker Compose dentro deles. Todo o estado também fica em um único diretório, facilitando o backup
    Se você só precisa de um único servidor, é a ferramenta de orquestração de contêineres mais fácil e melhor que já vi. Gosto do fato de toda a configuração ser declarada no repositório, todo o estado ficar em um diretório e tudo ser simplesmente arquivos Compose

  • Lendo os comentários aqui, me sinto velho. Fico pensando se agora ninguém mais usa só ssh e nginx
    É só enfiar tudo em uma única máquina e fazer backup dela de forma agressiva, e pronto. Para uso doméstico, gerenciamento de microsserviços realmente não é necessário

    • Eu uso apenas nginx e alguns serviços customizados, mas isso é possível porque meus requisitos são bem pequenos. Se ficar um pouco mais complexo ou se você precisar subir vários nós para ter redundância, contêineres começam a fazer muito sentido