Подключение sidecar к pod(s) приложения#

Примечание: В случае интеграции с secman, так же необходимо обратиться к соответствующей документации для создания, настройки и получения прав на сертификаты/ключи в Vault-хранилище.

Для доставки логов в хранилище Abyss используется sidecar, который включает в себя непосредственно само приложение fluent-bit,
а так же java-приложение fluent-controller, которое используется для запуска, доставки сертификатов, ключей, и отслеживания изменений конфигурационного файла fluent-bit.conf, после чего выполняется перезапуск процесса fluent-bit с обновленной конфигурацией.
Для добавления sidecar к pod(s) приложения необходимо:

  1. Добавить configMap для fluent-bit

  2. Добавить configMap для fluent-controller

  3. Добавить конфигурацию для параметризации fluent-bit и fluent-controller

  4. Добавить в deployment монтирование данных из configMap

  5. Добавить в deployment подключение fluent-bit-sidecar

  6. Добавить манифесты ISTIO для Kafka (KFKA)

Добавить configMap для fluent-bit#

В проекте с конфигурациями дистрибутива в дирректорию /k8s/base/configmaps/ необходимо добавить конфигурацию, в виде configMap (пример your-app-conf-fluent-bit-sidecar.yaml) со следующим содержимым:

apiVersion: v1
kind: ConfigMap
metadata:
  name: your-app-conf-fluent-bit-sidecar
data:
  fluent-bit.conf: |-
    [SERVICE]
       Flush        1
       Daemon       Off
       Parsers_File /fluent-bit/etc/parsers.conf
       HTTP_Server  On
       HTTP_Listen  0.0.0.0
       HTTP_PORT    9081
       Log_Level    info

    [INPUT]
       Name tail
       Tag file.tail
       Path /fluent-bit/etc/logs/*.json
       Mem_Buf_Limit 10MB
       Skip_Long_Lines On
       Refresh_Interval 2
       Rotate_Wait 1
       Read_from_Head Off
       DB /fluent-bit/etc/logs/kube.db
       Parser custom
    [FILTER]
       Name modify
       Match *
       Add hostname ${HOSTNAME}
    [FILTER]
       Name modify
       Match *
       Add tenant {{ TENANT_CODE }}
    [FILTER]
       Name modify
       Match *
       Add your-app-appFQDN ${your-app.server.appFQDN}
    [FILTER]
       Name modify
       Match *
       Add your-app-http.appFQDN ${your-app-http.server.appFQDN}
    [OUTPUT]
       Name kafka
       Match file.tail
       Timestamp_Key serverEventDatetime
       Brokers ${your-app.kafka.bootstrap.servers}
       Topics  ${your-app.kafka.topic}
       rdkafka.security.protocol ${your-app.kafka.security.protocol}
       rdkafka.ssl.key.location /vault/secrets/certs/private-key.pem
       rdkafka.ssl.certificate.location /vault/secrets/certs/cert.pem
       rdkafka.ssl.ca.location /vault/secrets/certs-ca/root.crt
       rdkafka.log_level 6
       rdkafka.queue.buffering.max.kbytes 5120
  parsers.conf: |-
    [PARSER]
       Name custom
       Format json

Если нужно преобразовать дату в логе из текстового формата "YYYY-MM-DDThh:mm:ss[.SSS]" в UNIX TIMESTAMP long(миллисекунды), используется скрипт из sidecar. Добавьте приведенную ниже секцию FILTER к файлу конфигурации описанному выше:

[FILTER]
  Name lua
  Match *
  script  /fluent-bit/lua/time_converter.lua
  call override_time
[FILTER]
  Name modify
  Match *
  Rename ts serverEventDatetime

Добавить configMap для fluent-controller#

Приложение fluent-controller находится в составе sidecar и отслеживает изменения в секретах и конфигурации fluent-bit, после чего перезапускает его процесс в контейнере, fluent-bit загружается с обновленными сертификатами и конфигурацией.

В проекте с конфигурациями дистрибутива k8s/base/configmaps/ необходимо добавить конфигурацию в виде configMap (пример your-app-cm-fluent-controller.yaml) со следующим содержимым:

kind: "ConfigMap"
apiVersion: v1
metadata:
  name: your-app-cm-fluent-controller.${distrib.release.version}
data:
  application.properties: |-
    fluent.conf.reload.enabled=${your-app.fluentbit-sidecar.conf.reload.enabled}
    spring.cloud.vault.enabled=${your-app.fluentbit-sidecar.vault.enabled}
    fluent.vault.reload.enabled=${your-app.fluentbit-sidecar.vault.reload.enabled}
  {% if your-app.fluentbit-sidecar.vault.enabled | bool %}
    spring.cloud.vault.uri=http://${your-app.vault.host}:${your-app.vault.port}
    spring.cloud.vault.namespace=${your-app.vault.client.method.namespace}
    spring.cloud.vault.authentication=${your-app.vault.client.method.authentication}
    spring.cloud.vault.kubernetes.role=${your-app.vault.client.method.config.role}
    spring.cloud.vault.kubernetes.path=${your-app.vault.client.method.mount_path}
    fluent-controller.cert.path=/vault/secrets/certs/
    fluent-controller.secret.cert.pem=${your-app.kafka.sslcert}
    fluent-controller.secret.private-key.pem=${your-app.kafka.sslkey}
  {% endif %}

где:

  • your-app.vault.enabled признак использования Secman (если в нем нет необходимости, можно не добавлять данные переменные).

  • your-app.vault.host host для подключения к Secman.

  • your-app.vault.port порт для подключения к Secman.

  • your-app.vault.client.method.namespace namespace в Secman, в котором хранятся секреты.

  • your-app.vault.client.method.authentication тип авторизации в Secman, рекомендуется использовать тип kubernetes.

  • your-app.vault.client.method.config.role роль для авторизации в Secman.

  • your-app.vault.client.method.mount_path путь для авторизации (например - os/stands-vdc01.solution.sbt).

  • fluent.vault.reload.enabled использовать механизм Secman hot reload.

  • your-app.fluentbit-sidecar.conf.reload.enabled позволяет включить автоматический перезапуск fluent-bit процесса,если будет изменение в его файле конфигурации.

  • fluent-controller.conf.path здесь можно переопределить путь к конфигурационному файлу fluent-bit (значение по умолчанию "/fluent-bit/etc/fluent-bit.conf").

Если требуется подключение fluent-controller к vault host по SSL (например https://secman-host:8443, минуя istio egress), то в application.properties нужно добавить переменные:

fluent-controller.secman.ssl.enabled=true
pvm.system.security.ssl.ca-certificates=${путь до СА сертификата root.crt секмана}

Добавить конфигурацию для параметризации fluent-bit и fluent-controller#

В проекте с конфигурациями дистрибутива в дирректорию /config/parameters/ необходимо добавить файл с конфигурацией (пример your-app.fluentbit.sidecar.all.conf) со следующим содержимым:

Файл с конфигурацией fluentbit в случае с интеграцией с Secman#

# your-app.fluentbit.sidecar.all.conf
# K8S
fluent-bit.ose.deployment.spec.template.spec.containers.indicator.securityContext.runAsUser=1001
#Docker образ logger (fluent-bit)
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.docker-image={{ registry }}{{ registry_path_loga }}/loga/fluent-bit@sha256:xxxx

#Лимиты и запросы для контейнера fluent-bit-sidecar
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.limits.cpu=300m
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.limits.memory=300Mi
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.requests.cpu=100m
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.requests.memory=300Mi

#Пути к сертификатам при включенной интеграции с Secman
fluent-bit.ose.configmaps.fluent-bit.data.key.location=/vault/secrets_fluent/certs/private-key.pem
fluent-bit.ose.configmaps.fluent-bit.data.certificate.location=/vault/secrets_fluent/certs/cert.pem
fluent-bit.ose.configmaps.fluent-bit.data.ca.location=/etc/ssl/certs/caCertificates.pem

#Параметры для ConfigMap файла /openshift/configmaps/fluent-bit.yaml
fluent-bit.ose.configmaps.fluent-bit.data.httpListen=0.0.0.0
fluent-bit.ose.configmaps.fluent-bit.data.httpPort=9081
fluent-bit.ose.configmaps.fluent-bit.data.memBufLimit=200MB
fluent-bit.ose.configmaps.fluent-bit.data.hostname=your-app-${distrib.release.version}
fluent-bit.ose.configmaps.fluent-bit.data.name=kafka
fluent-bit.ose.configmaps.fluent-bit.data.path-logs=/fluent-bit/etc/logs/your-app.*
fluent-bit.ose.configmaps.fluent-bit.data.outputs.match=*
fluent-bit.ose.configmaps.fluent-bit.data.read-from-head=On

#Параметры брокеров и topic куда отбрасывается лог
fluent-bit.ose.configmaps.fluent-bit.data.brokers=fluent-bit-data-broker-01.platformv.sbt:9093, fluent-bit-data-broker-02.platformv.sbt:9093, fluent-bit-data-broker-03.platformv.sbt:9093
fluent-bit.ose.configmaps.fluent-bit.data.topics=data_topics
fluent-bit.ose.configmaps.fluent-bit.data.security.protocol=SSL

### fluent-controller - vault ###
your-app.fluentbit-sidecar.vault.enabled=true
### Здесь трафик должен идти через egress на 80 порт
fluent-controller.vault.config.uri=http://${vault.host}
fluent-controller.vault.config.auto_auth.method.namespace=${vault.config.auto_auth.method.namespace}
fluent-controller.vault.config.auto_auth.method.config.role=${vault.config.auto_auth.method.config.role}
fluent-controller.vault.config.auto_auth.method.mount_path=os/stands
fluent-controller.vault.config.auto_auth.method.authentication=kubernetes
fluent-controller.vault.config.retry.maxAttempts=10

# Параметры fluent-controller
# Перечитать конфигурацию fluent-bit
your-app.fluentbit-sidecar.conf.reload.enabled=true
# Использовать механизм Secman Hotreload
your-app.fluentbit-sidecar.vault.reload.enabled=true

Так же добавить конфигурацию (пример your-app.all.conf) : Указать пути к сертификатам в Secman в формате имен секретов (описание нотации см. ниже)

# your-app.all.conf
# Настройки интеграции с vault
your-app.vault.enabled=true
#Пути к сертификатам, в случае использования KV-движка Secman
your-app.kafka.sslcert=$__vault{kv:DOMAIN/A/DEV/xxxx/KV:logger-certs:logger_cert.pem}
your-app.kafka.sslkey=$__vault{kv:DOMAIN/A/DEV/xxxx/KV:logger-certs:logger_private-key.pem}

#Либо пути к сертификатам, в случае использования PKI-движка Secman
your-app.kafka.sslcert=$__vault{pki:DEV/PKI:role-ga-secman-your-app:your-app.solution.sbt:certificate}
your-app.kafka.sslkey=$__vault{pki:DEV/PKI:role-ga-secman-your-app:your-app.solution.sbt:private_key}

xxxx - код компонента (LOGA, MONA, COTE, etc.)

Добавить файлы конфигурации DestinationRule, VirtualService, ServiceEntry в дирректорию k8s/base/istio/config/egress/, для подключения к Secman.
Пример:

          #your-app-se-secman.yaml
          {% if lookup('custom_vars','your-app.vault.enabled') | bool %}
          apiVersion: networking.istio.io/v1alpha3
          kind: ServiceEntry
          metadata:
            name: your-app-se-secman
          spec:
            exportTo:
              - .
            hosts:
              - ${your-app.vault.host}
            ports:
              - name: "secman-ext"
                number: ${your-app.vault.port}
                protocol: 'HTTPS'
            resolution: DNS
            location: MESH_EXTERNAL
          ---
          #your-app-vs-secman.yaml
          apiVersion: networking.istio.io/v1alpha3
          kind: VirtualService
          metadata:
            name: your-app-vs-secman
          spec:
            exportTo:
              - .
            hosts:
              - ${your-app.vault.host}
            gateways:
              - mesh
              - ${your-app.k8s.istio.egress.gateway.name}
            http:
              - match:
                  - gateways:
                      - mesh
                    port: 80
                route:
                  - destination:
                      host: your-app-svc-egressgateway-${distrib.release.version}
                      port:
                        number: 7070
              - match:
                  - gateways:
                      - ${your-app.k8s.istio.egress.gateway.name}
                    port: 7070
                route:
                  - destination:
                      host: ${your-app.vault.host}
                      port:
                        number: ${your-app.vault.port}
          ---
          #your-app-dr-egress-your-app-secman-${distrib.release.version}
          apiVersion: networking.istio.io/v1alpha3
          kind: DestinationRule
          metadata:
            name: your-app-dr-egress-your-app-secman-${distrib.release.version}
          spec:
            exportTo:
              - .
            host: ${your-app.vault.host}
            trafficPolicy:
              loadBalancer:
                simple: ROUND_ROBIN
              portLevelSettings:
                - port:
                    number: ${your-app.vault.port}
                  tls:
                    caCertificates: /vault/secrets/certs-ca/root.crt
                    clientCertificate: /vault/secrets/certs/tls.crt
                    mode: MUTUAL
                    privateKey: /vault/secrets/certs/tls.key
                    sni: ${your-app.vault.host}
            {% endif %}

Пример файла с конфигурацией fluentbit в случае отсутствия интеграции с Secman (сертификаты предоставлены на файловой системе)#

# K8S
fluent-bit.ose.deployment.spec.template.spec.containers.indicator.securityContext.runAsUser=1001
#Docker образ logger (fluent-bit)
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.docker-image={{ registry }}{{ registry_path_loga }}/loga/fluent-bit@sha256:xxxx

#Лимиты и запросы для контейнера fluent-bit-sidecar
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.limits.cpu=300m
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.limits.memory=300Mi
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.requests.cpu=100m
fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.requests.memory=300Mi

#Пути к сертификатам с отключенной интеграцией с Secman
fluent-bit.ose.configmaps.fluent-bit.data.key.location=/fluent-bit/cert/cert-key.pem
fluent-bit.ose.configmaps.fluent-bit.data.certificate.location=/fluent-bit/cert/cert.pem
fluent-bit.ose.configmaps.fluent-bit.data.ca.location=/fluent-bit/cert/root/cacert.pem

#Параметры для ConfigMap файла /openshift/configmaps/fluent-bit.yaml
fluent-bit.ose.configmaps.fluent-bit.data.httpListen=0.0.0.0
fluent-bit.ose.configmaps.fluent-bit.data.httpPort=9081
fluent-bit.ose.configmaps.fluent-bit.data.memBufLimit=200MB
fluent-bit.ose.configmaps.fluent-bit.data.hostname=your-app-${distrib.release.version}
fluent-bit.ose.configmaps.fluent-bit.data.name=kafka
fluent-bit.ose.configmaps.fluent-bit.data.path-logs=/fluent-bit/etc/logs/your-app.*
fluent-bit.ose.configmaps.fluent-bit.data.outputs.match=*
fluent-bit.ose.configmaps.fluent-bit.data.read-from-head=On

#Параметры брокеров и topic куда отбрасывается лог
fluent-bit.ose.configmaps.fluent-bit.data.brokers=fluent-bit-data-broker-01.platformv.sbt:9093, fluent-bit-data-broker-02.platformv.sbt:9093, fluent-bit-data-broker-03.platformv.sbt:9093
fluent-bit.ose.configmaps.fluent-bit.data.topics=data_topics
fluent-bit.ose.configmaps.fluent-bit.data.security.protocol=SSL

### fluent-controller - vault ###
your-app.fluentbit-sidecar.vault.enabled=false
### Здесь трафик должен идти через egress на 80 порт
fluent-controller.vault.config.uri=http://${vault.host}
fluent-controller.vault.config.auto_auth.method.namespace=${vault.config.auto_auth.method.namespace}
fluent-controller.vault.config.auto_auth.method.config.role=${vault.config.auto_auth.method.config.role}
fluent-controller.vault.config.auto_auth.method.mount_path=os/stands
fluent-controller.vault.config.auto_auth.method.authentication=kubernetes
fluent-controller.vault.config.retry.maxAttempts=10

# Параметры fluent-controller
# Перечитать конфигурацию fluent-bit
your-app.fluentbit-sidecar.conf.reload.enabled=true
# Использовать механизм Secman Hotreload
your-app.fluentbit-sidecar.vault.reload.enabled=false

Без интеграции Secman, не нужно заполнять значения your-app.kafka.sslcert и your-app.kafka.sslkey

#Пути к сертификатам, в случае использования KV-движка Secman
your-app.kafka.sslcert=
your-app.kafka.sslkey=

В файле с конфигурацией fluentbit, нужно изменить значения параметров, в случае работы без интеграции с Secman и при инициализации SSL на Egress#

#Параметры брокеров и topic куда отбрасывается лог
fluent-bit.ose.configmaps.fluent-bit.data.brokers=your_app-svc-egress-kafka-unver.${your_app.istio.namespace}.svc.cluster.local:19093
fluent-bit.ose.configmaps.fluent-bit.data.security.protocol=plaintext

### fluent-controller - vault ###
your-app.fluentbit-sidecar.vault.enabled=false

# Использовать механизм Secman Hotreload
your-app.fluentbit-sidecar.vault.reload.enabled=false

Примечание: В brokers указывается созданный Service для интеграции с kafka через Egress. Информацию о нем можно найти в пункте "Интеграция с kafka через egress (инициализация SSL средствами Egress)".

Описание формата имени для KV-секрета#

$__vault{kv:path/to/secret:secret_name:key_name}

где:

Часть нотации

Описание

$__vault

специальный маркер/placeholder для идентификации, что секрет должен быть взять из vault-хранилища (например, Secman)

kv

тип, из которого необходимо брать секрет. Другой возможный тип - pki.

path/to/secret

путь к секрету

secret_name

имя секрета

key_name

ключ значения в секрете

Пример значения:

$__vault{kv:DEV/LOGA/OM/KV:logger-kafka-certs:logger_cert.pem}

Описание формата имени для PKI-секрета#

Все выпускаемые сертификаты подписываются SecMan (т.е. issuer=SecMan). Это значит, что внешние системы, в которые происходят обращения с этими сертификатами должны доверять SecMan (в их CA должен быть добавлен сертификат SecMan).

$__vault{pki:path/to/pki/secret:role:common-name:secret_type}

где:

Часть нотации

Описание

$__vault

специальный маркер/placeholder для идентификации, что секрет должен быть взять из vault (например, secman)

pki

тип, из которого необходимо брать секрет. Другой возможный тип - kv.

path/to/pki/secret

путь к pki секрету

role

имя роли, которой предоставлен доступ к секрету в Secman

common-name

CN, идентифицирующий, клиента, для которого выпускается сертификат

secret_type

тип секрета, возможные значения (certificate, private_key)

Пример значения:

$__vault{pki:DEV/PKI:role-ga-secman-your-app:your-app.solution.sbt:certificate}

Добавить в deployment монтирование данных из configMap#

apiVersion: apps/v1
kind: Deployment

spec:

  template:

    spec:
      containers:

        #для контейнера вашего приложения
        - envFrom:
          volumeMounts:
            - name: logback-xml
              mountPath: '/opt/your-app/conf'
            - name: logsshare
              mountPath: '/fluent-bit/etc/logs'
      volumes:
        - name: logback-xml
          configMap:
            name: logback-xml
            defaultMode: 256
        - name: your-app-properties
          configMap:
            name: your-app-props
            defaultMode: 256
        - name: logsshare
          emptyDir: {}
        - name: fluent-bit-tmp
          emptyDir: {}
        {% if your-app.push_collector.api_key.enabled | bool %} #При использовании дополнительных секретов
        - name: fluent-controller-external-conf #При использовании дополнительных секретов, создать пустую директорию по пути /fluent-bit/etc/ext
          emptyDir: {}
        {% endif %}
        - name: volume-conf-fluent-bit-sidecar
          configMap:
            name: volume-conf-fluent-bit-sidecar
            defaultMode: 256
        {% if your-app.fluentbit-sidecar.vault.enabled | bool %} #При использовании Secman нужна пустая директория, в которую fluent-controller будет загружать сертификаты из secman
        - name: fluent-controller-certs-dir
          emptyDir: {}
        {% endif %}
        - name: ca-cert                       #root сертификат не считаем secrets
          configMap:
            name: your-app-secret-ca-${distrib.release.version}
            defaultMode: 256
        - name: fluent-controller-properties
          configMap:
            name: your-app-cm-fluent-controller.${distrib.release.version}
            defaultMode: 256

Добавить в deployment подключение fluent-bit-sidecar#

apiVersion: apps/v1
kind: Deployment
metadata:

spec:

  template:

    spec:
      containers:

        - name: fluent-bit-sidecar
          image: '${fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.docker-image}'
          imagePullPolicy: Always
          securityContext:
            runAsNonRoot: true
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          resources:
              limits:
                cpu: ${fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.limits.cpu}
                memory: ${fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.limits.memory}
              requests:
                cpu: ${fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.requests.cpu}
                memory: ${fluent-bit.ose.deployment.spec.template.spec.containers.fluent-bit.resources.requests.memory}
          env:       #В env можно положить необходимые статичные параметры, для обогащения ими логов
            - name: pod
              valueFrom:
                fieldRef:
                  appVersion: v1
                  fieldPath: metadata.name
            - name: spring.config.additional-location #Путь к конфигурации fluent-controller
              value: file:/vault/secrets/properties/application.properties
          volumeMounts:
       {% if not lookup('vars', 'your_app.k8s.istio.egress.kafka.target.enabled') | bool %} #При инициализации SSL на Egress, сертификаты для fluent-bit не требуются
       {% if your-app.fluentbit-sidecar.vault.enabled | bool %}   #При использовании Secman подключаем emptyDir для загрузки туда fluent-controller-ом сертификатов fluent-bit
            - name: fluent-controller-certs-dir
              mountPath: '/vault/secrets/certs'
       {% else %}                              #Иначе берем сертификаты не из Secman
            - name: cert-vol
              mountPath: '/vault/secrets/certs'
       {% endif %}
       {% endif %}
            - name: fluent-controller-properties  #Конфигурация fluent-controller
              mountPath: /vault/secrets/properties
            - name: ca-cert               #root сертификат не считаем secrets
              mountPath: '/vault/secrets/certs-ca'
            - name: logsshare
              mountPath: '/fluent-bit/etc/logs'
            - name: volume-conf-fluent-bit-sidecar
              mountPath: '/fluent-bit/etc'
        {% if your_app.remote_write.push_collector.api_key.enabled | bool %}
        {% if your-app.push_collector.api_key.enabled | bool %} #При использовании api ключей
            - name: fluent-controller-external-conf #При использовании дополнительных секретов, создать пустую директорию по пути /fluent-bit/etc/ext
              mountPath: '/fluent-bit/etc/ext'
        {% else %}
            - name: your-app-fluent-bit-secrets  #секрет с API-ключами, если работаем без Secman
              mountPath: '/fluent-bit/etc/ext'
        {% endif %}
        {% endif %}

Добавлены параметры управления памятью при обработке потока событий при переходе хоста кластера контейнеризации на SberLinux. Для уменьшения потребления памяти LOGA-sidecar, можно добавить параметр в env:

            - name: logger.fluentbit-sidecar.jemalloc.options
              value: 'confirm_conf:true,narenas:1,thp:never'

где

narenas - параметр регулирующий количество блоков памяти и потоков для работы с ними (арен), уменьшение данного значения уменьшает использование памяти процессом, увеличение количества блоков снижает конкуренцию, но может увеличить фрагментацию памяти. По умолчанию его значение равно 4 * количество_ЦПУ или 1 при одном ЦПУ.

арена - блок памяти и потоки для работы с ними

thp - управляет использованием transparent hugepage, значение "always" включает использование transparent hugepage, значение "never" - отключает

Добавить манифесты ISTIO для Kafka (KFKA)#

Интеграция с kafka в обход egress (инициализация SSL средствами самого fluent-bit)#

Для работы в данном режиме интеграции, требуется создать ServiceEntry следующего вида:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: your_app-se-kafka-${distrib.release.version}
  labels:
    group: ulogger
spec:
  exportTo:
    - .
  hosts:
    - ignored
  ports:
    - number: ${your_app.kafka.ports}
      name: tcp-kafka
      protocol: TCP
  location: MESH_EXTERNAL
  resolution: NONE

'${your_app.kafka.ports}' - порт kafka, например 9093.

Интеграция с kafka через egress (инициализация SSL средствами Egress)#

Данная интеграция, возможна только в случае использования контрольной панели SSM 3.9.1, а так же при условии соответствия настроек валидатора, предоставляемой функциональности SSM 3.9.1 (а именно должен быть разрешен префикс имени порта kafka*).

Для работы в данном режиме интеграции, требуется создать манифесты следующего вида:

{% if lookup('custom_vars', 'your_app.k8s.istio.egress.kafka.target.enabled') | default('false') | bool %}
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: your_app-dr-kafka
spec:
  exportTo:
    - '.'
{% set list_host = vars['your_app.k8s.istio.egress.kafka.hosts'].split(',') %}
{% set item_host = list_host[0] %}
  host: {{ item_host }}
  trafficPolicy:
    tls:
      mode: MUTUAL
      clientCertificate: /vault/secrets/certs/tls.crt
      privateKey: /vault/secrets/certs/tls.key
      caCertificates: /vault/secrets/certs-ca/root.crt
  workloadSelector:
    matchLabels:
      app: ${your_app.k8s.istio.egress.deployment.metadata.name}
{% endif %}

Примечание: Пути в clientCertificate, privateKey, caCertificates зависят от конфигурации Вашего Egress. Значение параметра your_app.k8s.istio.egress.kafka.hosts (адреса bootstap-серверов через запятую, без пробелов) для данного шаблона должно быть заполнено в формате: host1,host2,host3

{% if lookup('custom_vars', 'your_app.k8s.istio.egress.kafka.target.enabled') | default('false') | bool %}
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: your_app-dr-svc-kafka
spec:
  exportTo:
    - '.'
  host: your_app-svc-egress-kafka-${distrib.release.version}.${your_app.istio.namespace}.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
      sni: your_app-svc-egress-kafka-${distrib.release.version}.${your_app.istio.namespace}.svc.cluster.local
{% endif %}

Примечание: your_app.istio.namespace - имя проекта, в котором производится настройка интеграции.

{% if lookup('custom_vars', 'your_app.k8s.istio.egress.kafka.target.enabled') | default('false') | bool %}
{% set list_host = vars['your_app.k8s.istio.egress.kafka.hosts'].split(',') %}
{% set list_port = (vars['your_app.k8s.istio.egress.kafka.ports'] |  string).split(',') %}
{% set item_host = list_host[0] %}
{% set item_port = list_port[0] %}
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: your_app-se-kafka-${distrib.release.version}
spec:
  exportTo:
    - .
  hosts:
    - {{ item_host }}
  location: MESH_EXTERNAL
  ports:
    - number: {{ item_port }}
      name: kafka-{{ item_port }}
      protocol: kafka
  resolution: DNS
  endpoints:
{% for item_host in list_host %}
{% set item_port = list_port[loop.index-1] %}
    - address: {{ item_host }}
      ports:
        kafka-{{ item_port }}: {{ item_port }}
{% endfor %}
{% endif %}

Примечание: Значение параметра your_app.k8s.istio.egress.kafka.ports (порты bootstap-серверов через запятую, без пробелов) для данного шаблона должно быть заполнено в формате: 9093,9093,9093

{% if lookup('custom_vars', 'your_app.k8s.istio.egress.kafka.target.enabled') | default('false') | bool %}
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: your_app-gw-kafka
spec:
  selector:
    app: ${your_app.k8s.istio.egress.deployment.metadata.name}
    istio: ${your_app.k8s.istio.egress.deployment.metadata.name}
  servers:
    - hosts:
      - your_app-svc-egress-kafka-${distrib.release.version}.${your_app.istio.namespace}.svc.cluster.local
      port:
        name: kafka-19093
        number: 19093
        protocol: kafka
      tls:
        mode: ISTIO_MUTUAL
{% endif %}
{% if lookup('custom_vars', 'your_app.k8s.istio.egress.kafka.target.enabled') | default('false') | bool %}
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: your_app-vs-kafka
spec:
  exportTo:
    - .
  gateways:
    - your_app-gw-kafka
    - mesh
  hosts:
    - your_app-svc-egress-kafka-${distrib.release.version}.${your_app.istio.namespace}.svc.cluster.local
  tcp:
    - match:
        - gateways:
            - mesh
          port: 19093
      route:
        - destination:
            host: your_app-svc-egress-kafka-${distrib.release.version}
            port:
              number: 19093
          weight: 100
    - match:
        - gateways:
            - your_app-gw-kafka
          port: 19093
      route:
        - destination:
{% set list_host = vars['your_app.k8s.istio.egress.kafka.hosts'].split(',') %}
{% set list_port = (vars['your_app.k8s.istio.egress.kafka.ports'] |  string).split(',') %}
{% set item_host = list_host[0] %}
{% set item_port = list_port[0] %}
            host: {{ item_host }}
            port:
              number: {{ item_port }}
          weight: 100
{% endif %}
{% if lookup('custom_vars', 'your_app.k8s.istio.egress.kafka.target.enabled') | default('false') | bool %}
apiVersion: v1
kind: Service
metadata:
  name: your_app-svc-egress-kafka-${distrib.release.version}
spec:
  ports:
    - name: kafka-19093
      protocol: TCP
      port: 19093
      targetPort: 19093
  selector:
    app: ${your_app.k8s.istio.egress.deployment.metadata.name}
    istio: ${your_app.k8s.istio.egress.deployment.metadata.name}
  sessionAffinity: None
  type: ClusterIP
{% endif %}

Выше приведены примеры шаблонов манифестов, так же информацию о настройке интеграции, можно прочесть в документации Platform V Synapse Service Mesh (3.9.1) в разделе "Руководство прикладного разработчика".

Рассчитать лимиты sidecar#

'${your-app.fluent-bit.cpuLimit}' - рекомендуемое значение 300m-400m, уточняется во время проведения НТ; '${your-app.fluent-bit.memLimit}' - можно рассчитать по приблизительной формуле your-app.fluent-bit.memLimit = A + A * 0.1 + ROUND(N / 10) * 5

где A = 300 MB + Mem_Buf_Limit (всех INPUT плагинов, MB) + rdkafka.queue.buffering.max.kbytes (всех OUTPUT плагинов, MB); N - количество узлов в кластере kafka, на каждые 10 узлов в кластере для service discovery необходимо дополнительно порядка 5 МБ памяти (округление выполняется в большую сторону) Так же, в формулу добавляем объем памяти, потребляемой контроллером (~50 mb).