Стадия жизненного цикла модуля: Preview
У модуля есть требования для установки
В этом разделе приведены базовые примеры публикации приложений через модуль alb.
Публикация приложения через объект ClusterALBInstance
Этот сценарий предполагает, что объект ClusterALBInstance уже создан администратором кластера и перешёл в состояние Ready. Имя и неймспейс управляемого объекта Gateway нужно взять из поля status объекта ClusterALBInstance.
Затем создайте объект ListenerSet, который будет привязан к нужному Gateway (параметр spec.parentRef.name) и объекты (маршруты) HTTPRoute для маршрутизации входящих запросов к приложению. Пример:
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: app-listeners
namespace: prod
spec:
parentRef:
name: public-gw # Имя объекта Gateway из status ClusterALBInstance, предоставленное администратором.
namespace: d8-alb
listeners:
- name: app-http
port: 80 # Для HTTP трафика необходимо указывать 80 порт.
protocol: HTTP
hostname: app.example.com
- name: app-https
port: 443 # Для HTTPS трафика необходимо указывать 443 порт.
protocol: HTTPS
hostname: app.example.com
tls:
mode: Terminate
certificateRefs:
- name: app-tls # Наименование секрета, содержащего необходимый TLS-сертификат.
namespace: prod
---
# Маршрут для HTTP-трафика
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-http-route
namespace: prod
spec:
parentRefs:
- name: app-listeners # Имя ListenerSet.
namespace: prod
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: app-http
port: 80
hostnames:
- app.example.com
rules:
- backendRefs:
- name: app-svc # Наименование сервиса приложения.
port: 8080
---
# Маршрут для HTTPS-трафика
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-https-route
namespace: prod
spec:
parentRefs:
- name: app-listeners # Имя ListenerSet.
namespace: prod
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: app-https
port: 443
hostnames:
- app.example.com
rules:
- backendRefs:
- name: app-svc # Наименование сервиса приложения
port: 8080Публикация приложения через объект ALBInstance
В этом сценарии объекты ALBInstance, Gateway, ListenerSet и HTTPRoute находятся в одном неймспейсе.
Для публикации приложения через объект ALBInstance выполните следующие действия:
-
Создайте объект ALBInstance с учетом необходимых настроек:
apiVersion: network.deckhouse.io/v1alpha1 kind: ALBInstance metadata: name: app-gw namespace: prod spec: gatewayName: app-gw inlet: type: LoadBalancer -
После того как объект ALBInstance перейдёт в состояние
Ready, создайте объекты ListenerSet и HTTPRoute:apiVersion: gateway.networking.k8s.io/v1 kind: ListenerSet metadata: name: app-listeners namespace: prod spec: parentRef: name: app-gw # Имя объекта Gateway из поля status ALBInstance. namespace: prod listeners: - name: app-https port: 443 # Для HTTPS трафика необходимо указывать 443 порт. protocol: HTTPS hostname: app.example.com tls: mode: Terminate certificateRefs: - name: app-tls # Наименование секрета содержащего необходимый TLS-сертификат. namespace: prod --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: app-route namespace: prod spec: parentRefs: - name: app-listeners # Имя ListenerSet. namespace: prod kind: ListenerSet group: gateway.networking.k8s.io sectionName: app-https port: 443 hostnames: - app.example.com rules: - backendRefs: - name: app-svc # Наименование сервиса приложения. port: 8080
Объекты GRPCRoute, TLSRoute и TCPRoute
Объект GRPCRoute предназначен для маршрутизации gRPC-трафика. Для него создаётся объект ListenerSet со слушателем HTTPS, а затем добавляется объект GRPCRoute:
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: grpc-listeners
namespace: prod
spec:
parentRef:
name: app-gw # Имя объекта Gateway из поля status ALBInstance.
namespace: prod
listeners:
- name: grpc-https
port: 443 # Для HTTPS трафика необходимо указывать 443 порт.
protocol: HTTPS
hostname: grpc.example.com
tls:
mode: Terminate
certificateRefs:
- name: grpc-tls # Наименование секрета содержащего необходимый TLS-сертификат.
namespace: prod
---
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
name: grpc-route
namespace: prod
spec:
parentRefs:
- name: grpc-listeners # Имя ListenerSet.
namespace: prod
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: grpc-https
port: 443
hostnames:
- grpc.example.com
rules:
- backendRefs:
- name: grpc-svc # Наименование сервиса приложения.
port: 9090Для TLS passthrough, когда расшифровка трафика должна выполняться на стороне приложения, можно использовать либо TLS listener, либо HTTPS listener. Ниже показан вариант с TLS listener:
Дополнительно настройте в ALBInstance параметр additionalPorts для добавления TCP-обработчика:
apiVersion: network.deckhouse.io/v1alpha1
kind: ALBInstance
metadata:
name: app-gw
namespace: prod
spec:
gatewayName: app-gw
inlet:
type: LoadBalancer
additionalPorts:
- port: 8443 # Дополнительный TCP-порт для TLS-трафика.
protocol: TCPДалее настройте объекты ListenerSet и TLSRoute:
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: tls-pass-listeners
namespace: prod
spec:
parentRef:
name: app-gw # Имя объекта Gateway из поля status ALBInstance.
namespace: prod
listeners:
- name: tls-pass
port: 8443 # В данном примере для TLS трафика переиспользуется порт 8443.
protocol: TLS
hostname: pass.example.com
tls:
mode: Passthrough # Режим TLS - сквозной.
---
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: TLSRoute
metadata:
name: tls-pass-route
namespace: prod
spec:
parentRefs:
- name: tls-pass-listeners # Имя ListenerSet.
namespace: prod
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: tls-pass
port: 8443 # В данном примере для TLS трафика переиспользуется порт 8443.
hostnames:
- pass.example.com
rules:
- backendRefs:
- name: tls-pass-svc # Наименование сервиса приложения.
port: 8443Тот же сценарий можно реализовать и через HTTPS listener. Этот вариант особенно удобен, когда нужно использовать стандартный обработчик на порту 443, так как не требуется открывать дополнительный порт для TLS passthrough:
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: https-pass-listeners
namespace: prod
spec:
parentRef:
name: app-gw # Имя объекта Gateway из поля status ALBInstance.
namespace: prod
listeners:
- name: https-pass
port: 443 # В данном примере для TLS трафика переиспользуется порт 443.
protocol: HTTPS
hostname: pass.example.com
tls:
mode: Passthrough # Режим TLS - сквозной.
---
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: TLSRoute
metadata:
name: https-pass-route
namespace: prod
spec:
parentRefs:
- name: https-pass-listeners # Имя ListenerSet.
namespace: prod
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: https-pass
port: 443 # В данном примере для TLS трафика переиспользуется порт 443.
hostnames:
- pass.example.com
rules:
- backendRefs:
- name: tls-pass-svc # Наименование сервиса приложения.
port: 8443Если TLS нужно терминировать на шлюзе, а затем передать трафик дальше как обычный TCP-поток, создайте объект ListenerSet со слушателем TLS и режимом Terminate, после чего подключите объект TCPRoute:
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: tls-term-listeners
namespace: prod
spec:
parentRef:
name: app-gw # Имя объекта Gateway из поля status ALBInstance.
namespace: prod
listeners:
- name: tls-term
port: 443 # В данном примере для TLS трафика переиспользуется порт 443.
protocol: TLS
hostname: term.example.com
tls:
mode: Terminate # Режим TLS - терминация.
certificateRefs:
- name: term-tls # Наименование секрета содержащего необходимый TLS-сертификат.
namespace: prod
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: tls-term-route
namespace: prod
spec:
parentRefs:
- name: tls-term-listeners # Имя ListenerSet.
namespace: prod
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: tls-term
port: 443
rules:
- backendRefs:
- name: tls-svc # Наименование сервиса приложения.
port: 8080Перевод приложения на публикацию через другой Gateway
Если приложение нужно опубликовать через другой объект Gateway, выполните следующие шаги:
- Создайте новый объект ClusterALBInstance или ALBInstance, чтобы контроллер создал новый объект Gateway.
- Создайте объект ListenerSet с теми же именами хостов, портами и TLS-настройками. В
spec.parentRefукажите новый объект Gateway. - В существующий объект HTTPRoute в
parentRefsдобавьте ещё один объект, который указывает на новый объект ListenerSet. - Проверьте доступность приложения через новый шлюз.
- После проверки удалите из
parentRefsобъекта HTTPRoute ссылку на неактуальные ListenerSet.
Привязка маршрута в одном неймспейсе к ListenerSet объекту в другом неймспейсе
Если объект HTTPRoute создаётся в одном неймспейсе и должен подключаться к объекту ListenerSet в другом неймспейсе, в неймспейсе целевого объекта ListenerSet добавьте объект ReferenceGrant. В примере ниже показаны общий объект ListenerSet в неймспейсе shared-gw, прикладной объект HTTPRoute в неймспейсе prod и объект ReferenceGrant, который разрешает такую привязку:
apiVersion: gateway.networking.k8s.io/v1
kind: ListenerSet
metadata:
name: shared-listeners
namespace: shared-gw
spec:
parentRef:
name: public-gw
namespace: d8-alb
listeners:
- name: app-https
port: 443
protocol: HTTPS
hostname: app.example.com
tls:
mode: Terminate
certificateRefs:
- name: app-tls
namespace: shared-gw
---
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
name: allow-prod-httproute-to-shared-listeners
namespace: shared-gw
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: prod
to:
- group: gateway.networking.k8s.io
kind: ListenerSet
name: shared-listeners
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: prod
spec:
parentRefs:
- name: shared-listeners
namespace: shared-gw
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: app-https
port: 443
hostnames:
- app.example.com
rules:
- backendRefs:
- name: app-svc
port: 8080Настройка параметров TLS через BackendTLSPolicy
Если трафик от шлюза к backend должен идти по TLS, необходимо создать объект BackendTLSPolicy в неймспейсе backend-объекта Service. В примере ниже показаны объект HTTPRoute, backend-объект Service с именованным портом, ConfigMap с CA bundle и объект BackendTLSPolicy, который задаёт TLS-валидацию для этого backend:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: prod
spec:
parentRefs:
- name: app-listeners
namespace: prod
kind: ListenerSet
group: gateway.networking.k8s.io
sectionName: app-https
port: 443
hostnames:
- app.example.com
rules:
- backendRefs:
- name: app-svc
port: 8443
---
apiVersion: v1
kind: Service
metadata:
name: app-svc
namespace: prod
spec:
selector:
app: app
ports:
- name: https
port: 8443
targetPort: 8443
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-backend-ca
namespace: prod
data:
ca.crt: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
apiVersion: gateway.networking.k8s.io/v1
kind: BackendTLSPolicy
metadata:
name: app-svc-tls
namespace: prod
spec:
targetRefs:
- group: ""
kind: Service
name: app-svc
sectionName: https
validation:
hostname: app.internal.example.com
caCertificateRefs:
- group: ""
kind: ConfigMap
name: app-backend-caНастройка TLS для OpenTelemetry tracing
Если данные OpenTelemetry tracing нужно отправлять по TLS, создайте Kubernetes Secret с CA-сертификатом и укажите его в spec.openTelemetry.tracing.tls.caSecretName.
Для ClusterALBInstance и default deckhouse gateway разместите Secret в неймспейсе d8-alb. Secret должен содержать ключ cacert.
apiVersion: v1
kind: Secret
metadata:
name: otel-tracing-ca
namespace: d8-alb
type: Opaque
stringData:
cacert: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
apiVersion: network.deckhouse.io/v1alpha1
kind: ClusterALBInstance
metadata:
name: proxy-gw
spec:
gatewayName: proxy-gw
openTelemetry:
tracing:
service:
name: otel-collector
namespace: monitoring
port: 4318
protocol: HTTP
path: /v1/traces
tls:
sni: otel-collector.monitoring.svc.cluster.local
caSecretName: otel-tracing-caПоддерживаемые аннотации HTTPRoute
Так как текущая спецификация Gateway API пока не покрывает все возможности, необходимые для корректной работы кластера DKP, модуль предоставляет постепенно расширяющийся набор аннотаций объекта HTTPRoute, который добавляет недостающие параметры конфигурации. Контроллер читает эти ключи из HTTPRoute.metadata.annotations.
| Аннотация | Описание |
|---|---|
alb.network.deckhouse.io/tls-disable-protocol |
Отключает версию протокола TLS для обработчика с именем хоста этого маршрута (например значение http2). Может быть необходимо в редких случаях когда используется общий сертификат с несколькими DNS-именами в сочетании с перенаправлением запросов. |
alb.network.deckhouse.io/whitelist-source-range |
Ожидает список подсетей в формате CIDR через запятую: фильтр по IP на уровне маршрута; переопределяет глобальный whitelist (например 10.1.1.10/32, 10.2.2.2/32) |
alb.network.deckhouse.io/response-headers-to-add |
JSON-объект дополнительных заголовков ответа (например {“Strict-Transport-Security”: “max-age=31536000; includeSubDomains”}). |
alb.network.deckhouse.io/session-affinity |
JSON для cookie session affinity (mode, path, cookieName, ttl и др.); не все поля обязательны, (например {“mode”: “cookie”, “path”: “/path”, “cookieName”: “mycookie”, “ttl”: 0}). |
alb.network.deckhouse.io/hash-key |
Например source-ip: консистентный хэш для бэкендов Service у объекта HTTPRoute. |
alb.network.deckhouse.io/service-upstream |
"true": трафик к upstream идёт через соответствующий сервис, а не напрямую к подам. |
alb.network.deckhouse.io/basic-auth-secret |
namespace/secret с данными htpasswd для HTTP Basic Auth на этом маршруте. |
alb.network.deckhouse.io/satisfy |
all или any: определяет необходимость удовлетворения обеих проверок (whitelist и basic-auth) или какой-либо одной (по умолчанию all). |
alb.network.deckhouse.io/auth-url |
Определяет URL внешнего сервиса аутентификации. |
alb.network.deckhouse.io/auth-signin |
Определяет URL редиректа для авторизации в случае получения 401 от внешней аутентификации. |
alb.network.deckhouse.io/auth-response-headers |
Список через запятую: дополнительные заголовки из ответа auth для передачи в upstream (поверх стандартного allowlist). |
alb.network.deckhouse.io/mod-security |
JSON-конфигурация для WAF ModSecurity/Coraza на уровне маршрута. |
alb.network.deckhouse.io/rewrite-target |
Позволяет переопределять пути для правил с типом RegularExpression используя regex capture groups (например /my-path/\1). |
alb.network.deckhouse.io/buffer-max-request-bytes |
Определяет размер буфера, который допускается использовать в случае буферизации запросов (по умолчанию Envoy Proxy не буферизует запросы). |
alb.network.deckhouse.io/limit-rps |
Лимит RPS на маршрут. |
alb.network.deckhouse.io/backend-tls-settings |
Например {“mode”: “SIMPLE”, “insecureSkipVerify”: true, “clientCertificate”: “”, “privateKey”: “”, “caCertificates”: “”}; позволяет явно указать параметры TLS подключения к upstream. |
WAF на HTTPRoute
Аннотация alb.network.deckhouse.io/mod-security включает WAF ModSecurity/Coraza для конкретного HTTPRoute. Конфигурация применяется на уровне маршрута и не затрагивает другие маршруты, если на них нет такой же аннотации.
Поддерживаемые поля аннотации:
| Поле | Описание |
|---|---|
mode |
Режим работы WAF: on, off, либо любое другое значение для DetectionOnly. |
preset |
Опциональный preset правил. Сейчас поддерживается только owasp-crs. Если поле не указано, preset-правила не загружаются. |
paranoiaLevel |
Опциональный уровень CRS paranoia от 1 до 4. Применяется только если preset равен owasp-crs. |
configRef.namespace |
Опциональный неймспейс ConfigMap с пользовательскими правилами. По умолчанию используется неймспейс HTTPRoute. |
configRef.name |
Имя ConfigMap с пользовательскими правилами. |
configRef.key |
Опциональный ключ в ConfigMap. Если не указан, читаются все ключи в отсортированном порядке. |
directives |
Опциональный список директив ModSecurity/Coraza, заданных непосредственно в аннотации; они добавляются после правил из preset и ConfigMap. |
Порядок применения директив:
- Базовые директивы, поставляемые модулем (
@coraza.conf,SecRuleEngine,SecResponseBodyAccess Off). - Preset-правила из
preset. - Правила из
configRef. - Встроенные директивы из поля
directives.
Встроенные директивы применяются последними и могут переопределять preset или правила из ConfigMap.
Минимальный пример:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app
namespace: prod
annotations:
alb.network.deckhouse.io/mod-security: |
{
"mode": "on"
}
spec:
hostnames:
- app.example.com
parentRefs:
- group: gateway.networking.k8s.io
kind: ListenerSet
name: app-listeners
namespace: prod
sectionName: app-https
port: 443
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: app-svc
port: 8080Пример с preset OWASP CRS:
metadata:
annotations:
alb.network.deckhouse.io/mod-security: |
{
"mode": "on",
"preset": "owasp-crs",
"paranoiaLevel": 1
}Пример с пользовательскими правилами из ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: waf-rules
namespace: prod
data:
rules.conf: |
SecRule ARGS:test "@streq block" \
"id:1000001,phase:2,deny,status:403,msg:'test waf block'"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app
namespace: prod
annotations:
alb.network.deckhouse.io/mod-security: |
{
"mode": "on",
"preset": "owasp-crs",
"paranoiaLevel": 1,
"configRef": {
"name": "waf-rules",
"key": "rules.conf"
},
"directives": [
"SecResponseBodyAccess Off"
]
}Справка по синтаксису правил:
- синтаксис Coraza и формат
SecRule; - справочник ModSecurity по variables;
- справочник ModSecurity по operators;
- справочник ModSecurity по
SecRuleEngineи другим директивам.
Текущие особенности и ограничения:
- поддерживается только preset
owasp-crs; - параметр
paranoiaLevelприменяется только при использованииpreset: owasp-crs. Если preset не указан или имеет другое значение, параметрparanoiaLevelигнорируется; - допустимые значения
paranoiaLevel: от1до4. На практике рекомендуется начинать со значения1; - WAF проверяет только входящие запросы к приложению и при необходимости блокирует их. Ответы приложения клиенту не анализируются;
- правила, заданные через ConfigMap, могут быть многострочными: строки, завершающиеся символом
\, автоматически объединяются.
Использование GeoIP и GeoLite2
Модуль alb поддерживает обогащение входящих HTTP-запросов заголовками на основе данных баз MaxMind GeoIP/GeoLite2.
На данный момент возможно подключение следующих редакций баз:
- GeoIP2-Anonymous-IP;
- GeoIP2-City;
- GeoIP2-ISP;
- GeoIP2-ASN;
- GeoLite2-ASN;
- GeoLite2-City.
Текущая интеграция GeoIP поддерживает одновременное использование до 4 баз.
Скачивание баз GeoIP с MaxMind
Для подключения GeoIP и скачивания баз непосредственно с серверов MaxMind необходимо предварительно создать секрет, содержащий лицензионный ключ, например:
d8 k -n prod create secret generic geoip-license --from-literal=licenseKey='<MAXMIND_LICENSE_KEY>'При настройке GeoIP для ClusterALBInstance секрет может быть размещен в любом неймспейсе, но рекомендуется разместить его в d8-alb.
Для объектов ALBInstance секрет должен располагаться строго в том же неймспейсе, что и объект ALBInstance.
После создания секрета необходимо указать его в объекте ClusterALBInstance или ALBInstance, например:
apiVersion: network.deckhouse.io/v1alpha1
kind: ALBInstance
metadata:
name: main
namespace: prod
spec:
envoyLogLevel: Warning
gatewayName: custom-gateway
geoIP:
licenseKeySecretRef:
name: geoip-licenseСкачивание баз GeoIP с локального зеркала
Для подключения GeoIP и скачивания баз с локального зеркала необходимо указать адрес зеркала в формате URL, например:
apiVersion: network.deckhouse.io/v1alpha1
kind: ALBInstance
metadata:
name: main
namespace: prod
spec:
envoyLogLevel: Warning
gatewayName: custom-gateway
geoIP:
maxmindMirror:
url: "https://local.geoip:8443"В качестве URL допускается указание адреса локального кеширующего сервера GeoIP в другом неймспейсе, например:
apiVersion: network.deckhouse.io/v1alpha1
kind: ALBInstance
metadata:
name: main
namespace: prod
spec:
envoyLogLevel: Warning
gatewayName: custom-gateway
geoIP:
maxmindMirror:
url: "http://geoproxy-cluster.d8-alb.svc:8080/download"Использование заголовков GeoIP
В результате настройки GeoIP в неймспейсе, в котором располагается ClusterALBInstance или ALBInstance, будет запущен сервер кеширования и обновления баз GeoIP, а поды Envoy Proxy будут поочередно перезапущены с добавлением функциональности скачивания баз GeoIP с локального сервера GeoIP.
Для добавления данных на основе GeoIP в HTTP-запросы необходимо указать имена HTTP-заголовков, которые будут содержать соответствующую информацию, например:
apiVersion: network.deckhouse.io/v1alpha1
kind: ALBInstance
metadata:
name: main
namespace: prod
spec:
envoyLogLevel: Warning
gatewayName: custom-gateway
geoIP:
headers:
city: geoip_city
country: geoip_country
licenseKeySecretRef:
name: geoip-license
maxmindEditionIDs:
- GeoLite2-CityОбновление баз GeoIP осуществляется раз в сутки как на кеширующем сервере, так и в каждом отдельном поде Envoy Proxy с использованием кеширующего сервера.
Настройка OpenTelemetry Tracing
Модуль alb поддерживает экспорт трассировок OpenTelemetry из Envoy-прокси.
Для включения экспорта укажите адрес целевого OpenTelemetry Collector в формате URL. Трассировки могут передаваться по OTLP/HTTP или OTLP/gRPC. При необходимости можно настроить подключение с использованием TLS.
При использовании TLS рекомендуется явно задать параметр SNI, если OpenTelemetry Collector находится за прокси или балансировщиком, который выбирает upstream на основе Server Name Indication.