Migrazione da Nginx a Envoy Proxy

Ciao, Habr! Porto alla vostra attenzione la traduzione del post: Migrazione da Nginx a Envoy Proxy.

Envoy è un server proxy distribuito ad alte prestazioni (scritto in C++) progettato per singoli servizi e applicazioni, è anche un bus di comunicazione e un “piano dati universale” progettato per grandi architetture “service mesh” di microservizi. Durante la sua creazione, sono state prese in considerazione le soluzioni ai problemi sorti durante lo sviluppo di server come NGINX, HAProxy, bilanciatori di carico hardware e bilanciatori di carico cloud. Envoy funziona insieme a ciascuna applicazione ed astrae la rete per fornire funzionalità comuni indipendentemente dalla piattaforma. Quando tutto il traffico di servizio in un'infrastruttura scorre attraverso la rete mesh Envoy, diventa facile visualizzare le aree problematiche con osservabilità coerente, ottimizzare le prestazioni complessive e aggiungere funzionalità principali in una posizione specifica.

opportunità

  • Architettura out-of-process: Envoy è un server autonomo e ad alte prestazioni che occupa una piccola quantità di RAM. Funziona insieme a qualsiasi linguaggio o framework dell'applicazione.
  • Supporto http/2 e grpc: Envoy dispone di un supporto http/2 e grpc di prima classe per le connessioni in entrata e in uscita. Questo è un proxy trasparente da http/1.1 a http/2.
  • Bilanciamento del carico avanzato: Envoy supporta funzionalità avanzate di bilanciamento del carico tra cui tentativi automatici, interruzione della catena, limitazione della velocità globale, shadowing delle richieste, bilanciamento del carico della zona locale, ecc.
  • API di gestione della configurazione: Envoy fornisce una solida API per la gestione dinamica della configurazione.
  • Osservabilità: osservabilità approfondita del traffico L7, supporto nativo per il tracciamento distribuito e osservabilità di mongodb, dynamodb e molte altre applicazioni.

Passaggio 1: esempio di configurazione NGINX

Questo script utilizza un file appositamente predisposto nginx.conf, basato sull'esempio completo di NGINX Wiki. È possibile visualizzare la configurazione nell'editor aprendo nginx.conf

Configurazione sorgente 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;
    }
  }
}

Le configurazioni NGINX hanno in genere tre elementi chiave:

  1. Configurazione del server NGINX, della struttura dei log e della funzionalità Gzip. Questo è definito globalmente in tutti i casi.
  2. Configurazione di NGINX per accettare richieste all'host one.esempio.com sulla porta 8080.
  3. Impostazione della posizione target, come gestire il traffico per le diverse parti dell'URL.

Non tutta la configurazione verrà applicata a Envoy Proxy e non è necessario configurare alcune impostazioni. Envoy Proxy ha quattro tipi di chiavi, che supportano l'infrastruttura principale offerta da NGINX. Il nucleo è:

  • Ascoltatori: Determinano il modo in cui Envoy Proxy accetta le richieste in entrata. Envoy Proxy attualmente supporta solo ascoltatori basati su TCP. Una volta stabilita una connessione, viene passata a una serie di filtri per l'elaborazione.
  • Filtri: Fanno parte di un'architettura di pipeline in grado di elaborare i dati in entrata e in uscita. Questa funzionalità include filtri come Gzip, che comprime i dati prima di inviarli al client.
  • Router: Inoltrano il traffico alla destinazione richiesta, definita come cluster.
  • Cluster: Definiscono l'endpoint per il traffico e i parametri di configurazione.

Utilizzeremo questi quattro componenti per creare una configurazione Envoy Proxy che corrisponda a una specifica configurazione NGINX. L'obiettivo di Envoy è lavorare con API e configurazione dinamica. In questo caso, la configurazione di base utilizzerà impostazioni statiche e codificate da NGINX.

Passaggio 2: configurazione NGINX

La prima parte nginx.conf definisce alcuni interni NGINX che devono essere configurati.

Collegamenti dei lavoratori

La configurazione seguente determina il numero di processi di lavoro e connessioni. Ciò indica come NGINX si ridimensionerà per soddisfare la domanda.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy gestisce flussi di lavoro e connessioni in diversi modi.

Envoy crea un thread di lavoro per ogni thread hardware sul sistema. Ogni thread di lavoro esegue un ciclo di eventi non bloccante di cui è responsabile

  1. Ascoltare ogni ascoltatore
  2. Accettare nuove connessioni
  3. Creazione di una serie di filtri per una connessione
  4. Elabora tutte le operazioni di I/O durante la durata della connessione.

