Migrarea de la Nginx la Envoy Proxy

Salut, Habr! Îți propun un traducere a postării: Migrarea de la Nginx la Envoy Proxy.

Envoy este un proxy distribuit de înaltă performanță (scris în C++), destinat serviciilor și aplicațiilor individuale; este de asemenea un bus de comunicație și un "plan de date universal", dezvoltat pentru arhitecturi mari de microservicii "service mesh". La crearea sa, s-au ținut cont de soluțiile problemelor întâmpinate în dezvoltarea unor servere precum NGINX, HAProxy, echipamentele hardware de balansare a încărcării și echipamentele de balansare a încărcării în cloud. Envoy funcționează împreună cu fiecare aplicație și abstrează rețeaua, oferind funcții comune indiferent de platformă. Când tot traficul de serviciu din infrastructură trece prin rețeaua Envoy, devine ușor să vizualizezi zonele problematice printr-o observație consistentă, configurarea performanței generale și adăugarea de funcții cheie într-un anumit loc.

Funcționalități

  • Arhitectura de tip outside-of-process: envoy este un server autonom, de înaltă performanță, care ocupă o cantitate mică de memorie RAM. Acesta funcționează alături de orice limbaj de aplicație sau cadru.
  • Suport pentru http/2 și grpc: envoy are suport de primă clasă pentru http/2 și grpc pentru conexiuni de intrare și de ieșire. Este un proxy transparent de la http/1.1 la http/2.
  • Balansare avansată a încărcării: envoy suportă funcții avansate de balansare a încărcării, inclusiv retriere automată, tăierea lanțurilor, limitare globală a vitezei, umbrire a cererilor, balansare locală a încărcării pe zone etc.
  • API pentru gestionarea configurației: envoy oferă un API robust pentru gestionarea dinamică a configurației sale.
  • Observabilitate: observabilitate profundă a traficului L7, suport încorporat pentru trasare distribuită și observabilitate pentru mongodb, dynamodb și multe alte aplicații.

Pasul 1 — Exemplu de configurație NGINX

În acest scenariu se folosește un fișier special creat nginx.conf, bazat pe un exemplu complet din NGINX Wiki. Poți vizualiza configurația în editor, deschizând nginx.conf

Fișierul de configurare original 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;
    }
  }
}

Configurarea NGINX are de obicei trei elemente cheie:

  1. Configurarea serverului NGINX, structura jurnalelor și funcționalitatea Gzip. Acestea sunt definite global în toate cazurile.
  2. Configurarea NGINX pentru a accepta cereri pe gazda one.example.com pe portul 8080.
  3. Configurarea locației țintă, cum să gestionezi traficul pentru diferite părți ale URL-ului.

Nu toată configurația va fi aplicată pentru Envoy Proxy, și nu trebuie să configurezi anumite parametrii. Envoy Proxy are patru tipuri cheie, care susțin infrastructura de bază oferită de NGINX. Nucleul este:

  • Ascultătorii: Aceștia definesc cum Envoy Proxy acceptă cererile de intrare. În prezent, Envoy Proxy acceptă doar ascultători bazat pe TCP. Odată ce conexiunea este stabilită, aceasta este transmisă unui set de filtre pentru procesare.
  • Filtre: Acestea fac parte din arhitectura de tip canal, care poate gestiona datele de intrare și ieșire. Această funcționalitate include filtre, cum ar fi Gzip, care comprimă datele înainte de a le trimite clientului.
  • Routierele: Acestea redirecționează traficul către destinația dorită, definită ca un cluster.
  • Clusterurile: Acestea definesc punctul final pentru trafic și parametrii de configurare.

Vom folosi aceste patru componente pentru a crea configurația Envoy Proxy astfel încât să corespundă unei configurații specifice NGINX. Scopul Envoy este de a lucra cu API-uri și configurații dinamice. În acest caz, configurația de bază va folosi parametrii statici, rigizi din NGINX.

Pasul 2 — Configurarea NGINX

Partea întâi nginx.conf definește unele componente interne NGINX care ar trebui să fie configurate.

Conexiuni de lucru (Worker Connections)

Configurația de mai jos definește numărul de procese de lucru și conexiuni. Aceasta indică modul în care NGINX va scala pentru a satisface cererea.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy gestionează diferit procesele de lucru și conexiunile.

Envoy creează un flux de lucru pentru fiecare flux hardware din sistem. Fiecare flux de lucru execută un ciclu de evenimente non-blocant, responsabil pentru

  1. Ascultarea fiecărui ascultător (listener)
  2. Acceptarea noilor conexiuni
  3. Crearea unui set de filtre pentru conexiune
  4. Procesarea tuturor operațiunilor de intrare-ieșire pe durata existenței conexiunii.

