# Автор: Сергей Антропов, сайт: https://devops.org.ru # Назначение: Управление инфраструктурой SensusAgent и SensusWorker через Docker Compose SHELL := /bin/bash PROJECT_NAME := sensus-infra COMPOSE_FILE := docker-compose.yml # Загрузка переменных из .env файла ifneq (,$(wildcard ./.env)) include .env export endif .PHONY: help setup up down restart status logs clean ps .PHONY: kafka-topics kafka-create-topic kafka-ui postgres-cli clickhouse-cli .PHONY: health-check backup restore ssl-generate ssl-clean ssl-info .PHONY: docker-install docker-update docker-compose-install docker-compose-update docker-check # ============================================================================= # ОСНОВНЫЕ КОМАНДЫ # ============================================================================= help: ## Показать справку по командам @echo "Инфраструктура SensusAgent и SensusWorker" @echo "Автор: Сергей Антропов, сайт: https://devops.org.ru" @echo "" @echo "Доступные команды:" @awk 'BEGIN {FS = ":.*##"} /^[a-zA-Z_-]+:.*?##/ { printf "\033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) setup: ## Первоначальная настройка инфраструктуры @echo "🔧 Настройка инфраструктуры Sensus..." @if [ ! -f .env ]; then \ echo "⚠️ Файл .env не найден. Копирую env.example в .env..."; \ cp env.example .env; \ echo "✅ Файл .env создан на основе env.example"; \ echo "💡 Отредактируйте .env с вашими значениями при необходимости"; \ else \ echo "✅ Файл .env уже существует"; \ fi @echo "🔐 Генерация SSL сертификатов..." @$(MAKE) ssl-generate @echo "🚀 Запуск инфраструктуры..." @$(MAKE) up @echo "⏳ Ожидание готовности сервисов..." @sleep 30 @$(MAKE) health-check @echo "📝 Создание топика Kafka..." @$(MAKE) kafka-create-topic @echo "✅ Инфраструктура готова к работе!" # ============================================================================= # УСТАНОВКА И ОБНОВЛЕНИЕ DOCKER # ============================================================================= docker-install: ## Установить Docker через get.docker.com @echo "🐳 Установка Docker..." @if command -v docker >/dev/null 2>&1; then \ echo "⚠️ Docker уже установлен. Используйте 'make docker-update' для обновления."; \ exit 1; \ fi @echo "📥 Загрузка и установка Docker..." @curl -fsSL https://get.docker.com -o get-docker.sh @sudo sh get-docker.sh @rm get-docker.sh @echo "🔧 Добавление пользователя в группу docker..." @sudo usermod -aG docker $$USER @echo "✅ Docker установлен успешно!" @echo "💡 Перезайдите в систему или выполните 'newgrp docker' для применения изменений группы" docker-update: ## Обновить Docker до последней версии @echo "🔄 Обновление Docker..." @if ! command -v docker >/dev/null 2>&1; then \ echo "❌ Docker не установлен. Используйте 'make docker-install' для установки."; \ exit 1; \ fi @echo "📥 Загрузка и установка последней версии Docker..." @curl -fsSL https://get.docker.com -o get-docker.sh @sudo sh get-docker.sh @rm get-docker.sh @echo "✅ Docker обновлен успешно!" docker-compose-install: ## Установить Docker Compose @echo "🐳 Установка Docker Compose..." @if command -v docker-compose >/dev/null 2>&1 || docker compose version >/dev/null 2>&1; then \ echo "⚠️ Docker Compose уже установлен. Используйте 'make docker-compose-update' для обновления."; \ exit 1; \ fi @echo "📥 Загрузка Docker Compose..." @sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$$(uname -s)-$$(uname -m)" -o /usr/local/bin/docker-compose @sudo chmod +x /usr/local/bin/docker-compose @echo "✅ Docker Compose установлен успешно!" docker-compose-update: ## Обновить Docker Compose до последней версии @echo "🔄 Обновление Docker Compose..." @if ! command -v docker-compose >/dev/null 2>&1 && ! docker compose version >/dev/null 2>&1; then \ echo "❌ Docker Compose не установлен. Используйте 'make docker-compose-install' для установки."; \ exit 1; \ fi @echo "📥 Загрузка последней версии Docker Compose..." @sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$$(uname -s)-$$(uname -m)" -o /usr/local/bin/docker-compose @sudo chmod +x /usr/local/bin/docker-compose @echo "✅ Docker Compose обновлен успешно!" docker-check: ## Проверить версии Docker и Docker Compose @echo "🔍 Проверка версий Docker и Docker Compose..." @echo "" @echo "🐳 Docker:" @if command -v docker >/dev/null 2>&1; then \ docker --version; \ else \ echo "❌ Docker не установлен"; \ fi @echo "" @echo "🐳 Docker Compose:" @if command -v docker-compose >/dev/null 2>&1; then \ docker-compose --version; \ elif docker compose version >/dev/null 2>&1; then \ docker compose version; \ else \ echo "❌ Docker Compose не установлен"; \ fi @echo "" @echo "🔧 Docker Engine статус:" @if command -v docker >/dev/null 2>&1; then \ if docker info >/dev/null 2>&1; then \ echo "✅ Docker Engine запущен"; \ else \ echo "❌ Docker Engine не запущен"; \ fi; \ else \ echo "❌ Docker не установлен"; \ fi # ============================================================================= # УПРАВЛЕНИЕ ИНФРАСТРУКТУРОЙ # ============================================================================= up: ## Запустить всю инфраструктуру (Kafka, PostgreSQL, ClickHouse) @echo "🚀 Запуск инфраструктуры..." docker compose -f $(COMPOSE_FILE) up -d zookeeper kafka kafka-ui postgres clickhouse-1 clickhouse-2 clickhouse-lb @echo "✅ Инфраструктура запущена" down: ## Остановить всю инфраструктуру @echo "🛑 Остановка инфраструктуры..." docker compose -f $(COMPOSE_FILE) down @echo "✅ Инфраструктура остановлена" restart: ## Перезапустить всю инфраструктуру @echo "🔄 Перезапуск инфраструктуры..." @$(MAKE) down @sleep 5 @$(MAKE) up ps: ## Показать статус контейнеров Docker @echo "📊 Статус контейнеров Docker:" docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" # ============================================================================= # МОНИТОРИНГ И ДИАГНОСТИКА # ============================================================================= status: ## Показать статус всех сервисов @echo "📊 Статус всех сервисов:" docker compose -f $(COMPOSE_FILE) ps logs: ## Показать логи всех сервисов docker compose -f $(COMPOSE_FILE) logs -f health-check: ## Проверить здоровье сервисов @echo "🏥 Проверка здоровья сервисов..." @echo "Zookeeper:" @docker exec sensus-zookeeper bash -c "echo 'ruok' | timeout 5 nc -w 1 localhost 2181" && echo "✅ Zookeeper доступен" || echo "❌ Zookeeper недоступен" @echo "Kafka:" @docker exec sensus-kafka kafka-broker-api-versions --bootstrap-server localhost:9092 >/dev/null 2>&1 && echo "✅ Kafka доступен" || echo "❌ Kafka недоступен" @echo "PostgreSQL:" @docker exec sensus-postgres pg_isready -U sensus -d sensus >/dev/null 2>&1 && echo "✅ PostgreSQL доступен" || echo "❌ PostgreSQL недоступен" @echo "⏳ Ожидание готовности ClickHouse (30 секунд)..." @sleep 30 @echo "ClickHouse-1:" @docker exec sensus-clickhouse-1 wget --no-verbose --tries=1 --spider http://127.0.0.1:8123/ping >/dev/null 2>&1 && echo "✅ ClickHouse-1 доступен" || echo "❌ ClickHouse-1 недоступен" @echo "ClickHouse-2:" @docker exec sensus-clickhouse-2 wget --no-verbose --tries=1 --spider http://127.0.0.1:8123/ping >/dev/null 2>&1 && echo "✅ ClickHouse-2 доступен" || echo "❌ ClickHouse-2 недоступен" @echo "⏳ Ожидание готовности Load Balancer (10 секунд)..." @sleep 10 @echo "ClickHouse Load Balancer:" @docker exec sensus-clickhouse-lb wget --no-verbose --tries=1 --spider http://127.0.0.1:80/health >/dev/null 2>&1 && echo "✅ ClickHouse LB доступен" || echo "❌ ClickHouse LB недоступен" # ============================================================================= # РАБОТА С KAFKA # ============================================================================= kafka-topics: ## Показать список топиков Kafka @echo "📋 Список топиков Kafka:" docker exec sensus-kafka kafka-topics --bootstrap-server localhost:9092 --list kafka-create-topic: ## Создать топик Kafka с настройкой ретеншна @echo "📝 Создание топика Kafka..." @if [ -z "$(KAFKA_TOPIC)" ]; then \ echo "❌ Переменная KAFKA_TOPIC не задана в .env файле"; \ exit 1; \ fi @if [ -z "$(KAFKA_TOPIC_RETENTION_HOURS)" ]; then \ echo "❌ Переменная KAFKA_TOPIC_RETENTION_HOURS не задана в .env файле"; \ exit 1; \ fi @echo "🔧 Создание топика: $(KAFKA_TOPIC) с ретеншном: $(KAFKA_TOPIC_RETENTION_HOURS) часов" @docker exec sensus-kafka kafka-topics \ --bootstrap-server localhost:9092 \ --create \ --topic $(KAFKA_TOPIC) \ --partitions $(KAFKA_NUM_PARTITIONS) \ --replication-factor $(KAFKA_DEFAULT_REPLICATION_FACTOR) \ --config retention.ms=$$(($(KAFKA_TOPIC_RETENTION_HOURS) * 3600000)) \ --if-not-exists || echo "⚠️ Топик уже существует или произошла ошибка" @echo "✅ Топик $(KAFKA_TOPIC) создан с ретеншном $(KAFKA_TOPIC_RETENTION_HOURS) часов" kafka-ui: ## Открыть Kafka UI в браузере @echo "🌐 Kafka UI доступен по адресу: http://localhost:8080" # ============================================================================= # РАБОТА С БАЗАМИ ДАННЫХ # ============================================================================= postgres-cli: ## Подключиться к PostgreSQL @echo "🐘 Подключение к PostgreSQL..." docker exec -it sensus-postgres psql -U sensus -d sensus clickhouse-cli: ## Подключиться к ClickHouse (реплика 1) @echo "🦆 Подключение к ClickHouse..." docker exec -it sensus-clickhouse-1 clickhouse-client clickhouse-cli-2: ## Подключиться к ClickHouse (реплика 2) @echo "🦆 Подключение к ClickHouse (реплика 2)..." docker exec -it sensus-clickhouse-2 clickhouse-client clickhouse-cli-lb: ## Подключиться к ClickHouse через балансировщик @echo "⚖️ Подключение к ClickHouse через балансировщик нагрузки..." docker exec -it sensus-clickhouse-lb sh -c "echo 'SELECT version()' | nc localhost 9000" # ============================================================================= # ОЧИСТКА И ОБСЛУЖИВАНИЕ # ============================================================================= clean: ## Очистить все контейнеры и volumes @echo "🧹 Очистка всех контейнеров и volumes..." docker compose -f $(COMPOSE_FILE) down -v --remove-orphans docker system prune -f @echo "✅ Очистка завершена" clean-volumes: ## Очистить только volumes (данные) @echo "🧹 Очистка volumes..." docker compose -f $(COMPOSE_FILE) down -v @echo "✅ Volumes очищены" # ============================================================================= # РЕЗЕРВНОЕ КОПИРОВАНИЕ # ============================================================================= backup: ## Создать резервную копию данных @echo "💾 Создание резервной копии..." @mkdir -p ./backups @echo "PostgreSQL backup..." docker exec sensus-postgres pg_dump -U sensus sensus > ./backups/postgres_$(shell date +%Y%m%d_%H%M%S).sql @echo "ClickHouse backup..." docker exec sensus-clickhouse-1 clickhouse-backup create backup_$(shell date +%Y%m%d_%H%M%S) @echo "✅ Резервная копия создана в ./backups/" restore: ## Восстановить данные из резервной копии (укажите BACKUP_FILE) @if [ -z "$(BACKUP_FILE)" ]; then \ echo "❌ Укажите BACKUP_FILE=имя_файла"; \ exit 1; \ fi @echo "🔄 Восстановление из $(BACKUP_FILE)..." @if [ -f "./backups/$(BACKUP_FILE)" ]; then \ docker exec -i sensus-postgres psql -U sensus -d sensus < ./backups/$(BACKUP_FILE); \ echo "✅ Данные восстановлены"; \ else \ echo "❌ Файл ./backups/$(BACKUP_FILE) не найден"; \ fi # ============================================================================= # SSL СЕРТИФИКАТЫ # ============================================================================= ssl-generate: ## Генерация SSL сертификатов для Kafka и PostgreSQL @echo "🔐 Генерация SSL сертификатов для Kafka..." @mkdir -p ./kafka-ssl @docker build -t sensus-kafka-ssl ./kafka-ssl/ @docker run --rm -v $$PWD:/workspace \ -e KAFKA_SSL_KEYSTORE_PASSWORD=$${KAFKA_SSL_KEYSTORE_PASSWORD:-kafka123} \ -e KAFKA_SSL_TRUSTSTORE_PASSWORD=$${KAFKA_SSL_TRUSTSTORE_PASSWORD:-kafka123} \ -e KAFKA_SSL_KEY_PASSWORD=$${KAFKA_SSL_KEY_PASSWORD:-kafka123} \ sensus-kafka-ssl @echo "✅ SSL сертификаты Kafka созданы в ./kafka-ssl/" @echo "🔐 Генерация SSL сертификатов для PostgreSQL..." @mkdir -p ./postgres-ssl @chmod +x ./postgres-ssl/generate-ssl.sh @./postgres-ssl/generate-ssl.sh @echo "✅ SSL сертификаты PostgreSQL созданы в ./postgres-ssl/" ssl-clean: ## Очистка SSL сертификатов @echo "🧹 Очистка SSL сертификатов..." @rm -rf ./kafka-ssl/*.jks ./kafka-ssl/ca-* 2>/dev/null || true @rm -rf ./postgres-ssl/*.crt ./postgres-ssl/*.key 2>/dev/null || true @echo "✅ SSL сертификаты очищены" ssl-info: ## Информация о SSL сертификатах @echo "📋 Информация о SSL сертификатах:" @echo "" @echo "🔐 Kafka SSL сертификаты:" @if [ -f "./kafka-ssl/kafka.server.keystore.jks" ]; then \ echo "✅ Серверный keystore найден"; \ docker run --rm -v $$PWD:/workspace -w /workspace openjdk:11-jre-slim keytool -list -keystore /workspace/kafka-ssl/kafka.server.keystore.jks -storepass kafka123 -v | head -20; \ else \ echo "❌ Kafka SSL сертификаты не найдены"; \ fi @echo "" @echo "🔐 PostgreSQL SSL сертификаты:" @if [ -f "./postgres-ssl/server.crt" ]; then \ echo "✅ PostgreSQL сертификаты найдены:"; \ ls -la ./postgres-ssl/; \ echo ""; \ echo "📋 Информация о сертификате сервера:"; \ openssl x509 -in ./postgres-ssl/server.crt -text -noout | grep -E "(Subject:|Issuer:|Not Before|Not After)"; \ else \ echo "❌ PostgreSQL SSL сертификаты не найдены"; \ fi @echo "" @echo "💡 Для генерации сертификатов выполните: make ssl-generate"