Configuración de envoy como proxy frontal en Docker con comunicación a otros contenedores Docker

Tengo contenedores ya existentes que quiero usar envoy como proxy y gestor de https delante. Estoy aprendiendo a usar envoy, y estoy compartiendo algunos de mis aprendizajes aquí, ya que la documentación es un poco confusa para empezar.

Mi contenedor ya existente se llama "taxgod" - ejecuta una aplicación Crystal en el puerto 3000 (http). Quiero proxy al puerto 80 en el host para http, y el puerto 443 para https.

Utilizaré un certificado falso para fines de demostración. La creación de certificados está fuera del alcance de este artículo.

El contenedor de envío se va a llamar penvoyage (picockpit enviado )

Construcción de penvoyage

imagen

La carpeta penvoyage utilizada para la construcción contiene

  • Dockerfile
  • envoy.yaml
  • example.crt (certificado)
  • example.key (clave del certificado)

Dockerfile

FROM envoyproxy/envoy:latest
COPIAR envoy.yaml /etc/envoy/envoy.yaml
COPIAR ejemplo.crt /etc/ejemplo-com.crt
COPY example.key /etc/example-com.key
#VOLUME /etc/envoy/envoy.yaml

EXPOSE 80/tcp
EXPONER 443/tcp
#Educated adivina que esto es TCP
EXPOSE 9901/tcp

LABEL version="0.2.0″ \N - LABEL version="0.2.0″.
       description="penvoyage es el proxy de envoy para PiCockpit" \N -
       mantenedor=""

Ten cuidado con los caracteres ", WordPress podría estropearlos.

Pronto hablaré del envoy.yaml con un poco más de detalle. Basta con decir que está en esta carpeta y se copiará en la imagen del contenedor recién creado.

Para construir el contenedor ejecute (desde el directorio que contiene el directorio penvoyage):

docker build -t jasmine/penvoyage:0.2.0 -t jasmine/penvoyage:latest penvoyage

Su salida debe terminar con las líneas

Etiquetado con éxito jasmine/penvoyage:0.2.0
Etiquetado con éxito jasmine/penvoyage:latest

Crear la red docker

docker network create -d bridge my-bridge-network

Utilizaremos esta red para unir ambos contenedores entre sí, para que se vean mutuamente.

Los contenedores pueden hablar entre sí utilizando sus nombres de contenedor, cuando están en la misma red de contenedores.

Por ejemplo, puede hacer

ping taxgod

donde taxgod es el nombre del contenedor.

Para añadir un contenedor a una red después de haberlo ejecutado, haga lo siguiente:

docker network connect my-bridge-network taxgod

En este caso mi-red-puente es la red, y taxgod es el contenedor que se conecta a ella.

Para ver cómo se conecta un contenedor que se ejecuta a una red particular, vea a continuación.

Para ver qué contenedores están en una red Docker concreta, ejecute el siguiente comando:

docker network inspect my-bridge-network

Ejecutar la imagen del contenedor penvoyage

docker run -rm -it -p 80:80 -p 443:443 -p 9901:9901 -network=mi-red-puente jasmine/penvoyage

Esto lo hará:

  • -rm eliminar el contenedor después de que se apague
  • -it adjuntar al contenedor (para que pueda ver la salida de envoy)
  • -p 80:80 mapear el puerto 80 al puerto 80 dentro del contenedor (en el archivo Docker he definido que sea el puerto tcp)
  • repetir para el puerto 443 y el puerto 9901
  • adjuntar el contenedor a mi-red-puente
  • construir el contenedor a partir de la imagen jasmine/penvoyage:latest (:latest está implícito aquí)

¿Qué hará este contenedor?

Proxyará las conexiones al host (en mi caso en la IP 192.168.1.2) al contenedor taxgod, en el puerto 3000.

Actuará como un proxy https con los certificados de muestra, y proxy las conexiones al mismo contenedor taxgod, en el puerto 3000.

envoy.yaml

Por favor, tenga en cuenta: yaml utiliza espacios en blanco para la estructura, lo más probable es que WordPress lo estropee. ¡Así que use esto como una referencia, en lugar de una cosa de copiar y pegar!


static_resources:
   oyentes:
   - dirección:
       dirección_de_socket:
         dirección: 0.0.0.0
         valor_puerto: 80
     cadenas_de_filtro:
     - filtros:
       - nombre: envoy.http_connection_manager
         configurar:
           codec_type: auto
           stat_prefix: ingress_http
           route_config:
             nombre: ruta_local
             virtual_hosts:
             - nombre: servicio_local
               dominios: ["*"]
               rutas:
               - coincidencia: { prefijo: "/" }
                 ruta: { cluster: target_taxgod }
           http_filters:
           - nombre: envoy.router
   - dirección:
       dirección_de_socket:
         dirección: 0.0.0.0
         valor_de_puerto: 443
     cadenas_de_filtro:
     - tls_context:
         common_tls_context:
           tls_certificados:
           - cadena_certificada: { nombre de archivo: "/etc/ejemplo-com.crt" }
             private_key: { nombre de archivo: "/etc/ejemplo-com.key" }
       filtros:
       - nombre: envoy.http_connection_manager
         configurar:
           stat_prefix: ingress_https
           route_config:
             virtual_hosts:
             - nombre: por defecto
               dominios: ["*"]
               rutas:
               - coincidencia: { prefijo: "/" }
                 ruta: { cluster: target_taxgod }
           http_filters:
           - nombre: envoy.router
   racimos:
   - nombre: target_taxgod
     connect_timeout: 0.25s
     tipo: strict_dns
     lb_policy: round_robin
     anfitriones:
     - dirección_de_socket:
         dirección: taxgod
         valor_de_puerto: 3000
admin:
   access_log_path: "/tmp/envoy.log"
   dirección:
     dirección_de_socket:
       dirección: 0.0.0.0
       valor_puerto: 9901


Breve explicación del archivo envoy yaml:

Hay dos secciones principales, static_resources y admin

admin es para la administración de envoy y está fuera del alcance de este artículo. En un entorno de producción probablemente tendrá que asegurarlo apropiadamente. ¡¡¡NO COPIE Y PEGUE ESA PARTE!!!

static_resources define una configuración estática para envoy (envoy también se puede configurar utilizando su API)

en los escuchadores, definimos los puertos en los que queremos escuchar, y lo que debe ocurrir con las conexiones.

  • address - define la dirección y el puerto de escucha
    • envoy.http_connection_manager - gestiona las conexiones http, lee las cabeceras, etc. es un filtro predefinido
    • stat_prefix: define un nombre legible para los registros / estadísticas
    • dominios: ["*"] - coincide con todos los dominios
    • ruta: { cluster: target_taxgod } - dirigirá el tráfico a nuestro clúster target_taxgod (coincidirá para /, es decir, todo en el sitio)

la dirección y su subconfiguración se repite dos veces, una para el puerto 80 y otra para el 443. Para el puerto 443 también añadimos el tls_context y common_tls_context en el filter_chains para inyectar los certificados.

Tenga en cuenta que todavía es envoy.http_connection_managerNOT https_connection_manager para el puerto 443.

en los clústeres definimos nuestros puntos finales a los que queremos poder conectarnos / proxy de tráfico.

  • el clúster tiene un nombre
  • un tiempo de espera de la conexión
  • lb_policy - la política de equilibrio de carga. Sólo hay un host, por lo que recibirá todo el tráfico (round_robin significa que cada host recibirá el tráfico por turnos)
  • en los hosts, la dirección del socket se establece como dirección taxgod - este es el nombre Docker del contenedor, y el puerto como valor_puerto 3000

El puerto 3000 es el puerto interno del contenedor taxgod, no es el puerto al que se vincula en el host externo.

Espero que esta entrada del blog ayude a las personas que tratan de establecer una configuración de https:// en envoy.

Mensajes de error

imagen

Enviado no hay una corriente ascendente saludable mensaje de error

el contenedor enviado no está en la misma red Docker como su contenedor de destino, como no puede verlo, no puede conectarse a él.

imagen

Enviado error de conexión ascendente o desconexión/reinicio antes de las cabeceras error

Intenta eliminar

http2_protocolo_opciones: {}

de su envoy.yaml

Recursos útiles