Cgroups v2 no dia a dia do Linux
Tem um momento muito específico em que você percebe que Linux não é só aquele lugar confortável onde processos nascem e morrem felizes. É quando a máquina começa a engasgar. O navegador resolve consumir memória como se fosse infinito, um serviço Java faz cosplay de aspirador de RAM, o disco vira um funil, e o seu terminal… demora para responder ao simples comando ls.
Nessa hora, a explicação clássica costuma ser rasa. Memória acabou. CPU foi embora. I/O saturou. Só que o Linux sempre teve uma pergunta mais interessante escondida ali: quem, exatamente, deveria ter prioridade para continuar vivo?
É aí que entram os control groups, os cgroups. E mais especificamente o cgroups v2, que é uma espécie de amadurecimento do que a comunidade tentou fazer por anos no v1. Não é um detalhe de containers. Não é algo que existe só para Kubernetes. É uma camada de organização e disciplina dentro do kernel que muda como você pensa em recursos: CPU, memória, I/O, e até o tempo que o sistema passa esperando por eles.
Vou te guiar por essa ideia como eu faria num papo de corredor com alguém que administra Linux há um tempo, já tomou susto com OOM killer, já viu servidor morrer de swap thrash e já desconfiou, com razão, que só olhar load average não conta a história toda.
O que muda quando você para de pensar em processos e começa a pensar em grupos
No Linux tradicional, o processo parece a unidade natural do mundo. Você dá nice, manda kill, olha no top, vê PID, PPID, usuário.
Cgroups trazem uma mudança de lente: você organiza processos em grupos, cria uma hierarquia, e aplica políticas de recursos nesses grupos. Parece burocrático no começo, mas logo fica viciante porque resolve uma dor real: você consegue dizer ao sistema operacional como ele deve se comportar quando recursos ficam disputados.
O pulo do v2 é que ele tenta ser mais consistente. No v1, era comum você ter controladores diferentes montados em hierarquias diferentes, com regras meio tortas, e a sensação de que você estava pilotando um avião com painéis de fabricantes diferentes. O v2 vem com a ideia de hierarquia unificada e uma convenção mais previsível de interface.
E isso não é só elegância. Isso muda o resultado prático.
Quando você coloca um serviço dentro de um cgroup com limites, você para de depender de esperança e passa a depender de política. A esperança diz: espero que esse processo não surte. A política diz: se ele surtar, ele surta dentro do cercadinho dele.
Um passeio rápido pelo terreno
Onde vivem os cgroups e por que o sistema sempre parece já estar usando isso
Se você usa uma distro moderna com systemd, seu sistema muito provavelmente já organiza tudo em cgroups. Você só não vê porque o systemd faz isso por você e guarda numa árvore lógica que parece um mapa da cidade.
Mesmo que você nunca tenha criado um cgroup manualmente, você já se beneficia disso quando usa coisas como:
-
limites de CPU e memória em serviços
-
isolamento de sessões de usuários
-
contêineres e sandboxes
-
políticas automáticas de contenção quando o sistema vai para o limite
Tem uma sensação meio engraçada quando você percebe isso. É como descobrir que a casa em que você mora tem uma fundação de concreto enorme e você só estava olhando para as paredes.
CPU, memória e disco como personagens diferentes
CPU é disputa de tempo. Memória é disputa de espaço. Disco é disputa de fila.
A maioria das pessoas tenta tratar tudo igual, como se recurso fosse recurso e pronto. Só que a forma como o kernel reage à pressão muda bastante conforme o tipo:
CPU
Você pode limitar com uma espécie de orçamento: um grupo só pode usar uma fatia do tempo. Quando ele tenta passar disso, ele é desacelerado.
Memória
Memória tem algo cruel: quando de verdade não dá mais, o kernel precisa escolher alguém para matar ou precisa começar a empurrar páginas para swap. E swap, quando vira rotina, pode transformar uma máquina rápida numa coisa que parece estar rodando em câmera lenta.
I/O
Disco é menos sobre quantidade e mais sobre concorrência. Uma aplicação que faz escrita intensa pode atrasar todo mundo. Um backup mal programado pode causar um efeito dominó que ninguém entende olhando só CPU e RAM.
O cgroups v2 conversa com essas diferenças de um jeito mais coerente do que o v1 fazia. E o systemd, por cima disso, oferece um painel de controle bem humano.
A parte que muda jogo na vida real
Limites que não são só muro, são também aviso
Muita gente imagina limite como uma parede rígida. Atingiu, bateu, acabou. Só que a realidade fica mais interessante quando você tem limites graduais. Em cgroups v2, a memória tem pelo menos três ideias que valem a pena entender:
-
Um teto duro
Quando você define um máximo, você está dizendo: não ultrapasse. Se ultrapassar, alguém vai sofrer. Pode ser recusa de alocação. Pode ser morte por OOM dentro do grupo. Depende do cenário. -
Um ponto de pressão
Existe o conceito de um limite que não mata de imediato, mas começa a forçar reclaim com força dentro daquele grupo. O efeito é quase psicológico para o processo. Ele continua vivo, mas passa a sentir o chão ficando pegajoso. Latência sobe, caches caem, e a aplicação tem a chance de se ajustar.
Aqui entra um detalhe menos óbvio e muito humano: às vezes você não quer punir com morte, você quer punir com desconforto. É isso que evita tragédia.
-
Swap como válvula, mas com regra
Swap pode salvar um pico. Também pode destruir a responsividade de um host se virar padrão. O cgroups v2 deixa você limitar swap por grupo, o que é uma forma elegante de impedir que um único serviço arraste o resto para o fundo do poço.
Quando você olha por esse ângulo, cgroup deixa de ser um recurso de container e vira uma ferramenta de convivência entre processos.
Systemd como o jeito prático de usar cgroups sem sofrer
É raro alguém querer gerenciar a árvore de cgroups manualmente na unha. Dá para fazer, claro, e tem contextos onde isso faz sentido, mas no cotidiano é muito mais comum você usar systemd para isso.
E o motivo é simples: o systemd já organiza serviços, sessões, usuários e escopos. Acoplar isso com limites é quase natural.
Você consegue criar um escopo para um comando e limitar recursos sem transformar aquilo num container:
-
iniciar um processo dentro de um escopo controlado
-
impor limites de CPU, memória e I/O
-
observar comportamento com ferramentas do próprio sistema
Um exemplo que costuma ser revelador é quando você pega um processo conhecido por exagerar e coloca ele em quarentena. Não porque você odeia o processo. Só porque você gosta da máquina funcionando.
Pressão de recursos não aparece direito no load average
PSI é aquele instrumento que faz você confiar mais no diagnóstico
Load average é um clássico, existe em praticamente todas as distros linux que marcaram história. Muita gente cresce olhando load como se fosse o termômetro da saúde do servidor. Só que load tem limitações antigas e bem conhecidas: ele mistura coisas e não explica sofrimento.
É aí que o PSI entra como uma camada muito mais honesta. O PSI tenta medir quanto tempo tarefas passam sem conseguir progredir por falta de CPU, memória ou I/O. Em vez de falar só quanto trabalho está enfileirado, ele fala sobre espera real.
Tem algo quase reconfortante quando você lê PSI pela primeira vez e pensa: então era isso, o sistema estava preso esperando I/O, não era CPU alta, era um mundo de gente parada na fila.
E uma consequência direta disso aparece numa peça que muita gente conhece pelo susto.
Antes do OOM killer dar o espetáculo, dá para agir
systemd-oomd e a ideia de um bombeiro que chega antes do incêndio virar tragédia
O OOM killer tradicional é dramático. O kernel decide que acabou, escolhe uma vítima com base em heurísticas, e mata. Funciona, mas é aquele tipo de solução que resolve o problema atual criando uma nova investigação para depois.
Ferramentas como systemd-oomd trazem um comportamento mais antecipado. Elas observam pressão e tentam agir antes do sistema virar uma pedra. A sacada é que, com cgroups v2 e PSI, dá para tomar decisões melhores sobre quem sacrificar, porque você enxerga a pressão dentro de grupos, não só no sistema inteiro.
Isso se conecta com uma filosofia bem prática: matar um serviço específico pode ser menos pior do que deixar a máquina inteira entrar em colapso de responsividade.
Nem todo mundo gosta dessa ideia e, sinceramente, dá para entender. Em alguns ambientes, matar processo automaticamente é inaceitável. Em outros, deixar o host inteiro travado é ainda mais inaceitável. O interessante é que o Linux moderno te dá opções e te obriga a escolher conscientemente, em vez de ficar refém de um único comportamento padrão.
Um pequeno quadro mental para não se perder
O que você limita e o que você monitora
Você pode pensar assim:
-
Limites são o volante. Você define direção e evita sair da pista.
-
Monitoramento é o painel. Você percebe antes de dar ruim.
-
Ação automática é o airbag. Nem sempre você quer, mas às vezes ele salva o dia.
E cgroups v2 encaixa nisso como a infraestrutura que permite que tudo seja feito com menos improviso.
Para deixar isso mais palpável, aqui vai uma tabela rápida, sem aquela vibe de manual, só como referência para organizar o pensamento.
| Objetivo no mundo real | Recurso envolvido | Abordagem típica com cgroups v2 e systemd |
|---|---|---|
| Evitar que um serviço monopolize CPU | CPU | Limitar cota e prioridade do grupo |
| Impedir que um serviço derrube a máquina por memória | Memória | Definir teto e pontos de pressão para reclaim |
| Evitar que um job de backup destrua a latência do sistema | I/O | Definir limites por dispositivo e observar pressão |
| Detectar sofrimento antes do travamento | CPU, memória, I/O | Monitorar PSI e correlacionar com grupos |
| Reduzir impacto do OOM | Memória | Delegar política por grupo e usar ações antecipadas |
Essa tabela parece simples demais, mas é exatamente assim que você começa. Primeiro você cria um cercado. Depois você coloca um limite. Em seguida você observa o que acontece quando a vida real insiste em acontecer.
O detalhe menos óbvio que separa um ajuste bom de um ajuste que vira armadilha
O perigo do limite de memória que causa thrashing silencioso
Aqui vai um daqueles pontos que parecem chatos, mas mudam tudo.
Se você define limites de memória sem entender como o reclaim vai se comportar, você pode criar um cenário em que o processo não morre, mas também não anda. Ele passa a viver num ciclo de recuperar página, perder cache, acessar disco, recuperar de novo. A máquina não parece estar em colapso total, mas fica estranhamente lenta, com picos de latência que ninguém explica direito.
O mais traiçoeiro é que isso pode parecer, por alguns minutos, uma solução elegante. Nada morreu. O serviço continua. Só que a qualidade cai e a experiência do usuário vai junto.
Por isso, quando você brinca com pressão de memória, vale ter sempre em mente a pergunta: eu quero que esse grupo sobreviva com dignidade ou eu estou deixando ele viver em sofrimento permanente?
Essa pergunta parece filosófica, mas no fim ela vira números, limites e observação.
Um jeito amigável de começar sem transformar o sistema em laboratório
Um experimento seguro que ensina mais do que horas de teoria
Um bom começo é escolher um processo que você controla, algo como um teste que aloca memória ou faz escrita em disco, e rodar ele dentro de um escopo do systemd com limites. A graça é observar:
-
como a responsividade do restante do sistema muda
-
se o limite que você colocou realmente segura o comportamento
-
como os sintomas aparecem nos seus monitores e logs
O que normalmente acontece é que você ganha um novo instinto. Você começa a perceber que recursos não somem de forma mágica. Eles são disputados. E, quando você define regras de convivência, o sistema fica mais previsível.
Previsibilidade é um luxo em produção.
Fechando o círculo
Por que cgroups v2 não é moda e sim maturidade do Linux moderno
Cgroups v2 vira assunto sempre que alguém fala de containers, mas a história maior é outra. Ele é uma camada de governança de recursos que o Linux levou tempo para deixar confortável, consistente e delegável.
Quando você entende isso, você percebe que a pergunta mais importante nunca foi como limitar CPU. A pergunta real é como garantir que um sistema multipropósito continue utilizável quando coisas inevitavelmente dão errado. Um pico de tráfego. Um job fora de hora. Um bug que vazou memória. Um usuário que rodou algo pesado sem avisar.
Com cgroups v2, você ganha o direito de desenhar respostas menos dramáticas. Você cria cercas, coloca avisos, mede pressão, e só chama o bombeiro quando faz sentido.
Se você já viveu o tipo de incidente em que todo mundo olha para o host e diz ele está vivo mas ninguém consegue logar, você sabe por que isso importa.
E se você nunca viveu, ótimo. A ideia aqui é justamente continuar assim.
Muitas faculdades de engenharia, principalmente engenharia elétrica, ensinam diversas linguagens de programação para seus alunos. Algumas das mais complexas incluem Assembly e VHDL, esta última é a que discutiremos nesse artigo.
Dados estão por toda a parte, desde relatórios de empresas tentando catalogar seus produtos físicos até dados 100% virtuais como textos gerados na internet. Acredita-se que um percentual muito pequeno de tudo o que se gera de informação acabe sendo analisado na prática, e para isso que passou a existir a profissão de cientista de dados, ou analista de dados.