Привіт, Хабре! Пропоную вашій увазі переклад посту:
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
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 зазвичай мають три ключові елементи:
- Налаштування сервера NGINX, структури журналів та функціональності Gzip. Це визначається глобально у всіх випадках.
- Налаштування NGINX для прийому запитів на хост one.example.com порту 8080.
- Налаштування цільового розташування, як обробляти трафік для різних частин 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 створює робочий потік кожного апаратного потоку у системі. Кожен робочий потік виконує неблокуючий цикл подій, який відповідає за
- Прослуховування кожного слухача (listener)
- Прийняття нових підключень
- Створення набору фільтрів для з'єднання
- Обробка всіх операцій введення-виведення за час існування з'єднання.
Вся подальша обробка з'єднання повністю обробляється у робочому потоці, включаючи будь-яку поведінку переадресації.
Для кожного робочого потоку Envoy існує з'єднання в пулі. Таким чином, пули з'єднань HTTP/2 встановлюють лише одне з'єднання для кожного зовнішнього хоста за раз, за наявності чотирьох робочих потоків буде чотири з'єднання HTTP/2 для кожного зовнішнього хоста в стабільному стані. Зберігаючи все в одному робочому потоці, майже весь код може бути написаний без блокувань, ніби він був однопотоковим. Якщо робочих потоків виділено більше ніж необхідно, це може призвести до не раціонального використання пам'яті, створення великої кількості з'єднань, що простоюють, і зменшення кількості повернення з'єднання назад в пул.
Для отримання додаткової інформації відвідайте
Конфігурація 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 }
Немає необхідності визначати ім'я_сервера, тому що фільтри 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. Ви можете знайти повний список у
Для отримання додаткової інформації про інших політик балансування навантаження відвідайте
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 припускає, що він більше не існує, і відбиратиме трафік з будь-яких існуючих пулів з'єднань.
Для отримання додаткової інформації см.
Крок 6 - Доступ до журналу та помилки
Остаточна конфігурація - реєстрація. Замість того, щоб передавати журнали помилок на диск, Envoy Proxy використовує хмарний підхід. Усі журнали програм виводяться в stdout и stderr.
Коли користувачі запитують, журнали доступу є необов'язковими і за замовчуванням вимкнені. Щоб увімкнути журнали доступу для запитів HTTP, увімкніть конфігурацію access_log для диспетчера з'єднань HTTP. Шлях може бути пристроєм, таким як stdout, або файл на диску, залежно від ваших вимог.
Наступна конфігурація перенаправить усі журнали доступу до stdout (Примітка перекладача - 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)%"}
Для отримання додаткової інформації про методику реєстрації посланця, відвідайте
Ведення журналу – не єдиний спосіб отримати уявлення про роботу з 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 ви можете знайти на сайті
За замовчуванням у 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 є телеграм чат:
Envoy Proxy не має підтримки роздачі статичного вмісту. Тому хтось може проголосуйте за feature:
Тільки зареєстровані користувачі можуть брати участь в опитуванні.
Чи спонукав цей пост встановити і протестувати envoy proxy?
-
да
-
немає
Проголосували 75 користувачів. Утрималися 18 користувачів.
Джерело: habr.com