Migracja z Nginx do Envoy Proxy

Witaj, Habro! Zwracam uwagę na tłumaczenie postu: Migracja z Nginx do Envoy Proxy.

Envoy to wysokowydajny rozproszony serwer proxy (napisany w C++) przeznaczony dla indywidualnych usług i aplikacji, to także magistrala komunikacyjna i „uniwersalna płaszczyzna danych” przeznaczona dla dużych architektur mikroserwisowych „service mesh”. Przy jego tworzeniu wzięto pod uwagę rozwiązania problemów, które pojawiły się podczas rozwoju serwerów takich jak NGINX, HAProxy, sprzętowe równoważenie obciążenia i równoważenie obciążenia w chmurze. Envoy współpracuje z każdą aplikacją i wyodrębnia sieć, aby zapewnić wspólną funkcjonalność niezależnie od platformy. Kiedy cały ruch usługowy w infrastrukturze przepływa przez siatkę Envoy, łatwo jest wizualizować obszary problematyczne w sposób spójny i widoczny, dostrajać ogólną wydajność i dodawać podstawowe funkcje w określonej lokalizacji.

Możliwości

  • Architektura pozaprocesowa: envoy to samodzielny, wydajny serwer, który zajmuje niewielką ilość pamięci RAM. Działa w połączeniu z dowolnym językiem aplikacji lub frameworkiem.
  • Obsługa http/2 i grpc: envoy oferuje pierwszorzędną obsługę http/2 i grpc dla połączeń przychodzących i wychodzących. Jest to przezroczyste proxy od http/1.1 do http/2.
  • Zaawansowane równoważenie obciążenia: envoy obsługuje zaawansowane funkcje równoważenia obciążenia, w tym automatyczne ponawianie prób, łamanie łańcucha, globalne ograniczanie szybkości, śledzenie żądań, równoważenie obciążenia w strefie lokalnej itp.
  • Interfejs API zarządzania konfiguracją: envoy zapewnia solidny interfejs API do dynamicznego zarządzania konfiguracją.
  • Obserwowalność: głęboka obserwowalność ruchu L7, natywna obsługa rozproszonego śledzenia i obserwowalność mongodb, dynamodb i wielu innych aplikacji.

Krok 1 — Przykładowa konfiguracja NGINX

Skrypt ten wykorzystuje specjalnie spreparowany plik nginx.conf, w oparciu o pełny przykład z Wiki o Nginxie. Możesz wyświetlić konfigurację w edytorze, otwierając nginx.conf

konfiguracja źródła 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;
    }
  }
}

Konfiguracje NGINX zazwyczaj składają się z trzech kluczowych elementów:

  1. Konfiguracja serwera NGINX, struktury logów i funkcjonalności Gzip. We wszystkich przypadkach jest to definiowane globalnie.
  2. Konfigurowanie NGINX do akceptowania żądań do hosta one.example.com na porcie 8080.
  3. Konfigurowanie lokalizacji docelowej, jak obsługiwać ruch dla różnych części adresu URL.

Nie wszystkie konfiguracje będą miały zastosowanie do Envoy Proxy i nie ma potrzeby konfigurowania niektórych ustawień. Pełnomocnik Wysłannika ma cztery kluczowe typy, które obsługują podstawową infrastrukturę oferowaną przez NGINX. Rdzeń to:

  • Słuchacze: Określają, w jaki sposób Envoy Proxy akceptuje przychodzące żądania. Envoy Proxy obecnie obsługuje tylko odbiorniki oparte na protokole TCP. Po nawiązaniu połączenia jest ono przekazywane do zestawu filtrów w celu przetworzenia.
  • Filtry: Są częścią architektury potokowej, która może przetwarzać dane przychodzące i wychodzące. Ta funkcjonalność obejmuje filtry takie jak Gzip, który kompresuje dane przed wysłaniem ich do klienta.
  • Routery: Przekazują ruch do wymaganego miejsca docelowego, zdefiniowanego jako klaster.
  • Klastry: Definiują punkt końcowy dla parametrów ruchu i konfiguracji.

