Migración de Nginx a Envoy Proxy

Ola, Habr! Chamo á súa atención unha tradución do post: Migración de Nginx a Envoy Proxy.

Envoy é un servidor proxy distribuído de alto rendemento (escrito en C++) deseñado para servizos e aplicacións individuais, tamén é un bus de comunicación e un "plano de datos universal" deseñado para grandes arquitecturas de "malla de servizo" de microservizos. Ao crealo, tivéronse en conta as solucións aos problemas que xurdiron durante o desenvolvemento de servidores como NGINX, HAProxy, equilibradores de carga de hardware e equilibradores de carga na nube. Envoy traballa xunto a cada aplicación e abstrae a rede para ofrecer unha funcionalidade común independentemente da plataforma. Cando todo o tráfico de servizos nunha infraestrutura flúe a través da malla de Envoy, faise doado visualizar as áreas problemáticas cunha observabilidade consistente, axustar o rendemento xeral e engadir funcionalidades básicas nunha localización específica.

Capacidades

  • Arquitectura fóra de proceso: envoy é un servidor autónomo de alto rendemento que ocupa unha pequena cantidade de RAM. Funciona en conxunto con calquera linguaxe de aplicación ou marco.
  • Compatibilidade con http/2 e grpc: o envoy ten compatibilidade con http/2 e grpc de primeira clase para conexións entrantes e saíntes. Este é un proxy transparente de http/1.1 a http/2.
  • Equilibrio de carga avanzado: envoy admite funcións avanzadas de equilibrio de carga, incluíndo reintentos automáticos, ruptura de cadea, limitación de taxa global, sombreado de solicitudes, equilibrio de carga de zona local, etc.
  • API de xestión de configuración: envoy ofrece unha API robusta para xestionar dinámicamente a súa configuración.
  • Observabilidade: observabilidade profunda do tráfico L7, soporte nativo para o rastrexo distribuído e observabilidade de mongodb, dynamodb e moitas outras aplicacións.

Paso 1 - Exemplo de configuración de NGINX

Este script usa un ficheiro especialmente elaborado nginx.conf, baseado no exemplo completo de Wiki NGINX. Podes ver a configuración no editor abrindo nginx.conf

configuración da fonte 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;
    }
  }
}

As configuracións de NGINX adoitan ter tres elementos clave:

  1. Configurando o servidor NGINX, a estrutura de rexistro e a funcionalidade de Gzip. Isto defínese globalmente en todos os casos.
  2. Configurando NGINX para aceptar solicitudes ao host un.exemplo.com no porto 8080.
  3. Configurar a localización de destino, como xestionar o tráfico para diferentes partes do URL.

Non toda a configuración se aplicará a Envoy Proxy e non precisa configurar algunhas opcións. Envoy Proxy ten catro tipos de claves, que admiten a infraestrutura principal ofrecida por NGINX. O núcleo é:

  • Oíntes: Determinan como Envoy Proxy acepta as solicitudes entrantes. Envoy Proxy actualmente só admite oíntes baseados en TCP. Unha vez establecida unha conexión, pásase a un conxunto de filtros para procesala.
  • Filtros: Forman parte dunha arquitectura de canalización que pode procesar datos entrantes e saíntes. Esta funcionalidade inclúe filtros como Gzip, que comprime os datos antes de envialos ao cliente.
  • Routers: Reenvían o tráfico ao destino necesario, definido como un clúster.
  • Clústeres: Definen o punto final para o tráfico e os parámetros de configuración.

Usaremos estes catro compoñentes para crear unha configuración de Envoy Proxy que coincida cunha configuración específica de NGINX. O obxectivo de Envoy é traballar con API e configuración dinámica. Neste caso, a configuración base utilizará a configuración estática e codificada de NGINX.

Paso 2 - Configuración de NGINX

Primeira parte nginx.conf define algúns elementos internos de NGINX que deben configurarse.

Conexións de traballadores

A seguinte configuración determina o número de conexións e procesos de traballo. Isto indica como escalará NGINX para satisfacer a demanda.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy xestiona os fluxos de traballo e as conexións de diferentes xeitos.

Envoy crea un fío de traballo para cada fío de hardware do sistema. Cada fío de traballo executa un bucle de eventos non bloqueador que é responsable

  1. Escoitando a cada oínte
  2. Aceptando novas conexións
  3. Creando un conxunto de filtros para unha conexión
  4. Procese todas as operacións de E/S durante a vida útil da conexión.

Todo o procesamento de conexións adicionais manéxase integramente no fío de traballo, incluído calquera comportamento de reenvío.

