Migración de Nginx a Envoy Proxy

¡Hola, Habr! Les presento la traducción de la publicación: Migración de Nginx a Envoy Proxy.

Envoy es un 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 "data plane universal" desarrollado para grandes arquitecturas de microservicios "service mesh". En su creación se tuvieron en cuenta las soluciones a los problemas que surgieron al desarrollar servidores como NGINX, HAProxy, balanceadores de carga hardware y balanceadores de carga en la nube. Envoy trabaja junto a cada aplicación y abstrae la red, proporcionando funciones comunes sin importar la plataforma. Cuando todo el tráfico de servicio en la infraestructura pasa a través de la malla Envoy, se vuelve fácil visualizar las áreas problemáticas mediante una observabilidad coherente, configurar el rendimiento general y agregar funciones clave en un lugar específico.

Funcionalidades

  • Arquitectura fuera del proceso: envoy es un servidor autónomo de alto rendimiento que ocupa poca memoria. Funciona junto con cualquier lenguaje de aplicación o marco de trabajo.
  • Soporte para http/2 y grpc: envoy tiene soporte de primera clase para http/2 y grpc para conexiones entrantes y salientes. Es un proxy transparente de http/1.1 a http/2.
  • Balanceo de carga avanzado: envoy admite características avanzadas de balanceo de carga, incluidas reintentos automáticos, ruptura de cadena, limitación de velocidad global, sombreado de solicitudes, balanceo de carga local por zona, etc.
  • API para gestionar la configuración: envoy proporciona una API robusta para gestionar dinámicamente su configuración.
  • Observabilidad: observabilidad profunda del tráfico L7, soporte incorporado para trazado distribuido y observabilidad en mongodb, dynamodb y muchas otras aplicaciones.

Paso 1 - Ejemplo de configuración de NGINX

En este escenario se utiliza un archivo creado especialmente nginx.conf, basado en un ejemplo completo de NGINX Wiki. Puedes revisar la configuración en el editor abriendo nginx.conf

La configuración original de nginx

usuario  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 generalmente tienen tres elementos clave:

  1. La configuración del servidor NGINX, la estructura de registro y la funcionalidad de Gzip. Esto se define globalmente en todos los casos.
  2. Configuración de NGINX para aceptar solicitudes en el host one.example.com en el puerto 8080.
  3. Configuración de la ubicación objetivo, cómo manejar el tráfico para diferentes partes de la URL.

No toda la configuración se aplicará a Envoy Proxy, y no necesitas configurar algunos parámetros. Envoy Proxy tiene cuatro tipos clave, que respaldan la infraestructura básica ofrecida por NGINX. El núcleo es:

  • Escuchadores: Definen cómo Envoy Proxy acepta solicitudes entrantes. Actualmente, Envoy Proxy solo admite escuchadores basados en TCP. Una vez que se establece la conexión, se pasa a un conjunto de filtros para su procesamiento.
  • Filtros: Son parte de una arquitectura de canalización, que puede manejar datos entrantes y salientes. Esta funcionalidad incluye filtros como Gzip, que comprime datos antes de enviarlos al cliente.
  • Enrutadores: Redirigen el tráfico al destino requerido, definido como un clúster.
  • Clústeres: 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 se ajuste a una configuración específica de NGINX. El objetivo de Envoy es trabajar con API y configuración dinámica. En este caso, la configuración básica utilizará parámetros estáticos predeterminados de NGINX.

Paso 2 — Configuración de NGINX

Primera parte nginx.conf define algunos componentes internos de NGINX que deben configurarse.

Worker Connections (Conexiones de trabajo)

La configuración a continuación define la cantidad de procesos de trabajo y conexiones. Esto indica cómo NGINX se escalará para satisfacer la demanda.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy gestiona de manera diferente los procesos de trabajo y las conexiones.

Envoy crea un hilo de trabajo para cada hilo de hardware en el sistema. Cada hilo de trabajo ejecuta un ciclo de eventos no bloqueante, el cual es responsable de

  1. Escuchar cada listener
  2. Aceptar nuevas conexiones
  3. Crear un conjunto de filtros para la conexión
  4. Manejar todas las operaciones de entrada y salida durante la existencia de la conexión.

Todo el procesamiento posterior de la conexión se maneja completamente en el hilo de trabajo, incluyendo cualquier comportamiento de redirección.