Użyjemy tych czterech komponentów, aby utworzyć konfigurację Envoy Proxy pasującą do konkretnej konfiguracji NGINX. Celem Envoy jest praca z API i dynamiczna konfiguracja. W tym przypadku konfiguracja podstawowa będzie używać statycznych, zakodowanych na stałe ustawień z NGINX.

Krok 2 – Konfiguracja NGINX

Pierwsza część nginx.conf definiuje niektóre elementy wewnętrzne NGINX, które należy skonfigurować.

Połączenia pracownicze

Poniższa konfiguracja określa liczbę procesów roboczych i połączeń. Wskazuje to, w jaki sposób NGINX będzie skalować, aby zaspokoić popyt.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy zarządza przepływem pracy i połączeniami na różne sposoby.

Envoy tworzy wątek roboczy dla każdego wątku sprzętowego w systemie. Każdy wątek roboczy wykonuje nieblokującą pętlę zdarzeń, za którą odpowiada

  1. Słuchanie każdego słuchacza
  2. Akceptowanie nowych połączeń
  3. Tworzenie zestawu filtrów dla połączenia
  4. Przetwarzaj wszystkie operacje we/wy w trakcie trwania połączenia.

Całe dalsze przetwarzanie połączenia jest obsługiwane całkowicie w wątku roboczym, łącznie z wszelkimi zachowaniami przekazywania.

Dla każdego wątku roboczego w Envoy istnieje pula połączeń. Zatem pule połączeń HTTP/2 nawiązują jednocześnie tylko jedno połączenie na host zewnętrzny. Jeśli istnieją cztery wątki robocze, będą cztery połączenia HTTP/2 na host zewnętrzny w stanie stabilnym. Utrzymując wszystko w jednym wątku roboczym, prawie cały kod można zapisać bez blokowania, tak jakby był jednowątkowy. Jeśli przydzielonych zostanie więcej wątków roboczych niż jest to konieczne, może to prowadzić do marnowania pamięci, tworzenia dużej liczby bezczynnych połączeń i zmniejszania liczby połączeń zwracanych z powrotem do puli.

po więcej informacji odwiedź Blog Envoy Proxy.

Konfiguracja HTTP

Poniższy blok konfiguracyjny NGINX definiuje ustawienia HTTP, takie jak:

  • Jakie typy MIME są obsługiwane
  • Domyślne limity czasu
  • Konfiguracja Gzipa

Możesz dostosować te aspekty za pomocą filtrów w Envoy Proxy, co omówimy później.

Krok 3 - Konfiguracja serwera

W bloku konfiguracyjnym HTTP konfiguracja NGINX określa nasłuchiwanie na porcie 8080 i odpowiadanie na przychodzące żądania dotyczące domen one.example.com и www.one.example.com.

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

Wewnątrz Envoy jest kontrolowany przez Słuchaczy.

Wysłannicy słuchaczy

Najważniejszym aspektem rozpoczęcia korzystania z Envoy Proxy jest zdefiniowanie odbiorców. Musisz utworzyć plik konfiguracyjny opisujący sposób uruchamiania instancji Envoy.

Poniższy fragment utworzy nowego słuchacza i powiąże go z portem 8080. Konfiguracja informuje Envoy Proxy, z którymi portami powinien się wiązać dla przychodzących żądań.

Envoy Proxy używa do swojej konfiguracji notacji YAML. Wprowadzenie do tej notacji można znaleźć tutaj link.

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

Nie trzeba definiować server_name, ponieważ filtry proxy Envoy sobie z tym poradzą.

Krok 4 – Konfiguracja lokalizacji