Para cada fío de traballo en Envoy, hai un grupo de conexións. Polo tanto, os conxuntos de conexións HTTP/2 só establecen unha conexión por host externo á vez, se hai catro fíos de traballo, haberá catro conexións HTTP/2 por host externo nun estado estable. Ao manter todo nun fío de traballo, case todo o código pódese escribir sen bloquealo, coma se fose un fío único. Se se asignan máis fíos de traballo dos necesarios, isto pode provocar un desperdicio de memoria, creando un gran número de conexións inactivas e reducindo o número de veces que as conexións se devolven ao grupo.

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

Configuración HTTP

O seguinte bloque de configuración de NGINX define a configuración HTTP como:

  • Que tipos de mime son compatibles
  • Tempos de espera predeterminados
  • Configuración Gzip

Podes personalizar estes aspectos usando filtros en Envoy Proxy, dos que falaremos máis tarde.

Paso 3 - Configuración do servidor

No bloque de configuración HTTP, a configuración de NGINX especifica escoitar no porto 8080 e responder ás solicitudes entrantes de dominios un.exemplo.com и www.one.example.com.

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

Dentro de Envoy, está controlado por Listeners.

Enviados oíntes

O aspecto máis importante de comezar con Envoy Proxy é definir os teus oíntes. Debe crear un ficheiro de configuración que describa como quere executar a instancia de Envoy.

O fragmento seguinte creará un novo oínte e vincularao ao porto 8080. A configuración indica a Envoy Proxy a que portos debe vincularse para as solicitudes entrantes.

Envoy Proxy usa a notación YAML para a súa configuración. Para unha introdución a esta notación, consulte aquí ligazón.

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

Non hai que definir nome_servidor, xa que os filtros de Envoy Proxy xestionarán isto.

Paso 4 - Configuración da localización

Cando unha solicitude chega a NGINX, o bloque de localización determina como procesar e onde dirixir o tráfico. No seguinte fragmento, todo o tráfico ao sitio transfírese a un clúster upstream (nota do tradutor: upstream adoita ser un servidor de aplicacións) chamado targetCluster. O clúster ascendente define os nodos que deben procesar a solicitude. Discutirémolo no seguinte paso.

location / {
    proxy_pass         http://targetCluster/;
    proxy_redirect     off;

    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
}

En Envoy, Filtros fai isto.

Filtros Envoy

Para unha configuración estática, os filtros determinan como procesar as solicitudes entrantes. Neste caso establecemos filtros que coincidan nomes_servidores no paso anterior. Cando chegan solicitudes entrantes que coinciden con certos dominios e rutas, o tráfico envíase ao clúster. Este é o equivalente a unha 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

nome enviado.http_connection_manager é un filtro incorporado en Envoy Proxy. Outros filtros inclúen Redis, Mongo, TCP. Podes atopar a lista completa en documentación.

Para obter máis información sobre outras políticas de equilibrio de carga, visite Documentación do enviado.

Paso 5: configuración de proxy e upstream

En NGINX, a configuración ascendente define un conxunto de servidores de destino que procesarán o tráfico. Neste caso, asignáronse dous clusters.

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

En Envoy, isto está xestionado por clústeres.

Clústers de enviados

O equivalente augas arriba defínese como clusters. Neste caso, identificáronse os hosts que atenderán o tráfico. A forma en que se accede aos hosts, como os tempos de espera, defínese como unha configuración de clúster. Isto permite un control máis granular sobre aspectos como a latencia e o 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 }}
    ]

Cando se utiliza o servizo de descubrimento STRICT_DNS Envoy resolverá de forma continua e asíncrona os obxectivos DNS especificados. Cada enderezo IP devolto do resultado DNS considerarase un host explícito no clúster ascendente. Isto significa que se unha solicitude devolve dous enderezos IP, Envoy asumirá que hai dous hosts no clúster e que ambos deben estar equilibrados. Se se elimina un host do resultado, Envoy asumirá que xa non existe e extraerá o tráfico dos conxuntos de conexións existentes.

Para máis información consulte Documentación de proxy de Envoy.

Paso 6: acceso ao rexistro e erros

A configuración final é o rexistro. En lugar de enviar os rexistros de erros ao disco, Envoy Proxy adopta un enfoque baseado na nube. Todos os rexistros das aplicacións saen a stdout и stderr.