Toată procesarea ulterioară a conexiunii este complet gestionată în fluxul de lucru, inclusiv orice comportament de redirecționare.

Pentru fiecare flux de lucru în Envoy există o conexiune în pool. Astfel, pool-urile de conexiuni HTTP/2 stabilesc doar o conexiune pentru fiecare gazdă externă deodată. Când sunt disponibile patru fluxuri de lucru, vor exista patru conexiuni HTTP/2 pentru fiecare gazdă externă în stare stabilă. Păstrând totul într-un singur flux de lucru, aproape tot codul poate fi scris fără blocări, ca și cum ar fi într-un singur fir. Dacă sunt alocate mai multe fluxuri de lucru decât este necesar, acest lucru poate duce la o utilizare ineficientă a memoriei, creând un număr mare de conexiuni inactive și reducând numărul de returnări ale conexiunilor înapoi în pool.

Pentru mai multe informații, vizitați Blogul Envoy Proxy.

Configurarea HTTP

Următorul bloc de configurare NGINX definește setările HTTP, cum ar fi:

  • Ce tipuri MIME sunt acceptate
  • Timpurile de așteptare implicite
  • Configurarea Gzip

Puteți configura acești aspecte cu ajutorul filtrelor în Envoy Proxy, despre care vom discuta mai târziu.

Pasul 3 — Configurarea Serverului

În blocul de configurare HTTP, configurația NGINX specifică să asculte pe portul 8080 și să răspundă la cererile de intrare pentru domeniile one.example.com și www.one.example.com.

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

În interiorul Envoy, aceste lucruri sunt gestionate de Ascultători.

Ascultătorii Envoy

Cel mai important aspect pentru a începe cu Envoy Proxy este definirea ascultătorilor. Trebuie să creați un fișier de configurare care descrie cum doriți să rulați o instanță Envoy.

Fragmentul de mai jos va crea un nou ascultător și îl va lega de portul 8080. Configurația indică Proxy-ul Envoy la ce porturi trebuie să fie legat pentru cererile de intrare.

Proxy-ul Envoy folosește notația YAML pentru configurația sa. Pentru a te familiariza cu această notație, consultă aici linkul.

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

Nu este necesar să definim server_name, deoarece filtrele Proxy-ului Envoy se vor ocupa de aceasta.

Pasul 4 - Configurarea locației

Când o cerere ajunge la NGINX, blocul de locație definește cum să se proceseze și unde să se direcționeze traficul. În fragmentul următor, tot traficul către site este direcționat către clusterul upstream (notă a traducătorului: upstream este, de obicei, servere de aplicații) numit targetCluster. Clusterul upstream definește nodurile care trebuie să proceseze cererea. Vom discuta despre aceasta în pasul următor.

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

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

În Envoy, acest lucru este gestionat de filtre.

Filtre Envoy

Pentru configurația statică, filtrele definesc cum să se proceseze cererile de intrare. În acest caz, setăm filtrele care corespund server_names din pasul anterior. Când sosesc cereri de intrare care corespund anumitor domenii și rute, traficul este direcționat către cluster. Aceasta este echivalentul configurației upstream din 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

Nume envoy.http_connection_manager este un filtru încorporat în Proxy-ul Envoy. Alte filtre includ Redis, Mongo, TCP. Poți găsi lista completă în documentation.

Pentru informații suplimentare despre alte politici de echilibrare a încărcării, vizitează Documentația Envoy.

Pasul 5 - Configurarea Proxy-ului și Upstream

În NGINX, configurația upstream definește un set de servere țintă care vor procesa traficul. În acest caz, două clustere au fost atribuite.

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

În Envoy, acest lucru este gestionat de clustere.

Clustere Envoy

Echivalentul upstream este definit ca clustere. În acest caz, au fost definite gazdele care vor gestiona traficul. Modul de acces la gazde, cum ar fi timpul de așteptare, este definit ca o configurație de cluster. Aceasta permite un control mai precis asupra granularității unor aspecte, cum ar fi timpul de așteptare și echilibrarea încărcării.

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

Atunci când se utilizează detectarea serviciului STRICT_DNS Envoy va rezolva continuu și asynchronizat țintele DNS specificate. Fiecare adresă IP returnată în urma DNS-ului va fi considerată o gazdă explicită în clusterul ascendent. Aceasta înseamnă că, dacă o solicitare returnează două adrese IP, Envoy va presupune că în cluster există două gazde, iar ambele trebuie să fie echilibrate la încărcătură. Dacă o gazdă este eliminată din rezultat, Envoy presupune că aceasta nu mai există și va extrage traficul din orice grupuri de conexiuni existente.

Pentru mai multe informații, consultați Documentația serverului proxy Envoy.

Pasul 6 — Accesarea jurnalelor și erorilor

Configurarea finală — înregistrarea. În loc să transmită jurnalele de erori pe disc, Envoy Proxy adoptă o abordare bazată pe cloud. Toate jurnalele aplicațiilor sunt redirecționate către stdout și stderr.

Când utilizatorii fac o solicitare, jurnalele de acces sunt opționale și, în mod implicit, dezactivate. Pentru a activa jurnalele de acces pentru solicitările HTTP, activați configurația access_log pentru managerul de conexiuni HTTP. Calea poate fi fie un dispozitiv, cum ar fi stdout, fie un fișier pe disc, în funcție de cerințele dumneavoastră.

Următoarea configurație va redirecționa toate jurnalele de acces către stdout (notă a traducătorului — stdout este necesar pentru utilizarea envoy în interiorul docker. Dacă utilizați fără docker, atunci înlocuiți \/dev\/stdout cu calea către un fișier de jurnal obișnuit). Copiați fragmentul în secțiunea de configurare pentru managerul de conexiuni:

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

Rezultatele ar trebui să arate astfel:

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

Implicit, Envoy are un șir de format care include detalii despre solicitarea 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

Rezultatul acestei linii de format:

[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"

Conținutul ieșirii poate fi configurat setând câmpul de format. De exemplu:

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"

Linia de jurnal poate fi de asemenea produsă în format JSON setând câmpul json_format. De exemplu:

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

Pentru informații suplimentare despre metodologia de jurnalizare a Envoy, vizitați

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

Jurnalizarea nu este singura modalitate de a obține o viziune asupra funcționării Envoy Proxy. Acesta include capabilități avansate de trasare și metrici. Puteți învăța mai multe din documentația de trasare sau prin Scenariul de trasare interactivă.

Pasul 7 — Lansare

Acum ați transformat configurația de la NGINX către Envoy Proxy. Ultimul pas este să rulați un exemplar Envoy Proxy pentru a-l testa.

Rulare ca utilizator

În partea de sus a configurației NGINX, linia user www www; indicată pentru a rula NGINX ca utilizator cu privilegii reduse pentru a îmbunătăți securitatea.

Envoy Proxy adoptă o abordare bazată pe cloud în gestionarea proprietarului procesului. Atunci când rulăm Envoy Proxy printr-un container, putem specifica un utilizator cu privilegii reduse.

Rularea Envoy Proxy

Comanda de mai jos va rula Envoy Proxy printr-un container Docker pe gazdă. Această comandă îi oferă lui Envoy posibilitatea de a asculta cererile de intrare pe portul 80. Totuși, așa cum este specificat în configurația listener-ului, Envoy Proxy ascultă traficul de intrare pe portul 8080. Acest lucru permite procesului să fie lansat ca utilizator cu privilegii reduse.

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

Testare

Cu proxy-ul pornit, acum se pot face și procesa teste. Comanda cURL următoare emite o cerere cu antetul gazdei definit în configurația proxy.

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

Cererea HTTP va duce la o eroare 503Acest lucru se datorează faptului că conexiunile ascendente nu funcționează și nu sunt disponibile. Astfel, Envoy Proxy nu are destinatari disponibili pentru solicitare. Comanda următoare va lansa o serie de servicii HTTP care corespund configurației definite pentru Envoy.

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

Cu serviciile disponibile, Envoy poate proxifica cu succes traficul către destinație.

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

Trebuie să vedeți un răspuns care indică ce container Docker a procesat solicitația. În jurnalele Envoy Proxy, ar trebui să vedeți, de asemenea, linia de acces afișată.

Antete suplimentare ale răspunsului HTTP

În antetele răspunsului pentru cererea validă, veți vedea antete HTTP suplimentare. Antetul indică timpul pe care hostul superior l-a petrecut procesând cererea. Este exprimat în milisecunde. Acest lucru este util dacă clientul dorește să determine timpul de servicii comparativ cu întârzierea din rețea.

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

Configurația 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 }

Informații suplimentare de la traducător

Puteți găsi instrucțiunile de instalare pentru Envoy Proxy pe site-ul https://www.getenvoy.io/

În mod implicit, rpm-ul nu conține configurația serviciului systemd.

Adăugați configurația serviciului systemd în /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

Trebuie să creați directorul \/etc\/envoy\/ și să plasați acolo configurația config.yaml.

Există un chat pe Telegram pentru envoy proxy: https://t.me/envoyproxy_ru

Envoy Proxy nu oferă suport pentru distribuirea conținutului static. De aceea, cei care pot să voteze pentru caracteristica: https://github.com/envoyproxy/envoy/issues/378

Numai utilizatorii înregistrați pot participa la sondaj. Conectați-vă, vă rugăm.

Te-a încântat acest post să instalezi și să testezi envoy proxy?

  • da

  • nu

75 de utilizatori au votat. 18 utilizatori s-au abținut.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster