O seu portátil mostra un túnel verde, o rexistro do cliente indica que se enviaron rutas, e a única dirección que responde é a IP do túnel do propio servidor VPN. Os pings máis alá morren sen importar a onde apunte, xa sexa un ClusterIP, a dirección doutro pod ou un nome de host público. Esa combinación é diagnóstica, non vaga: a desencapsulación funciona e o segundo salto non.

Atopei isto nun nodo Debian con unha imaxe de OpenVPN instalada por chart, e o túnel era a parte fácil. O cliente tomou unha concesión 10.8.0.x, 10.8.0.1 respondeu, e 10.96.0.10, o servizo DNS do clúster, esgotou o tempo. Nada do rexistro do servidor parecía enfermizo, e por iso mesmo a xente comeza a reescribir regras de iptables que nunca necesitou tocar.

Un pod de VPN é un enrutador, e paga a pena dicilo sen rodeos. Os paquetes cifrados chegan, desenvólvense no namespace de rede do propio pod e despois teñen que saír por outra interface. Linux rexeita ese segundo paso salvo que o reenvío estea activado dentro dese mesmo namespace.

A que pode e a que non pode chegar o cliente

A dirección que responde pertence ao extremo do túnel, e o proceso da VPN posúea localmente, así que o reenvío non intervén en absoluto. Todo o demais, incluído outro pod, un VIP de servizo ou internet, necesita que o núcleo mova un paquete de tun0 a eth0. Cando ese movemento se rexeita, o síntoma é un silencio uniforme e non un rexeitamento, porque nada xera un erro ICMP de volta polo túnel. Obtén tempos de espera, non mensaxes de inalcanzable, e esa é a pista de que ninguén está a enrutar en absoluto.

Dous minutos de clasificación estreitan a capa. Se os nomes DNS fallan mentres os pings crus a unha IP de servizo funcionan, o problema é a fontanaría DNS, non o reenvío. Se todo destino máis alá da dirección do par esgota o tempo, incluída unha IP espida, comece polo namespace.

Lea o axuste dentro do namespace

Cada pod recibe o seu propio namespace de rede, e net.ipv4.ip_forward é un sysctl por namespace. Cambialo no nodo non lle di nada sobre o contedor, e é unha forma fiable de pasar unha tarde na máquina equivocada.

kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0

Un cero confirma o diagnóstico. O valor tampouco se herda da configuración de execución do nodo: parte do valor predeterminado da imaxe cada vez que se crea un contedor. Por iso unha corrección aplicada a man con kubectl exec ... sysctl -w desaparece no seguinte reinicio e volve como unha avaría que parece intermitente.

Activalo para que o manifesto o conserve

A opción duradeira é un contedor init que se executa no mesmo pod sandbox e escribe o valor antes de que arrinque o contedor da VPN. Os contedores dun pod comparten un namespace de rede, así que o axuste pasa ao contedor principal.

initContainers:
- name: enable-forwarding
  image: busybox:1.36
  command: ["sysctl", "-w", "net.ipv4.ip_forward=1"]
  securityContext:
    privileged: true

Ese privileged: true é a liña á que os revisores se opoñen, e teñen razón. Escribir un sysctl require privilexio ou unha capacidade de alcance estreito, e un clúster que aplica o Pod Security Standard restrinxido pode rexeitar de plano un contedor init privilexiado. Se a admisión rexeita o pod, sábeo no momento de crealo, o que polo menos é honesto e fácil de ler.

A alternativa máis limpa é a lista securityContext.sysctls a nivel de pod, que permite ao kubelet aplicar sysctls con namespace sen conceder privilexios a ningún contedor. Só cobre nomes da lista de permitidos do clúster. Que net.ipv4.ip_forward estea nesa lista depende de como se configurou o kubelet, e un pod que pide un sysctl fóra dela rexéitase na admisión ou queda atascado en CreateContainerConfigError mentres se reintenta o sandbox. Comprobe a lista de permitidos antes de supor que o campo está roto.

Antes de construír a man calquera dos dous enfoques, mire se o chart xa expón o interruptor, a miúdo como algo parecido a ipForwardInitContainer: true. Usar o valor do chart mantén pequeno o seu ficheiro de anulación e sobrevive á próxima actualización, cousa que as edicións de Deployment parcheadas a man non fan.

A segunda metade: ruta de volta e política

O reenvío activado é necesario, non suficiente. Se os clientes usan un grupo privado para o que a rede do clúster non ten ruta, as respostas non atopan o camiño de volta ao túnel, e o pod ten que enmascarar ese tráfico cara ao seu destino.

A política apoia sobre iso. Os obxectos NetworkPolicy e as regras de devasas da nube avalíanse contra a dirección de orixe que leva o paquete tras a tradución, así que unha regra escrita para o grupo de clientes pode deixar de coincidir en silencio en canto se activa a máscara.

Cando os clientes só necesitan chegar a servizos dentro do clúster, que a VPN termine no VIP do servizo é un deseño máis pequeno que enrutar cara á rede de pods. Tamén mantén o grupo de clientes completamente fóra da táboa de rutas do CNI.

Illar o salto que falla respecto do cliente

Traballa cara a fóra e detente no primeiro paso silencioso. Comeza polo par da VPN, despois proba a dirección dalgún pod, despois un VIP de servizo e só despois un destino público. Cada éxito move a fronteira un salto, e cada fallo nomea a capa que merece inspección. Despois de calquera despregamento, entra con exec e le o sysctl de novo, porque un pod substituído parte do valor predeterminado da imaxe e unha corrección que nunca estivo no manifesto xa se foi.

A documentación de Kubernetes sobre o uso de sysctls nun clúster enumera que nomes se poden definir mediante o contexto de seguridade do pod, e é o primeiro lugar onde mirar cando a admisión rexeita o cambio.

Artigos relacionados