Cando os usuarios fan unha solicitude, os rexistros de acceso son opcionais e están desactivados por defecto. Para activar os rexistros de acceso para as solicitudes HTTP, active a configuración rexistro_acceso para o xestor de conexións HTTP. O camiño pode ser un dispositivo como stdout, ou un ficheiro no disco, dependendo dos seus requisitos.

A seguinte configuración redirixirá todos os rexistros de acceso a stdout (Nota do tradutor: stdout é necesario para usar Envoy dentro do docker. Se se usa sen docker, entón substitúe /dev/stdout polo camiño a un ficheiro de rexistro normal). Copia o fragmento na sección de configuración do xestor de conexións:

Copy to Clipboardaccess_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"

Os 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:

Por defecto, Envoy ten unha cadea de formato que inclúe os detalles da solicitude 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

O resultado desta cadea 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"

O contido de saída pódese personalizar configurando o campo de formato. Por exemplo:

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"

A liña de rexistro tamén se pode emitir en formato JSON configurando o campo formato_json. Por exemplo:

access_log:
- name: envoy.file_access_log
  config:
    path: "/dev/stdout"
    json_format: {"protocol": "%PROTOCOL%", "duration": "%DURATION%", "request_method": "%REQ(:METHOD)%"}

Para obter máis información sobre a Metodoloxía de rexistro de Envoy, visite

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

O rexistro non é a única forma de obter información sobre o traballo con Envoy Proxy. Ten incorporadas capacidades avanzadas de seguimento e métricas. Podes saber máis en documentación de rastrexo ou a través Script de rastrexo interactivo.

Paso 7 - Iniciar

Agora migraches a túa configuración de NGINX a Envoy Proxy. O último paso é iniciar unha instancia de Envoy Proxy para probala.

Executar como usuario

Na parte superior da liña de configuración de NGINX usuario www www; especifica executar NGINX como un usuario con baixos privilexios para mellorar a seguridade.

Envoy Proxy adopta un enfoque baseado na nube para xestionar quen é o propietario dun proceso. Cando executamos Envoy Proxy a través dun contedor, podemos especificar un usuario con privilexios baixos.

Iniciando Envoy Proxy

O seguinte comando executará Envoy Proxy a través dun contedor Docker no host. Este comando dálle a Envoy a posibilidade de escoitar as solicitudes entrantes no porto 80. Non obstante, tal e como se especifica na configuración do escoitador, Envoy Proxy escoita o tráfico entrante no porto 8080. Isto permite que o proceso se execute como un usuario con baixos privilexios.

docker run --name proxy1 -p 80:8080 --user 1000:1000 -v /root/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy

Probas

Co proxy en execución, agora pódense facer e procesar probas. O seguinte comando cURL emite unha solicitude coa cabeceira do host definida na configuración do proxy.

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

A solicitude HTTP producirá un erro 503. Isto débese a que as conexións ascendentes non funcionan e non están dispoñibles. Polo tanto, Envoy Proxy non ten destinos dispoñibles para a solicitude. O seguinte comando iniciará unha serie de servizos HTTP que coincidan coa configuración definida para Envoy.

docker run -d katacoda/docker-http-server; docker run -d katacoda/docker-http-server;

Cos servizos dispoñibles, Envoy pode enviar o tráfico con éxito ao seu destino.

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

Debería ver unha resposta que indica que contenedor Docker procesou a solicitude. Nos rexistros de Envoy Proxy tamén deberías ver unha saída de cadea de acceso.

Cabeceiras de resposta HTTP adicionais

Verá cabeceiras HTTP adicionais nas cabeceiras de resposta da solicitude real. A cabeceira mostra o tempo que o servidor anterior pasou procesando a solicitude. Expresado en milisegundos. Isto é útil se o cliente quere determinar o tempo de servizo en comparación coa latencia da rede.

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 do tradutor

As instrucións para instalar Envoy Proxy pódense atopar no sitio web https://www.getenvoy.io/

Por defecto, rpm non ten unha configuración de servizo systemd.

Engade a configuración do servizo 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

Debes crear un directorio /etc/envoy/ e poñer alí a configuración config.yaml.

Hai un chat de telegram usando o proxy de Envoy: https://t.me/envoyproxy_ru

Envoy Proxy non admite a publicación de contido estático. Polo tanto, quen pode votar pola función: https://github.com/envoyproxy/envoy/issues/378

Só os usuarios rexistrados poden participar na enquisa. Rexístrate, por favor.

Esta publicación animouche a instalar e probar o proxy de Envoy?

  • si

  • non

Votaron 75 usuarios. 18 usuarios abstivéronse.

Fonte: www.habr.com

Engadir un comentario