Migrarea de la Nginx la Envoy Proxy

Bună, Habr! Vă aduc la cunoștință o traducere a postării: Migrarea de la Nginx la Envoy Proxy.

Envoy este un server proxy distribuit de înaltă performanță (scris în C++) conceput pentru servicii și aplicații individuale, este, de asemenea, o magistrală de comunicații și un „plan de date universal” conceput pentru arhitecturi mari de microservicii „mesh de servicii”. La crearea acestuia, s-au luat în considerare soluțiile la problemele apărute în timpul dezvoltării serverelor precum NGINX, HAProxy, echilibrare de încărcare hardware și echilibrare de încărcare în cloud. Envoy lucrează alături de fiecare aplicație și extrage rețeaua pentru a oferi funcționalități comune, indiferent de platformă. Când tot traficul de servicii dintr-o infrastructură circulă prin rețeaua Envoy, devine ușor să vizualizați zonele cu probleme cu observabilitate consecventă, să reglați performanța generală și să adăugați funcționalitate de bază într-o anumită locație.

Capabilitățile

  • Arhitectură în afara procesului: envoy este un server autonom, de înaltă performanță, care ocupă o cantitate mică de RAM. Funcționează împreună cu orice limbaj de aplicație sau cadru.
  • Suport http/2 și grpc: envoy are suport http/2 și grpc de primă clasă pentru conexiunile de intrare și de ieșire. Acesta este un proxy transparent de la http/1.1 la http/2.
  • Echilibrare avansată a sarcinii: envoy acceptă funcții avansate de echilibrare a încărcăturii, inclusiv reîncercări automate, întrerupere a lanțului, limitare globală a ratei, umbrire a solicitărilor, echilibrare a încărcăturii în zonă locală etc.
  • API de gestionare a configurației: envoy oferă un API robust pentru gestionarea dinamică a configurației.
  • Observabilitate: observabilitate profundă a traficului L7, suport nativ pentru urmărirea distribuită și observabilitatea mongodb, dynamodb și multe alte aplicații.

Pasul 1 — Exemplu de configurare NGINX

Acest script folosește un fișier special creat nginx.conf, pe baza exemplului complet din NGINX Wiki. Puteți vizualiza configurația în editor deschizând nginx.conf

Configurarea sursei 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;
    }
  }
}

Configurațiile NGINX au de obicei trei elemente cheie:

  1. Configurarea serverului NGINX, a structurii jurnalului și a funcționalității Gzip. Aceasta este definită global în toate cazurile.
  2. Se configurează NGINX pentru a accepta cereri către gazdă one.example.com pe portul 8080.
  3. Configurarea locației țintă, cum să gestionați traficul pentru diferite părți ale adresei URL.

Nu toate configurațiile se vor aplica pentru Envoy Proxy și nu trebuie să configurați unele setări. Envoy Proxy are patru tipuri de chei, care acceptă infrastructura de bază oferită de NGINX. Nucleul este:

  • Ascultători: Ei determină modul în care Envoy Proxy acceptă cererile primite. În prezent, Envoy Proxy acceptă doar ascultătorii bazați pe TCP. Odată stabilită o conexiune, aceasta este transmisă unui set de filtre pentru procesare.
  • Filtre: Ele fac parte dintr-o arhitectură pipeline care poate procesa datele de intrare și de ieșire. Această funcționalitate include filtre precum Gzip, care comprimă datele înainte de a le trimite către client.
  • Routere: Ei redirecționează traficul către destinația necesară, definită ca un cluster.
  • Clustere: Ele definesc punctul final pentru trafic și parametrii de configurare.

Vom folosi aceste patru componente pentru a crea o configurație Envoy Proxy care să se potrivească cu o anumită configurație NGINX. Scopul lui Envoy este să lucreze cu API-uri și configurație dinamică. În acest caz, configurația de bază va folosi setări statice, codificate de la NGINX.

Pasul 2 - Configurarea NGINX

Prima parte nginx.conf definește unele elemente interne NGINX care trebuie configurate.

Conexiuni de muncitor

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

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy gestionează fluxurile de lucru și conexiunile în moduri diferite.

