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
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.yamlEXPOSE 80/tcp
EXPONER 443/tcp
#Educated adivina que esto es TCP
EXPOSE 9901/tcpLABEL 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
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.
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
- https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http_connection_management
- https://runnable.com/docker/basic-docker-networking
- https://docs.docker.com/engine/reference/commandline/network_create/
- https://docs.docker.com/v17.09/engine/userguide/networking/
- https://github.com/envoyproxy/envoy/tree/master/examples/front-proxy
- https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/http_routing
- https://www.envoyproxy.io/docs/envoy/latest/configuration/http_conn_man/header_sanitizing
- https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route.proto#envoy-api-field-route-routeaction-host-rewrite
- prefix_rewrite parece interesante - permite cambiar las URLs de las aplicaciones a una ruta diferente a la expuesta en la capa del proxy inverso
- https://www.envoyproxy.io/docs/envoy/latest/api-v2/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#envoy-api-enum-config-filter-network-http-connection-manager-v2-httpconnectionmanager-codectype
- hay filtros incorporados
- https://www.envoyproxy.io/docs/envoy/latest/configuration/http_filters/router_filter#config-http-filters-router
- "El filtro del enrutador implementa el reenvío HTTP. Se utilizará en casi todos los escenarios de proxy HTTP para los que se despliega Envoy".
- https://blog.turbinelabs.io/setting-up-ssl-with-envoy-f7c5aa06a5ce
- tiene una sección sobre la redirección del tráfico inseguro
- https://www.envoyproxy.io/try/migrating-from-nginx-to-envoy
- útil también como introducción a Envoy
- https://www.envoyproxy.io/docs/envoy/latest/configuration/access_log#config-access-log-format-dictionaries