Tutta l'ulteriore elaborazione della connessione viene gestita interamente nel thread di lavoro, incluso qualsiasi comportamento di inoltro.

Per ogni thread di lavoro in Envoy esiste un pool di connessioni. Pertanto, i pool di connessioni HTTP/2 stabiliscono solo una connessione per host esterno alla volta, se sono presenti quattro thread di lavoro ci saranno quattro connessioni HTTP/2 per host esterno in uno stato stabile. Mantenendo tutto in un thread di lavoro, quasi tutto il codice può essere scritto senza blocchi, come se fosse a thread singolo. Se vengono allocati più thread di lavoro del necessario, ciò può comportare uno spreco di memoria, la creazione di un numero elevato di connessioni inattive e la riduzione del numero di volte in cui le connessioni vengono restituite al pool.

Per maggiori informazioni visita Blog di Envoy Proxy.

Configurazione HTTP

Il seguente blocco di configurazione NGINX definisce le impostazioni HTTP come:

  • Quali tipi MIME sono supportati
  • Timeout predefiniti
  • Configurazione Gzip

Puoi personalizzare questi aspetti utilizzando i filtri in Envoy Proxy, di cui parleremo più avanti.

Passaggio 3: configurazione del server

Nel blocco di configurazione HTTP, la configurazione NGINX specifica di ascoltare sulla porta 8080 e rispondere alle richieste in arrivo per i domini one.esempio.com и www.one.example.com.

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

All'interno di Envoy, è controllato dagli ascoltatori.

Inviato ascoltatori

L'aspetto più importante per iniziare con Envoy Proxy è definire i tuoi ascoltatori. È necessario creare un file di configurazione che descriva come si desidera eseguire l'istanza di Envoy.

Lo snippet seguente creerà un nuovo ascoltatore e lo collegherà alla porta 8080. La configurazione indica a Envoy Proxy a quali porte deve collegarsi per le richieste in entrata.

Envoy Proxy utilizza la notazione YAML per la sua configurazione. Per un'introduzione a questa notazione, guarda qui collegamento.

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

Non c'è bisogno di definire nome del server, poiché i filtri Envoy Proxy gestiranno questo problema.

Passaggio 4: configurazione della posizione

Quando una richiesta arriva a NGINX, il blocco di posizione determina come elaborare e dove instradare il traffico. Nel frammento seguente, tutto il traffico verso il sito viene trasferito a un cluster upstream (nota del traduttore: upstream è solitamente un server delle applicazioni) denominato targetCluster. Il cluster upstream definisce i nodi che dovrebbero elaborare la richiesta. Ne discuteremo nel passaggio successivo.

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

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

In Envoy, Filters fa questo.

Filtri inviati

Per una configurazione statica, i filtri determinano come elaborare le richieste in entrata. In questo caso impostiamo i filtri che corrispondono nomi_server nel passaggio precedente. Quando arrivano richieste in entrata che corrispondono a determinati domini e percorsi, il traffico viene instradato al cluster. Questo è l’equivalente di una configurazione bottom-up di 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 inviato.http_connection_manager è un filtro integrato in Envoy Proxy. Altri filtri includono Redis, Mongo, TCP. Puoi trovare l'elenco completo su documentazione.

Per ulteriori informazioni su altre policy di bilanciamento del carico, visitare Documentazione dell'inviato.

Passaggio 5: configurazione proxy e upstream

In NGINX, la configurazione upstream definisce un insieme di server di destinazione che elaboreranno il traffico. In questo caso sono stati assegnati due cluster.

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

In Envoy, questo è gestito dai cluster.

Cluster di inviati

L'equivalente a monte è definito come cluster. In questo caso sono stati identificati gli host che serviranno il traffico. La modalità di accesso agli host, ad esempio i timeout, è definita come configurazione del cluster. Ciò consente un controllo più granulare su aspetti quali latenza e bilanciamento del carico.

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 }}
    ]

Quando si utilizza il rilevamento dei servizi RIGOROSAMENTE DNS Envoy risolverà in modo continuo e asincrono le destinazioni DNS specificate. Ogni indirizzo IP restituito dal risultato DNS verrà considerato un host esplicito nel cluster upstream. Ciò significa che se una richiesta restituisce due indirizzi IP, Envoy presuppone che siano presenti due host nel cluster ed entrambi devono avere un carico bilanciato. Se un host viene rimosso dal risultato, Envoy presuppone che non esista più e attirerà il traffico da eventuali pool di connessioni esistenti.

ля получения дополнительной информации см. Documentazione della delega di Envoy.

Passaggio 6: accesso ed errori di registro

La configurazione finale è la registrazione. Invece di inviare i log degli errori su disco, Envoy Proxy adotta un approccio basato su cloud. Tutti i registri dell'applicazione vengono inviati a stdout и stderr.

