v0.41.0 — um pod voltava do respawn do holder sem rede, em silêncio
v0.41.0 — um pod voltava do respawn do holder sem rede, em silêncio
Continuação directa da v0.40.0, que trouxe pods e VMs para dentro do isolamento
de namespace. Trazê-los para dentro tornou visível a pergunta seguinte: e quando
o holder morre e volta?
A resposta, medida antes de escrever código:
recovered 1 container(s) stranded by the previous holder (restarted)
pa-c0 Up 32 seconds → ping: Network unreachable
O container foi recuperado. O pod ficou vivo, sem rede, sem a sua chain de
isolamento, e sem uma linha a dizê-lo. Uma recuperação que reporta sucesso
por cima de um workload que acabou de abandonar é pior do que uma que não faz
nada — porque a primeira é lida como "está tratado".
A raiz: a associação ao pod nunca era persistida
Container tem um campo pod desde sempre. O describe sempre o imprimiu.
Nada alguma vez lho atribuiu — o único traço de pertença em disco era uma
label. É a quarta vez que este repositório paga exactamente esta armadilha (o
-v não persistido, o -p numa rede custom, as redes extra perdidas no
restart), e a regra continua a mesma: estado necessário para RECONSTRUIR o
recurso tem de ser persistido, não só usado uma vez na criação.
Duas consequências, ambas reproduzidas:
container describenum membro de pod não mostrava pod nenhum;container restartde um membro morria comclone failed: EPERMe deixava-o
Dead, sem caminho de volta — ocmd_startreconstrói o spec a partir do
registo e não tinha como saber que devia re-entrar na netns partilhada.
O que passou a funcionar
container restartde um membro de pod volta a entrar na netns do pod,
com o mesmo IP, sem tocar nos peers. Se a netns já não existir (o holder foi
substituído), é recriada — com a namespace do membro, portanto o isolamento
volta com ela.- Um respawn do holder recupera pods como já recuperava containers.
Dois bugs apanhados pelo caminho, ambos só visíveis ao vivo
reexec_start ignorava o seu próprio parâmetro netns e usava o id.
Funcionava por coincidência: o único chamador passava um netns igual ao id. Um
membro de pod é o primeiro caso em que diferem — com o código antigo teria
tentado entrar numa netns com o nome do container, que não existe. Mesma família
dos ajudantes públicos, mortos e com defeito à espera do primeiro chamador que
este repo já teve de apagar duas vezes. O caminho de falha ganhou também um
owns_netns: só se desmonta uma netns que seja nossa — a de um pod é partilhada,
e derrubá-la porque um membro não voltou tiraria a rede aos outros.
A guarda de idempotência da recuperação estava a saltar membros. Perguntava,
dentro do ciclo, «o holder serve esta netns?» — e a resposta passa a sim assim
que o primeiro membro recupera, pelo que todos os seguintes eram tratados
como saudáveis enquanto continuavam dentro da netns morta. Foi a primeira versão
desta correcção, e só um pod de dois containers a mostrou:
recovered 2 container(s) pa-c0 → Network unreachable
A pergunta passou a ser feita uma vez, antes do ciclo. Aí é a pergunta certa:
no início da passagem, ou o holder servia a netns do pod (nada morreu — saltam-se
todos os membros) ou não servia (estão todos encalhados — reiniciam-se todos).
Para um container, cuja netns é só sua, snapshot e consulta ao vivo são
equivalentes.
Validação
Ao vivo, no sandbox isolado: restart de um membro com um peer a correr (o peer
não perde um pacote, o membro volta ao mesmo IP do pod); respawn do holder com um
pod de dois membros + um container em rede custom — os três recuperados, os
dois membros no mesmo IP, e o isolamento reconstruído (cross-namespace bloqueado
nos dois sentidos, mesmo-pod aberto).
Cenário de caos novo (pod_holder_respawn), deliberadamente com dois
containers no pod: com um só, a guarda partida ainda passava. Falha com a
correcção revertida (c0=down c1=down) e passa com ela. Arnês completo:
16 PASS · 0 FAIL · 0 SKIP.
Ainda em aberto
A recuperação continua a ser por reinício, não por adopção: adoptar a netns
viva para dentro do holder novo é impossível no kernel em rootless (ip netns attach precisa de CAP_SYS_ADMIN sobre o userns do holder que morreu), e isso
está medido e documentado desde a v0.39. VMs continuam fora da reconciliação — o
tap morre com o holder e nada o repõe.