Pozdrowienia! To krótki artykuł, który odpowiada na pytania: „czym jest poseł?”, „do czego jest potrzebny?” i „od czego zacząć?”.
Co to jest?
Envoy to balanser L4-L7 napisany w C++, nastawiony na wysoką wydajność i dostępność. Z jednej strony jest to w pewnym sensie analogia nginx i haproxy, porównywalna z nimi wydajnością. Z drugiej strony jest bardziej zorientowany na architekturę mikroserwisową i ma funkcjonalność nie gorszą od balanserów Java i Go, takich jak zuul czy traefik.
Tabela porównawcza haproxy/nginx/envoy, nie rości sobie prawa do absolutnej prawdy, ale daje ogólny obraz.
nginx
haproxy
wysłannik
Traefik
gwiazdy na githubie
11.2 tys./lustro
1.1 tys./lustro
12.4k
27.6k
napisane w
C
C
C + +
go
API
nie
Tylko gniazdo/wciśnij
dataplane/pull
Ciągnąć
aktywna kontrola stanu
nie
tak
tak
tak
Otwarte śledzenie
wtyczka zewnętrzna
nie
tak
tak
JWT
wtyczka zewnętrzna
nie
tak
nie
rozbudowa
Lua/C
Lua/C
Lua/C++
nie
Po co
To młody projekt, brakuje mu wielu rzeczy, niektóre są w fazie wczesnej alfa. Ale wysłannik, również ze względu na swoją młodość, szybko się rozwija i posiada już wiele ciekawych funkcji: dynamiczną konfigurację, wiele gotowych filtrów, prosty interfejs do pisania własnych filtrów.
Z tego wynikają obszary zastosowań, ale najpierw istnieją 2 antywzorce:
- Odrzut statyczny.
Fakt jest taki, że w tej chwili w wysłannik brak obsługi buforowania. Pracownicy Google próbują tego
Na razie użyj Nginx do statyki.
- Konfiguracja statyczna.
Możesz z tego skorzystać, ale wysłannik Nie po to został stworzony. Funkcje w konfiguracji statycznej nie będą widoczne. Jest wiele momentów:
Edytując konfigurację w YAML, popełnisz błąd, zbesztasz programistów za gadatliwość i pomyślisz, że konfiguracje nginx/haproxy, choć mniej uporządkowane, są bardziej zwięzłe. O to chodzi. Konfiguracja Nginx i Haproxy została stworzona do ręcznej edycji i wysłannik do generowania z kodu. Całość konfiguracji opisana jest w
Scenariusze wdrożeń Canary, b/g i wiele innych są zwykle wdrażane tylko w konfiguracji dynamicznej. Nie twierdzę, że nie można tego zrobić statycznie, wszyscy to robimy. Ale w tym celu musisz założyć kule w dowolnym z balanserów wysłannik włącznie z.
Zadania, do których Envoy jest niezastąpiony:
- Równoważenie ruchu w systemach złożonych i dynamicznych. Obejmuje to siatkę usług, ale niekoniecznie jest to jedyna.
- Zapotrzebowanie na funkcjonalność rozproszonego śledzenia, złożoną autoryzację lub inną funkcjonalność dostępną w wysłannik od razu po wyjęciu z pudełka lub wygodnie zaimplementowany, ale w nginx/haproxy musisz być otoczony lua i podejrzanymi wtyczkami.
Oba, jeśli to konieczne, zapewniają wysoką wydajność.
Jak to działa
Envoy jest dystrybuowany w postaci binarnej wyłącznie jako obraz okna dokowanego. Obraz zawiera już przykład konfiguracji statycznej. Ale interesuje nas to tylko w celu zrozumienia struktury.
Konfiguracja statyczna 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
Konfiguracja dynamiczna
Na jaki problem szukamy rozwiązania? Nie można po prostu przeładować konfiguracji modułu równoważenia obciążenia pod obciążeniem; pojawią się „małe” problemy:
- Walidacja konfiguracji.
Konfiguracja może być duża, może być bardzo duża, jeśli przeciążymy ją całą na raz, ryzyko wystąpienia gdzieś błędu wzrasta.
- Długowieczne połączenia.
Inicjując nowego słuchacza należy zadbać o połączenia działające na starym; jeśli zmiany zachodzą często i połączenia są długotrwałe, trzeba będzie szukać kompromisu. Witam, ingres Kubernetes na Nginx.
- Aktywne kontrole stanu.
Jeśli mamy aktywne kontrole stanu, musimy je ponownie sprawdzić w nowej konfiguracji przed wysłaniem ruchu. Jeśli jest dużo upstreamów, zajmuje to trochę czasu. Witaj haproxy.
Jak to jest rozwiązane w wysłannikŁadując konfigurację dynamicznie, zgodnie z modelem puli, możesz podzielić ją na osobne części i nie inicjować ponownie części, która się nie zmieniła. Na przykład słuchacz, którego ponowna inicjalizacja jest kosztowna i rzadko się zmienia.
Konfiguracja wysłannik (z pliku powyżej) ma następujące podmioty:
- słuchacz — słuchacz zawieszony na określonym adresie IP/porcie
- wirtualny host - wirtualny host według nazwy domeny
- trasa - zasada równoważenia
- grupa — grupa upstreamów o parametrach bilansujących
- Punkt końcowy — adres instancji nadrzędnej
Każdą z tych encji oraz kilka innych można wypełnić dynamicznie, w tym celu konfiguracja określa adres usługi, z której zostanie pobrana konfiguracja. Usługą może być REST lub gRPC, preferowana jest gRPC.
Usługi noszą odpowiednio nazwy: LDS, VHDS, RDS, CDS i EDS. Można łączyć konfigurację statyczną i dynamiczną, z zastrzeżeniem, że zasobu dynamicznego nie można określić w statycznym.
Do większości zadań wystarczy wdrożenie trzech ostatnich usług, nazywane są one ADS (Aggregated Discovery Service), dla
Konfiguracja ma następującą postać:
Konfiguracja dynamiczna 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
Podczas uruchamiania wysłannik przy tej konfiguracji połączy się z płaszczyzną sterowania i spróbuje zażądać konfiguracji RDS, CDS i EDS. Opisano, jak zachodzi proces interakcji
W skrócie, wysłannik wysyła żądanie wskazujące rodzaj żądanego zasobu, wersję i parametry węzła. W odpowiedzi otrzymuje zasób i wersję; jeśli wersja na płaszczyźnie kontrolnej nie uległa zmianie, nie odpowiada.
Istnieją 4 opcje interakcji:
- Jeden strumień gRPC dla wszystkich typów zasobów, wysyłany jest pełny status zasobu.
- Oddzielne strumienie, stan pełny.
- Jeden strumień, stan przyrostowy.
- Oddzielne strumienie, stan przyrostowy.
Przyrostowy xDS pozwala zredukować ruch pomiędzy płaszczyzną kontrolną i wysłannik, jest to istotne w przypadku dużych konfiguracji. Ale to komplikuje interakcję, żądanie zawiera listę zasobów do anulowania subskrypcji i subskrypcji.
W naszym przykładzie zastosowano ADS - jeden strumień dla RDS, CDS, EDS i trybu nieprzyrostowego. Aby włączyć tryb przyrostowy, musisz określić api_type: DELTA_GRPC
Ponieważ żądanie zawiera parametry węzła, możemy wysyłać różne zasoby do płaszczyzny kontrolnej dla różnych instancji wysłannikJest to wygodne w przypadku tworzenia siatki usług.
Rozgrzewka
Na wysłannik przy uruchomieniu lub otrzymaniu nowej konfiguracji z płaszczyzny kontrolnej uruchamiany jest proces rozgrzewania zasobów. Dzieli się na rozgrzewkę słuchacza i rozgrzewkę klastra. Pierwsza uruchamia się w przypadku zmian w RDS/LDS, druga w przypadku CDS/EDS. Oznacza to, że jeśli zmienią się tylko kanały nadrzędne, słuchacz nie zostanie odtworzony.
Podczas procesu rozgrzewania oczekuje się zasobów zależnych z płaszczyzny sterującej w czasie przekroczenia limitu czasu. Jeśli nastąpi przekroczenie limitu czasu, inicjalizacja nie powiedzie się i nowy słuchacz nie rozpocznie nasłuchiwania na porcie.
Kolejność inicjalizacji: EDS, CDS, aktywna kontrola stanu, RDS, LDS. Po włączeniu aktywnych kontroli stanu ruch będzie przesyłany w górę dopiero po jednej pomyślnej kontroli stanu.
Jeżeli słuchacz został utworzony od nowa, stary przechodzi w stan DRAIN i zostanie usunięty po zamknięciu wszystkich połączeń lub upłynięciu limitu czasu --drain-time-s
, domyślnie 10 minut.
Aby być kontynuowane.
Źródło: www.habr.com