Мигриране от Nginx на Envoy Proxy

Здравей, Хабр! Предлагам ви превод на поста: Мигриране от Nginx на Envoy Proxy.

Envoy е високо производителен разпределен прокси сървър (написан на C++), предназначен за отделни услуги и приложения, също така е комуникационен хъб и "универсален данни план", разработен за големи микросервисни архитектури "service mesh". При създаването му са взети предвид решения на проблеми, които възникват при разработката на такива сървъри, като NGINX, HAProxy, хардуерни балансировчици на натоварване и облачни балансировчици на натоварване. Envoy работи с всяко приложение и абстрахира мрежата, предоставяйки общи функции независимо от платформата. Когато целият служебен трафик в инфраструктурата преминава през Envoy мрежата, става лесно да се визуализират проблемните области с помощта на консистентно наблюдение, настройка на общата производителност и добавяне на основни функции в конкретно място.

Възможности

  • Архитектура извън процеса: envoy е автономен, високо производителен сървър, заемащ малко оперативна памет. Той работи съвместно с всеки език на приложение или рамка.
  • Поддръжка на http/2 и grpc: envoy има първокласна поддръжка на http/2 и grpc за входящи и изходящи връзки. Това е прозрачен прокси от http/1.1 до http/2.
  • Разширено натоварване на баланс: envoy поддържа разширени функции на натоварване на баланс, включително автоматични повторни опити, разкъсване на верига, глобално ограничаване на скоростта, затеняване на заявки, локално натоварване на зона и т.н.
  • API за управление на конфигурация: envoy предоставя надежден API за динамично управление на своята конфигурация.
  • Наблюдаемост: дълбока наблюдаемост на трафика L7, вградена поддръжка на разпределено проследяване и наблюдаемост на mongodb, dynamodb и много други приложения.

Стъпка 1 — Пример на конфигурация NGINX

В този сценарий се използва специално създаден файл nginx.conf, основан на пълен пример от NGINX Wiki. Можете да видите конфигурацията в редактора, отваряйки nginx.conf

Изходна конфигурация 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;
    }
  }
}

Конфигурациите на NGINX обикновено имат три ключови елемента:

  1. Настройка на NGINX сървъра, структура на логовете и функционалност на Gzip. Те се определят глобално за всички случаи.
  2. Настройка на NGINX за получаване на заявки на хост one.example.com на порт 8080.
  3. Настройка на целевото местоположение, как да се обработва трафикът за различни части от URL.

Не всяка конфигурация ще се прилага към Envoy Proxy и не е необходимо да настройвате някои параметри. Envoy Proxy има четири ключови типа, които поддържат базовата инфраструктура, предлагана от NGINX. Ядро е:

  • Слушатели: Те определят как Envoy Proxy приема входящи заявки. В момента Envoy Proxy поддържа само TCP базирани слушатели. След като връзката е установена, тя се предава на набор от филтри за обработка.
  • Филтри: Те са част от конвейерна архитектура, която може да обработва входящи и изходящи данни. Тази функционалност включва филтри, като Gzip, който компресира данните преди да ги изпрати на клиента.
  • Маршрутизатори: Те пренасочват трафика към необходимата дестинация, определена като клъстер.
  • Клъстери: Те определят крайната точка за трафика и параметрите на конфигурацията.

Ще използваме тези четири компонента, за да създадем конфигурация на Envoy Proxy, за да отговорим на определена конфигурация на NGINX. Целта на Envoy е работа с API и динамична конфигурация. В този случай базовата конфигурация ще използва статични, твърдо зададени параметри от NGINX.

Стъпка 2 — Конфигурация на NGINX

Първа част nginx.conf определя някои вътрешни компоненти на NGINX, които трябва да бъдат настроени.

Работни връзки (Worker Connections)

Следната конфигурация определя количеството работни процеси и връзки. Това указва как NGINX ще се мащабира, за да отговори на търсенето.

worker_processes  2;

events {
  worker_connections   2000;
}

Envoy Proxy управлява работните процеси и връзките по различен начин.

Envoy създава работен поток за всеки хардуерен поток в системата. Всеки работен поток изпълнява неблокиращ цикъл на събития, отговорен за

  1. Слушането на всеки слушател (listener)
  2. Приемане на нови връзки
  3. Създаване на набор от филтри за връзката
  4. Обработка на всички операции за вход/изход по време на съществуването на връзката.

