---
title: "Аддон Envoy Gateway для Kubernetes"
description: "Аддон Envoy Gateway для Kubernetes. Установка, настройка, примеры использования. Документация и инструкции по работе с облачными сервисами Timeweb Cloud."
---

# Envoy Gateway

> Полный индекс документации для ИИ-агентов: [llms.txt](https://timeweb.cloud/llms.txt).

Envoy Gateway — это контроллер Gateway API для Kubernetes, который использует Envoy Proxy для обработки входящего трафика. С его помощью можно публиковать HTTP, HTTPS, gRPC, TCP и UDP-сервисы, настраивать маршрутизацию по доменам и путям, управлять TLS и применять политики трафика через стандартные Kubernetes-ресурсы.

Gateway API можно рассматривать как развитие Ingress. Вместо одного ресурса Ingress используются несколько объектов с разными зонами ответственности:

-   `GatewayClass` — указывает, какой контроллер будет обслуживать шлюзы.
    
-   `Gateway` — описывает точку входа: порты, протоколы и TLS-настройки.
    
-   `HTTPRoute` — задает правила маршрутизации HTTP-трафика к сервисам.
    
-   `GRPCRoute`, `TCPRoute`, `UDPRoute`, `TLSRoute` — используются для других типов трафика.
    

Envoy Gateway отслеживает эти ресурсы и на их основе создает Envoy Proxy, который принимает внешний трафик и направляет его к сервисам внутри кластера.

## Установка

Для установки Envoy Gateway откройте панель управления кластером, перейдите во вкладку «Дополнения» и выберите Envoy Gateway.

В открывшемся мастере установки можно оставить параметры по умолчанию или включить продвинутую установку и изменить `values.yaml`. Для начала работы достаточно настроек по умолчанию.

Нажмите «Установить» и дождитесь завершения установки. После этого проверьте, что поды Envoy Gateway запущены:

```bash
kubectl get pods -n envoy-gateway-system
```

Все поды должны находиться в статусе `Running`.

Также можно проверить, что в кластере появились ресурсы Gateway API:

```shell
kubectl api-resources | grep gateway.networking.k8s.io
```

## Пример использования

Рассмотрим пример, в котором Envoy Gateway будет принимать HTTP-трафик на одном внешнем IP-адресе и направлять запросы в два разных сервиса:

-   `http://app.example.com/service1` — в сервис `service1`;
    
-   `http://app.example.com/service2` — в сервис `service2`.
    

Для примера создадим отдельный неймспейс:

```bash
kubectl create namespace envoy-example
```

### Создание ConfigMap

Создайте файл `configmap.yaml` с HTML-страницами для двух сервисов:

```shell
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-pages
  namespace: envoy-example
data:
  service1.html: |
    <html>
      <head><title>Service 1</title></head>
      <body><h1>Service 1</h1></body>
    </html>
  service2.html: |
    <html>
      <head><title>Service 2</title></head>
      <body><h1>Service 2</h1></body>
    </html>
```

Примените манифест:

```bash
kubectl apply -f configmap.yaml
```

### Создание Deployment и Service

Создайте файл `service1.yaml`:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: service1
  namespace: envoy-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service1
  template:
    metadata:
      labels:
        app: service1
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          configMap:
            name: nginx-pages
            items:
              - key: service1.html
                path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service1
  namespace: envoy-example
spec:
  selector:
    app: service1
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: ClusterIP
```

Создайте файл `service2.yaml`:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: service2
  namespace: envoy-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service2
  template:
    metadata:
      labels:
        app: service2
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          configMap:
            name: nginx-pages
            items:
              - key: service2.html
                path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service2
  namespace: envoy-example
spec:
  selector:
    app: service2
  ports:
    - name: http
      port: 80
      targetPort: 80
  type: ClusterIP
```

Примените манифесты:

```bash
kubectl apply -f service1.yaml 
kubectl apply -f service2.yaml
```

Проверьте, что поды запущены:

```bash
kubectl get pods -n envoy-example
```

### Создание GatewayClass

`GatewayClass` связывает Gateway API с контроллером Envoy Gateway. Создайте файл `gatewayclass.yaml`:

```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: envoy-gateway
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
```

Примените манифест:

```bash
kubectl apply -f gatewayclass.yaml
```

Проверьте статус:

```bash
kubectl get gatewayclass envoy-gateway
```

В колонке `ACCEPTED` должно быть значение `True`. Это означает, что Envoy Gateway принял `GatewayClass` и будет обслуживать связанные с ним ресурсы `Gateway`.

### Создание Gateway

Gateway описывает внешний вход в приложение. Создайте файл `gateway.yaml`:

```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: app-gateway
  namespace: envoy-example
spec:
  gatewayClassName: envoy-gateway
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same
```

Примените манифест:

```bash
kubectl apply -f gateway.yaml
```

Когда `Gateway` будет создан, Envoy Gateway развернет Envoy Proxy и балансировщик нагрузки. Создание балансировщика можно отследить [в панели управления](https://timeweb.cloud/my/balancer) или проверить командой:

```bash
kubectl get gateway app-gateway -n envoy-example
```

Дождитесь, когда в колонке `PROGRAMMED` появится значение `True`, а в колонке `ADDRESS` — внешний IP-адрес.

Также можно посмотреть созданный сервис:

```bash
kubectl get svc -n envoy-gateway-system \
  -l gateway.envoyproxy.io/owning-gateway-namespace=envoy-example,gateway.envoyproxy.io/owning-gateway-name=app-gateway
```

Envoy Gateway по умолчанию создает балансировщик для каждого `Gateway`. Поэтому отдельный манифест `Service` типа `LoadBalancer`, как в классическом сценарии с Ingress-контроллером, не требуется.

### Создание HTTPRoute

HTTPRoute задает правила маршрутизации. Создайте файл `httproute.yaml`:

```yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: envoy-example
spec:
  parentRefs:
    - name: app-gateway
  hostnames:
    - app.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /service1
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
      backendRefs:
        - name: service1
          port: 80
    - matches:
        - path:
            type: PathPrefix
            value: /service2
      filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
      backendRefs:
        - name: service2
          port: 80
```

Примените манифест:

```bash
kubectl apply -f httproute.yaml
```

Проверьте, что маршрут принят:

```bash
kubectl get httproute app-route -n envoy-example -o yaml
```

В статусе ресурса должно быть:

```bash
status: "True" type: Accepted
```

В этом манифесте `HTTPRoute` принимает запросы с доменом `app.example.com` и направляет их в разные сервисы по префиксу пути. Фильтр `URLRewrite` заменяет префиксы `/service1` и `/service2` на `/`, чтобы Nginx внутри каждого сервиса отдавал свою главную страницу.

### Проверка работы

Получите внешний IP-адрес Gateway:

```bash
kubectl get gateway app-gateway -n envoy-example
```

Пропишите этот IP-адрес в DNS-настройках домена app.example.com в виде A-записи. После обновления DNS проверьте доступность сервисов:

```bash
curl http://app.example.com/service1
curl http://app.example.com/service2
```

Если DNS еще не обновился, можно выполнить проверку по IP-адресу, передав заголовок `Host`:

```bash
curl -H "Host: app.example.com" http://<EXTERNAL_IP>/service1
curl -H "Host: app.example.com" http://<EXTERNAL_IP>/service2
```

В ответе должны отображаться страницы `Service 1` и `Service 2`.

### Удаление примера

Чтобы удалить ресурсы, созданные в примере, выполните:

```bash
kubectl delete namespace envoy-example
kubectl delete gatewayclass envoy-gateway
```

Дополнение Envoy Gateway при этом останется установленным в кластере. Удалить его можно во вкладке «Дополнения» в панели управления кластером.

## Миграция с Nginx Ingress на Envoy Gateway

Envoy Gateway можно развернуть рядом с Nginx Ingress и переносить маршруты постепенно. Такой подход позволяет сначала проверить ресурсы Gateway API на отдельном внешнем IP-адресе, а затем переключить DNS-записи или трафик на новый Gateway.

Для автоматической конвертации Ingress-ресурсов можно использовать утилиту [ingress2gateway](https://github.com/kubernetes-sigs/ingress2gateway). Она читает существующие Ingress-ресурсы из кластера и выводит эквивалентные ресурсы Gateway API: `Gateway`, `HTTPRoute` и другие объекты.

> [!NOTE]
> ingress2gateway помогает подготовить миграцию, но не заменяет ручную проверку. Некоторые аннотации Nginx Ingress могут быть не поддержаны или потребовать ручной настройки после конвертации.

### Требования

Перед миграцией подготовьте кластер:

-   установите Envoy Gateway;
    
-   [создайте GatewayClass](https://timeweb.cloud/docs/k8s/addons/envoy-gateway#sozdanie-gateway) для Envoy Gateway;
    
-   проверьте, что исходные Ingress-ресурсы работают через Nginx Ingress.
    

Проверьте, что в кластере есть нужные классы:

```bash
kubectl get ingressclass
kubectl get gatewayclass
```

В выводе должны быть:

-   `IngressClass` с именем `nginx`;
    
-   `GatewayClass` с именем `envoy-gateway`.
    

### Установка ingress2gateway

Если на локальной машине установлен Go, установите ingress2gateway командой:

```bash
go install github.com/kubernetes-sigs/ingress2gateway@v1.0.0
```

После установки бинарный файл будет доступен в директории `$(go env GOPATH)/bin`. Убедитесь, что эта директория добавлена в `PATH`.

Также можно установить ingress2gateway через Homebrew:

```bash
brew install ingress2gateway
```

Или скачать готовый бинарный файл со страницы [релизов проекта](https://github.com/kubernetes-sigs/ingress2gateway/releases).

### Исходный пример

В примере ниже миграция выполняется для приложения, которое уже опубликовано через Nginx Ingress.

В кластере есть неймспейс `ingress-migration-demo`. В нем находятся:

-   Ingress `migration-source`;
    
-   Service `service1` и `service2`;
    
-   два правила маршрутизации для домена `ingress-migration.example.com`:
    

-   `/service1` направляет трафик в `service1`;
    
-   `/service2` направляет трафик в `service2`.
    

Проверьте исходный Ingress:

```bash
kubectl get ingress -n ingress-migration-demo
```

В колонке `CLASS` должно быть значение `nginx`.

### Конвертация Ingress-ресурсов

Чтобы сконвертировать этот Ingress в ресурсы Gateway API, выполните:

```bash
ingress2gateway print \
 --providers=ingress-nginx \
 --emitter=envoy-gateway \
 --ingress-nginx-ingress-class=nginx \
 --namespace=ingress-migration-demo > gateway-migration.yaml
```

В этой команде:

-   `print` — режим, в котором ingress2gateway выводит сгенерированные ресурсы в стандартный вывод. За счет перенаправления `>` результат сохраняется в файл `gateway-migration.yaml`.
    
-   `--providers=ingress-nginx` — указывает тип исходного Ingress-контроллера. В этом примере исходные маршруты обслуживает Nginx Ingress, поэтому используется значение `ingress-nginx`.
    
-   `--emitter=envoy-gateway` — указывает, для какого Gateway API-контроллера подготовить результат. В этом примере целевой контроллер — Envoy Gateway.
    
-   `--ingress-nginx-ingress-class=nginx` — выбирает только Ingress-ресурсы класса `nginx`. Такой класс создает аддон Nginx Ingress в Timeweb Cloud.
    
-   `--namespace=ingress-migration-demo` — ограничивает чтение ресурсов неймспейсом `ingress-migration-demo`, где находится исходный Ingress из примера.
    

Откройте файл `gateway-migration.yaml` и проверьте сгенерированные ресурсы перед применением.

Проверьте `gatewayClassName` у ресурса `Gateway`. ingress2gateway может сгенерировать это значение на основе имени исходного `IngressClass`. Например, если исходный Ingress использует класс `nginx`, в сгенерированном Gateway может появиться:

```yaml
spec:
 gatewayClassName: nginx
```

Envoy Gateway не будет обрабатывать такой `Gateway`, если в кластере нет `GatewayClass` с именем `nginx`. Для `GatewayClass` из примера замените значение на `envoy-gateway`:

```yaml
spec:
 gatewayClassName: envoy-gateway
```

### Применение ресурсов Gateway API

После проверки примените файл:

```bash
kubectl apply -f gateway-migration.yaml
```

Проверьте, что Gateway создан и получил внешний IP-адрес:

```bash
kubectl get gateway -A
```

### Тестирование перед переключением трафика

Пока DNS-записи указывают на старый Nginx Ingress, новый Gateway можно проверить по внешнему IP-адресу с заголовком `Host`:

```bash
curl -H "Host: app.example.com" http://<EXTERNAL_IP>/<path>
```

Где:

-   `app.example.com` — домен из `HTTPRoute`;
    
-   `<EXTERNAL_IP>` — IP-адрес нового Gateway;
    
-   `<path>` — путь, который должен обрабатываться маршрутом.
    

Сравните ответы старого Ingress и нового Gateway.

Если все работает корректно, можно изменить DNS-записи на IP нового балансировщика.
