Envoy — это сервисный прокси с открытым исходным кодом, специально разработанный для облачных приложений. Он обладает широким набором функций, таких как пул соединений, механизм повторных попыток, управление TLS, сжатие, проверка работоспособности, устранение ошибок, ограничение скорости, авторизация и т.д.. Они достигаются с помощью встроенных http-фильтров. И сегодня я расскажу о специальном фильтре, который называется WASM Filter.
Эта статья не предназначена для объяснения того, что такое WASM, поэтому я пропущу объяснение WASM и добавлю ресурсы для этого в конце статьи.
- Почему мы используем WASM-фильтр
- Написание WASM в Go
- mstrYoda / envoy-proxy-wasm-filter-golang
- Фильтр WASM для Envoy Proxy, написанный на языке Golang
- envoy-proxy-wasm-filter-golang
- Сборка
- Запуск Envoy Proxy в Docker с помощью WASM-фильтра
- Ресурсы
- WebAssembly | MDN
- Модули Wasm и расширяемость Envoy, часть 1 — Новый стек
- tetratelabs / proxy-wasm-go-sdk
- WebAssembly для прокси (Go SDK)
- WebAssembly для прокси (Go SDK)
- Начало работы
- Требования
- Установка
Почему мы используем WASM-фильтр
В Trendyol Tech. Мы используем Istio в качестве сетки сервисов. В обязанности нашей команды (DevX) входит улучшение опыта разработчиков путем разработки приложений, отвечающих общим требованиям микросервисов, таким как кэширование, авторизация, ограничение скорости, межкластерное обнаружение сервисов и т. д.
Поскольку мы уже используем Istio, почему бы не воспользоваться преимуществами расширяемости Envoy Proxy.
Наш сценарий использования — получение JWT-токена для микросервиса, который идентифицирует приложение микросервиса. Когда мы хотим избежать того, чтобы каждая команда писала один и тот же код на разных языках, мы можем создать WASM Filter и внедрить его в Envoy Proxy.
Преимущества фильтров WASM:
- Позволяют писать код на любом языке, который поддерживает WASM.
- Динамическая загрузка кода в Envoy
- Код WASM изолирован от Envoy, поэтому сбои в WASM не влияют на Envoy.
В Envoy Proxy есть рабочие потоки, которые обрабатывают входящие запросы. Каждый рабочий поток имеет свою собственную виртуальную машину WASM. Поэтому если вы пишете операционный код, основанный на времени, он работает отдельно для каждого потока.
В Envoy Proxy каждый рабочий поток изолирован друг от друга и имеет одну или несколько WASM VM. Существует также концепция под названием WASM Service для межпотоковых коммуникаций и обмена данными (мы не будем ее рассматривать).
Написание WASM в Go
Мы будем использовать tetratelabs/proxy-wasm-go-sdk для написания WASM в Go. Нам также понадобится TinyGo, чтобы собрать наш Go-код как WASM.
Наш сценарий использования очень прост, поэтому мы напишем код, который отправляет запрос на JWT Api каждые 15 секунд. Он извлекает заголовок авторизации, устанавливает его значение в глобальную переменную и помещает это значение в заголовок ответа каждого входящего запроса. Мы также устанавливаем значение «hello from wasm» в другой заголовок под названием «x-wasm-filter».
В функции OnTick мы выполняем http-вызов к службе, известной в Envoy как кластер.
Давайте соберем наш go-код как WASM:
tinygo build -o optimized.wasm -scheduler=none -target=wasi ./main.go
Теперь нам нужно настроить Envoy Proxy на использование WASM Filter для входящих запросов. Мы определим правило маршрутизации и WASM-фильтр для нашего WASM-кода, а также определим кластер, который представляет наш сервис.
Я поместил все файлы в одну директорию. Теперь давайте запустим Envoy Proxy в Docker:
docker run -it — rm -v "$PWD"/envoy.yaml:/etc/envoy/envoy.yaml -v "$PWD"/optimized.wasm:/etc/envoy/optimized.wasm -p 9901:9901 -p 10000:10000 envoyproxy/envoy:v1.17.0
Как мы видим из логов, наш WASM-фильтр начал работать и отправлять запрос на JWT Api каждые 15 секунд.
Теперь давайте отправим запрос на Envoy Proxy. Мы настроим Envoy на прослушивание входящих запросов с 1000 порта и запустим наш контейнер с отображением портов. Таким образом, мы можем отправить запрос на localhost:10000:
В заголовках ответа мы видим значения «x-wasm-filter: hello from wasm» и «x-auth».
Спасибо, что дочитали до этого момента. Надеюсь, это даст вам представление о том, как и зачем использовать WASM в Envoy Proxy.
Полный пример вы можете посмотреть на github:
mstrYoda / envoy-proxy-wasm-filter-golang
Фильтр WASM для Envoy Proxy, написанный на языке Golang
envoy-proxy-wasm-filter-golang
WASM-фильтр для Envoy Proxy, написанный на языке Golang
Сборка
tinygo build -o optimized.wasm -scheduler=none -target=wasi ./main.go
Запуск Envoy Proxy в Docker с помощью WASM-фильтра
docker run -it --rm -v "$PWD"/envoy.yaml:/etc/envoy/envoy.yaml -v "$PWD"/optimized.wasm:/etc/envoy/optimized.wasm -p 9901:9901 -p 10000:10000 envoyproxy/envoy:v1.17.0
Ресурсы

WebAssembly | MDN
WebAssembly — это новый тип кода, который может быть запущен в современных веб-браузерах. Это низкоуровневый ассемблероподобный язык с компактным двоичным форматом, который работает с производительностью, близкой к нативной, и предоставляет таким языкам, как C/C++, C# и Rust, возможность компиляции, чтобы они могли работать в Интернете. Он также разработан для работы вместе с JavaScript, позволяя обоим работать вместе.


Модули Wasm и расширяемость Envoy, часть 1 — Новый стек
Если вы когда-либо задавались вопросом, что такое WebAssembly (Wasm) и как он вписывается в экосистему сервисной сетки, то вам стоит прочитать именно эту статью.

tetratelabs / proxy-wasm-go-sdk
WebAssembly для прокси (Go SDK)
Этот проект находится на ранней стадии, и API, скорее всего, будет меняться и не будет стабильным.
WebAssembly для прокси (Go SDK)

Go SDK дляProxy-Wasm, позволяющий разработчикам писать плагины Proxy-Wasm в GoЭтот SDK работает на TinyGo и не поддерживает официальный компилятор Go.
Начало работы
- каталог examples содержит коды примеров поверх этого SDK.
- OVERVIEW.md обзор Proxy-Wasm, API этого SDK, и вещи, которые вы должны знать при написании плагинов.
Требования
- Go 1.17 или выше.
- TinyGo — Этот SDK зависит от TinyGo и использует его WASI (WebAssembly System Interface) цель. Пожалуйста, следуйте официальной инструкции здесь для установки TinyGo.
- Envoy — Для запуска скомпилированных примеров вам необходимо иметь бинарный файл Envoy. Мы рекомендуем использовать func-e как самый простой способ начать работу с Envoy. Также вы можете следовать официальной инструкции.
Установка
go get
не может быть использован…
Вы можете следить за мной на:
Github