Как создать простого бота ChatOps из Kafka, Grafana, Prometheus и Slack

1656683416 kak sozdat prostogo bota chatops iz kafka grafana prometheus i

Люк Рассел

В данном руководстве описан подход к созданию простого бота ChatOps, использующего Slack и Grafana для запроса состояния системы. Идея состоит в том, чтобы иметь возможность проверить состояние вашей системы с помощью разговорного интерфейса, если вы не за рабочим столом, но все еще имеете базовое подключение, например, на своем телефоне:

1*WveK_6zazTq19xMOmSAT6w

Учебник разделен на две части: первая часть настроит инфраструктуру для мониторинга Kafka с помощью Prometheus и Grafana, а вторая часть создаст простого бота из Python, который может отвечать на вопросы и возвращать графики Grafana через Slack.

Уведомление является родной функцией Grafana, то есть возможность отправлять уведомления на канал Slack, если условия нарушены. Бот Slack – это немного другой инструмент. Он сможет ответить на простые вопросы о состоянии системы, чтобы помочь с устранением неисправностей.

Цель состоит в том, чтобы разработать что-то, работающее внутри брандмауэра, без доступа к прокси-серверу или доступа к любым сторонним службам, таким как Amazon S3. Поэтому изображения графов генерируются в локальной файловой системе и загружаются как вложенные файлы в Slack во избежание размещения в публичной инфраструктуре.

1*DCM8T-qqEnWuNsgp3kmvWQ

компоненты

Основными компонентами здесь являются:

Кафка: Платформа потоковой передачи сообщений. Это система, которую мы заинтересованы контролировать.

Прометей: система мониторинга для сбора показателей через заданные промежутки времени, оценки правил и запуска предупреждений.

prometheus-jmx-exporter: Сборник Prometheus, который может очищать и открывать данные JMX, что позволяет собирать показатели от Kafka.

Графана: Платформа визуализации, обычно используемая для визуализации данных временных рядов для аналитики инфраструктуры и программ. Это позволяет графически отображать собранные показатели.

Томно: программа обмена сообщениями, которая позволит нам взаимодействовать с нашим чат-ботом.

Слак бот: Описанный во второй части ниже простой скрипт Python, который может получать графики из Grafana и загружать их в Slack.

Эти шаги основаны на мониторинге Kafka, но тот же общий подход применим для интеграции с другими службами.

Давайте начнем

Полный исходный код доступен здесь.

предпосылки

  • Базовые знания Python: код, написанный для Python 3.6.
  • Docker: docker-compose используется для запуска брокера Kafka.
  • kafkacat: это полезный инструмент для взаимодействия с Kafka (например, публикация сообщений по темам)

Если вы спешите все запустить, просто клонируйте проект по ссылке выше и запустите docker-compose up -d.

Остаток этого руководства состоит из двух частей. В первой части описано, как настроить инфраструктуру мониторинга, а во второй описан код Python для бота Slack.

Часть первая: Соберите стек мониторинга

Мы используем Grafana и Prometheus, чтобы настроить стек мониторинга. Сервисом, который будет отслеживаться, является Kafka, что означает, что нам понадобится мост для экспорта данных JMX из Kafka в Prometheus. Этот образ докера prometheus-jmx-exporter отлично выполняет эту роль. Эта служба извлекает показатели из JMX-сервера Kafka и предоставляет их через HTTP, чтобы Prometheus мог их опрашивать.

Чтобы включить метрику JMX на сервере Kafka, нам нужно применить некоторые настройки конфигурации к серверу Kafka и связать kafka-jmx-exporter контейнер с сервером Kafka:

  1. Обеспечить KAFKA_JMX_OPTSи JMX_PORT переменные среды устанавливаются на Кафка контейнер
  2. Обеспечить kafka-jmx-exporter и Кафка контейнеры находятся в одной сети (backend)
  3. Обеспечить JMX_HOST значение для kafka-jmx-exporter контейнер отвечает KAFKA_ADVERTISED_HOST_NAME на Кафка контейнер
  4. Обеспечить KAFKA_ADVERTISED_HOST_NAME имеет соответствующую запись в /etc/hosts.
  5. Pin wurstmeister/kafka к версии 1.0.0. Может возникнуть проблема с настройкой JMX с предыдущими версиями wurstmeister/kafka изображение
  6. Pin prom/prometheus к версии v2.0.0
  7. Для этого обновления требуется одно изменение совместимости, а именно переименование target_groups к static_configs в prometheus.yml файл.

Полученные разделы docker-compose.yml должны выглядеть следующим образом:

    kafka:
    image: wurstmeister/kafka:1.0.0
    ports:
      - "9092:9092"
      - "1099:1099"
    depends_on:
      - zookeeper
    environment:
      - KAFKA_ADVERTISED_PORT=9092
      - KAFKA_BROKER_ID=1
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper
      - KAFKA_ADVERTISED_HOST_NAME=kafka
      - ZOOKEEPER_CONNECTION_TIMEOUT_MS=180000
      - KAFKA_CREATE_TOPICS=transactions:1:1
      - KAFKA_JMX_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka -Dcom.sun.management.jmxremote.rmi.port=1099
      - JMX_PORT=1099
    networks:
      - backend

  kafka-jmx-exporter:
    build: ./prometheus-jmx-exporter
    ports:
      - "8080:8080"
    links:
      - kafka
    environment:
      - JMX_PORT=1099
      - JMX_HOST=kafka
      - HTTP_PORT=8080
      - JMX_EXPORTER_CONFIG_FILE=kafka.yml
    networks:
        - backend

  prometheus:
    ports:
      - 9090:9090/tcp
    image: prom/prometheus:v2.0.0
    volumes:
      - ./etc:/etc/prometheus
      - prometheus_data:/prometheus
    links:
      - kafka-jmx-exporter
    restart: always
    networks:
        - backend
docker-compose.yml

Grafana можно настроить для чтения файла информационной панели JSON при запуске – такой файл предоставляется в etc/Kafka.jsonпредварительно сконфигурированный с образцом информации мониторинга Kafka.

Запустите стек мониторинга

Если все настроено должным образом, вы сможете начать стек docker-compose up -d. Затем отправьте несколько сообщений Кафцы с помощью kafkacat:

for i in `seq 1 3`;
do
        echo "hello"  | kafkacat -b kafka:9092 -t transactions
done

Просмотрите информационную панель Kafka по адресу, и вы увидите что-нибудь вроде этого:

1*MMFgf0tEOfcZ_6vB7bl1Cw

Часть вторая: Создание Slack Bot

Имея инфраструктуру мониторинга, теперь мы можем написать наш простой бот Slack. В этом разделе описаны этапы создания бота и некоторые фрагменты кода.

Первым шагом является создание и регистрация бота на веб-сайте Slack.

0*DZFd81DpC6d6BdOO
Создайте бота

На следующем экране можно настроить детали, например добавить значок и описание для бота.

Когда ваш бот будет создан, пригласите его куда-нибудь. Вы можете создать частный канал для тестирования:

1*710brQbgNbc5Z1OIUBWDww
Создайте канал для тестирования

Затем пригласите бота на тестовый канал с помощью /invite @handy_bot:

1*tlgyhs1wU1Gh1IXWgxCzYQ
Пригласите бота

Наш бот ответит на несколько простых вопросов, на которые мы определимся строки 1–3:

		self.respond_to = ['list graph shortcuts',
                           'graph <shortcut>',
                           'help']
        self.help_msg = '```\n'
        for answer in self.respond_to:
            self.help_msg += f'{answer}\n'
        self.help_msg += '```'

в app.pyмы прочтем наш конфигурационный файл и запустим бота:

def main(arguments=None):
    if not arguments:
        arguments = docopt(__doc__)
    config = configure(arguments['--config-file'])
    mybot = SlackBot(config)
    mybot.start()

The start способ выглядит так:

    def start(self):
        if self.slack_client.rtm_connect():
            print("Bot is alive and listening for messages...")
            while True:
                events = self.slack_client.rtm_read()
                for event in events:
                    if event.get('type') == 'message':
                        # If we received a message, read it and respond if necessary
                        self.on_message(event)

                time.sleep(1)

линия 2: создает подключение к Slack API

строка 5: на заданной частоте опроса (1 секунда) проверить наличие новых событий

строка 7: если событие является сообщением, перейдите к on_message метод, и если мы получим ответ от этого метода, распечатаем его на канал, на котором было опубликовано сообщение:

    def on_message(self, event):
       ...
        full_text = event.get('text', '') or ''

        if full_text.startswith(self.bot_id):
            question = full_text[len(self.bot_id):]
            if len(question) > 0:
                question = question.strip().lower()
                channel = event['channel']
                ...
                elif 'graph' in question:
                    self.respond(channel, 'Please wait...', True)

The on_message метод, где мы решим как реагировать на сообщения, которые получает бот. The generate_and_upload_graph метод является наиболее интересным ответом. Идея состоит в том, чтобы запустить временный контейнер Docker, чтобы сделать снимок экрана.

Grafana имеет возможность отобразить любой график в формате PNG. Однако в последнем выпуске Grafana есть ошибка phantomjs библиотеки, которая используется внутренне для создания изображений.

Более надежной утилитой для безголового просмотра является Puppeteer, основанный на Google Chrome, и кто-то уже завернул это в образ Docker. Это дает нам возможность экспериментировать с API Docker Python:

    def generate_and_upload_graph(self, filename, url, channel):
        dir_name = os.path.dirname(os.path.abspath(__file__))

        client = docker.APIClient()

        container = client.create_container(
            image="alekzonder/puppeteer:1.0.0",
            command=f'screenshot \'{url}\' 1366x768',
            volumes=[dir_name],

            host_config=client.create_host_config(binds={
                dir_name: {
                    'bind': '/screenshots'
                }
            }, network_mode="host")
        )

        files1 = prepare_dir(dir_name)

        client.start(container)

        # Poll for new files
        while True:
            time.sleep(2)
            files2 = os.listdir(dir_name)
            new = [f for f in files2 if all([f not in files1, f.endswith(".png")])]
            for f in new:
                with open(f, 'rb') as in_file:
                    ret = self.slack_client.api_call(
                        "files.upload",
                        filename=filename,
                        channels=channel,
                        title=filename,
                        file=io.BytesIO(in_file.read()))
                    if 'ok' not in ret or not ret['ok']:
                        print('File upload failed %s', ret['error'])
                os.remove(f)
            break

строки 6:16: используйте API Docker Python для динамического создания контейнера на основе alekzonder/puppeteer изображение

строка 13: привязывает текущий каталог к /screenshots в контейнере, чтобы мы могли записать файл в доступное место

строка 15: наборы network_mode=host чтобы контейнер мог получить доступ к Grafana на локальном хосте

строки 23:38 будет наблюдать за добавлением новых изображений в каталог и загружать их

Запустите бота

Когда стек мониторинга запущен, вы можете запустить бота. от slackbot каталог:

$ python bot.py --config=config.yaml 
Bot is alive and listening for messages...

Бот может отвечать на несколько основных запросов, как показано ниже, и вы, конечно, можете адаптировать возможности бота к конкретным системам, которые вы хотите контролировать.

1*IoEdeXpri05C-NKdzx8q9Q
Ответ на справочное сообщение

Вывод

Боты ChatOps могут быть полезными помощниками, которые помогут вам управлять запущенной системой. Это упрощенный вариант использования, но общую концепцию можно расширить для поддержания более сложных требований.

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

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

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