Envoy creează un fir de lucru pentru fiecare fir hardware de pe sistem. Fiecare thread de lucru execută o buclă de evenimente neblocante care este responsabilă

  1. Ascultarea fiecărui ascultător
  2. Acceptarea noilor conexiuni
  3. Crearea unui set de filtre pentru o conexiune
  4. Procesați toate operațiunile I/O pe durata de viață a conexiunii.

Toate procesările ulterioare ale conexiunii sunt gestionate în întregime în firul de lucru, inclusiv orice comportament de redirecționare.

Pentru fiecare fir de lucru din Envoy, există un pool de conexiuni. Deci, grupurile de conexiuni HTTP/2 stabilesc o singură conexiune per gazdă externă la un moment dat, dacă există patru fire de lucru, vor exista patru conexiuni HTTP/2 per gazdă externă într-o stare stabilă. Păstrând totul într-un singur thread de lucru, aproape tot codul poate fi scris fără blocare, ca și cum ar fi un singur thread. Dacă sunt alocate mai multe fire de execuție decât este necesar, acest lucru poate duce la irosirea memoriei, creând un număr mare de conexiuni inactive și reducând numărul de ori când conexiunile sunt returnate înapoi la pool.

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

Configurare HTTP

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

  • Ce tipuri de mime sunt acceptate
  • Timpuri implicite
  • Configurare Gzip

Puteți personaliza aceste aspecte folosind filtre î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 solicitările primite pentru domenii one.example.com и www.one.example.com.

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

În interiorul Envoy, este controlat de Ascultători.

Trimis ascultătorilor

Cel mai important aspect al începerii cu Envoy Proxy este definirea ascultătorilor. Trebuie să creați un fișier de configurare care să descrie modul în care doriți să rulați instanța Envoy.

Fragmentul de mai jos va crea un nou ascultător și îl va lega la portul 8080. Configurația îi spune lui Envoy Proxy la ce porturi ar trebui să se lege pentru solicitările primite.

Envoy Proxy folosește notația YAML pentru configurația sa. Pentru o introducere în această notație, uitați-vă aici legătură.

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

Nu trebuie definit numele serverului, deoarece filtrele Envoy Proxy se vor ocupa de acest lucru.

Pasul 4 - Configurarea locației

Când o solicitare vine în NGINX, blocul de locație determină cum să proceseze și unde să direcționeze traficul. În următorul fragment, tot traficul către site este transferat către un cluster în amonte (nota traducătorului: în amonte este de obicei un server de aplicații) numit targetCluster. Clusterul din amonte definește nodurile care ar trebui să proceseze cererea. Vom discuta acest lucru î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;
}

La Envoy, Filters face acest lucru.

Filtre Envoy

Pentru o configurație statică, filtrele determină modul de procesare a cererilor primite. În acest caz, setăm filtre care se potrivesc nume_server în pasul anterior. Când sosesc solicitări care se potrivesc cu anumite domenii și rute, traficul este direcționat către cluster. Acesta este echivalentul unei configurații de jos în sus 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 Envoy Proxy. Alte filtre includ Redis, mongo, TCP. Lista completă o găsiți la documentație.

Pentru mai multe informații despre alte politici de echilibrare a sarcinii, vizitați Documentația trimisului.

Pasul 5 - Configurare proxy și în amonte

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

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

În Envoy, acest lucru este gestionat de clustere.

Clustere de trimis

Echivalentul din amonte este definit ca clustere. În acest caz, au fost identificate gazdele care vor deservi traficul. Modul în care sunt accesate gazdele, cum ar fi timeout-urile, este definit ca o configurație de cluster. Acest lucru permite un control mai granular asupra aspectelor precum latența și echilibrarea sarcinii.

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

Când utilizați descoperirea serviciului STRICT_DNS Envoy va rezolva continuu și asincron țintele DNS specificate. Fiecare adresă IP returnată din rezultatul DNS va fi considerată o gazdă explicită în clusterul din amonte. Aceasta înseamnă că, dacă o solicitare returnează două adrese IP, Envoy va presupune că există două gazde în cluster și ambele trebuie să fie echilibrate. Dacă o gazdă este eliminată din rezultat, Envoy va presupune că nu mai există și va extrage trafic din toate grupurile de conexiuni existente.

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