Para cada hilo de trabajo en Envoy, hay una conexión en la piscina. Así, las conexiones HTTP/2 solo establecen una conexión para cada host externo a la vez; con cuatro hilos de trabajo habrá cuatro conexiones HTTP/2 por cada host externo en estado estable. Manteniendo todo en un solo hilo de trabajo, casi todo el código puede ser escrito sin bloqueos, como si fuera de un solo hilo. Si se asignan más hilos de trabajo de los necesarios, esto puede resultar en un uso ineficiente de la memoria, creando un gran número de conexiones inactivas y reduciendo el número de retornos de conexión a la piscina.

Para más información, visite Blog de Envoy Proxy.

Configuración HTTP

El siguiente bloque de configuración de NGINX define los ajustes HTTP, tales como:

  • Qué tipos de mime son admitidos
  • Timeouts por defecto
  • Configuración de Gzip

Puedes ajustar estos aspectos usando filtros en Envoy Proxy, de lo que hablaremos más adelante.

Paso 3 — Configuración del servidor

En el bloque de configuración HTTP, la configuración de NGINX indica escuchar en el puerto 8080 y responder a las solicitudes entrantes para los dominios one.example.com y www.one.example.com.

 server {
    listen        8080;
    server_name   one.example.com  www.one.example.com;

Dentro de Envoy, esto es gestionado por los listeners.

Listeners de Envoy

El aspecto más importante para empezar a trabajar con Envoy Proxy es la definición de los listeners. Necesitas crear un archivo de configuración que describa cómo quieres ejecutar una instancia de Envoy.

El fragmento a continuación creará un nuevo listener y lo vinculará al puerto 8080. La configuración indica a Envoy Proxy a qué puertos debe estar vinculado para las solicitudes entrantes.

Envoy Proxy utiliza la notación YAML para su configuración. Para familiarizarse con esta notación, consulte aquí. el enlace.

Copy to Editorstatic_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }

No es necesario definir server_name, ya que los filtros de Envoy Proxy se encargarán de eso.

Paso 4 — Configuración del location

Cuando llega una solicitud a NGINX, el bloque location define cómo manejar y hacia dónde dirigir el tráfico. En el siguiente fragmento, todo el tráfico hacia el sitio se envía al clúster upstream (nota del traductor: el upstream suele ser servidores de aplicaciones) llamado targetCluster. El clúster upstream determina qué nodos deben manejar la solicitud. Lo discutiremos 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, esto es gestionado por Filters.

Envoy Filters

Para una configuración estática, los filtros definen cómo manejar las solicitudes entrantes. En este caso, establecemos filtros que coinciden con server_names del paso anterior. Cuando llegan solicitudes entrantes que coinciden con ciertos dominios y rutas, el tráfico se dirige al clúster. Esto es equivalente a la configuración upstream en 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 envoy.http_connection_manager es un filtro integrado en Envoy Proxy. Otros filtros incluyen Redis, Mongo, TCP. Puede encontrar la lista completa en la documentación.

Para obtener más información sobre otras políticas de balanceo de carga, visite Documentación de Envoy.

Paso 5 — Configuración de Proxy y Upstream

En NGINX, la configuración upstream define un conjunto de servidores objetivo que manejarán el tráfico. En este caso, se han asignado dos clústeres.

  upstream targetCluster {
    172.18.0.3:80;
    172.18.0.4:80;
  }

En Envoy, esto es gestionado por clústeres.

Envoy Clusters

El equivalente upstream se define como clústeres. En este caso, se han definido hosts que atenderán el tráfico. El método de acceso a los hosts, como el tiempo de espera, se define como configuración del clúster. Esto permite un control más preciso de aspectos como el tiempo de espera y el balanceo de carga.

Copiar al editor  clústeres:
  - 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 usar la detección de servicios STRICT_DNS Envoy resolverá de manera continua y asíncrona los objetivos DNS especificados. Cada dirección IP devuelta como resultado de DNS se considerará un host explícito en el clúster ascendente. Esto significa que si la consulta devuelve dos direcciones IP, Envoy asumirá que hay dos hosts en el clúster y ambos deben ser balanceados. Si un host se elimina del resultado, Envoy supone que ya no existe y comenzará a desviar el tráfico de cualquier grupo de conexiones existente.

Para más información, consulte La documentación del proxy Envoy.