Цялата по-нататъшна обработка на връзката се извършва изцяло в работния поток, включително всякакво поведение на пренасочване.

За всеки работен поток в Envoy съществува връзка в.pool. По този начин, HTTP/2 пуловете на връзки установяват само една връзка за всеки външен хост наведнъж, при наличие на четири работни потока ще има четири HTTP/2 връзки за всеки външен хост при стабилно състояние. Поддържайки всичко в един работен поток, почти целият код може да бъде написан неблокирано, сякаш е еднопоточен. Ако работните потоци са разпределени повече от необходимото, това може да доведе до нерационално използване на паметта, генериране на много неактивни връзки и намаляване на броя на връщанията на връзките обратно в.pool.

За допълнителна информация, посетете блога на Envoy Proxy.

HTTP конфигурация

Следният блок на конфигурация на NGINX определя настройките на HTTP, като:

  • Кои mime типове се поддържат
  • Настройки на таймаутите по подразбиране
  • Конфигурация на Gzip

Можете да настроите тези аспекти с помощта на филтри в Envoy Proxy, което ще обсъдим по-късно.

Стъпка 3 — Конфигурация на сървъра

В блока за конфигуриране на HTTP, конфигурацията на NGINX указва да слуша порт 8080 и да отговаря на входящи заявки за домейните one.example.com и www.one.example.com.

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

В Envoy това се управлява от Слушателите.

Слушатели на Envoy

Най-важният аспект на започването с Envoy Proxy е определянето на слушателите. Трябва да създадете конфигурационен файл, който описва как искате да стартирате инстанцията на Envoy.

По-долу представен фрагмент, който ще създаде нов слушател и ще го свърже с порт 8080. Конфигурацията указва на Envoy Proxy, към които портове трябва да бъде свързан за входящи заявки.

Envoy Proxy използва YAML нотация за своята конфигурация. За запознаване с тази нотация, вижте тук линка.

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

Няма нужда да се определя server_name, тъй като филтрите на Envoy Proxy ще се справят с това.

Стъпка 4 — Конфигурация на местоположението

Когато заявка постъпи в NGINX, блокът за местоположение определя как да се обработи и накъде да се насочи трафикът. В следващия фрагмент целият трафик към сайта се предава в upstream (примечание на преводача: upstream обикновено е сървъри на приложения) клъстер с име targetCluster. Upstream клъстерът определя възлите, които трябва да обработват заявката. Ще разгледаме това в следващата стъпка.

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

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

В Envoy това се прави от филтрите.

Envoy Filters

За статичната конфигурация филтрите определят как да се обработват входящите заявки. В този случай задаваме филтри, които отговарят на server_names от предишната стъпка. Когато постъпват входящи заявки, които отговарят на определени домейни и маршрути, трафикът се насочва към клъстера. Това е еквивалент на съществуващата конфигурация на 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

Име envoy.http_connection_manager е вграден филтър в Envoy Proxy. Други филтри включват Redis, Mongo, TCP. Можете да намерите пълен списък в документацията.

За допълнителна информация относно другите политики за балансиране на натоварването, посетете Документацията на Envoy.

Стъпка 5 — Конфигурация на проксито и upstream

В NGINX конфигурацията на upstream определя набор от целеви сървъри, които ще обработват трафика. В този случай два клъстера бяха назначени.

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

В Envoy това се управлява от клъстери.

Envoy Clusters

Еквивалентът на upstream се определя като клъстери. В този случай бяха определени хостове, които ще обслужват трафика. Начинът на достъп до хостовете, например времето за изчакване, се определя като конфигурация на клъстера. Това позволява по-точно контролиране на детайлите на аспекти като време за изчакване и баланс на натоварването.

Copy to Editor  клъстери:
  - 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 }}
    ]

При използване на откритие на услуги STRICT_DNS Envoy ще разрешава непрекъснато и асинхронно посочените DNS цели. Всеки върнат IP адрес в резултат на DNS ще се счита за явен хост в клъстера. Това означава, че ако запитването върне два IP адреса, Envoy ще предположи, че в клъстера има два хоста, и двата трябва да бъдат балансирани по натоварване. Ако хостът бъде премахнат от резултата, Envoy предположи, че той вече не съществува и ще взима трафика от всякакви съществуващи пулове на връзките.

За допълнителна информация вижте Документацията на прокси сървъра Envoy.