Kiedy żądanie przychodzi do NGINX, blok lokalizacji określa, jak przetworzyć i gdzie skierować ruch. W poniższym fragmencie cały ruch do witryny jest przenoszony do klastra nadrzędnego (uwaga tłumacza: upstream to zwykle serwer aplikacji) o nazwie klaster docelowy. Klaster nadrzędny definiuje węzły, które powinny przetworzyć żądanie. Omówimy to w następnym kroku.

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

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

W Envoy firma Filters robi to.

Filtry wysłanników

W przypadku konfiguracji statycznej filtry określają sposób przetwarzania żądań przychodzących. W tym przypadku ustawiamy pasujące filtry nazwy_serwerów w poprzednim kroku. Po nadejściu żądań przychodzących pasujących do określonych domen i tras ruch jest kierowany do klastra. Jest to odpowiednik konfiguracji oddolnej 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

nazwa wysłannik.http_connection_manager to wbudowany filtr w Envoy Proxy. Inne filtry obejmują Redis, Mongo, TCP. Pełną listę znajdziesz pod adresem dokumentacja.

Więcej informacji na temat innych zasad równoważenia obciążenia można znaleźć na stronie Dokumentacja wysłannika.

Krok 5 — Konfiguracja serwera proxy i przesyłania nadrzędnego

W NGINX konfiguracja nadrzędna definiuje zestaw serwerów docelowych, które będą przetwarzać ruch. W tym przypadku przydzielono dwa klastry.

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

W Envoy jest to zarządzane przez klastry.

Grona wysłanników

Odpowiednik wyższego szczebla definiuje się jako klastry. W tym przypadku zidentyfikowano hosty, które będą obsługiwać ruch. Sposób dostępu do hostów, np. limity czasu, definiuje się jako konfigurację klastra. Pozwala to na bardziej szczegółową kontrolę nad takimi aspektami, jak opóźnienia i równoważenie obciążenia.

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

Podczas korzystania z wykrywania usług STRICT_DNS Envoy będzie stale i asynchronicznie rozpoznawać określone cele DNS. Każdy zwrócony adres IP z wyniku DNS będzie uważany za jawny host w klastrze nadrzędnym. Oznacza to, że jeśli żądanie zwróci dwa adresy IP, Envoy założy, że w klastrze znajdują się dwa hosty i oba muszą być zrównoważone pod względem obciążenia. Jeśli host zostanie usunięty z wyniku, Envoy uzna, że ​​już nie istnieje i przeciągnie ruch ze wszystkich istniejących pul połączeń.

Aby uzyskać więcej informacji zobacz Dokumentacja pełnomocnika wysłannika.

Krok 6 — Dostęp do dziennika i błędy

Ostateczną konfiguracją jest rejestracja. Zamiast przesyłać dzienniki błędów na dysk, Envoy Proxy wykorzystuje podejście oparte na chmurze. Wszystkie dzienniki aplikacji są wysyłane do stdout и stderr.

Gdy użytkownicy wysyłają żądanie, dzienniki dostępu są opcjonalne i domyślnie wyłączone. Aby włączyć dzienniki dostępu dla żądań HTTP, włącz konfigurację dziennik_dostępu dla menedżera połączeń HTTP. Ścieżką może być urządzenie takie jak stdoutlub plik na dysku, w zależności od wymagań.

Poniższa konfiguracja przekieruje wszystkie logi dostępu do stdout (Uwaga tłumacza - aby używać envoy w oknie dokowanym, wymagane jest stdout. Jeśli jest używane bez okna dokowanego, zastąp /dev/stdout ścieżką do zwykłego pliku dziennika). Skopiuj fragment do sekcji konfiguracji menedżera połączeń:

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

Wyniki powinny wyglądać następująco:

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

Domyślnie Envoy ma ciąg formatujący, który zawiera szczegóły żądania 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

Wynikiem tego ciągu formatującego jest:

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

Treść wyjściową można dostosować, ustawiając pole formatu. Na przykład:

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"

Wiersz dziennika można również wyprowadzić w formacie JSON, ustawiając pole format_json. Na przykład:

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