Quando gli utenti effettuano una richiesta, i log di accesso sono facoltativi e disabilitati per impostazione predefinita. Per abilitare i log di accesso per le richieste HTTP, abilitare la configurazione registro_accesso per la gestione connessione HTTP. Il percorso può essere un dispositivo come stdouto un file su disco, a seconda delle vostre esigenze.

La seguente configurazione reindirizzerà tutti i log di accesso a stdout (nota del traduttore: per utilizzare Envoy all'interno della finestra mobile è necessario stdout. Se utilizzato senza finestra mobile, sostituire /dev/stdout con il percorso di un normale file di registro). Copia lo snippet nella sezione di configurazione per la gestione connessione:

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

I risultati dovrebbero assomigliare a questo:

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

Per impostazione predefinita, Envoy ha una stringa di formato che include i dettagli della richiesta 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

Il risultato di questa stringa di 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"

Il contenuto di output può essere personalizzato impostando il campo formato. Per esempio:

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 riga di registro può anche essere emessa in formato JSON impostando il campo json_format. Ad esempio:

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

Per ulteriori informazioni sulla metodologia di registrazione di Envoy, visitare

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

La registrazione non è l'unico modo per ottenere informazioni dettagliate sull'utilizzo di Envoy Proxy. Dispone di funzionalità avanzate di tracciamento e metrica integrate. Puoi saperne di più su documentazione di tracciamento o tramite Script di tracciamento interattivo.

Passaggio 7: avvio

Ora hai migrato la tua configurazione da NGINX a Envoy Proxy. L'ultimo passaggio consiste nell'avviare un'istanza di Envoy Proxy per testarla.

Esegui come utente

In cima alla linea di configurazione NGINX utentewwwwww; specifica di eseguire NGINX come utente con privilegi limitati per migliorare la sicurezza.

Envoy Proxy adotta un approccio basato sul cloud per gestire chi possiede un processo. Quando eseguiamo Envoy Proxy tramite un contenitore, possiamo specificare un utente con privilegi limitati.

Avvio di Envoy Proxy

Il comando seguente eseguirà Envoy Proxy tramite un contenitore Docker sull'host. Questo comando dà a Envoy la possibilità di ascoltare le richieste in entrata sulla porta 80. Tuttavia, come specificato nella configurazione del listener, Envoy Proxy ascolta il traffico in entrata sulla porta 8080. Ciò consente al processo di essere eseguito come utente con privilegi limitati.

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

Test

Con il proxy in esecuzione, è ora possibile effettuare ed elaborare i test. Il seguente comando cURL invia una richiesta con l'intestazione host definita nella configurazione del proxy.

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

La richiesta HTTP genererà un errore 503. Questo perché le connessioni upstream non funzionano e non sono disponibili. Pertanto, Envoy Proxy non ha destinazioni disponibili per la richiesta. Il comando seguente avvierà una serie di servizi HTTP che corrispondono alla configurazione definita per Envoy.

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

Con i servizi disponibili, Envoy può inoltrare con successo il traffico verso la sua destinazione.

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

Dovresti vedere una risposta che indica quale contenitore Docker ha elaborato la richiesta. Nei registri di Envoy Proxy dovresti vedere anche l'output di una stringa di accesso.

Intestazioni di risposta HTTP aggiuntive

Vedrai intestazioni HTTP aggiuntive nelle intestazioni di risposta della richiesta effettiva. L'intestazione visualizza il tempo impiegato dall'host upstream nell'elaborazione della richiesta. Espresso in millisecondi. Ciò è utile se il client desidera determinare il tempo di servizio rispetto alla latenza di rete.

x-envoy-upstream-service-time: 0
server: envoy

Configurazione finale

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 }

Ulteriori informazioni dal traduttore

Le istruzioni per l'installazione di Envoy Proxy sono disponibili sul sito Web https://www.getenvoy.io/

Per impostazione predefinita, RPM non ha una configurazione del servizio systemd.

Aggiungi la configurazione del servizio 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

Devi creare una directory /etc/envoy/ e inserire lì la configurazione config.yaml.

Esiste una chat di Telegram utilizzando il proxy Envoy: https://t.me/envoyproxy_ru

Envoy Proxy non supporta la fornitura di contenuto statico. Pertanto, chi può votare per la funzionalità: https://github.com/envoyproxy/envoy/issues/378

Solo gli utenti registrati possono partecipare al sondaggio. AccediPer favore.

Questo post ti ha incoraggiato a installare e testare il proxy Envoy?

  • no

75 utenti hanno votato. 18 utenti si sono astenuti.

Fonte: habr.com

Aggiungi un commento