Стъпка 6 — Достъп до логовете и грешките

Крайната конфигурация — регистрация. Вместо да предава грешковите логове на диск, Envoy Proxy използва облачен подход. Всички логове на приложенията се извеждат в stdout и stderr.

Когато потребителите правят запитване, логовете за достъп са необходими и по подразбиране са деактивирани. За да активирате логовете за достъп за HTTP запитвания, активирайте конфигурацията access_log за HTTP диспечера на връзките. Пътят може да бъде или устройство, като stdout, или файл на диска, в зависимост от вашите изисквания.

Следващата конфигурация ще пренасочи всички логове за достъп в stdout (примечание на преводача — stdout е необходимо за използване на envoy в docker. Ако се използва без docker, заменете \/dev\/stdout с пътя до обикновен лог-файл). Копирайте фрагмента в секцията за конфигурация на мениджъра на връзките:

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

Резултатите трябва да изглеждат така:

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

По подразбиране Envoy има формат на ред, който включва детайли на 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

Резултатът от този формат е:

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

Съдържанието на изхода може да бъде конфигурирано чрез задаване на поле за формат. Например:

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"

Строката за журналиране също може да бъде извеждана във формат JSON, като се зададе поле json_format. Например:

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

За допълнителна информация относно методологията на журнала на Envoy, посетете

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

Журналирането не е единственият начин да получите представа за работата с Envoy Proxy. Той включва разширени функции за проследяване и метрики. Можете да научите повече в документацията за проследяване или чрез Интерактивния сценарий за проследяване.

Стъпка 7 — Стартиране

Сега вече сте превели конфигурацията от NGINX на Envoy Proxy. Последната стъпка е да стартирате инстанция на Envoy Proxy за тестване.

Стартиране от потребител

В горната част на конфигурацията на NGINX редът user www www; означава, че NGINX ще бъде стартиран като потребител с по-ниски привилегии за повишаване на сигурността.

Envoy Proxy използва облачен подход за управление на това, кой е собственик на процеса. Когато стартираме Envoy Proxy през контейнер, можем да зададем потребител с по-ниски привилегии.

Стартиране на Envoy Proxy

Командата по-долу ще стартира Envoy Proxy в Docker контейнер на хост. Тази команда предоставя на Envoy възможността да слуша входящи заявки през порт 80. Обаче, както е посочено в конфигурацията на слушателя, Envoy Proxy слуша входящия трафик на порт 8080. Това позволява на процеса да бъде стартиран като потребител с по-ниски привилегии.

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

Тестване

С активиран прокси, тестовете вече могат да бъдат извършени и обработени. Следващата команда cURL изпраща заявка с заглавие на хоста, определено в конфигурацията на проксито.

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

HTTP заявка ще доведе до грешка 503Това се дължи на факта, че изходящите връзки не работят и не са налични. Следователно, Envoy Proxy няма налични целеви адреси за заявката.

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

С наличните услуги Envoy успешно проксира трафика до местоназначението.

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

Трябва да видите отговор, указващ кой Docker контейнер е обработил заявката. В журналите на Envoy Proxy също трябва да видите извеждане на запис за достъпа.

Допълнителни HTTP заглавки (HTTP Response)

В заглавките на валидната заявка ще видите допълнителни HTTP заглавки. В заглавието е показано времето, което горният хост е отделил за обработка на заявката. Изразява се в милисекунди. Това е полезно, ако клиентът иска да определи времето за обслужване спрямо закъснението в мрежата.

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

Краен конфиг

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 }

Допълнителна информация от преводача

Инструкции за инсталиране на Envoy Proxy можете да намерите на сайта https://www.getenvoy.io/

По подразбиране в rpm липсва конфигурация на systemd service.

Добавете конфигурация на systemd service \/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

Трябва да създадете директория \/etc\/envoy\/ и да положите там конфигурацията config.yaml.

По отношение на envoy proxy има Telegram чат: https://t.me/envoyproxy_ru

Envoy Proxy не поддържа раздаване на статично съдържание. Затова, моля, гласувайте за функция: https://github.com/envoyproxy/envoy/issues/378

Само регистрирани потребители могат да участват в анкетата. Влезте, моля.

Постът ви вдъхнови ли да инсталирате и тествате envoy proxy?

  • да

  • недостъпен

75 потребители гласуваха. 18 потребители се въздържаха.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster