Enviado. 1. Introdución

Saúdos! Este é un artigo breve que responde ás preguntas: "que é enviado?", "por que é necesario?" e "por onde comezar?".

Que é isto?

Envoy é un equilibrador L4-L7 escrito en C++, centrado no alto rendemento e dispoñibilidade. Por unha banda, este é dalgún xeito un análogo de nginx e haproxy, comparable en rendemento a eles. Por outra banda, está máis orientado á arquitectura de microservizos e ten unha funcionalidade non peor que os equilibradores de java e go, como zuul ou traefik.

Táboa de comparación de haproxy/nginx/envoy, non pretende ser a verdade absoluta, pero dá unha imaxe xeral.

Nginx
haproxi
enviado
traefik

estrelas en github
11.2 k/espello
1.1 k/espello
12.4k
27.6k

escrito en
C
C
C ++
go

API
non
só toma/empuxar
plano de datos/pull
tirar

revisión de saúde activa
non
si
si
si

Trazado aberto
plugin externo
non
si
si

J.W.T.
plugin externo
non
si
non

extensión
Lua/C
Lua/C
Lua/C++
non

Para que serve

Este é un proxecto novo, faltan moitas cousas, algunhas en alfa inicial. Pero enviado, tamén pola súa xuventude, está a desenvolverse rapidamente e xa ten moitas características interesantes: configuración dinámica, moitos filtros preparados, unha interface sinxela para escribir os teus propios filtros.
Disto seguen as áreas de aplicación, pero primeiro hai 2 antipatróns:

  • Retroceso estático.

O caso é que de momento en enviado sen soporte de caché. Os mozos de Google están intentando isto para arranxar. A idea implementarase unha vez dentro enviado todas as sutilezas (encabezados do zoo) do cumprimento de RFC, e para implementacións específicas fai unha interface. Pero de momento nin sequera é alfa, a arquitectura está en discusión, PR aberto (mentres escribía o artigo de PR, o PR conxelouse, pero este punto aínda é relevante).

Polo momento, usa nginx para a estática.

  • Configuración estática.

Podes usalo, pero enviado Non foi para iso. As funcións nunha configuración estática non serán expostas. Hai moitos momentos:

Ao editar a configuración en yaml, equivocarase, reprende aos desenvolvedores pola verbosidade e pense que as configuracións de nginx/haproxy, aínda que están menos estruturadas, son máis concisas. Ese é o punto. A configuración de Nginx e Haproxy creouse para editar a man e enviado para a xeración a partir de código. Toda a configuración descríbese en protobuf, xeralo a partir de ficheiros proto é moito máis difícil cometer un erro.

Os escenarios de implantación de Canary, b/g e moito máis adoitan implementarse só nunha configuración dinámica. Non digo que non se poida facer de forma estática, facémolo todos. Pero para iso cómpre poñer muletas, en calquera dos equilibradores, en enviado incluíndo.

Tarefas para as que Envoy é indispensable:

  • Equilibrio de tráfico en sistemas complexos e dinámicos. Isto inclúe a malla de servizo, pero non é necesariamente a única.
  • A necesidade dunha funcionalidade de rastrexo distribuído, autorización complexa ou outra funcionalidade dispoñible en enviado listo ou implementado convenientemente, pero en nginx/haproxy necesitas estar rodeado de plugins lua e dubidosos.

Ambos, se é necesario, proporcionan un alto rendemento.

Chat isto

Envoy distribúese en binarios só como imaxe docker. A imaxe xa contén un exemplo de configuración estática. Pero é interesante para nós só para comprender a estrutura.

configuración estática envoy.yaml

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite: www.google.com
                  cluster: service_google
          http_filters:
          - name: envoy.router
  clusters:
  - name: service_google
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service_google
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: www.google.com
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.api.v2.auth.UpstreamTlsContext
        sni: www.google.com

Configuración dinámica

Para que problema buscamos solución? Non pode simplemente recargar a configuración do equilibrador de carga baixo carga; xurdirán "pequenos" problemas:

  • Validación da configuración.

A configuración pode ser grande, pode ser moi grande, se a sobrecargamos todo á vez, as posibilidades de que se produza un erro nalgún lugar aumentan.

  • Conexións de longa duración.

Ao inicializar un novo oínte, cómpre coidar das conexións que se executan no antigo; se os cambios ocorren con frecuencia e hai conexións de longa duración, terás que buscar un compromiso. Ola, entrada de kubernetes en nginx.

  • Comprobacións sanitarias activas.

Se temos comprobacións de saúde activas, necesitamos verificalas todas na nova configuración antes de enviar tráfico. Se hai moitos ríos arriba, isto leva tempo. Ola haproxy.

Como se resolve isto en enviadoAo cargar a configuración de forma dinámica, segundo o modelo da piscina, pode dividila en partes separadas e non reiniciar a parte que non cambiou. Por exemplo, un oínte, que é caro reiniciar e raramente cambia.

Configuración enviado (do ficheiro anterior) ten as seguintes entidades:

  • oínte — oínte colgado nun IP/port específico
  • host virtual - host virtual por nome de dominio
  • ruta - regra de equilibrio
  • acio — un grupo de augas arriba con parámetros de equilibrio
  • punto final - enderezo da instancia ascendente

Cada unha destas entidades e algunhas outras pódense cubrir de forma dinámica; para iso, a configuración especifica o enderezo do servizo desde onde se recibirá a configuración. O servizo pode ser REST ou gRPC, é preferible o gRPC.

Os servizos denomínanse respectivamente: LDS, VHDS, RDS, CDS e EDS. Pode combinar configuración estática e dinámica, coa limitación de que non se pode especificar un recurso dinámico nun estático.

Para a maioría das tarefas, abonda con implementar os tres últimos servizos, denomínanse ADS (Aggregated Discovery Service), para java e vai alí hai unha implementación preparada de gRPC dataplane na que só tes que encher os obxectos da túa fonte.

A configuración toma a seguinte forma:

configuración dinámica envoy.yaml

dynamic_resources:
  ads_config:
    api_type: GRPC
    grpc_services:
      envoy_grpc:
        cluster_name: xds_clr
  cds_config:
    ads: {}
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
          stat_prefix: ingress_http
          rds:
            route_config_name: local_route
            config_source:
              ads: {}
          http_filters:
          - name: envoy.router
  clusters:
  - name: xds_clr
    connect_timeout: 0.25s
    type: LOGICAL_DNS
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: xds_clr
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: xds
                port_value: 6565

No inicio enviado con esta configuración, conectarase ao plano de control e intentará solicitar a configuración RDS, CDS e EDS. Descríbese como se produce o proceso de interacción aquí.

En resumo, enviado envía unha solicitude indicando o tipo de recurso que se solicita, a versión e os parámetros do nodo. En resposta, recibe un recurso e unha versión; se a versión no plano de control non cambiou, non responde.
Hai 4 opcións de interacción:

  • Un fluxo gRPC para todo tipo de recursos, envíase o estado completo do recurso.
  • Fluxos separados, estado completo.
  • Un fluxo, estado incremental.
  • Fluxos separados, estado incremental.

XDS incremental permítelle reducir o tráfico entre o plano de control e enviado, isto é relevante para configuracións grandes. Pero complica a interacción; a solicitude contén unha lista de recursos para cancelar a subscrición e subscribirse.

O noso exemplo usa ADS: un fluxo para RDS, CDS, EDS e o modo non incremental. Para activar o modo incremental, cómpre especificar api_type: DELTA_GRPC

Dado que a solicitude contén parámetros de nodo, podemos enviar diferentes recursos ao plano de control para diferentes instancias enviado, isto é conveniente para construír unha malla de servizo.

Quentar

En enviado ao inicio ou ao recibir unha nova configuración do plano de control, lánzase o proceso de quecemento do recurso. Divídese en quecemento do oínte e quecemento do clúster. O primeiro lánzase cando hai cambios en RDS/LDS, o segundo cando CDS/EDS. Isto significa que se só cambian as correntes ascendentes, o oínte non se recrea.

Durante o proceso de quecemento, espéranse recursos dependentes do plano de control durante o tempo de espera. Se se produce o tempo de espera, a inicialización non terá éxito e o novo oínte non comezará a escoitar no porto.
Orde de inicialización: EDS, CDS, comprobación de saúde activa, RDS, LDS. Cos comprobacións de saúde activas activadas, o tráfico irá ascendente só despois dunha comprobación de estado exitosa.

Se se recreou o oínte, o antigo pasa ao estado DRAIN e eliminarase despois de que se pechen todas as conexións ou caduque o tempo de espera --drain-time-s, por defecto 10 minutos.

Continuar.

Fonte: www.habr.com

Engadir un comentario