Сборка логов в kubernetes. Установка EFK стека с LDAP интеграцией. (Bitnami, opendistro)

от автора

Постепенно эволюционируя, каждая организация переходит от ручного grep логов к более современным инструментам для сбора, анализа логов. Если вы работаете с kubernetes, где приложение может масштабироваться горизонтально и вертикально, вас просто вынуждают отказаться от старой парадигмы сбора логов. В текущее время существует большое количество вариантов систем централизованного логирования, причем каждый выбирает наиболее приемлемый вариант для себя. В данной статье пойдет речь о наиболее популярном и зарекомендовавшем себя стэке Elasticsearch + Kibana + Fluentd в связке с плагином OpenDistro Security. Данный стэк полностью open source, что придает ему особую популярность.

Проблематика

Нам необходимо было наладить сборку логов с кластера kubernetes. Из требований:

  • Использовать только открытые решения.

  • Сделать очистку логов.

  • Необходимо прикрутить LDAP, для разграничения прав.

Пререквизиты

Данный материал предполагает:

  • Имеется установленный kuberenetes 1.18 или выше (ниже версию не проверяли)

  • Установленный пакетный менеджер helm 3

Немного о helm chart

Наиболее популярным способом установки приложения в kubernetes является helm. Helm это пакетный менеджер, с помощью которого можно подготовить набор компонентов для установки и связать их вместe, дополнив необходимыми метриками и конфигурацией.

В своей практике мы используем helm chart от компании bitnami(подразделение vmware)

  • собраны open source продукты на все случаи жизни.

  • корпоративные стандарты по разработке чатов и докер образов

  • красивая документация

  • проект живой и активно поддерживается сообществом

Выбор стека

Во многом выбор стека технологий определило время. С большой долей вероятностью два года назад мы бы деплоили ELK стек вместо EFK и не использовали helm chart.

Fluentd часто упоминается в документации, широко распространен, имеет большое количество плагинов, на все случаи жизни. К тому же у нас есть человек, который после обучение в rebrain и очень хотел внедрить fluentd.

Elasticsearch и kibana поставляются с открытой лицензией, однако плагины для security и других вкусностей идут под иной лицензией. Однако компания Amazon выпустила плагины Open Distro, которые покрывают оставшийся функционал под открытой лицензией.

Схема выглядит примерно так

Хорошим тоном является вынесение инфраструктурных компонентов в отдельный кластер, поэтому зеленым прямоугольником выделена та часть, которая должна быть установлена на все кластера в которых должны собираться логи.

Минимальный деплой EFK стека (без Security)

Сборка EFK стека была произведена по статье Collect and Analyze Log Data for a Kubernetes Cluster with Bitnami’s Elasticsearch, Fluentd and Kibana Charts. Компоменты упакованы в отдельный чат. Исходники можно взять здесь и произвести командой

helm dependency update helm upgrade --install efk . -f values-minimal.yaml

Из исходников values-minimal.yaml

elasticsearch:   volumePermissions:     enabled: true  kibana:   volumePermissions:     enabled: true   elasticsearch:     hosts:     - "efk-elasticsearch-coordinating-only"     port: 9200 # Пропишите свой хост, если используете ингресс   ingress:     enabled: true     hostname: kibana.local # Либо    service:     type: NodePort     port: 30010 fluentd:   aggregator:     enabled: true     configMap: elasticsearch-output     extraEnv:     - name: ELASTICSEARCH_HOST       value: "efk-elasticsearch-coordinating-only"     - name: ELASTICSEARCH_PORT       value: "9200"   forwarder: #    Чтение логов с диска /var/log/containers/* отключено     enabled: false     configMap: apache-log-parser     extraEnv:     - name: FLUENTD_DAEMON_USER       value: root     - name: FLUENTD_DAEMON_GROUP       value: root

Кибана будет доступна по адресу http://minikube_host:30010/, либо http://kibana.local.

Как видим компонент fluentd forwarder не включен. Перед включением парсинга, я рекомендовал бы настроить на определенные логи, иначе еластику может быть послано слишком большое количество логов. Правила для парсинга описаны в файле apache-log-parser.yaml.

Как отправить логи в EFK

Существует много способов, для начала предлагаем либо включить fluentd forwarder, либо воспользоваться простейшим приложением на python. Ниже пример для bare metal. Исправьте FLUENT_HOST FLUENT_PORT на ваши значения.

cat <<EOF | kubectl apply -f - apiVersion: apps/v1 kind: Deployment metadata:   name: helloworld   labels:     app: helloworld spec:   replicas: 1   template:     metadata:       name: helloworld       labels:         app: helloworld     spec:       containers:         - name: helloworld           image: sergbs/django-hello-world:1           imagePullPolicy: Always           ports:             - containerPort: 8000           env:             - name: FLUENT_HOST               value: "efk-fluentd-headless"             - name: FLUENT_PORT               value: "24224"   selector:     matchLabels:       app: helloworld --- apiVersion: v1 kind: Service metadata:   name: helloworld spec:   selector:     app: helloworld   ports:     - port: 8000       nodePort: 30011   type: NodePort EOF

