Міграцыя з Nginx на Envoy Proxy

Прывітанне, Хабр! Прапаную вашай увазе пераклад посту: Міграцыя з Nginx на Envoy Proxy.

Envoy – гэта высокапрадукцыйны размеркаваны проксі-сервер (напісаны на C++), прызначаны для асобных сэрвісаў і прыкладанняў, таксама гэта камунікацыйная шына і "universal data plane", распрацаваны для вялікіх мікрасэрвісных архітэктур "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 існуе злучэнне ў пуле. Такім чынам, пулы злучэнняў HTTP/2 усталёўваюць толькі адно злучэнне для кожнага вонкавага хаста за раз, пры наяўнасці чатырох працоўных струменяў будзе чатыры злучэння HTTP/2 для кожнага вонкавага хаста ў стабільным стане. Захоўваючы ўсё ў адным працоўным струмені, амаль увесь код можа быць напісаны без блакіровак, як калі б ён быў аднаструменным. Калі працоўных струменяў вылучана больш чым неабходна, гэта можа прывесці да не рацыянальнага выкарыстання памяці, стварэнню вялікай колькасці прастойваюць злучэнняў і памяншэнні колькасці зваротаў злучэння зваротна ў пул.

Для атрымання дадатковай інфармацыі наведайце Envoy Proxy blog.

Канфігурацыя HTTP

Наступны блок канфігурацыі NGINX вызначае налады HTTP, такія як:

  • Якія mime тыпы падтрымліваюцца
  • Тайм-аўты па змаўчанні
  • Канфігурацыя Gzip

Вы можаце наладзіць гэтыя аспекты з дапамогай фільтраў у Envoy Proxy, што мы абмяркуем пазней.

Крок 3 – Канфігурацыя Server

У блоку канфігуравання 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 гэтым займаецца Filters.

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, Монго, TCP. Вы можаце знайсці поўны спіс у дакументацыі.

Для атрымання дадатковай інфармацыі аб іншых палітыках балансавання нагрузкі наведайце Дакументацыю Envoy.

Step 5 - Proxy and Upstream Configuration

У NGINX канфігурацыя upstream вызначае набор мэтавых сервераў, якія будуць апрацоўваць трафік. У гэтым выпадку два кластары былі прызначаны.

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

У Envoy гэта кіруецца кластарамі.

Envoy Clusters

Эквівалент upstream вызначаецца як кластары. У гэтым выпадку былі вызначаны хасты, якія будуць абслугоўваць трафік. Спосаб доступу да хастаў, напрыклад час чакання, вызначаецца як канфігурацыя кластара. Гэта дазваляе больш дакладна кантраляваць зярністасць такіх аспектаў, як час чакання і балансіроўка нагрузкі.

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

Пры выкарыстанні выяўлення службы STRICT_DNS Envoy будзе бесперапынна і асінхронна дазваляць паказаныя мэты DNS. Кожны вернуты IP-адрас у выніку DNS будзе лічыцца відавочным хастом ва ўзыходзячым кластары. Гэта азначае, што калі запыт вяртае два IP-адрасы, Envoy выкажа здагадку, што ў кластары ёсць два хасты, і абодва павінны быць збалансаваны па нагрузцы. Калі хост выдалены з выніку, Envoy мяркуе, што ён больш не існуе, і будзе адбіраць трафік з любых існуючых пулаў злучэнняў.

Для атрымання дадатковай інфармацыі см. Дакументацыю проксі-сервера Envoy.

Крок 6 - Доступ да часопіса і памылкі

Канчатковая канфігурацыя - рэгістрацыя. Замест таго, каб перадаваць часопісы памылак на дыск, Envoy Proxy выкарыстоўвае хмарны падыход. Усе часопісы прыкладанняў выводзяцца ў выбіты и цвярдзей.

Калі карыстачы робяць запыт, часопісы доступу з'яўляюцца неабавязковымі і па змаўчанні адключаныя. Каб уключыць часопісы доступу для запытаў HTTP, уключыце канфігурацыю доступ_журнал для дыспетчара падлучэнняў HTTP. Шлях можа быць альбо прыладай, такім як выбіты, альбо файлам на дыску, у залежнасці ад вашых патрабаванняў.

Наступная канфігурацыя перанакіруе ўсе часопісы доступу ў выбіты (нататка перакладніка — stdout неабходна для выкарыстання envoy усярэдзіне docker. Калі выкарыстаць без docker, то заменіце /dev/stdout на шлях да звычайнага лог-файла). Скапіюйце фрагмент у раздзел канфігурацыі для мэнэджара злучэнняў:

Copy to Clipboardaccess_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)%"}

Для атрымання дадатковай інфармацыі аб методыцы рэгістрацыі пасланніка, наведайце

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 няма даступных мэтавых адрасатаў для запыту. Наступная каманда запусціць серыю HTTP-сэрвісаў, якія адпавядаюць канфігурацыі, вызначанай для Envoy.

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 ёсць тэлеграм чат: https://t.me/envoyproxy_ru

Envoy Proxy няма падтрымкі раздачы статычнага змесціва. Таму хто можа прагаласуйце за feature: https://github.com/envoyproxy/envoy/issues/378

Толькі зарэгістраваныя карыстачы могуць удзельнічаць у апытанні. Увайдзіце, Калі ласка.

Ці падштурхнуў гэты пост ўсталяваць і пратэставаць envoy proxy?

  • ды

  • няма

Прагаласавалі 75 карыстальнікаў. Устрымаліся 18 карыстальнікаў.

Крыніца: habr.com

Дадаць каментар