Руководство прикладного разработчика#

Термины и определения#

Термин/аббревиатура

Определение

Платформа

Платформа оркестрации приложений со средствами автоматизации и управления на основе политик, например Kubernetes

Istio SE

Настраиваемая сервисная сетка с открытым исходным кодом, служащая для взаимодействия, мониторинга и обеспечения безопасности контейнеров в кластере Kubernetes

Контрольная панель

Проект, где запущены управляющие приложения (компонент POLM)

Управление политиками / POLM

Компонент Управление политиками

Граничный прокси / IGEG

Компонент Граничный прокси

Сервисный прокси / SVPX

Компонент Сервисный прокси

Ingress Gateway

Входная точка в проект компонента IGEG

Egress Gateway

Выходная точка из проекта компонента IGEG

istio-proxy

Граничный прокси — контейнер, предназначенный для маршрутизации трафика

Deployment

Набор инструкций для запуска приложения в Kubernetes

Pod

Набор контейнеров внутри узла кластера Kubernetes

TLS

Transport Layer Security, протокол защиты транспортного уровня

Системные требования#

Для использования компонента Граничный прокси необходимо выполнение следующих пререквизитов:

  1. Кластер Kubernetes (версии 1.19 и выше) развернут и настроен в соответствии с требованиями, предъявляемыми к Платформе.

  2. В проекте создана учетная запись с правами на создание конфигураций.

  3. Настроен доступ для публикации образов разрабатываемых приложений в Docker-репозиторий.

  4. На рабочей машине пользователя установлен клиент Kubernetes (kubectl) для доступа в Kubernetes c использованием консоли.

  5. На рабочей машине пользователя установлен клиент 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 по обычному сценарию.

Пререквизиты#
  1. Выпущены клиентские сертификаты и ключи для egressgateway.

  2. Аутентификация на стороне кластера 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

Проверьте корректность подключения к контрольной панели.
Проверьте значения переменных окружения PROXY_CONFIG и CA_ADDR — в них должен быть указан корректный адрес сервиса istiod (из состава POLM)
Обратитесь к системным администраторам контрольной панели

До прикладного приложения не доходят запросы

Проверьте логи граничного прокси. Возможные варианты сообщений описаны ниже

В логе граничного прокси видно сообщение:
NR (No route configured):
В конфигурации граничного прокси отсутствует требуемый маршрут

Авторизуйтесь в прикладном проекте. Если вызов направлен на внутренний сервис, проверьте наличие сервиса с таким именем, проверьте корректность параметров хост/порт в конфигурационных файлах прикладного проекта — Gateway, DestinationRule и VirtualService. Если вызов направлен на внешний host, проверьте наличие конфигурационного файла ServiceEntry для данного сочетания host/порт

В логе граничного прокси видно сообщение:
UO (Upstream overflow with circuit breaking):
Поставщик перегружен запросами

Авторизуйтесь в прикладном проекте. Проверьте корректность конфигурации раздела connectionPoolSettings в DestinationRule

В логе граничного прокси видно сообщение:
UF (Failed to connect to upstream):
Поставщик сбросил соединение

Авторизуйтесь в прикладном проекте. Если используется автоматическая аутентификация ISTIO_MUTUAL — проверьте наличие конфликта в разделе trafficPolicy конфигурационного файла DestinationRule, относящегося к проблемному сервису, и раздела Spec/mtls конфигурационного файла peerAuthentication. В случае указания разных режимов работы в поле tls — возможны указанные ошибки

В логе граничного прокси видно сообщение:
UH (No healthy upstream):
Поставщик неработоспособен

Авторизуйтесь в прикладном проекте. Проверьте наличие вызываемого сервиса — в веб-интерфейсе Home/Networking/Services/Search_by_name найдите сервис. Проверьте наличие запущенного Pod, на который ссылается сервис — в веб-интерфейсе кликните правой кнопкой мыши на найденный сервис, выберите вкладку Pods на открывшейся странице. Убедитесь, что статус Pods на данной странице имеет значение running

В логе граничного прокси видны сообщения:
gRPC config for Cluster rejected: Error adding/updating cluster(s): Proto constraint validation failed:
Ошибка валидации конфигурации

Проверьте имена портов в объектах Service: они должны иметь формат <протокол>-<номер_порта>. Если имя порта начинается с kafka, postgres, mongo или других слов, обозначающих дополнительные протоколы, istiod попытается создать кластеры с указанными протоколами, что вызовет ошибку

Если указанные пути решения не помогли, обратитесь к системным администраторам контрольной панели.