Руководство прикладного разработчика#
Термины и определения#
Термин/аббревиатура |
Определение |
|---|---|
Платформа |
Платформа оркестрации приложений со средствами автоматизации и управления на основе политик, например Kubernetes |
Istio SE |
Настраиваемая сервисная сетка с открытым исходным кодом, служащая для взаимодействия, мониторинга и обеспечения безопасности контейнеров в кластере Kubernetes |
Контрольная панель |
Проект, где запущены управляющие приложения (компонент POLM) |
Управление политиками / POLM |
Компонент Управление политиками |
Граничный прокси / IGEG |
Компонент Граничный прокси |
Сервисный прокси / SVPX |
Компонент Сервисный прокси |
Ingress Gateway |
Входная точка в проект компонента IGEG |
Egress Gateway |
Выходная точка из проекта компонента IGEG |
istio-proxy |
Граничный прокси — контейнер, предназначенный для маршрутизации трафика |
Deployment |
Набор инструкций для запуска приложения в Kubernetes |
Pod |
Набор контейнеров внутри узла кластера Kubernetes |
TLS |
Transport Layer Security, протокол защиты транспортного уровня |
Системные требования#
Для использования компонента Граничный прокси необходимо выполнение следующих пререквизитов:
Кластер Kubernetes (версии 1.19 и выше) развернут и настроен в соответствии с требованиями, предъявляемыми к Платформе.
В проекте создана учетная запись с правами на создание конфигураций.
Настроен доступ для публикации образов разрабатываемых приложений в Docker-репозиторий.
На рабочей машине пользователя установлен клиент Kubernetes (kubectl) для доступа в Kubernetes c использованием консоли.
На рабочей машине пользователя установлен клиент istioctl, поставляемый в дистрибутиве.
Подключение и конфигурирование#
Подключение#
Подключение осуществляется администраторами прикладного проекта. Процесс описан в документе Руководство по установке.
Конфигурирование#
Сценарий 1. Настройка обработчиков на Ingress Gateway для входящего трафика#
Для настройки маршрутизации трафика на Ingress Gateway необходимо определиться с протоколом входящего трафика. Далее разберем примеры с HTTP- и HTTPS-трафиком.
HTTP-трафик
Шаблон конфигурации Service для граничного прокси:
kind: Service
apiVersion: v1
metadata:
name: <имя_сервиса_по_которому_будут_обращаться_к_граничному_прокси>
spec:
ports:
- name: http
protocol: TCP
port: <порт_на_который_будут_обращаться_к_граничному_прокси>
targetPort: <порт_на_котором_будет_поднят_обработчик>
selector:
<label1>: <value1>
<label2>: <value2>
...
type: ClusterIP
Пример Service:
kind: Service
apiVersion: v1
metadata:
name: istio-ingressgateway
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
selector:
app: istio-ingressgateway
istio: ingressgateway
type: ClusterIP
Конфигурация Service позволит обращаться к граничному прокси. Для работы обработчика событий необходимо создать конфигурацию Gateway.
Шаблон конфигурации Gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: <имя_конфига_gateway>
spec:
selector:
<label1>: <value1>
<label2>: <value2>
servers:
- port:
number: <порт_обработчика_событий>
name: <имя_порта>
protocol: <протокол_обработчика_событий>
hosts:
- <имя_хоста_на_который_пришел_запрос>
Для Pod в разделе selector указываются labels. Gateway будет получать трафик c Pod, на которых объявлены метки, указанные в labels конфигурации Gateway.
В host могут указываться как wildcard-значения, так и доменные имена в формате FQDN.
Для HTTP-трафика значение поля host должно совпадать со значением заголовка Host в поступающем запросе.
Для HTTP2/gRPC значение поле host должно совпадать со значением заголовка Authority.
В protocol в качестве протокола можно выбрать: HTTP, HTTPS, GRPC, HTTP2, MONGO, TCP или TLS 1.2.
Пример конфигурации Gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-ingress
spec:
selector:
app: istio-ingressgateway
istio: ingressgateway
servers:
- port:
number: 8080
name: http
protocol: HTTP
hosts:
- "*"
Для маршрутизации запроса, полученного граничным прокси, в прикладной сервис необходимо создать конфигурацию VirtualService.
Шаблон конфигурации VirtualService:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: <имя_конфига>
spec:
exportTo:
- '.'
hosts:
- <имя_хоста_на_который_пришел_запрос>
gateways:
- <имя_конфига_Gateway>
<протокол_трафика>:
- match:
- port: <порт_обработчика_Gateway>
route:
- destination:
host: <имя_прикладного_сервиса>
port:
number: <порт_прикладного_сервиса>
В качестве <протокол_трафика> можно указать http для протоколов HTTP/HTTP2/gRPC и для терминированного на граничном прокси трафика HTTPS.
Для нетерминированного трафика TLS 1.2 / HTTPS в качестве <протокол_трафика> используется tls или tcp.
Для трафика TCP в качестве <протокол_трафика> выставляется tcp.
Если в VirtualService в разделе route.destination указан хост, не объявленный как Service или ServiceEntry, то при загрузке конфигурации в проект в логах контрольной панели будет предупреждение вида:
warn No Service or ServiceEntry found for host test-cluster.XXXX.XX.XXX used as destination in some VirtualService, namespace: test-projeect
Пример VirtualService:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: service-vs
spec:
exportTo:
- '.'
hosts:
- istio-ingressgateway
gateways:
- my-ingress
http:
- match:
- port: 8080
route:
- destination:
host: my-server.default.svc.cluster.local
port:
number: 8686
HTTPS-трафик
Конфигурация для HTTPS отличается от HTTP протоколом обработчика и наличием сертификатов.
HTTPS в качестве протокола безопасности использует TLS 1.2.
Для одностороннего TLS 1.2 валидируются только сертификаты сервера, а для двустороннего (mutual TLS 1.2, mTLS 1.2) валидируются сертификаты клиента и сервера. В режиме mTLS 1.2 клиенту необходимо предъявлять свой сертификат, иначе SSL 1.0 handshake не будет установлен.
В отличие от HTTP, для трафика HTTPS в конфигурации Gateway в параметре host указывается значение SNI протокола TLS 1.2. SNI проставляется на стороне клиента и обычно совпадает с DNS-именем host, на который отправляется запрос.
Шаблон конфигурации Gateway для одностороннего HTTPS:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: <имя_конфига>
spec:
selector:
<label1>: <value1>
<label2>: <value2>
servers:
- port:
number: 8080
name: https
protocol: HTTPS
hosts:
- <имя_хоста_на_который_пришел_запрос>
tls:
mode: SIMPLE
caCertificates: <путь_к_цепочке_сертификатов_в_формате_pem>
serverCertificate: <путь_к_серверному_сертификату_в_формате_pem>
privateKey: <путь_к_дешифрованному_приватному_ключу_для_серверного_сертификата_в_формате_pem>
В полях caCertificates, serverCertificate и privateKey задаются пути к соответствующим файлам в Pod.
Для корректной работы обработчика событий (а также для запуска и работы контейнера istio-proxy) необходимо подмонтировать сертификаты и ключ в Pod, а затем указать в перечисленных выше полях конфигурации абсолютный путь к файлам.
Шаблон конфигурации Gateway для двустороннего TLS 1.2:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: <имя_конфига>
spec:
selector:
<label1>: <value1>
<label2>: <value2>
servers:
- port:
number: 8080
name: https
protocol: HTTPS
hosts:
- <имя_хоста_на_который_пришел_запрос>
tls:
mode: MUTUAL
caCertificates: <путь_к_цепочке_сертификатов_в_формате_pem>
serverCertificate: <путь_к_серверному_сертификату_в_формате_pem>
privateKey: <путь_к_дешифрованному_приватному_ключу_для_серверного_сертификата_в_формате_pem>
Пример Gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-ingress
spec:
selector:
app: istio-ingressgateway
istio: ingressgateway
servers:
- port:
number: 8080
name: http
protocol: HTTP
hosts:
- "*"
tls:
mode: MUTUAL
caCertificates: /etc/certs/ca.pem
serverCertificate: /etc/certs/servercert.pem
privateKey: /etc/certs/privatekey.pem
Шифрование трафика на участке Ingress Gateway - прикладной сервис
По умолчанию трафик, поступивший на Ingress Gateway, расшифровывается, и дальнейший вызов прикладного сервиса выполняется в виде plain text. Рекомендуется настроить шифрование (терминацию) трафика на граничном прокси.
Для добавления шифрования между входным граничным прокси и прикладным сервисом необходимо создать конфигурацию DestinationRule.
Шаблон конфигурации DestinationRule:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: <имя_конфига>
spec:
exportTo:
- '.'
host: <имя_прикладного_сервиса>
workloadSelector:
matchLabels:
<label1>: <value1>
<label2>: <value2>
trafficPolicy:
portLevelSettings:
- port:
number: <порт_прикладного_сервиса>
tls:
mode: ISTIO_MUTUAL
Пример конфигурации DestinationRule:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: mtls-service
spec:
exportTo:
- '.'
host: my-server.default.svc.cluster.local
workloadSelector:
matchLabels:
app: dbserver
version: v1
trafficPolicy:
portLevelSettings:
- port:
number: 8686
tls:
mode: ISTIO_MUTUAL
Значение mode: ISTIO_MUTUAL означает, что при взаимодействии между Pods прикладных сервисов внутри проекта будет использоваться двусторонний TLS 1.2, а в качестве сертификатов будут использоваться специальные сертификаты, выпускаемые компонентом POLM.
Сервис управления политиками (POLM) генерирует специальные сертификаты для шифрования трафика внутри проекта. Сертификаты автоматически создаются, добавляются в нужные прокси и обновляются, когда срок их службы подходит к концу.
Сценарий 2. Настройка маршрутизации трафика на Egress Gateway#
Для настройки маршрутизации исходящего из проекта трафика на граничном прокси (Egress Gateway) необходимо создать ряд конфигураций.
Если в Istio на уровне сервиса управления политиками в настройке outboundTrafficPolicy.mode включен режим REGISTRY_ONLY, то перед тем как создать конфиги для маршрутизации трафика на Egress Gateway, нужно создать конфигурацию ServiceEntry.
Значение REGISTRY_ONLY настройки outboundTrafficPolicy.mode настраивает все прокси таким образом, что они пропускают трафик только на сервисы, объявленные внутри проекта. На любой внешний host/сервис необходимо создавать конфигурацию ServiceEntry, которая зарегистрирует внешний host в реестре сервисов проекта. Тогда прокси смогут обращаться к host.
Противоположное REGISTRY_ONLY значение — ALLOW_ANY, такое значение не требует создание конфигураций ServiceEntry.
Шаблон конфигурации ServiceEntry:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: <имя_конфига>
spec:
exportTo:
- '.'
hosts:
- <внешний_хост>
ports:
- number: <порт_внешнего_сервиса>
name: <имя_порта_внешнего_сервиса>
protocol: <протокол_внешнего_сервиса>
resolution: <способ_резолвинга_ip_внешнего_хоста>
location: MESH_EXTERNAL
Пример конфигурации ServiceEntry:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: tl-snap-28
spec:
exportTo:
- '.'
hosts:
- tl-snap-28.ms.cloud.ru
ports:
- number: 9440
name: http
protocol: HTTP
resolution: DNS
location: MESH_EXTERNAL
Теперь нужно создать Service для Egress Gateway. Именно через этот Service будут проходить запросы к сервисам извне кластера. Конфигурация аналогична Ingress.
Пример конфигурации Service:
kind: Service
apiVersion: v1
metadata:
name: istio-egressgateway
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
selector:
app: istio-egressgateway
istio: egressgateway
type: ClusterIP
Чтобы настроить маршрутизацию трафика на Egress Gateway, нужно создать по аналогии с Ingress Gateway конфигурацию Gateway.
Пример конфигурации Gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-egress
spec:
selector:
app: istio-egressgateway
istio: egressgateway
servers:
- port:
number: 8080
name: http
protocol: HTTP
hosts:
- tl-snap-28.ms.cloud.ru
Далее необходимо создать конфигурацию VirtualService, которая будет получать запросы к внешнему по отношению к проекту host на Service Egress, а затем уже отправлять его с Egress Gateway.
Шаблон конфигурации VirtualService:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: <имя_конфига>
spec:
exportTo:
- '.'
hosts:
- <внешний_хост>
gateways:
- <имя_конфига_Gateway_для_Egress>
- mesh
http:
- match:
- gateways:
- mesh
port: <порт_внешнего_хоста>
route:
- destination:
host: <имя_сервиса_Egress>
port:
number: <порт_сервиса_Egress>
weight: 100
- match:
- gateways:
- <имя_конфига_Gateway_для_Egress>
port: <порт_сервиса_Egress>
route:
- destination:
host: <внешний_хост>
port:
number: <порт_внешнего_хоста>
weight: 100
Пример конфигурации VirtualService:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-for-tl-snap-28
spec:
exportTo:
- '.'
hosts:
- tl-snap-28.ms.cloud.ru
gateways:
- my-egress
- mesh
http:
- match:
- gateways:
- mesh
port: 9440
route:
- destination:
host: istio-egressgateway.default.svc.cluster.local
port:
number: 80
weight: 100
- match:
- gateways:
- my-egress
port: 80
route:
- destination:
host: tl-snap-28.ms.cloud.ru
port:
number: 9440
weight: 100
Если в VirtualService в разделе route.destination указан хост, не объявленный как Service или ServiceEntry, то при загрузке конфигурации в проект в логах контрольной панели будет предупреждение вида:
warn No Service or ServiceEntry found for host test-cluster.XXXX.XX.XXX used as destination in some VirtualService, namespace: test-projeect
HTTPS для исходящего трафика
Если требуется устанавливать шифрование исходящего трафика, исходящего из граничного прокси, то необходимо заменить протокол с HTTP на HTTPS в ServiceEntry.
Пример ServiceEntry:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: tl-snap-28
spec:
exportTo:
- '.'
hosts:
- tl-snap-28.ms.cloud.ru
ports:
- number: 9440
name: http
protocol: HTTPS
resolution: DNS
location: MESH_EXTERNAL
Далее необходимо создать конфигурацию DestinationRule, где указать сертификаты для обращения к внешнему адресу.
Пример DestinationRule:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: mtls-tl-snap-28
spec:
exportTo:
- '.'
host: tl-snap-28.ms.cloud.ru
trafficPolicy:
portLevelSettings:
- port:
number: 9440
tls:
mode: MUTUAL
sni: tl-snap-28.ms.cloud.ru
clientCertificate: /etc/certs/myclientcert.pem
privateKey: /etc/certs/client_private_key.pem
caCertificates: /etc/certs/ca.pem
В DestinationRule пути к файлам указываются аналогично сертификатам в конфигурации Gateway, только для клиентских сертификатов, с которыми будет совершаться вызов внешнего host с граничного прокси Egress Gateway. Соответственно, файлы нужно подмонтировать в Pod Egress Gateway по путям, которые были указаны в DestinationRule.
Далее необходимо настроить маршрутизацию от Egress к внешнему сервису с помощью конфигурации VirtualService.
Пример VirtualService:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: vs-for-tl-snap-28
spec:
exportTo:
- '.'
hosts:
- tl-snap-28.ms.cloud.ru
gateways:
- my-egress
- mesh
http:
- match:
- gateways:
- mesh
port: 9440
route:
- destination:
host: istio-egressgateway.default.svc.cluster.local
port:
number: 80
weight: 100
- match:
- gateways:
- my-egress
port: 80
route:
- destination:
host: tl-snap-28.ms.cloud.ru
port:
number: 9440
weight: 100
Также рекомендуется создать конфигурацию DestinationRule для шифрования внутреннего трафика между Service Mesh и граничным прокси Egress.
Пример DestinationRule:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: mtls-egress
spec:
exportTo:
- '.'
host: istio-egressgateway.default.svc.cluster.local
trafficPolicy:
portLevelSettings:
- port:
number: 9440
tls:
mode: ISTIO_MUTUAL
И добавить шифрование в конфигурацию Gateway.
Пример Gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-egress
spec:
selector:
app: istio-egressgateway
istio: egressgateway
servers:
- hosts:
- tl-snap-28.ms.cloud.ru
port:
number: 8080
name: http
protocol: HTTP
tls:
mode: ISTIO_MUTUAL
Сценарий 3. Отключение обслуживания новых соединений после получения sigTerm#
Мягкое отключение подразумевает, что после получения sigTERM Pod будет вести себя следующим образом:
прекращает прием новых запросов;
закрывает персистентные соединения;
ожидает завершения (drain) открытых запросов.
С целью обеспечения функциональности мягкого отключения рекомендуется в Deployment граничных прокси указать:
spec:
terminationGracePeriodSeconds: 60 # время на завершение контейнера в секундах
containers:
- name: istio-proxy
env:
- name: TERMINATION_DRAIN_DURATION_SECONDS
value: '45' # время на завершение запросов и соединений в секундах
Использование аннотаций обеспечивает мягкое отключение оставшихся Pods, для этого в Deployment сервисов с бизнес-логикой необходимо добавить:
spec:
template:
metadata:
annotations:
proxy.istio.io/config: |
proxyMetadata:
TERMINATION_DRAIN_DURATION_SECONDS: "45"
Сценарий 4. Настройка защищенного соединения с PostgreSQL на Egress Gateway#
Подключение к БД PostgreSQL по SSL 1.0 и выше выполняется без необходимости написания дополнительного envoy-фильтра.
Также реализована возможность подключения к БД PostgreSQL через Egress без шифрования.
Работоспособность проверена с версиями PostgreSQL 11.2 и 14.1.
Можно подключиться с разными клиентскими сертификатами для нескольких пользователей БД (от разных клиентских приложений).
Сертификаты для подключения к БД настраиваются на Egress, клиентское приложение не хранит их.
Клиентское приложение должно инициировать подключение к БД без шифрования (параметр sslmode=disable строки подключения), так как его устанавливает Egress.
Настройка сертификатов для одного пользователя
Для настройки защищенного соединения к PostgreSQL необходимо создать ServiceEntry, для добавления сервера БД в реестр сервисов Istio, и указать там протокол postgres (регистр не важен).
Если подключение к БД выполняется с шифрованием, то в DestinationRule, которое маршрутизирует трафик к серверу БД, необходимо указать клиентские сертификаты из файлов, подмонтированных в Deployment Egress'а, или secrets Kubernetes. Параметр tls.mode должен быть установлен равным MUTUAL.
Если подключение к БД выполняется без шифрования, то можно не указывать параметры шифрования в DestinationRule, которое маршрутизирует трафик к серверу БД.
Пример Gateway:
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: egress-gw
spec:
selector:
app: egress
servers:
- hosts:
- test-postgres-db.XXXX.XX.XXX
port:
name: tls-54321
number: 54321
protocol: TLS
tls:
mode: ISTIO_MUTUAL
Пример сервиса для обращения к Gateway по DNS-имени:
apiVersion: v1
kind: Service
metadata:
name: egress-gw-svc
spec:
ports:
- name: tcp-54321
port: 54321
protocol: TCP
targetPort: 54321
selector:
app: egress
sessionAffinity: None
type: ClusterIP
Пример DestinationRule для обращения к сервису Gateway с шифрованием ISTIO_MUTUAL:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: egress-gw-svc-dr
spec:
exportTo:
- .
host: egress-gw-svc.test-pg-single.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
portLevelSettings:
- port:
number: 54321
tls:
mode: ISTIO_MUTUAL
sni: test-postgres-db.XXXX.XX.XXX
Пример ServiceEntry для обращения к серверу БД:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: postgres-se
spec:
exportTo:
- '.'
hosts:
- test-postgres-db.XXXX.XX.XXX
ports:
- name: postgres-5432
number: 5432
protocol: postgres
resolution: DNS
location: MESH_EXTERNAL
Пример DestinationRule для обращения к серверу БД с шифрованием (сертификаты должны быть в текстовом формате pem):
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: postgres-dr
spec:
exportTo:
- .
host: test-postgres-db.XXXX.XX.XXX
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
tls:
caCertificates: /var/lib/postgresql/tucerts/ca.crt
clientCertificate: /var/lib/postgresql/tucerts/tls.crt
mode: MUTUAL
privateKey: /var/lib/postgresql/tucerts/tls.key
workloadSelector:
matchLabels:
app: egress
Пример DestinationRule для обращения к серверу БД без шифрования:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: postgres-dr
spec:
exportTo:
- .
host: test-postgres-db.XXXX.XX.XXX
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
# tls:
# caCertificates: /var/lib/postgresql/tucerts/ca.crt
# clientCertificate: /var/lib/postgresql/tucerts/tls.crt
# mode: MUTUAL
# privateKey: /var/lib/postgresql/tucerts/tls.key
workloadSelector:
matchLabels:
app: egress
Пример virtualService для маршрутизации запроса на Gateway и затем на сервер БД:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: postgres-vs
spec:
exportTo:
- .
gateways:
- egress-gw
- mesh
hosts:
- test-postgres-db.XXXX.XX.XXX
tcp:
- match:
- gateways:
- mesh
route:
- destination:
host: egress-gw-svc.test-pg-single.svc.cluster.local
port:
number: 54321
- match:
- gateways:
- egress-gw
port: 54321
route:
- destination:
host: test-postgres-db.XXXX.XX.XXX
port:
number: 5432
Пример проекта с одним пользователем
Проект Kubernetes / OpenShift находится в папке
/IGEG/info/samples/postgres_ssl_single
Описание его сущностей:
/IGEG/info/samples/postgres_ssl_single/README.md
Описание тестирования:
/IGEG/info/samples/postgres_ssl_single/index.md
Настройка сертификатов для нескольких пользователей
Чтобы указать разные сертификаты для подключения к одному адресу и порту БД, нужно:
поднять внутренний
Gatewayс таким количеством портов, сколько будет разных пользователей БД (т.е. разных сертификатов для подключения к БД):
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: egress-gw
spec:
selector:
app: egress
servers:
- hosts:
- test-postgres-db.XXXX.XX.XXX
port:
name: tls-54320-postgres
number: 54320
protocol: TLS
tls:
mode: ISTIO_MUTUAL
- hosts:
- test-postgres-db.XXXX.XX.XXX
port:
name: tls-54321-testuser
number: 54321
protocol: TLS
tls:
mode: ISTIO_MUTUAL
определить DNS-имя сервиса, по которому будет доступен
Gateway:
kind: Service
apiVersion: v1
metadata:
name: egress-gw-svc
spec:
ports:
- name: tcp-54320
protocol: TCP
port: 54320
targetPort: 54320
- name: tcp-54321
protocol: TCP
port: 54321
targetPort: 54321
selector:
app: egress
type: ClusterIP
sessionAffinity: None
в
VirtualServiceразвести трафик от разных клиентских приложений по разным портам внутреннегоGateway, используяlabelsклиентских приложений, и направить трафик, который должен быть зашифрован разными сертификатами, на разныеsubsets:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: postgres-vs
spec:
exportTo:
- .
gateways:
- egress-gw
- mesh
hosts:
- test-postgres-db.XXXX.XX.XXX
tcp:
- match:
- gateways:
- mesh
sourceLabels:
app: pg-client-postgres
route:
- destination:
host: egress-gw-svc.test-pg-multi.svc.cluster.local
port:
number: 54320
- match:
- gateways:
- mesh
sourceLabels:
app: pg-client-testuser
route:
- destination:
host: egress-gw-svc.test-pg-multi.svc.cluster.local
port:
number: 54321
- match:
- gateways:
- mesh
sourceLabels:
app: pg-client-java
route:
- destination:
host: egress-gw-svc.test-pg-multi.svc.cluster.local
port:
number: 54321
- match:
- gateways:
- egress-gw
port: 54320
route:
- destination:
host: test-postgres-db.XXXX.XX.XXX
port:
number: 5432
subset: postgres-back
- match:
- gateways:
- egress-gw
port: 54321
route:
- destination:
host: test-postgres-db.XXXX.XX.XXX
port:
number: 5432
subset: testuser-back
объявить соответствующие
subsetsвDestination Ruleи прописать там сертификаты (они должны быть в текстовом форматеpem):
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: postgres-dr
spec:
exportTo:
- .
host: test-postgres-db.XXXX.XX.XXX
workloadSelector:
matchLabels:
app: egress
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
subsets:
- labels:
version: postgres-back
name: postgres-back
trafficPolicy:
portLevelSettings:
- port:
number: 5432
tls:
mode: MUTUAL
clientCertificate: /var/lib/postgresql/pgcerts/tls.crt
privateKey: /var/lib/postgresql/pgcerts/tls.key
caCertificates: /var/lib/postgresql/pgcerts/ca.crt
- labels:
version: testuser-back
name: testuser-back
trafficPolicy:
portLevelSettings:
- port:
number: 5432
tls:
mode: MUTUAL
clientCertificate: /var/lib/postgresql/tucerts/tls.crt
privateKey: /var/lib/postgresql/tucerts/tls.key
caCertificates: /var/lib/postgresql/tucerts/ca.crt
создать столько
ServiceEntryиWorkloadEntry, сколько будет разных пользователей БД (т.е. разных сертификатов для подключения к БД), и связать каждыйServiceEntryсWorkloadEntry:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: postgres-back-se
spec:
exportTo:
- '.'
hosts:
- test-postgres-db.XXXX.XX.XXX
ports:
- name: postgres-5432-postgres
number: 5432
protocol: postgres
resolution: DNS
location: MESH_EXTERNAL
workloadSelector:
labels:
version: postgres-back
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:
name: postgres-we
spec:
address: test-postgres-db.XXXX.XX.XXX
labels:
version: postgres-back
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: testuser-back-se
spec:
exportTo:
- '.'
hosts:
- test-postgres-db.XXXX.XX.XXX
ports:
- name: postgres-5432-testuser
number: 5432
protocol: postgres
resolution: DNS
location: MESH_EXTERNAL
workloadSelector:
labels:
version: testuser-back
apiVersion: networking.istio.io/v1beta1
kind: WorkloadEntry
metadata:
name: testuser-we
spec:
address: test-postgres-db.XXXX.XX.XXX
labels:
version: testuser-back
для шифрования соединения между сайдкаром клиентского приложения и Egress необходимо определить
DestinationRuleс шифрованиемISTIO_MUTUAL:
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: egress-gw-svc-dr
spec:
exportTo:
- '.'
host: egress-gw-svc.test-pg-multi.svc.cluster.local
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
portLevelSettings:
- port:
number: 54320
tls:
mode: ISTIO_MUTUAL
sni: test-postgres-db.XXXX.XX.XXX
- port:
number: 54321
tls:
mode: ISTIO_MUTUAL
sni: test-postgres-db.XXXX.XX.XXX
Пример проекта с несколькими пользователями
Проект Kubernetes / OpenShift находится в папке:
/IGEG/info/samples/postgres_ssl_multi
Описание его сущностей:
/IGEG/info/samples/postgres_ssl_multi/README.md,
Описание тестирования:
/IGEG/info/samples/postgres_ssl_multi/index.md
Сценарий 5. Подключение к bootstrap-серверам кластера kafka через Egress#
Начиная с версии SSM 3.9.1 добавлена возможность подключения к кластеру kafka через Egress с использованием сертификатов. При этом достаточно указать только адреса нескольких (или одного) bootstrap-серверов, которые не будут меняться в процессе изменения топологии кластера. К остальным узлам кластера Egress подключится автоматически, опрашивая указанные bootstrap-сервера. В момент подключения Egress к кластеру kafka должен быть доступен хотя бы один из указанных брокеров. Если после подключения Egress некоторые брокеры (или даже единственный указанный) стали недоступны, подключение останется активным за счет остальных доступных узлов кластера.
Работа сценария тестировалась с Kafka версии 2.2, Сorax 6.272.0 (Core version: 2.7.2).
Применение сценария#
Данный сценарий взаимодействия предназначен для организации взаимодействия клиентского приложения kafka (в режиме потребителя или поставщика) с кластером kafka, часто меняющим топологию, например при регулярном масштабировании/переносе brokers на новые сетевые узлы.
Если кластер kafka имеет постоянную топологию, или изменения не требуют изменения конфигураций у большого (неизвестного) числа потребителей, то достаточно организовать взаимодействие через Egress по обычному сценарию.
Пререквизиты#
Выпущены клиентские сертификаты и ключи для egressgateway.
Аутентификация на стороне кластера kafka настроена по SSL 1.0 и выше. Режим SASL не поддерживается IGEG.
Настройка#
Для настройки подключения, не зависящего от изменений топологии кластера kafka, через Egress, необходимо:
создать объект Gateway и указать протокол порта: kafka;
создать объект Service, определяющий имя сервиса Gateway;
создать объект VirtualService с правилами маршрутизации трафика на сервис Gateway и после — в целевой кластер kafka;
создать объект ServiceEntry с протоколом портов: kafka и адресами bootstrap-серверов кластера kafka;
создать объект DestinationRule с правилами шифрования соединения от sidecar клиентского приложения до сервиса Gateway;
создать объект DestinationRule с правилами шифрования соединения от сервиса Gateway до целевого кластера kafka.
Пример Gateway
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: egress-gw
spec:
selector:
app: egress
servers:
- hosts:
- egress-kafka.kafka-test.svc.cluster.local
port:
name: kafka-19093
number: 19093
protocol: kafka
tls:
mode: ISTIO_MUTUAL
Пример сервиса для Gateway
apiVersion: v1
kind: Service
metadata:
name: egress-kafka
spec:
ports:
- name: kafka-19093
protocol: TCP
port: 19093
targetPort: 19093
selector:
app: egress
sessionAffinity: None
type: ClusterIP
Пример ServiceEntry
Для корректной работы протокола необходимо указать location: MESH_EXTERNAL в ServiceEntry, чтобы конфигурации внутреннего сервиса Gateway для kafka и внешнего адреса отличались для Envoy proxy.
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: kafka-cluster-se
spec:
exportTo:
- '.'
hosts:
- bootstrap1.sy.dev
ports:
- number: 9092
name: kafka-9092
protocol: kafka
endpoints:
- address: bootstrap1.sy.dev
ports:
kafka-9092: 9092
- address: bootstrap2.sy.dev
ports:
kafka-9092: 9092
location: MESH_EXTERNAL
resolution: DNS
Пример DestinationRule для настройки шифрования к кластеру kafka
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: dr-kafka
spec:
exportTo:
- '.'
host: bootstrap1.sy.dev
trafficPolicy:
tls:
mode: MUTUAL
clientCertificate: /kafka-tls/tls.crt
privateKey: /kafka-tls/tls.key
caCertificates: /kafka-root/kafka-root.crt
workloadSelector:
matchLabels:
app: egress
Пример DestinationRule для настройки шифрования от сайдкара клиентского приложения до сервиса Gateway
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: dr-egress-svc
spec:
exportTo:
- '.'
host: egress-kafka.kafka-test.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
sni: egress-kafka.kafka-test.svc.cluster.local
Пример VirtualService для маршрутизации запроса с Gateway в кластер kafka
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: egress-vs
spec:
exportTo:
- '.'
gateways:
- egress-gw
- mesh
hosts:
- egress-kafka.kafka-test.svc.cluster.local
tcp:
- match:
- gateways:
- egress-gw
port: 19093
route:
- destination:
host: bootstrap1.sy.dev
port:
number: 9092
weight: 100
Пример настроенного проекта находится в папке /IGEG/info/samples/kafka_test.
Состав проекта:
приложение fluent-producer с sidecar istio-proxy, посылающее сообщения в кластер kafka;
приложение fluent-consumer с sidecar istio-proxy, получающее сообщения из кластера kafka;
приложение Egress, устанавливающее защищенное подключение к кластеру kafka;
configmaps для настройки приложений fluent-producer и fluent-consumer;
DestinationRule для шифрования соединения между sidecars клиентских приложений и Egress;
DestinationRule для шифрования соединения между Egress и кластером kafka;
Gateway, определяющий сервис Egress, доступный клиентским приложениям;
ServiceEntry с адресами bootstrap-серверов кластера kafka;
Service для сервиса Egress;
VirtualService для маршрутизации трафика.
Проверка взаимодействия#
В случае успешной настройки в логах контейнеров fluent-bit приложений producer и consumer будут постоянно появляться записи о чтении и записи сообщений в topic kafka.
Если кластер kafka развернут на виртуальных машинах, то для проверки взаимодействия можно использовать приложение KafkaTool на локальной машине, подключившись к кластеру и посмотрев подключенных клиентов и записанные сообщения.
Если клиент является opensource-образом kafka (Apache или Bitnami), развернутом в проекте, то можно воспользоваться приложением из набора штатных утилит kafka, расположенных по пути:
/opt/Apache/kafka/bin
или
/opt/bitnami/kafka/bin
Пример проверки:
kafka-topics.sh --list --bootstrap-server egress-kafka:19093
где egress-kafka - это имя Service Egress, и 19093 — порт Gateway.
Приложение должно при этом использовать настройки plaintext, защищенное соединение будет установлено с кластером kafka граничным прокси.
По завершении сессии в логе граничного прокси появится запись, указывающая на факт соединения Pod приложения 192.168.y.y с нашим граничным прокси 192.168.x.x, например:
[2023-08-13T11:39:11.099Z] "- - -" 0 - - - "-" 25524 71908 106291 - "-" "-" "-" "-" "-" - - 192.168.x.x:9093 192.168.y.y:41776
Отладка kafka-proxy#
Для включения расширенной отладки фильтра kafka-proxy, с целью анализа проблем подключения, выполните в терминале контейнера istio-proxy Pod граничного прокси команду:
curl -X POST localhost:15000/logging?kafka=trace
Также через установленную на рабочем месте администратора утилиту istioctl:
istioctl pc log <egress-pod> --level=kafka:trace
После включения отладки в системном журнале граничного прокси появятся дополнительные сообщения, например:
[debug][kafka] [C182] Kafka client send message, api key 1, version 11, correlation id 528744
[debug][kafka] [C181] Kafka client receive response, api key 3, version 9, correlation id 528743
[trace][kafka] [C177] Kafka proxy receives response api key 3, version 9, correlation id 528743
[debug][kafka] [C177] Metadata Response :
Brokers :
#0 : id 2, host x.x.x.x:9093
#1 : id 3, host y.y.y.y:9093
#2 : id 1, host z.z.z.z:9093
Topics :
Name : quickstart-events
Partitions :
Index 0 error 0 leader_id 3
Index 5 error 0 leader_id 1
Index 8 error 0 leader_id 2
Миграция на текущую версию#
Для миграции на различные версии требуется провести установку. Процесс описан в документе Руководство по установке.
Быстрый старт#
Для получения примера конфигураций Ingress и Egress можно обратиться к администраторам контрольной панели за выгрузкой Deployments istio-ingressgateway и istio-egressgateway, которые разворачиваются с помощью IstioOperator.
Использование программного компонента#
Компонент Граничный прокси предназначен для обеспечения управляемого вызова интеграционных сервисов прикладной части в проекте Kubernetes. Также используется для контроля входа и выхода из прикладного проекта.
Часто встречающиеся проблемы и пути их устранения#
Проблема |
Пути решения |
|---|---|
Граничный прокси не может подключиться к компоненту POLM, в системном журнале видно сообщение Envoy proxy is NOT ready |
Проверьте корректность подключения к контрольной панели. |
До прикладного приложения не доходят запросы |
Проверьте логи граничного прокси. Возможные варианты сообщений описаны ниже |
В логе граничного прокси видно сообщение: |
Авторизуйтесь в прикладном проекте. Если вызов направлен на внутренний сервис, проверьте наличие сервиса с таким именем, проверьте корректность параметров хост/порт в конфигурационных файлах прикладного проекта — Gateway, DestinationRule и VirtualService. Если вызов направлен на внешний host, проверьте наличие конфигурационного файла ServiceEntry для данного сочетания host/порт |
В логе граничного прокси видно сообщение: |
Авторизуйтесь в прикладном проекте. Проверьте корректность конфигурации раздела connectionPoolSettings в DestinationRule |
В логе граничного прокси видно сообщение: |
Авторизуйтесь в прикладном проекте. Если используется автоматическая аутентификация ISTIO_MUTUAL — проверьте наличие конфликта в разделе trafficPolicy конфигурационного файла DestinationRule, относящегося к проблемному сервису, и раздела |
В логе граничного прокси видно сообщение: |
Авторизуйтесь в прикладном проекте. Проверьте наличие вызываемого сервиса — в веб-интерфейсе Home/Networking/Services/Search_by_name найдите сервис. Проверьте наличие запущенного Pod, на который ссылается сервис — в веб-интерфейсе кликните правой кнопкой мыши на найденный сервис, выберите вкладку Pods на открывшейся странице. Убедитесь, что статус Pods на данной странице имеет значение running |
В логе граничного прокси видны сообщения: |
Проверьте имена портов в объектах Service: они должны иметь формат <протокол>-<номер_порта>. Если имя порта начинается с |
Если указанные пути решения не помогли, обратитесь к системным администраторам контрольной панели.