Unha máquina, dúas cargas de traballo e un requisito que as separa: un cliente de descargas que debe saír por unha VPN comercial e unha interface de administración que debe seguir usando a conexión da máquina. Instalar o cliente VPN na máquina incumpre o requisito de inmediato, porque entón ambas as cargas comparten unha soa saída. O patrón que si funciona é trasladar o túnel ao seu propio contedor e permitir que só as cargas que o necesitan se unan ao espazo de nomes de rede dese contedor. Todo o demais mantén o camiño habitual de Docker, e os detalles que seguen son consecuencias de quen posúe o espazo de nomes.

Por que un espazo de nomes compartido cambia as regras

Un contedor que se une ao espazo de nomes doutro non obtén a súa propia pila de rede. Ve as mesmas interfaces, a mesma táboa de encamiñamento e o mesmo loopback que o contedor ao que se uniu, e precisamente por iso o patrón é útil: a carga resolve e conecta con normalidade, e o túnel de debaixo captura o tráfico sen que a aplicación o saiba. O custo é que cada axuste de rede ten agora un só propietario, e o contedor que se une non o é.

Esa regra de propiedade responde a maioría das preguntas de configuración antes de que se formulen. Se un axuste vive na pila de rede, pertence ao contedor lateral. Se describe o proceso, queda coa carga.

O loopback é a parte que sorprende a xente. Dentro do contedor que se une, localhost resólvese ao loopback do contedor lateral, non a un privado propio, así que un servizo que se liga a 127.0.0.1 esperando illamento agora comparte ese enderezo co contedor do túnel.

Publica os portos no contedor que posúe o espazo de nomes

A asignación de portos pertence ao propietario do espazo de nomes mesmo cando o proceso que escoita se executa no outro contedor. Declara a asignación no contedor lateral e deixa que a carga conserve a súa propia configuración de proceso intacta. Unha asignación no servizo que se une non pode surtir efecto, xa sexa porque o motor a rexeita ou porque a ignora en silencio segundo como se inicie o contedor, e por iso unha interface que era accesible hai un momento desaparece en canto se aplica o patrón.

services:
  gluetun:
    image: qmcgaw/gluetun
    cap_add: [NET_ADMIN]
    ports: ["8080:8080"]
  client-vpn:
    image: example/client
    network_mode: "service:gluetun"
  client-direct:
    image: example/client
    ports: ["8081:8080"]

Le ese bloque como tres decisións en lugar de tres servizos. O contedor lateral posúe o túnel e o porto publicado; o cliente que se une non declara ningunha rede; o cliente directo conserva unha asignación propia na rede predeterminada. A capacidade NET_ADMIN é o que permite ao contedor lateral crear interfaces e alterar rutas, e é a razón pola que este contedor necesita máis privilexios que as cargas ás que serve.

O servizo que queda directo conserva a súa propia rede

A carga que non debe pasar polo túnel conserva a ponte predeterminada ou unha rede definida polo usuario propia, co seu propio porto publicado e a súa propia saída. É tentador conectala á rede do contedor lateral para que os dous contedores poidan falar por nome, pero ese único paso traslada o seu tráfico ao túnel sen avisar. Se necesitan alcanzarse, constrúe unha rede definida polo usuario á parte, conecta ambos a ela e deixa o contedor lateral como a única vía de saída.

Mantén as dúas preguntas separadas: que contedores poden alcanzarse e cal sae por onde. Fusionalas é a forma máis habitual de que este deseño volva converterse nunha VPN para toda a máquina.

Unha matriz de fallos para a primeira hora

A maioría dos primeiros intentos fallan dunha de catro maneiras, e cada unha ten unha causa distinta. Compróbaas nesta orde, porque as dúas primeiras explican case todos os informes.

SymptomLikely cause
Web UI unreachable after the changePort mapping declared on the joining container instead of the sidecar
Both containers show the provider's exit addressThe direct service was attached to the sidecar network
Internal names stop resolvingResolver settings live on the host, not in the shared namespace
Health check fails but the app worksThe check probes localhost, which now means the sidecar

A cuarta fila é a que a xente diagnostica mal como un fallo da aplicación. Unha sonda escrita contra o loopback propio da carga agora está a probar o contedor do túnel, así que ou falla ou informa dun servizo completamente equivocado.

Cando un só nome de máquina necesita o túnel

Ás veces un túnel completo é demasiado: un nome interno debe pasar por unha VPN corporativa mentres un socket local ou unha conexión de pantalla segue funcionando. Un túnel completo dentro do contedor rompe esa ruta e todo o dirixido á máquina, así que encamiña só o prefixo que o necesita. Un envoltorio de encamiñamento dividido arredor do cliente fai iso, enviando o nome de máquina indicado polo túnel e deixando a ruta anterior intacta para todo o demais.

Escolle isto cando só necesitas alcanzar un servizo e non intentas mover todo o tráfico do contedor. É unha ferramenta distinta do contedor lateral e responde a unha pregunta distinta.

Verifica e logo fai que sobreviva a un reinicio

Pregunta a cada contedor de que enderezo parece vir. O do túnel debería imprimir o enderezo do provedor e o directo a saída da máquina. Respostas idénticas significan que o servizo directo herdou o espazo de nomes equivocado ou que unha VPN a nivel de máquina segue capturándoo todo, e esas dúas correccións son distintas. Volve executar a comprobación despois de cada edición de compose, porque un só bloque de servizo copiado abonda para reintroducir o problema.

Tres cousas adoitan romper máis adiante. O DNS segue o propietario do espazo de nomes, así que os axustes de resolutor e de dominio de busca pertencen ao contedor lateral e non á máquina. Unha VPN con reenvío de portos cambia o seu porto de escoita ao reconectar, así que o porto reenviado do provedor e o porto de escoita do lado do contedor deben volver escribirse na configuración do cliente ou na asignación de portos, normalmente mediante un pequeno actualizador que le a API do provedor. E calquera sonda escrita contra localhost agora pregunta ao contedor do túnel e non á carga.

Escribe o patrón, incluído que contedor posúe o espazo de nomes e que portos lle pertencen. A seguinte persoa engadirá un servizo, copiará o bloque equivocado e reproducirá o primeiro fallo deste artigo.

Artigos relacionados