Paso 6: Acceso a los registros y errores

La configuración final es la registro. En lugar de enviar los registros de errores al disco, Envoy Proxy usa un enfoque en la nube. Todos los registros de aplicaciones se envían a stdout y stderr.

Cuando los usuarios realizan una solicitud, los registros de acceso son opcionales y están desactivados por defecto. Para habilitar los registros de acceso para solicitudes HTTP, active la configuración access_log para el administrador de conexiones HTTP. La ruta puede ser un dispositivo, como stdout, o un archivo en disco, según sus requisitos.

La siguiente configuración redirigirá todos los registros de acceso a stdout (Nota del traductor: stdout es necesario para usar envoy dentro de Docker. Si se usa sin Docker, sustituya /dev/stdout por la ruta a un archivo de registro normal). Copie el fragmento en la sección de configuración para el gestor de conexiones:

Copiar al portapapeles access_log:
- name: envoy.file_access_log
  config:
    path: "\/dev\/stdout"

Los resultados deben lucir 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:

Por defecto, 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 línea de formato:

[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 la 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 json_formatPor 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 técnica de registro del proxy, visite

https://www.envoyproxy.io/docs/envoy/latest/configuration/access_log#config-access-log-format-dictionaries

El registro no es la única forma de obtener una visión del funcionamiento de Envoy Proxy. Incorpora capacidades avanzadas de trazado y métricas. Puede aprender más en la documentación de trazado o a través de El guion de trazado interactivo.

Paso 7 — Ejecución

Ahora ha trasladado la configuración de NGINX a Envoy Proxy. El último paso es ejecutar una instancia de Envoy Proxy para probarlo.

Ejecución como usuario

En la parte superior de la configuración de NGINX, la línea user www www; indica ejecutar NGINX como un usuario con bajo privilegio para mejorar la seguridad.

Envoy Proxy utiliza un enfoque basado en la nube para gestionar quién posee el proceso. Cuando ejecutamos Envoy Proxy a través de un contenedor, podemos especificar un usuario con bajo privilegio.

Ejecución de Envoy Proxy

El siguiente comando ejecutará Envoy Proxy a través de un contenedor Docker en el host. Este comando permite que Envoy escuche las solicitudes entrantes a través del puerto 80. Sin embargo, como se indica en la configuración del oyente, Envoy Proxy escucha el tráfico entrante a través del puerto 8080. Esto permite que el proceso se ejecute como un usuario con bajo privilegio.

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 funcionamiento, ahora se pueden realizar y procesar pruebas. El siguiente comando cURL emite una solicitud con el encabezado de host definido en la configuración del proxy.

curl -H "Host: one.example.com" localhost -i

La solicitud HTTP resultará en un error 503Esto se debe a que las conexiones ascendentes no funcionan y no están disponibles. Por lo tanto, Envoy Proxy no tiene destinatarios disponibles para la solicitud. El siguiente comando iniciará una serie de servicios HTTP que corresponden a 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 enrutear el tráfico con éxito al destino.

curl -H "Host: one.example.com" localhost -i

Deberías ver una respuesta que indique qué contenedor Docker manejó la solicitud. En los registros de Envoy Proxy también deberías ver la línea de acceso mostrada.

Encabezados de respuesta HTTP adicionales (HTTP Response)

En los encabezados de la respuesta de la solicitud válida verás encabezados HTTP adicionales. En el encabezado se muestra el tiempo que el host ascendente tardó en procesar la solicitud. Se expresa 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

Puedes encontrar las instrucciones para instalar Envoy Proxy en el sitio web https://www.getenvoy.io/

Por defecto, el rpm no incluye la configuración del servicio systemd.

Agrega 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

Necesitas crear el directorio \/etc\/envoy\/ y poner allí el archivo de configuración config.yaml.

Hay un chat de Telegram sobre Envoy Proxy: https://t.me/envoyproxy_ru

Envoy Proxy no soporta la entrega de contenido estático. Por lo tanto, quien pueda, vote por esta función: https://github.com/envoyproxy/envoy/issues/378

Solo los usuarios registrados pueden participar en la encuesta. Inicie sesión, por favor.

¿Te ha motivado esta publicación a instalar y probar Envoy Proxy?

  • sí

  • no

75 usuarios votaron. 18 usuarios se abstuvieron.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster