¡Hola Habr! Les traigo una traducción del post:
Envoy es un servidor proxy distribuido de alto rendimiento (escrito en C++) diseñado para servicios y aplicaciones individuales, también es un bus de comunicación y un "plano de datos universal" diseñado para grandes arquitecturas de "malla de servicios" de microservicios. Al crearlo se tuvieron en cuenta soluciones a problemas que surgieron durante el desarrollo de servidores como NGINX, HAProxy, balanceadores de carga de hardware y balanceadores de carga en la nube. Envoy trabaja junto con cada aplicación y abstrae la red para proporcionar una funcionalidad común independientemente de la plataforma. Cuando todo el tráfico de servicios en una infraestructura fluye a través de la malla de Envoy, resulta fácil visualizar áreas problemáticas con observabilidad consistente, ajustar el rendimiento general y agregar funcionalidad central en una ubicación específica.
oportunidades
- Arquitectura fuera de proceso: envoy es un servidor autónomo de alto rendimiento que ocupa una pequeña cantidad de RAM. Funciona en conjunto con cualquier lenguaje o marco de aplicación.
- Compatibilidad con http/2 y grpc: envoy tiene compatibilidad con http/2 y grpc de primera clase para conexiones entrantes y salientes. Este es un proxy transparente de http/1.1 a http/2.
- Equilibrio de carga avanzado: envoy admite funciones avanzadas de equilibrio de carga que incluyen reintentos automáticos, interrupción de cadena, limitación de velocidad global, seguimiento de solicitudes, equilibrio de carga de zona local, etc.
- API de gestión de configuración: envoy proporciona una API sólida para gestionar dinámicamente su configuración.
- Observabilidad: observabilidad profunda del tráfico L7, soporte nativo para seguimiento distribuido y observabilidad de mongodb, dynamodb y muchas otras aplicaciones.
Paso 1: ejemplo de configuración de NGINX
Este script utiliza un archivo especialmente diseñado nginx.conf, basado en el ejemplo completo de
configuración de fuente nginx
user www www;
pid /var/run/nginx.pid;
worker_processes 2;
events {
worker_connections 2000;
}
http {
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
log_format download '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_range" "$sent_http_content_range"';
upstream targetCluster {
172.18.0.3:80;
172.18.0.4:80;
}
server {
listen 8080;
server_name one.example.com www.one.example.com;
access_log /var/log/nginx.access_log main;
error_log /var/log/nginx.error_log info;
location / {
proxy_pass http://targetCluster/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
Las configuraciones de NGINX suelen tener tres elementos clave:
- Configuración del servidor NGINX, estructura de registros y funcionalidad Gzip. Esto se define globalmente en todos los casos.
- Configurar NGINX para aceptar solicitudes al host uno.ejemplo.com en el puerto 8080.
- Configurar la ubicación de destino, cómo manejar el tráfico para diferentes partes de la URL.
No todas las configuraciones se aplicarán a Envoy Proxy y no es necesario configurar algunas configuraciones. Envoy Proxy tiene cuatro tipos de claves, que respaldan la infraestructura central ofrecida por NGINX. El núcleo es:
- Oyentes: Determinan cómo Envoy Proxy acepta las solicitudes entrantes. Actualmente, Envoy Proxy solo admite escuchas basadas en TCP. Una vez que se establece una conexión, se pasa a un conjunto de filtros para su procesamiento.
- Filtros: Son parte de una arquitectura de canalización que puede procesar datos entrantes y salientes. Esta funcionalidad incluye filtros como Gzip, que comprime los datos antes de enviarlos al cliente.
- Enrutadores: Reenvían el tráfico al destino requerido, definido como un clúster.
- Grupos: Definen el punto final para el tráfico y los parámetros de configuración.
Usaremos estos cuatro componentes para crear una configuración de Envoy Proxy que coincida con una configuración NGINX específica. El objetivo de Envoy es trabajar con API y configuración dinámica. En este caso, la configuración base utilizará configuraciones estáticas codificadas de NGINX.
Paso 2: configuración de NGINX
La primera parte nginx.conf define algunos componentes internos de NGINX que deben configurarse.
Conexiones de trabajadores
La siguiente configuración determina la cantidad de procesos y conexiones de trabajo. Esto indica cómo NGINX escalará para satisfacer la demanda.
worker_processes 2;
events {
worker_connections 2000;
}
Envoy Proxy gestiona flujos de trabajo y conexiones de diferentes maneras.
Envoy crea un subproceso de trabajo para cada subproceso de hardware del sistema. Cada hilo de trabajo ejecuta un bucle de eventos sin bloqueo que es responsable de
- Escuchando a cada oyente
- Aceptar nuevas conexiones
- Crear un conjunto de filtros para una conexión
- Procese todas las operaciones de E/S durante la vida útil de la conexión.
Todo el procesamiento de conexión adicional se maneja completamente en el subproceso de trabajo, incluido cualquier comportamiento de reenvío.
Para cada subproceso de trabajo en Envoy, hay una conexión en el grupo. Por lo tanto, los grupos de conexiones HTTP/2 solo establecen una conexión por host externo a la vez; si hay cuatro subprocesos de trabajo, habrá cuatro conexiones HTTP/2 por host externo en un estado estable. Al mantener todo en un subproceso de trabajo, casi todo el código se puede escribir sin bloqueo, como si fuera de un solo subproceso. Si se asignan más subprocesos de trabajo de los necesarios, esto puede generar un desperdicio de memoria, lo que crea una gran cantidad de conexiones inactivas y reduce la cantidad de veces que las conexiones se devuelven al grupo.
Para más información visite
Configuración HTTP
El siguiente bloque de configuración de NGINX define configuraciones HTTP como:
- ¿Qué tipos de mime son compatibles?
- Tiempos de espera predeterminados
- Configuración Gzip
Puede personalizar estos aspectos utilizando filtros en Envoy Proxy, que analizaremos más adelante.
Paso 3: configuración del servidor
En el bloque de configuración HTTP, la configuración de NGINX especifica escuchar en el puerto 8080 y responder a las solicitudes entrantes de dominios. uno.ejemplo.com и www.one.ejemplo.com.
server {
listen 8080;
server_name one.example.com www.one.example.com;
Dentro de Envoy, está controlado por oyentes.
Oyentes enviados
El aspecto más importante al empezar a utilizar Envoy Proxy es definir a sus oyentes. Debe crear un archivo de configuración que describa cómo desea ejecutar la instancia de Envoy.
El siguiente fragmento creará un nuevo oyente y lo vinculará al puerto 8080. La configuración le indica a Envoy Proxy a qué puertos debe vincularse para las solicitudes entrantes.
Envoy Proxy utiliza la notación YAML para su configuración. Para una introducción a esta notación, mire aquí
Copy to Editorstatic_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
No es necesario definir nombre del servidor, ya que los filtros de Envoy Proxy se encargarán de esto.
Paso 4: Configuración de la ubicación
Cuando llega una solicitud a NGINX, el bloque de ubicación determina cómo procesar y dónde enrutar el tráfico. En el siguiente fragmento, todo el tráfico al sitio se transfiere a un clúster ascendente (nota del traductor: el ascendente suele ser un servidor de aplicaciones) llamado objetivoClúster. El clúster ascendente define los nodos que deben procesar la solicitud. Discutiremos esto en el siguiente paso.
location / {
proxy_pass http://targetCluster/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
En Envoy, Filters hace esto.
Filtros de enviado
Para una configuración estática, los filtros determinan cómo procesar las solicitudes entrantes. En este caso configuramos filtros que coinciden nombres_servidor en el paso anterior. Cuando llegan solicitudes entrantes que coinciden con ciertos dominios y rutas, el tráfico se dirige al clúster. Este es el equivalente a una configuración ascendente de NGINX.
Copy to Editor filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "one.example.com"
- "www.one.example.com"
routes:
- match:
prefix: "/"
route:
cluster: targetCluster
http_filters:
- name: envoy.router
nombre enviado.http_connection_manager es un filtro incorporado en Envoy Proxy. Otros filtros incluyen Redis, Mongo, TCP. Puedes encontrar la lista completa en
Para obtener más información sobre otras políticas de equilibrio de carga, visite
Paso 5: configuración de proxy y ascendente
En NGINX, la configuración ascendente define un conjunto de servidores de destino que procesarán el tráfico. En este caso se asignaron dos grupos.
upstream targetCluster {
172.18.0.3:80;
172.18.0.4:80;
}
En Envoy, esto se gestiona mediante clústeres.
Grupos de enviados
El equivalente ascendente se define como clústeres. En este caso, se han identificado los hosts que atenderán el tráfico. La forma en que se accede a los hosts, como los tiempos de espera, se define como una configuración de clúster. Esto permite un control más granular sobre aspectos como la latencia y el equilibrio de carga.
Copy to Editor clusters:
- name: targetCluster
connect_timeout: 0.25s
type: STRICT_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
hosts: [
{ socket_address: { address: 172.18.0.3, port_value: 80 }},
{ socket_address: { address: 172.18.0.4, port_value: 80 }}
]
Al utilizar el descubrimiento de servicios STRICT_DNS Envoy resolverá de forma continua y asincrónica los objetivos DNS especificados. Cada dirección IP devuelta por el resultado DNS se considerará un host explícito en el clúster ascendente. Esto significa que si una solicitud devuelve dos direcciones IP, Envoy asumirá que hay dos hosts en el clúster y que ambos deben tener equilibrio de carga. Si se elimina un host del resultado, Envoy asumirá que ya no existe y extraerá el tráfico de cualquier grupo de conexiones existente.
Para más información, ver
Paso 6: acceso al registro y errores
La configuración final es el registro. En lugar de enviar registros de errores al disco, Envoy Proxy adopta un enfoque basado en la nube. Todos los registros de la aplicación se envían a stdout и stderr.
Cuando los usuarios realizan una solicitud, los registros de acceso son opcionales y están deshabilitados de forma predeterminada. Para habilitar los registros de acceso para solicitudes HTTP, habilite la configuración registro_acceso para el administrador de conexiones HTTP. La ruta puede ser un dispositivo como stdout, o un archivo en el disco, según sus requisitos.
La siguiente configuración redirigirá todos los registros de acceso a stdout (Nota del traductor: se requiere stdout para usar envoy dentro de Docker. Si se usa sin Docker, reemplace /dev/stdout con la ruta a un archivo de registro normal). Copie el fragmento en la sección de configuración del administrador de conexiones:
Copy to Clipboardaccess_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
Los resultados deberían verse así:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
access_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
route_config:
De forma predeterminada, Envoy tiene una cadena de formato que incluye los detalles de la solicitud HTTP:
[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n
El resultado de esta cadena de formato es:
[2018-11-23T04:51:00.281Z] "GET / HTTP/1.1" 200 - 0 58 4 1 "-" "curl/7.47.0" "f21ebd42-6770-4aa5-88d4-e56118165a7d" "one.example.com" "172.18.0.4:80"
El contenido de salida se puede personalizar configurando el campo de formato. Por ejemplo:
access_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
format: "[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"n"
La línea de registro también se puede generar en formato JSON configurando el campo formato_json. Por ejemplo:
access_log:
- name: envoy.file_access_log
config:
path: "/dev/stdout"
json_format: {"protocol": "%PROTOCOL%", "duration": "%DURATION%", "request_method": "%REQ(:METHOD)%"}
Para obtener más información sobre la Metodología de registro de enviados, visite
El registro no es la única forma de obtener información sobre cómo trabajar con Envoy Proxy. Tiene capacidades avanzadas de seguimiento y métricas integradas. Puedes obtener más información en
Paso 7 - Lanzar
Ahora ha migrado su configuración de NGINX a Envoy Proxy. El último paso es iniciar una instancia de Envoy Proxy para probarla.
Ejecutar como usuario
En la parte superior de la línea de configuración de NGINX usuario www www; especifica ejecutar NGINX como un usuario con pocos privilegios para mejorar la seguridad.
Envoy Proxy adopta un enfoque basado en la nube para gestionar quién es el propietario de un proceso. Cuando ejecutamos Envoy Proxy a través de un contenedor, podemos especificar un usuario con pocos privilegios.
Lanzamiento del proxy Envoy
El siguiente comando ejecutará Envoy Proxy a través de un contenedor Docker en el host. Este comando le da a Envoy la capacidad de escuchar solicitudes entrantes en el puerto 80. Sin embargo, como se especifica en la configuración del oyente, Envoy Proxy escucha el tráfico entrante en el puerto 8080. Esto permite que el proceso se ejecute como un usuario con pocos privilegios.
docker run --name proxy1 -p 80:8080 --user 1000:1000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy
pruebas
Con el proxy en ejecución, ahora se pueden realizar y procesar pruebas. El siguiente comando cURL emite una solicitud con el encabezado del host definido en la configuración del proxy.
curl -H "Host: one.example.com" localhost -i
La solicitud HTTP resultará en un error. 503. Esto se debe a que las conexiones ascendentes no funcionan y no están disponibles. Por lo tanto, Envoy Proxy no tiene destinos disponibles para la solicitud. El siguiente comando iniciará una serie de servicios HTTP que coinciden con la configuración definida para Envoy.
docker run -d katacoda/docker-http-server; docker run -d katacoda/docker-http-server;
Con los servicios disponibles, Envoy puede enviar con éxito el tráfico a su destino.
curl -H "Host: one.example.com" localhost -i
Debería ver una respuesta que indique qué contenedor Docker procesó la solicitud. En los registros de Envoy Proxy también debería ver una salida de cadena de acceso.
Encabezados de respuesta HTTP adicionales
Verá encabezados HTTP adicionales en los encabezados de respuesta de la solicitud real. El encabezado muestra el tiempo que el host ascendente dedicó a procesar la solicitud. Expresado en milisegundos. Esto es útil si el cliente desea determinar el tiempo de servicio en comparación con la latencia de la red.
x-envoy-upstream-service-time: 0
server: envoy
Configuración final
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: backend
domains:
- "one.example.com"
- "www.one.example.com"
routes:
- match:
prefix: "/"
route:
cluster: targetCluster
http_filters:
- name: envoy.router
clusters:
- name: targetCluster
connect_timeout: 0.25s
type: STRICT_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
hosts: [
{ socket_address: { address: 172.18.0.3, port_value: 80 }},
{ socket_address: { address: 172.18.0.4, port_value: 80 }}
]
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9090 }
Información adicional del traductor.
Las instrucciones para instalar Envoy Proxy se pueden encontrar en el sitio web
De forma predeterminada, rpm no tiene una configuración de servicio systemd.
Agregue la configuración del servicio systemd /etc/systemd/system/envoy.service:
[Unit]
Description=Envoy Proxy
Documentation=https://www.envoyproxy.io/
After=network-online.target
Requires=envoy-auth-server.service
Wants=nginx.service
[Service]
User=root
Restart=on-failure
ExecStart=/usr/bin/envoy --config-path /etc/envoy/config.yaml
[Install]
WantedBy=multi-user.target
Debe crear un directorio /etc/envoy/ y colocar la configuración config.yaml allí.
Hay un chat de Telegram que utiliza el proxy enviado:
Envoy Proxy no admite la publicación de contenido estático. Por lo tanto, ¿quién puede votar por la función?
Solo los usuarios registrados pueden participar en la encuesta.
¿Esta publicación lo animó a instalar y probar el proxy enviado?
-
sí
-
no
75 usuarios votaron. 18 usuarios se abstuvieron.
Fuente: habr.com