Więcej informacji na temat metodologii rejestracji wysłanników można znaleźć na stronie

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

Logowanie to nie jedyny sposób na uzyskanie wglądu w pracę z Envoy Proxy. Ma wbudowane zaawansowane funkcje śledzenia i metryk. Więcej informacji znajdziesz na dokumentacja śledzenia lub poprzez formularz Interaktywny skrypt śledzenia.

Krok 7 - Uruchom

Dokonałeś migracji konfiguracji z NGINX do Envoy Proxy. Ostatnim krokiem jest uruchomienie instancji Envoy Proxy w celu jej przetestowania.

Uruchom jako użytkownik

Na górze linii konfiguracyjnej NGINX użytkownik www www; określa uruchomienie NGINX jako użytkownik o niskich uprawnieniach w celu poprawy bezpieczeństwa.

Envoy Proxy wykorzystuje podejście oparte na chmurze do zarządzania właścicielami procesu. Kiedy uruchamiamy Envoy Proxy poprzez kontener, możemy określić użytkownika o niskich uprawnieniach.

Uruchamianie serwera proxy Envoy

Poniższe polecenie uruchomi Envoy Proxy poprzez kontener Docker na hoście. To polecenie umożliwia Envoy nasłuchiwanie przychodzących żądań na porcie 80. Jednakże, jak określono w konfiguracji odbiornika, Envoy Proxy nasłuchuje ruchu przychodzącego na porcie 8080. Dzięki temu proces może działać jako użytkownik o niskich uprawnieniach.

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

Testowanie

Po uruchomieniu serwera proxy można teraz wykonywać i przetwarzać testy. Następujące polecenie cURL wysyła żądanie z nagłówkiem hosta zdefiniowanym w konfiguracji proxy.

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

Żądanie HTTP spowoduje błąd 503. Dzieje się tak, ponieważ połączenia nadrzędne nie działają i są niedostępne. W związku z tym Envoy Proxy nie ma dostępnych miejsc docelowych dla żądania. Poniższe polecenie uruchomi serię usług HTTP zgodnych z konfiguracją zdefiniowaną dla Envoy.

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

Dzięki dostępnym usługom Envoy może z powodzeniem przesyłać ruch do miejsca docelowego.

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

Powinieneś zobaczyć odpowiedź wskazującą, który kontener Docker przetworzył żądanie. W dziennikach Envoy Proxy powinieneś także zobaczyć wynikowy ciąg znaków dostępu.

Dodatkowe nagłówki odpowiedzi HTTP

Dodatkowe nagłówki HTTP zobaczysz w nagłówkach odpowiedzi rzeczywistego żądania. Nagłówek wyświetla czas, jaki host nadrzędny spędził na przetwarzaniu żądania. Wyrażone w milisekundach. Jest to przydatne, jeśli klient chce określić czas usługi w porównaniu z opóźnieniem sieci.

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

Ostateczna konfiguracja

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 }

Dodatkowe informacje od tłumacza

Instrukcję instalacji Envoy Proxy znajdziesz na stronie internetowej https://www.getenvoy.io/

Domyślnie RPM nie ma konfiguracji usługi systemowej.

Dodaj konfigurację usług systemowych /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

Musisz utworzyć katalog /etc/envoy/ i umieścić tam konfigurację config.yaml.

Istnieje czat telegramowy przy użyciu serwera proxy wysłannika: https://t.me/envoyproxy_ru

Envoy Proxy nie obsługuje udostępniania treści statycznych. Kto zatem może głosować na tę funkcję: https://github.com/envoyproxy/envoy/issues/378

W ankiecie mogą brać udział tylko zarejestrowani użytkownicy. Zaloguj się, Proszę.

Czy ten post zachęcił Cię do zainstalowania i przetestowania proxy Envoy?

  • tak

  • nie

Głosowało 75 użytkowników. 18 użytkowników wstrzymało się od głosu.

Źródło: www.habr.com

Dodaj komentarz