По ссылке http://minikube_host:30011/ Будет выведено «Hello, world!» И лог уйдет в elastic

Пример

Включить fluentd forwarder, он создаст daemon set, т.е. запустится на каждой ноде вашего кубернетеса и будет читать логи docker container-ов.

Добавить в ваш докер контейнер драйвер fluentd, тем более можно добавлять более одного драйвера

Добавить в ваше приложение библиотеку, которая будет напрямую логировать. Пример приложения на python. Используйте его, как отладочное средство при установке EFK.

И как показывает практика, логировать напрямую эффективный, но далеко не самый надежный способ. Даже если вы логируете сразу в fluentd и в консоль. В случае потери конекта, во fluentd часть логов просто не смогут попасть и будут потеряны для него навсегда. Поэтому наиболее надежный способ, это считывать логи с диска для отправки в EFK.

Очистка логов

Для очистки логов используется curator. Его можно включить, добавив в yaml файл:

elasticsearch:   curator:     enabled: true

По умолчанию его конфигурация уже предусматривает удаление через индекса старше 90 дней это можно увидеть внутри подчата efk/charts/elasticsearch-12.6.1.tgz!/elasticsearch/values.yaml

configMaps:   # Delete indices older than 90 days   action_file_yml: |-       ...  	unit: days 	unit_count: 90

Security

Как обычно security доставляет основную боль при настройке и использовании. Но если ваша организация чуть подросла, это необходимый шаг. Стандартом де факто при настройке безопасности является интеграция с LDAP. Официальные плагины от еластика выходят не под открытой лицензией, поэтому приходится использовать плагин Open Distro. Далее продемонстрируем, как его можно запустить.

Сборка elasticsearch c плагином opendistro

Вот проект в котором собирали docker images.

Для установки плагина, необходимо, чтобы версия elasticsearch соответствовала версии плагина.

В quickstart плагина рекомендуется установить install_demo_configuration.sh с демо сертификатами.

FROM bitnami/elasticsearch:7.10.0  RUN elasticsearch-plugin install -b https://d3g5vo6xdbdb9a.cloudfront.net/downloads/elasticsearch-plugins/opendistro-security/opendistro_security-1.12.0.0.zip RUN touch /opt/bitnami/elasticsearch/config/elasticsearch.yml  USER root RUN /bin/bash /opt/bitnami/elasticsearch/plugins/opendistro_security/tools/install_demo_configuration.sh -y -i RUN mv /opt/bitnami/elasticsearch/config/elasticsearch.yml /opt/bitnami/elasticsearch/config/my_elasticsearch.yml COPY my_elasticsearch.yml /opt/bitnami/elasticsearch/config/my_elasticsearch.yml USER 1001

Есть небольшая магия, ввиду, того что плагин дополняет elasticsearch.yml, а контейнеры bitnami только при старте генерируют этот файл. Дополнительные же настройки они просят передавать через my_elasticsearch.yml

В my_elasticsearch.yml мы изменили настройку, это позволит нам обращаться к рестам elasticsearch по http.

# turn off REST layer  tlsopendistro_security.ssl.http.enabled: false

Сделано это в демонстрационных целях, для облегчения запуска плагина. Если вы захотите включить Rest Layer tls придется добавлять соответствующие настройки во все компоненты, которые общаются с elasticsearch.

Запуск docker-compose с LDAP интеграцией

Запустим проект с помощью docker-compose up , и залогинимся на http://0:5601 под admin/admin

Теперь у нас есть вкладка Security

Можно посмотреть настройку LDAP через интерфейс кибаны

Настройки должны совпадать с файлами конфигурации. Стоит обратить внимание, что плагин хранит свои данные в индексе еластика, и файлы конфигурации применяет при инициализации, т.е. если индекс не создан. Если вы измените файлы позже то вам придется воспользоваться утилитой securityadmin.sh

docker exec -it elasticsearch /bin/bash I have no name!@68ac2255bb85:/$ ./securityadmin_demo.sh Open Distro Security Admin v7 Will connect to localhost:9300 ... done Connected as CN=kirk,OU=client,O=client,L=test,C=de Elasticsearch Version: 7.10.0 Open Distro Security Version: 1.12.0.0 Contacting elasticsearch cluster 'elasticsearch' and wait for YELLOW clusterstate ... Clustername: elasticsearch Clusterstate: YELLOW Number of nodes: 1 Number of data nodes: 1 .opendistro_security index already exists, so we do not need to create one. Populate config from /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/ Will update '_doc/config' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/config.yml     SUCC: Configuration for 'config' created or updated Will update '_doc/roles' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/roles.yml     SUCC: Configuration for 'roles' created or updated Will update '_doc/rolesmapping' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/roles_mapping.yml     SUCC: Configuration for 'rolesmapping' created or updated Will update '_doc/internalusers' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/internal_users.yml     SUCC: Configuration for 'internalusers' created or updated Will update '_doc/actiongroups' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/action_groups.yml     SUCC: Configuration for 'actiongroups' created or updated Will update '_doc/tenants' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/tenants.yml     SUCC: Configuration for 'tenants' created or updated Will update '_doc/nodesdn' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/nodes_dn.yml     SUCC: Configuration for 'nodesdn' created or updated Will update '_doc/whitelist' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/whitelist.yml     SUCC: Configuration for 'whitelist' created or updated Will update '_doc/audit' with /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/audit.yml     SUCC: Configuration for 'audit' created or updated Done with success I have no name!@68ac2255bb85:/$  

настройка Ldap

Для настройки интеграции с LDAP необходимо заполнить соответствующие секции в elastisearch-opendistro-sec/config.yml, ссылка на официальную документацию по authentication

config:   dynamic:     authc:       # тут можно настроить авторизацию	           authz:       # а здесь аутентификацию	

В случае с Active Directory, необходимо будет изменить конфигурационный файл примерно так:

       # тут можно настроить авторизацию           ldap:         ...             hosts:               - ldaphost:389             bind_dn: cn=LDAP,ou=Example,dc=example,dc=ru             password: CHANGEME             userbase: 'DC=example,DC=ru'             usersearch: '(sAMAccountName={0})'             username_attribute: sAMAccountName 

Не забудьте воспользоваться securityadmin.sh после изменения конфигурации. Процедура была описана в предыдущем параграфе.

Установка EFK + Opendistro в kubernetes

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

helm upgrade --install efk . -f values.yaml  

Нам необходимо будет

Для настройка OpenDistro Security plugin мы скопировали файл конфигурации, которые поместим в секреты kubernetes.

  extraVolumes:   - name: config     secret:       secretName: opendistro-config       items:         - key: config.yml           path: config.yml   - name: roles-mapping     secret:       secretName: opendistro-config       items:         - key: roles_mapping.yml           path: roles_mapping.yml   extraVolumeMounts:     - mountPath: /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/config.yml       subPath: config.yml       name: config     - mountPath: /opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig/roles_mapping.yml       subPath: roles_mapping.yml       name: roles-mapping

Чтобы настройки применялись при команде helm upgrade, мы сделали job, который будет запускаться при каждой команде helm upgrade

apiVersion: batch/v1 kind: Job metadata:     name: opendistro-config-reload     labels:         app.kubernetes.io/managed-by: {{.Release.Service | quote }}         app.kubernetes.io/instance: {{.Release.Name | quote }}     annotations:         "helm.sh/hook": post-upgrade         "helm.sh/hook-delete-policy": hook-succeeded spec:     template:         metadata:             name: config-reload             labels:                 app.kubernetes.io/managed-by: {{.Release.Service | quote }}                 app.kubernetes.io/instance: {{.Release.Name | quote }}         spec:             initContainers:                 - name: "wait-for-db"                   image: "alpine:3.6"                   command:                       - 'sh'                       - '-c'                       - >                           until nc -z -w 2 efk-elasticsearch-coordinating-only 9300 && echo elastic is ok; do                             sleep 2;                           done;             containers:                 - name: opendistro-config-reload                   image: "{{ .Values.elasticsearch.image.registry }}/{{ .Values.elasticsearch.image.repository}}:{{ .Values.elasticsearch.image.tag }}"                   imagePullPolicy: {{ .Values.elasticsearch.image.pullPolicy | quote }}                 {{- if .Values.elasticsearch.master.securityContext.enabled }}                   securityContext:                     runAsUser: {{ .Values.elasticsearch.master.securityContext.runAsUser }}                  {{- end }}                   command:                     - 'bash'                     - '-c'                     - >                        "/opt/bitnami/elasticsearch/plugins/opendistro_security/tools/securityadmin.sh" -h efk-elasticsearch-coordinating-only -cd "/opt/bitnami/elasticsearch/plugins/opendistro_security/securityconfig" -icl -key "/opt/bitnami/elasticsearch/config/kirk-key.pem" -cert "/opt/bitnami/elasticsearch/config/kirk.pem" -cacert "/opt/bitnami/elasticsearch/config/root-ca.pem" -nhnv             restartPolicy: Never     backoffLimit: 1 

Итоги

Если вы собираетесь организовать централизованную сборку логов для приложений под управление kubernetes, данный вариант мог бы стать вполне обоснованным решением. Все продукты поставляются под открытыми лицензиями. В статье приведена заготовка из которой можно создать production ready решение. Спасибо за внимание!

ссылка на оригинал статьи https://habr.com/ru/post/537736/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *