Envoy proxy#
Envoy proxy - настраиваемый прокси-сервер, разработанный для микросервисной архитектуры со следующими основными функциями:
L4-L7 балансирование нагрузки;
динамическая маршрутизация;
управление трафиком между микросервисами.
Envoy proxy легко обрабатывает сложные сценарии маршрутизации и, при возникновении проблем с сетью и приложениями, оперативно определяет источник проблемы, а также может использоваться как обратный прокси-сервер для HTTP и TCP-трафика.
Envoy proxy - автономный процесс, который предназначен для работы на каждом сервере приложений. Все Envoy proxy образуют прозрачную коммуникационную сеть, в которой каждое приложение отправляет и получает сообщения на локальный хост и обратно, и не имеет доступа к топологии сети.
Преимущества такой внепроцессной архитектуры по сравнению с традиционным библиотечным подходом к взаимодействию между сервисами:
Envoy proxy работает с любым прикладным языком. Одно развертывание может объединить
Java,C++,Go,PHP,Pythonи т.д.;Envoy proxy быстро и прозрачно развертывается и обновляется во всей инфраструктуре, в отличие от сервис-ориентированных архитектур, для которых развертывание обновлений библиотек может быть длительным и трудоемким процессом.
Envoy proxy поддерживает:
функции сетевого проксирования уровня L3/L4. Подключаемый механизм цепочки фильтров позволяет создавать фильтры для выполнения различных задач прокси TCP/UDP и накладывать их на основной сервер. Существуют фильтры для поддержки различных задач, таких как необработанный TCP-прокси, UDP-прокси, HTTP-прокси, проверка подлинности сертификата клиента TLS, Redis, MongoDB, Postgres и т.д;
дополнительный уровень фильтра HTTP L7. HTTP-фильтры могут быть подключены к подсистеме управления HTTP-соединениями, которые выполняют различные задачи, такие как буферизация, ограничение скорости, маршрутизация/переадресация;
в режиме
HTTP Envoy- HTTP/1.1, HTTP/2, HTTP/3. Envoy proxy работает как прозрачный прокси-сервер с HTTP/1.1, HTTP/2 и HTTP/3 в исходящем и входящем потоке данных. Любая комбинация клиентов HTTP/1.1 и HTTP/2 и целевых серверов может быть объединена в мост;в режиме
HTTP Envoyподсистему маршрутизации, способную маршрутизировать и перенаправлять запросы на основе пути, полномочий, типа контента, значений времени выполнения и т. д. Функция востребована при использовании Envoy proxy в качестве Frontend или пограничного сервера прокси, а также при создании сервисной сетки;систему удаленного вызова процедур gRPC. gRPC - это платформа RPC, которая использует HTTP/2 или более позднюю версию в качестве базового мультиплексированного транспорта. Envoy поддерживает все функции HTTP/2;
обнаружение сервисов и динамическую конфигурацию. Использует многоуровневый набор API динамической конфигурации для централизованного управления. Уровни предоставляют Envoy proxy динамические обновления: о хостах в Backend-кластере, о Backend-кластерах, маршрутизации HTTP, прослушивающих сокетах и криптографическом материале. Для простого развертывания обнаружение серверного хоста может быть выполнено с помощью разрешения DNS, а дополнительные уровни заменены статическими файлами конфигурации;
функцию автоматической проверки работоспособности вышестоящих сервисных кластеров. Envoy proxy использует объединение информации об обнаружении сервисов и проверке работоспособности для определения объектов балансировки нагрузки. Envoy proxy также поддерживает пассивную проверку работоспособности с помощью подсистемы обнаружения выбросов;
методы балансировки нагрузки и осуществляет доступ к балансировке приложениям. Envoy proxy поддерживает автоматические повторные попытки подключения, отслеживание разрыва цепи, глобальное ограничение скорости посредством внешней службы ограничения скорости, теневое копирование запросов и обнаружение выбросов;
функции Frontend/пограничного проксирования: использование одного и того же программного обеспечения на периферии позволяет упростить наблюдаемость, управление, обеспечить идентичность алгоритмов обнаружения сервисов и балансировки нагрузки;
сбор статистики для всех подсистем.
Архитектура#
Envoy proxy использует единый процесс с многопоточной архитектурой.
Один основной поток управляет различными задачами координации, в то время как некоторое количество рабочих потоков выполняет прослушивание, фильтрацию и пересылку.
Как только слушатель принимает соединение, оно остается привязанным к одному рабочему потоку. Это позволяет большинству экземпляров Envoy proxy быть в основном однопоточными, что приводит к трудностям распараллеливания, с небольшим количеством сложной координации обработки кода между рабочими потоками.
Балансировка подключений слушателя#
По умолчанию координация между рабочими потоками отсутствует. Это означает, что все рабочие потоки независимо пытаются принимать соединения от каждого слушателя и полагаются на ядро для выполнения надлежащей балансировки между потоками. Envoy proxy позволяет настраивать различные типы балансировки подключений для каждого слушателя.
TCP#
Каждый слушатель независимо настраивается с помощью filter_chains, где отдельная цепочка фильтров выбирается на основе критериев соответствия filter_chain_match.
Отдельная цепочка фильтров состоит из одного или нескольких фильтров сетевого уровня (L3/L4).
Когда слушатель получает новое соединение, выбирается соответствующая цепочка filter_chain, и создается экземпляр настроенного стека фильтров connection-local, который начинает обрабатывать последующие события.
Фильтры слушателя#
Фильтры слушателя Envoy proxy могут использоваться для манипулирования метаданными соединения.
Основная цель фильтров слушателя - упростить добавление дополнительных функций системной интеграции, не требуя внесения изменений в основные функциональные возможности Envoy proxy, а также сделать взаимодействие между несколькими такими функциями более понятным.
API для фильтров слушателей относительно прост, поскольку в конечном итоге эти фильтры работают с вновь принятыми сокетами.
Фильтры в цепочке могут останавливать и впоследствии продолжать итерацию для других фильтров. Это позволяет использовать более сложные сценарии, такие как вызов службы, ограничивающей скорость, и т.д.
Цепочки фильтров#
Сетевые фильтры объединяются в упорядоченный список FilterChain.
У каждого слушателя может быть несколько цепочек фильтров и необязательная default_filter_chain.
При получении запроса используется цепочка фильтров с наиболее подходящими критериями соответствия параметров запроса.
Сценарий развертывания#
Сценарий развертывания Envoy proxy в качестве балансировщика нагрузки перед службой:
Создайте сервис
headless serviceсо следующим yaml:apiVersion: v1 kind: Service metadata: name: myapp spec: clusterIP: None ports: - name: HTTP port: 80 targetPort: HTTP protocol: TCP selector: app: myappPods имеют метку
appсос именемmyapp.Сервис
headless serviceне предоставляет один IP-адрес и балансировку нагрузки для pods, имеет конфигурацию DNS с IP-адресом для всех pods, соответствующих селектору меток. Этот тип службы предназначен для использования в сценариях реализации балансировки нагрузки и самостоятельной поддержки соединения с pods.Проверьте записи DNS для сервиса внутри кластера DropApp:
nslookup myapp Server: 00.00.0.00 Address: 00.00.0.10#53 Non-authoritative answer: Name: myapp.namespace.svc.cluster.local Address: 000.000.000.000 Name: myapp.namespace.svc.cluster.local Address: 000.000.000.000 Name: myapp.namespace.svc.cluster.local Address: 000.000.000.000Примечание
IP адреса являются ненастоящими и приведены в качестве примера.
В приведенном сценарии выведены отдельные записи с IP-адресами для трех pods в сводке DNS.
Примените файл манифеста, выполните команду:
kubectl apply -f ./dapp-envoy-proxy-deployment.yamlСодержание манифеста будет следующим:
dapp-envoy-proxy-deployment.yaml
apiVersion: v1 kind: ConfigMap metadata: name: app-test-configmap labels: app: app-test-envoy data: envoy.yaml: | # Простая завершающая конфигурация Sidecar Envoy TLS 1.2. static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 8080 filter_chains: - filters: - name: envoy.filters.network.HTTP_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.HTTP_connection_manager.v3.HTTPConnectionManager codec_type: AUTO stat_prefix: ingress_HTTP route_config: name: local_route virtual_hosts: - name: service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: local_service_app } HTTP_filters: - name: envoy.filters.HTTP.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: local_service_app connect_timeout: 0.25s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: local_service_app endpoints: - lb_endpoints: - endpoint: address: socket_address: address: app-test-service.default.svc.cluster.local port_value: 80 admin: access_log_path: /dev/null address: socket_address: address: 0.0.0.0 port_value: 8082Флаг
type: STRICT_DNSуказывает тип обнаружения службы.Флаг
lb_policy: LEAST_REQUESTпозволяет выбрать различные алгоритмы балансировки из типовROUND_ROBINиLEAST_REQUEST.Флаг
hosts: [{ socket_address: { address: myapp, port_value: 80 }}]указывает в полеaddressна доменное имя, с которого Envoy proxy должен получить записи для маршрутизации.Убедитесь в том, что deployment успешно получен:
kubectl rollout status deployment.apps/sidecar-test-deploy -n defaultВнесите содержание манифестов:
Ниже приведен фрагмент кода YAML-файла для развертывания приложения с названием app-test с тремя репликами. В этом приложении используется образ Docker nginx, и контейнер имеет порт HTTP на порту 80.
apiVersion: apps/v1 kind: Deployment metadata: name: app-test-deploy labels: app: app-test spec: replicas: 3 selector: matchLabels: app: app-test template: metadata: name: app-test-pod labels: app: app-test spec: containers: # Приложение было спроксировано. - name: app-test image: "nginx:1.14.2" ports: - name: http containerPort: 80 protocol: TCPНиже представлен фрагмент кода из YAML-файла, который описывает кластерную службу для приложения app-test. Служба предоставляет доступ к приложению через порт 80 и имеет тип ClusterIP, что означает, что она доступна только внутри кластера. В файле также указаны метки и селектор для службы, которые позволяют ей быть найденной и управляемой в DropApp.
apiVersion: v1 kind: Service metadata: name: app-test-envoy-service labels: app: app-test-envoy spec: type: NodePort selector: app: app-test-envoy ports: - port: 8080 targetPort: 8080 nodePort: 3000Ниже приведен фрагмент кода YAML-файла для развертывания приложения envoy. Приложение использует образ Docker с именем example и контейнером app-test-envoy. Контейнер имеет один порт HTTP, который настроен на прослушивание на порту 8080. Контейнер также использует файл конфигурации
/etc/envoy, который хранится в конфигурации DropApp.example-app-test-envoy.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: sidecar-test-deploy labels: app: sidecar-test spec: selector: matchLabels: app: sidecar-test template: metadata: name: sidecar-test-pod labels: app: sidecar-test spec: containers: # The application being proxied. - name: app image: "nginx:1.14.2" ports: - name: http containerPort: 80 protocol: TCP # The sidecar. - name: sidecar image: dappregistry/envoy:distroless-v1.25.2 ports: - name: http containerPort: 8080 protocol: TCP volumeMounts: - name: sidecar-config mountPath: "/etc/envoy" readOnly: true volumes: - name: app-config configMap: name: sidecar-test-configmapНиже представлена конфигурация для Envoy, которая используется для обработки запросов к серверу.
Где:
apiVersionуказывает на версию API, на которую должна соответствовать конфигурация. В данном случае это v1;kindуказывает на тип объекта конфигурации. В данном случае это ConfigMap;metadataсодержит информацию о конфигурации, такую как имя и метки;dataсодержит содержимое конфигурации, в данном случае файлenvoy.yaml;static_resources- это раздел конфигурации, который определяет статические ресурсы, такие как фильтры и слушатели;listeners- это список слушателей, которые обрабатывают запросы. Каждый слушатель определяет адрес, на который будет отправлен запрос, и настройки фильтрации;filter_chains- это раздел, который определяет, какие фильтры должны быть применены к запросу. В данном примере используется фильтр Envoy для обработки HTTP-запросов;nameиtyped_configопределяют параметры фильтра;route_config- это раздел, определяющий маршрутизацию запросов;domains- это список доменов, к которым будет применяться маршрутизация;routes- это список маршрутов, которые будут применены к запросам. Каждый маршрут определяет префикс запроса, который должен соответствовать, и действия, которые должны быть выполнены.
В целом, данная конфигурация определяет настройки Envoy для обработки запросов к серверу, который расположен на адресе 0.0.0.0 и прослушивает порт 8080.
Настройки Envoy для обработки запросов к серверу
apiVersion: v1 kind: ConfigMap metadata: name: sidecar-test-configmap labels: app: sidecar-test data: envoy.yaml: | static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 8080 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager codec_type: AUTO stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: local_service } http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: local_service connect_timeout: 0.25s type: STATIC lb_policy: ROUND_ROBIN load_assignment: cluster_name: local_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 80 admin: access_log_path: /dev/null address: socket_address: address: 0.0.0.0 port_value: 8082Перенаправьте существующий порт на локальный:
kubectl port-forward service/sidecar-test-service -n default --address localhost 8099:8080Введите команду для просмотра локального порта:
Curl localhost:8099Проверьте, что на выходные данные возвращают страницу
nginxа прокси-сервер является Envoy proxy.