Pasul 6 — Acces în jurnal și erori

Configurația finală este înregistrarea. În loc să împingă jurnalele de erori pe disc, Envoy Proxy adoptă o abordare bazată pe cloud. Toate jurnalele aplicației sunt trimise către stdout и stderr.

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

Următoarea configurație va redirecționa toate jurnalele de acces către stdout (Nota traducătorului - stdout este necesar pentru a utiliza envoy în interiorul docker. Dacă este utilizat fără docker, înlocuiți /dev/stdout cu calea către un fișier 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:

În mod implicit, Envoy are un șir de format care include detaliile solicitării 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 acestui șir de format este:

[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 de ieșire poate fi personalizat prin setarea câmpului 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 scoasă și în format JSON prin setarea câmpului 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 mai multe informații despre Metodologia de înregistrare a Envoyului, vizitați

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

Înregistrarea nu este singura modalitate de a obține informații despre lucrul cu Envoy Proxy. Are capabilități avansate de urmărire și metrică încorporate. Puteți afla mai multe la documentația de urmărire sau prin Script de urmărire interactiv.

Pasul 7 - Lansați

Acum ați migrat configurația de la NGINX la Envoy Proxy. Ultimul pas este să lansați o instanță Envoy Proxy pentru a o testa.

Rulați ca utilizator

În partea de sus a liniei de configurare NGINX utilizator www www; specifică rularea NGINX ca utilizator cu privilegii reduse pentru a îmbunătăți securitatea.

Envoy Proxy adoptă o abordare bazată pe cloud pentru a gestiona cine deține un proces. Când rulăm Envoy Proxy printr-un container, putem specifica un utilizator cu privilegii reduse.

Se lansează Envoy Proxy

Comanda de mai jos va rula Envoy Proxy printr-un container Docker de pe gazdă. Această comandă oferă Envoy posibilitatea de a asculta cererile primite pe portul 80. Cu toate acestea, așa cum se specifică în configurația de ascultător, Envoy Proxy ascultă traficul de intrare pe portul 8080. Acest lucru permite procesului să ruleze ca un utilizator cu privilegii reduse.

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

Testarea

Cu proxy-ul în funcțiune, testele pot fi acum făcute și procesate. Următoarea comandă cURL emite o solicitare cu antetul gazdei definit în configurația proxy.

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

Solicitarea HTTP va avea ca rezultat o eroare 503. Acest lucru se datorează faptului că conexiunile în amonte nu funcționează și nu sunt disponibile. Prin urmare, Envoy Proxy nu are destinații disponibile pentru cerere. Următoarea comandă va porni o serie de servicii HTTP care se potrivesc cu configurația definită pentru Envoy.

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

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

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

Ar trebui să vedeți un răspuns care indică ce container Docker a procesat cererea. În jurnalele Envoy Proxy, ar trebui să vedeți și un șir de acces.

Antete suplimentare de răspuns HTTP

Veți vedea anteturi HTTP suplimentare în anteturile de răspuns ale cererii reale. Antetul afișează timpul petrecut de gazda din amonte procesând cererea. Exprimat în milisecunde. Acest lucru este util dacă clientul dorește să determine timpul de serviciu în comparație cu latența rețelei.

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

Configurație 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

Instrucțiunile pentru instalarea Envoy Proxy pot fi găsite pe site-ul web https://www.getenvoy.io/

În mod implicit, rpm nu are o configurație de serviciu systemd.

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

Trebuie să creați un director /etc/envoy/ și să puneți acolo configurația config.yaml.

Există un chat de telegramă folosind proxy envoy: https://t.me/envoyproxy_ru

Envoy Proxy nu acceptă difuzarea de conținut static. Prin urmare, cine poate vota pentru funcția: https://github.com/envoyproxy/envoy/issues/378

Numai utilizatorii înregistrați pot participa la sondaj. Loghează-te, Vă rog.

Această postare v-a încurajat să instalați și să testați proxy envoy?

  • da

  • nu

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

Sursa: www.habr.com

Adauga un comentariu