WSL и Docker для локального развертывания Apache Kafka с GUI и всеми компонентами в контейнере: моя реальная история поиска веб-интерфейса и настройки портов (начало).
Развертывание Kafka на Windows с Docker в WSL
В конце августа 2024 года команда serverless-платформы Upstash, на которой у меня есть рабочий инстанс Apache Kafka, разослала своим пользователям «письма счастья», о том, что через полгода поддержка этого брокера сообщений прекращается. Поиск бесплатного аналога не дал результатов, поэтому пришлось разворачивать собственный экземпляр Kafka. Исходных требований к нему у меня было совсем немного:
- возможность запуска по желанию в любое время суток;
- невысокое потребление ресурсов обычного офисного ноутбука с ОС Windows;
- наличие всех необходимых компонентов для работы платформы, таких как Zookeeper, JMX и пр., а также дополнительных модулей (ksqlDB, Kafka Connect, REST Proxy, Schema Registry);
- наличие GUI.
Требования 1 и 2 можно реализовать с помощью Docker-контейнеров, запускаемых на WSL (Windows Subsystem for Linux) — подсистеме Windows для Linux, позволяющей запускать среду Linux на ОС Windows без отдельной виртуальной машины. С помощью Windows Subsystem for Linux (WSL) можно запускать Linux в оболочке Bash, чтобы работать с CLI-интерфейсом и приложениями Linux. В отличие от полноценной виртуальной машины, WSL потребляет сильно меньше ресурсов (ЦП, памяти и хранилища), а также может обращаться к файлам Windows в Linux.
А чтобы изолировать приложения друг от друга, исключая конфликты с взаимозависимостями, WSL поддерживает контейнеризацию. Самым известным инструментом контейнеризации сегодня является Docker, который позволяет упаковать приложение со всем его окружением и зависимостями в контейнер, чтобы запустить его на любой Linux-подобной системе. Так можно изолировать приложения от инфраструктуры, перезапуская их по мере необходимости в виде контейнеров. Docker-контейнер – это запущенный и изолированный образ одного или нескольких приложений, поддерживающий временное хранение данных, которые записываются в его верхний слой и удаляются при удалении контейнера. Каждый контейнер запускается в отдельном процессе. Контейнеры создаются на основе Docker-образа — исполняемого пакета со всеми компонентами для запуска приложения: код, среда выполнения, библиотеки, переменные окружения и файлы конфигурации. Он состоит из слоев, причем каждое изменение записывается в новый слой. Docker-образ можно развертывать многократно, получая независимые контейнеры с рабочими приложениями. Инструкция о том, как собран Docker-образ и как запускать контейнеры, хранится в конфигурационном файле Dockerfile.
Приняв решение об использовании Docker как среды развертывания Kafka и всех ее компонентов, мне нужно было найти подходящий Docker-образ. Все нужные мне компоненты платформы Kafka (сам Kafka брокер, Zookeeper, Kafka JMX, ksqlDB, Kafka Connect, REST Proxy и Schema Registry) есть в Docker-образе от Confluent. Его описание можно посмотреть в Github-репозитории [1]. Однако, версия сообщества cp-all-in-one-community не содержит веб-интерфейса для работы с компонентами Kafka и мониторинга системы. Поэтому в качестве GUI я решила выбрать сервис AKHQ – веб-интерфейс для управления и мониторинга Apache Kafka. AKHQ предоставляет мощный набор инструментов для администрирования и мониторинга Kafka, позволяя достаточно просто управлять кластером Kafka даже неопытным пользователям. AKHQ поддерживает управление топиками, включая создание, удаление и изменение конфигураций, а также просмотр их метаданных: количество разделов и реплик. Можно просматривать и фильтровать сообщения в реальном времени, следить за статистикой отправки сообщений, состоянием продюсеров, потребителей и их групп, смещением и задержками. Еще AKHQ поддерживает интеграцию с системами аутентификации и авторизации, такими как LDAP, системами мониторинга, такими как Prometheus и Grafana, позволяет настраивать роли и разрешения для пользователей. Наконец, с AKHQ можно развернуть Kafka в Kubernetes, в т.ч. с использованием Helm Chart для упрощения установки. AKHQ отлично разворачивается в Docker, интегрируясь с платформой Kafka и всеми ее компонентами: Kafka брокер, Zookeeper, Kafka JMX, ksqlDB, Kafka Connect, REST Proxy и Schema Registry.
Docker Compose и настройка конфигураций
Таким образом, чтобы развернуть Kafka с веб-GUI в контейнере, необходимо модифицировать Docker-образ от Confluent под названием cp-all-in-one-community, включив в него AKHQ для визуального управления кластером. Поскольку этот Docker-образ будет запускать несколько контейнеров, надо использовать Docker Compose — систему сборки, запуска и управления множеством контейнеров. Она позволяет управлять набором контейнеров, включая сборку, запуск с учетом зависимостей и конфигурирование. Конфигурация Docker Compose описывается в YAML-файле docker-compose.yml, лежащем в корне проекта. В моем первоначальном варианте это файл выглядел так:
version: '3.6' volumes: zookeeper-data: driver: local zookeeper-log: driver: local kafka-data: driver: local services: akhq: # build: # context: . image: tchiotludo/akhq restart: unless-stopped environment: AKHQ_CONFIGURATION: | akhq: connections: docker-kafka-server: properties: bootstrap.servers: "kafka:9092" schema-registry: url: "http://schema-registry:8085" connect: - name: "connect" url: "http://connect:8083" ports: - 8080:8080 links: - kafka - schema-registry zookeeper: image: confluentinc/cp-zookeeper:7.5.0 restart: unless-stopped volumes: - zookeeper-data:/var/lib/zookeeper/data:Z - zookeeper-log:/var/lib/zookeeper/log:Z environment: ZOOKEEPER_CLIENT_PORT: '2181' ZOOKEEPER_ADMIN_ENABLE_SERVER: 'false' kafka: image: confluentinc/cp-kafka:7.5.0 restart: unless-stopped volumes: - kafka-data:/var/lib/kafka/data:Z environment: KAFKA_BROKER_ID: '0' KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181' KAFKA_NUM_PARTITIONS: '12' KAFKA_COMPRESSION_TYPE: 'gzip' KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: '1' KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: '1' KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: '1' KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://kafka:9092' KAFKA_CONFLUENT_SUPPORT_METRICS_ENABLE: 'false' KAFKA_JMX_PORT: '9091' KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true' KAFKA_AUTHORIZER_CLASS_NAME: 'kafka.security.authorizer.AclAuthorizer' KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: 'true' links: - zookeeper schema-registry: image: confluentinc/cp-schema-registry:7.5.0 restart: unless-stopped depends_on: - kafka environment: SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: 'PLAINTEXT://kafka:9092' SCHEMA_REGISTRY_HOST_NAME: 'schema-registry' SCHEMA_REGISTRY_LISTENERS: 'http://0.0.0.0:8085' SCHEMA_REGISTRY_LOG4J_ROOT_LOGLEVEL: 'INFO' connect: image: confluentinc/cp-kafka-connect:7.5.0 restart: unless-stopped depends_on: - kafka - schema-registry environment: CONNECT_BOOTSTRAP_SERVERS: 'kafka:9092' CONNECT_REST_PORT: '8083' CONNECT_REST_LISTENERS: 'http://0.0.0.0:8083' CONNECT_REST_ADVERTISED_HOST_NAME: 'connect' CONNECT_CONFIG_STORAGE_TOPIC: '__connect-config' CONNECT_OFFSET_STORAGE_TOPIC: '__connect-offsets' CONNECT_STATUS_STORAGE_TOPIC: '__connect-status' CONNECT_GROUP_ID: 'kafka-connect' CONNECT_KEY_CONVERTER_SCHEMAS_ENABLE: 'true' CONNECT_KEY_CONVERTER: 'io.confluent.connect.avro.AvroConverter' CONNECT_KEY_CONVERTER_SCHEMA_REGISTRY_URL: 'http://schema-registry:8085' CONNECT_VALUE_CONVERTER_SCHEMAS_ENABLE: 'true' CONNECT_VALUE_CONVERTER: 'io.confluent.connect.avro.AvroConverter' CONNECT_VALUE_CONVERTER_SCHEMA_REGISTRY_URL: 'http://schema-registry:8085' CONNECT_INTERNAL_KEY_CONVERTER: 'org.apache.kafka.connect.json.JsonConverter' CONNECT_INTERNAL_VALUE_CONVERTER: 'org.apache.kafka.connect.json.JsonConverter' CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: '1' CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: '1' CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: '1' CONNECT_PLUGIN_PATH: ' /usr/share/java/' ksqldb: image: confluentinc/cp-ksqldb-server:7.5.0 restart: unless-stopped depends_on: - kafka - connect - schema-registry ports: - 8088:8088 environment: KSQL_BOOTSTRAP_SERVERS: 'kafka:9092' KSQL_LISTENERS: 'http://0.0.0.0:8088' KSQL_KSQL_SERVICE_ID: 'ksql' KSQL_KSQL_SCHEMA_REGISTRY_URL: 'http://schema-registry:8085' KSQL_KSQL_CONNECT_URL: 'http://connect:8083' KSQL_KSQL_SINK_PARTITIONS: '1' KSQL_KSQL_LOGGING_PROCESSING_TOPIC_REPLICATION_FACTOR: '1' test-data: image: gradle:8-jdk11 command: "gradle --no-daemon testInjectData -x installFrontend -x assembleFrontend" restart: unless-stopped working_dir: /app volumes: - ./:/app:z links: - kafka - schema-registry kafkacat: image: confluentinc/cp-kafkacat:7.1.14 restart: unless-stopped depends_on: - kafka command: - bash - -c - | kafkacat -P -b kafka:9092 -t json << EOF {"_id":"5c4b2b45ab234c86955f0802","index":0,"guid":"d3637b06-9940-4958-9f82-639001c14c34"} {"_id":"5c4b2b459ffa9bb0c0c249e1","index":1,"guid":"08612fb5-40a7-45e5-9ff2-beb89a1b2835"} {"_id":"5c4b2b4545d7cbc7bf8b6e3e","index":2,"guid":"4880280a-cf8b-4884-881e-7b64ebf2afd0"} {"_id":"5c4b2b45dab381e6b3024c6d","index":3,"guid":"36d04c26-0dae-4a8e-a66e-bde9b3b6a745"} {"_id":"5c4b2b45d1103ce30dfe1947","index":4,"guid":"14d53f2c-def3-406f-9dfb-c29963fdc37e"} {"_id":"5c4b2b45d6d3b5c51d3dacb7","index":5,"guid":"a20cfc3a-934a-4b93-9a03-008ec651b5a4"} EOF kafkacat -P -b kafka:9092 -t csv << EOF 1,Sauncho,Attfield,sattfield0@netlog.com,Male,221.119.13.246 2,Luci,Harp,lharp1@wufoo.com,Female,161.14.184.150 3,Hanna,McQuillan,hmcquillan2@mozilla.com,Female,214.67.74.80 4,Melba,Lecky,mlecky3@uiuc.edu,Female,158.112.18.189 5,Mordecai,Hurdiss,mhurdiss4@rambler.ru,Male,175.123.45.143 EOF kafkacat -b kafka:9092 -o beginning -G json-consumer json links: - kafka
После создания Docker-контейнеров с помощью команды
docker-compose up –d
в WSL из директории, где лежит YAML-файл docker-compose.yml, веб-GUI AKHQ успешно запустился на локальном хосте, на порту 8080, как и прописано в конфигурации. Однако, чтобы полноценно работать с Kafka, публикуя и потребляя из нее сообщения с помощью программного кода, этого оказалось недостаточно. Проблема была связана с портами и слушателями этой потоковой платформы передачи событий. Как ее удалось решить, изменив конфигурационный файл docker-compose.yml, я расскажу завтра.
Научитесь администрированию и эксплуатации Apache Kafka на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
- Apache Kafka для инженеров данных
- Администрирование кластера Kafka
- Администрирование Arenadata Streaming Kafka
Источники: