Compare commits

...

2 Commits

Author SHA1 Message Date
50dd48bcb7 merge: Resolve conflicts with remote repository
- Keep our comprehensive README.md with full documentation
- Keep our .gitignore with SSL certificate exclusions
- Add LICENSE file from remote repository

Author: Сергей Антропов
Site: https://devops.org.ru
2025-09-10 11:21:34 +03:00
7877590440 feat: Initial infrastructure setup for SensusAgent and SensusWorker
- Add Kafka with SSL support and KafkaUI with authentication
- Add PostgreSQL with initialization scripts
- Add ClickHouse cluster with 2 replicas and load balancer
- Add Nginx load balancer for ClickHouse
- Add comprehensive Makefile for infrastructure management
- Add SSL certificate generation for Kafka
- Add complete documentation and quickstart guide
- Add environment configuration with real values

Author: Сергей Антропов
Site: https://devops.org.ru
2025-09-10 11:20:47 +03:00
11 changed files with 1672 additions and 229 deletions

294
.gitignore vendored
View File

@ -1,239 +1,77 @@
# ---> macOS
# General
.DS_Store
.AppleDouble
.LSOverride
# Автор: Сергей Антропов, сайт: https://devops.org.ru
# Назначение: Игнорирование файлов для SensusInfra
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# ---> VirtualEnv
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
.Python
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
go.work.sum
# env file
# =============================================================================
# ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ
# =============================================================================
.env
.env.local
.env.production
.env.staging
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# =============================================================================
# DOCKER
# =============================================================================
.docker/
docker-compose.override.yml
docker-compose.*.yml
!docker-compose.yml
# C extensions
*.so
# =============================================================================
# РЕЗЕРВНЫЕ КОПИИ
# =============================================================================
backups/
*.sql
*.backup
*.dump
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
# =============================================================================
# ЛОГИ
# =============================================================================
logs/
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
*.log.*
# Flask stuff:
instance/
.webassets-cache
# =============================================================================
# ВРЕМЕННЫЕ ФАЙЛЫ
# =============================================================================
tmp/
temp/
.tmp/
.temp/
# Scrapy stuff:
.scrapy
# =============================================================================
# СИСТЕМНЫЕ ФАЙЛЫ
# =============================================================================
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Sphinx documentation
docs/_build/
# =============================================================================
# IDE
# =============================================================================
.vscode/
.idea/
*.swp
*.swo
*~
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# =============================================================================
# SSL СЕРТИФИКАТЫ
# =============================================================================
kafka-ssl/*.jks
kafka-ssl/ca-*
kafka-ssl/*.pem
kafka-ssl/*.key
kafka-ssl/*.crt
# =============================================================================
# ПРОЧИЕ
# =============================================================================
*.pid
*.seed
*.pid.lock

181
Makefile Normal file
View File

@ -0,0 +1,181 @@
# Автор: Сергей Антропов, сайт: https://devops.org.ru
# Назначение: Управление инфраструктурой SensusAgent и SensusWorker через Docker Compose
SHELL := /bin/bash
PROJECT_NAME := sensus-infra
COMPOSE_FILE := docker-compose.yml
.PHONY: help setup up down restart status logs clean
.PHONY: kafka-topics kafka-ui postgres-cli clickhouse-cli
.PHONY: health-check backup restore ssl-generate ssl-clean ssl-info
# =============================================================================
# ОСНОВНЫЕ КОМАНДЫ
# =============================================================================
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"; \
echo " cp env.example .env"; \
echo " # Отредактируйте .env с вашими значениями"; \
exit 1; \
fi
@echo "✅ Файл .env найден"
@echo "🔐 Генерация SSL сертификатов..."
@$(MAKE) ssl-generate
@echo "🚀 Запуск инфраструктуры..."
@$(MAKE) up
@echo "⏳ Ожидание готовности сервисов..."
@sleep 30
@$(MAKE) health-check
@echo "✅ Инфраструктура готова к работе!"
# =============================================================================
# УПРАВЛЕНИЕ ИНФРАСТРУКТУРОЙ
# =============================================================================
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
# =============================================================================
# МОНИТОРИНГ И ДИАГНОСТИКА
# =============================================================================
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' | nc localhost 2181" || 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-1:"
@docker exec sensus-clickhouse-1 wget --no-verbose --tries=1 --spider http://localhost: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://localhost:8123/ping >/dev/null 2>&1 && echo "✅ ClickHouse-2 доступен" || echo "❌ ClickHouse-2 недоступен"
@echo "ClickHouse Load Balancer:"
@docker exec sensus-clickhouse-lb wget --no-verbose --tries=1 --spider http://localhost: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-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
@echo "🔐 Генерация SSL сертификатов для Kafka..."
@mkdir -p ./kafka-ssl
@docker run --rm -v $$PWD:/workspace -w /workspace openjdk:11-jre-slim bash -c "apt-get update && apt-get install -y openssl && chmod +x /workspace/kafka-ssl/generate-ssl.sh && /workspace/kafka-ssl/generate-ssl.sh"
@echo "✅ SSL сертификаты созданы в ./kafka-ssl/"
ssl-clean: ## Очистка SSL сертификатов
@echo "🧹 Очистка SSL сертификатов..."
@rm -rf ./kafka-ssl/*.jks ./kafka-ssl/ca-* 2>/dev/null || true
@echo "✅ SSL сертификаты очищены"
ssl-info: ## Информация о SSL сертификатах
@echo "📋 Информация о 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 "❌ SSL сертификаты не найдены. Выполните: make ssl-generate"; \
fi

69
QUICKSTART.md Normal file
View File

@ -0,0 +1,69 @@
# Быстрый старт SensusInfra
**Автор:** Сергей Антропов, сайт: https://devops.org.ru
## 🚀 Запуск за 3 шага
### 1. Подготовка
```bash
cd SensusInfra
cp env.example .env
# Отредактируйте .env с вашими паролями
```
### 2. Запуск инфраструктуры
```bash
make setup
```
### 3. Управление инфраструктурой
```bash
make up # Запуск
make down # Остановка
make restart # Перезапуск
```
## 📊 Проверка работы
```bash
# Статус сервисов
make status
# Проверка здоровья
make health-check
# Логи
make logs
```
## 🌐 Веб-интерфейсы
- **Kafka UI:** http://localhost:8080 (логин: admin, пароль: admin)
- **PostgreSQL:** localhost:5432
- **ClickHouse:** localhost:8123 (реплика 1), localhost:8124 (реплика 2)
- **ClickHouse LB:** localhost:8125 (HTTP), localhost:9002 (TCP)
## 🛠 Полезные команды
```bash
# Подключение к базам данных
make postgres-cli
make clickhouse-cli
# Просмотр топиков Kafka
make kafka-topics
# SSL сертификаты
make ssl-generate # Генерация SSL сертификатов
make ssl-info # Информация о сертификатах
# Остановка системы
make down
# Очистка данных
make clean
```
## 📚 Подробная документация
См. [README.md](README.md) для полной документации.

350
README.md
View File

@ -1,2 +1,350 @@
# SensusInfra
# SensusInfra — Инфраструктура для SensusAgent и SensusWorker
**Автор:** Сергей Антропов
**Сайт:** https://devops.org.ru
## Описание
SensusInfra — это полная инфраструктура для работы с системой мониторинга Sensus, включающая:
- **Kafka** — брокер сообщений для передачи метрик от агентов к воркерам
- **KafkaUI** — веб-интерфейс для мониторинга Kafka
- **PostgreSQL** — база данных для хранения метаданных агентов и конфигураций
- **ClickHouse** — аналитическая база данных для хранения и анализа метрик (2 реплики)
- **Nginx Load Balancer** — балансировщик нагрузки для ClickHouse
## Архитектура
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ SensusAgent │───▶│ Kafka │───▶│ SensusWorker │
│ (сбор метрик) │ │ (брокер) │ │ (обработка) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ KafkaUI │ │ PostgreSQL │
│ (мониторинг) │ │ (метаданные) │
└─────────────────┘ └─────────────────┘
┌─────────────────┐
│ ClickHouse │
│ Load Balancer │
│ (Nginx) │
└─────────────────┘
┌─────────────────┐
│ ClickHouse │
│ (аналитика) │
│ (2 реплики) │
└─────────────────┘
```
## Быстрый старт
### 1. Подготовка окружения
```bash
# Клонируйте репозиторий и перейдите в директорию
cd SensusInfra
# Создайте файл .env на основе env.example
cp env.example .env
# Отредактируйте .env с вашими значениями
nano .env
```
### 2. Запуск инфраструктуры
```bash
# Первоначальная настройка (создание .env, генерация SSL, запуск сервисов)
make setup
# Или пошагово:
make ssl-generate # Генерация SSL сертификатов
make up # Запуск инфраструктуры
make health-check # Проверка здоровья сервисов
```
### 3. Управление инфраструктурой
```bash
make up # Запуск инфраструктуры
make down # Остановка инфраструктуры
make restart # Перезапуск инфраструктуры
make status # Статус сервисов
make logs # Логи всех сервисов
```
## Управление через Makefile
### Основные команды
| Команда | Описание |
|---------|----------|
| `make setup` | Первоначальная настройка инфраструктуры |
| `make up` | Запустить инфраструктуру |
| `make down` | Остановить инфраструктуру |
| `make restart` | Перезапустить инфраструктуру |
| `make status` | Показать статус всех сервисов |
| `make logs` | Показать логи всех сервисов |
| `make health-check` | Проверить здоровье сервисов |
### Работа с базами данных
| Команда | Описание |
|---------|----------|
| `make postgres-cli` | Подключиться к PostgreSQL |
| `make clickhouse-cli` | Подключиться к ClickHouse (реплика 1) |
| `make clickhouse-cli-2` | Подключиться к ClickHouse (реплика 2) |
| `make clickhouse-cli-lb` | Подключиться к ClickHouse через балансировщик |
| `make kafka-topics` | Показать список топиков Kafka |
| `make kafka-ui` | Открыть Kafka UI в браузере |
### SSL сертификаты
| Команда | Описание |
|---------|----------|
| `make ssl-generate` | Генерация SSL сертификатов для Kafka |
| `make ssl-clean` | Очистка SSL сертификатов |
| `make ssl-info` | Информация о SSL сертификатах |
### Обслуживание
| Команда | Описание |
|---------|----------|
| `make clean` | Очистить все контейнеры и volumes |
| `make clean-volumes` | Очистить только volumes (данные) |
| `make backup` | Создать резервную копию данных |
| `make restore BACKUP_FILE=имя_файла` | Восстановить данные из резервной копии |
## Конфигурация
### Переменные окружения
Все настройки хранятся в файле `.env`. Основные переменные:
#### Kafka
- `KAFKA_BROKER_ID` — ID брокера Kafka (по умолчанию 1)
- `KAFKA_EXTERNAL_PORT` — внешний порт Kafka (по умолчанию 9092)
- `KAFKA_SSL_PORT` — SSL порт Kafka (по умолчанию 9093)
- `KAFKA_TOPIC` — топик для метрик (по умолчанию sensus.metrics)
- `KAFKA_UI_PORT` — порт Kafka UI (по умолчанию 8080)
- `KAFKA_SSL_KEYSTORE_PASSWORD` — пароль keystore (по умолчанию kafka123)
- `KAFKA_SSL_KEY_PASSWORD` — пароль ключа (по умолчанию kafka123)
- `KAFKA_SSL_TRUSTSTORE_PASSWORD` — пароль truststore (по умолчанию kafka123)
#### Kafka UI авторизация
- `KAFKA_UI_AUTH_TYPE` — тип авторизации (по умолчанию LOGIN_FORM)
- `KAFKA_UI_USERNAME` — логин для входа (по умолчанию admin)
- `KAFKA_UI_PASSWORD` — пароль для входа (по умолчанию admin)
- `KAFKA_UI_USER_ROLES` — роли пользователя (по умолчанию ADMIN)
#### PostgreSQL
- `POSTGRES_DB` — имя базы данных (по умолчанию sensus)
- `POSTGRES_USER` — пользователь (по умолчанию sensus)
- `POSTGRES_PASSWORD` — пароль (обязательно изменить!)
- `POSTGRES_PORT` — порт (по умолчанию 5432)
#### ClickHouse
- `CLICKHOUSE_DB` — имя базы данных (по умолчанию sensus_metrics)
- `CLICKHOUSE_USER` — пользователь (по умолчанию sensus)
- `CLICKHOUSE_PASSWORD` — пароль (обязательно изменить!)
- `CLICKHOUSE_SECURE` — безопасный режим (по умолчанию true)
- `CLICKHOUSE_1_PORT` — порт первой реплики (по умолчанию 8123)
- `CLICKHOUSE_2_PORT` — порт второй реплики (по умолчанию 8124)
#### ClickHouse Load Balancer
- `CLICKHOUSE_LB_HTTP_PORT` — HTTP порт балансировщика (по умолчанию 8125)
- `CLICKHOUSE_LB_TCP_PORT` — TCP порт балансировщика (по умолчанию 9002)
### Структура базы данных
#### PostgreSQL
**Схема `agents`** — метаданные агентов:
- `agents` — зарегистрированные агенты
- `collectors` — коллекторы агентов
**Схема `configs`** — конфигурации:
- `agent_configs` — конфигурации агентов
- `config_history` — история изменений
**Схема `metrics`** — метрики:
- `raw_metrics` — сырые метрики
- `processed_metrics` — обработанные метрики
**Схема `system`** — системные таблицы:
- `system_state` — состояние системы
- `system_logs` — логи системы
#### ClickHouse
**База `sensus_metrics`**:
- `metrics_raw` — сырые метрики
- `metrics_processed` — обработанные метрики
- `metrics_aggregated_hourly` — агрегация по часам
- `metrics_aggregated_daily` — агрегация по дням
- `agents_info` — информация об агентах
- `collectors_info` — информация о коллекторах
**База `system`**:
- `system_logs` — логи системы
- `system_state` — состояние системы
## Мониторинг
### Kafka UI
- URL: http://localhost:8080
- **Логин:** admin
- **Пароль:** admin
- Мониторинг топиков, консьюмеров, партиций
- Просмотр сообщений в реальном времени
- Авторизация через форму входа
### Health Check
```bash
make health-check
```
Проверяет доступность всех сервисов:
- Zookeeper
- Kafka
- PostgreSQL
- ClickHouse (обе реплики)
### Логи
```bash
# Все сервисы
make logs
# Конкретный сервис
make infra-logs
make agent-logs
make worker-logs
```
## Резервное копирование
### Создание резервной копии
```bash
make backup
```
Создает резервные копии:
- PostgreSQL: `./backups/postgres_YYYYMMDD_HHMMSS.sql`
- ClickHouse: `backup_YYYYMMDD_HHMMSS`
### Восстановление
```bash
make restore BACKUP_FILE=postgres_20241201_120000.sql
```
## Безопасность
### SSL/TLS
Инфраструктура поддерживает SSL/TLS для Kafka:
- **Автоматическая генерация** SSL сертификатов при `make setup`
- **Поддержка SSL** на порту 9093
- **Клиентские сертификаты** для аутентификации
- **Truststore** для проверки сертификатов
### Рекомендации
1. **Обязательно измените пароли** в файле `.env`
2. **Не коммитьте файл `.env`** в git
3. **Используйте сильные пароли** для production
4. **Настройте firewall** для ограничения доступа к портам
5. **Регулярно обновляйте** образы Docker
6. **Используйте SSL** для production окружения
7. **Регулярно обновляйте** SSL сертификаты
8. **Измените пароль Kafka UI** для production (по умолчанию admin/admin)
### Порты
- **9092** — Kafka (внешний, PLAINTEXT)
- **9093** — Kafka (SSL)
- **8080** — Kafka UI
- **5432** — PostgreSQL
- **8123** — ClickHouse (реплика 1)
- **8124** — ClickHouse (реплика 2)
- **8125** — ClickHouse Load Balancer (HTTP)
- **9002** — ClickHouse Load Balancer (TCP)
## Устранение неполадок
### Проблемы с запуском
```bash
# Проверить статус сервисов
make status
# Проверить логи
make logs
# Проверить здоровье
make health-check
# Перезапустить инфраструктуру
make restart
```
### Проблемы с сетью
```bash
# Проверить Docker сеть
docker network ls
docker network inspect sensus-network
```
### Проблемы с данными
```bash
# Очистить volumes
make clean-volumes
# Пересоздать инфраструктуру
make clean
make setup
```
### Проблемы с производительностью
1. Увеличьте лимиты памяти в `.env`
2. Настройте партиционирование в ClickHouse
3. Оптимизируйте индексы в PostgreSQL
## Разработка
### Добавление новых сервисов
1. Добавьте сервис в `docker-compose.yml`
2. Добавьте переменные в `env.example`
3. Добавьте команды в `Makefile`
4. Обновите документацию
### Тестирование
```bash
# Запуск тестовой среды
make setup
# Проверка работы инфраструктуры
make status
make health-check
make logs
# Проверка SSL сертификатов
make ssl-info
# Проверка баз данных
make postgres-cli
make clickhouse-cli
```
## Лицензия
Код сопровождается подробными комментариями на русском языке. Автор — **Сергей Антропов** (сайт: https://devops.org.ru).
## Поддержка
При возникновении проблем:
1. Проверьте логи: `make logs`
2. Проверьте здоровье: `make health-check`
3. Обратитесь к документации проектов SensusAgent и SensusWorker
4. Создайте issue в репозитории

View File

@ -0,0 +1,102 @@
<!-- Автор: Сергей Антропов, сайт: https://devops.org.ru -->
<!-- Назначение: Конфигурация кластера ClickHouse для SensusAgent и SensusWorker -->
<!-- Настройка репликации между двумя репликами ClickHouse -->
<yandex>
<!-- Конфигурация кластера для репликации -->
<remote_servers>
<sensus_cluster>
<!-- Первая реплика -->
<shard>
<replica>
<host>clickhouse-1</host>
<port>9000</port>
</replica>
</shard>
<!-- Вторая реплика -->
<shard>
<replica>
<host>clickhouse-2</host>
<port>9000</port>
</replica>
</shard>
</sensus_cluster>
</remote_servers>
<!-- Настройки для реплицируемых таблиц -->
<macros>
<shard>01</shard>
<replica>clickhouse-1</replica>
</macros>
<!-- Настройки сети -->
<networks>
<ip>::/0</ip>
</networks>
<!-- Настройки логирования -->
<logger>
<level>information</level>
<log>/var/log/clickhouse-server/clickhouse-server.log</log>
<errorlog>/var/log/clickhouse-server/clickhouse-server.err.log</errorlog>
<size>1000M</size>
<count>10</count>
</logger>
<!-- Настройки HTTP сервера -->
<http_server_default_response><![CDATA[<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>]]></http_server_default_response>
<!-- Настройки для работы с большими данными -->
<max_memory_usage>10000000000</max_memory_usage>
<max_bytes_before_external_group_by>20000000000</max_bytes_before_external_group_by>
<max_bytes_before_external_sort>20000000000</max_bytes_before_external_sort>
<!-- Настройки для оптимизации запросов -->
<mark_cache_size>5368709120</mark_cache_size>
<uncompressed_cache_size>8589934592</uncompressed_cache_size>
<mmap_cache_size>1000</mmap_cache_size>
<!-- Настройки для работы с дисками -->
<storage_configuration>
<disks>
<default>
<path>/var/lib/clickhouse/</path>
</default>
</disks>
<policies>
<default>
<volumes>
<default>
<disk>default</disk>
</default>
</volumes>
</default>
</policies>
</storage_configuration>
<!-- Настройки для работы с ZooKeeper (если потребуется) -->
<zookeeper>
<node>
<host>zookeeper</host>
<port>2181</port>
</node>
</zookeeper>
<!-- Настройки для работы с Kafka -->
<kafka>
<broker_list>kafka:29092</broker_list>
<security_protocol>plaintext</security_protocol>
<topic_list>
<topic>sensus.metrics</topic>
</topic_list>
</kafka>
<!-- Настройки для работы с PostgreSQL -->
<postgresql>
<host>postgres</host>
<port>5432</port>
<database>sensus</database>
<user>sensus</user>
<password>sensus_secure_password_2024</password>
</postgresql>
</yandex>

View File

@ -0,0 +1,128 @@
<!-- Автор: Сергей Антропов, сайт: https://devops.org.ru -->
<!-- Назначение: Конфигурация таблиц метрик для ClickHouse -->
<!-- Определение структуры таблиц для хранения метрик от SensusAgent -->
<yandex>
<!-- Настройки для таблиц метрик -->
<dictionaries_config>*_dictionary.xml</dictionaries_config>
<!-- Настройки для работы с метриками -->
<format_schema_path>/var/lib/clickhouse/format_schemas/</format_schema_path>
<!-- Настройки для сжатия данных -->
<compression>
<case>
<min_part_size>10000000000</min_part_size>
<min_part_size_ratio>0.01</min_part_size_ratio>
<method>lz4</method>
</case>
</compression>
<!-- Настройки для партиционирования -->
<part_log>
<database>system</database>
<table>part_log</table>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</part_log>
<!-- Настройки для работы с большими запросами -->
<max_query_size>268435456</max_query_size>
<max_ast_depth>1000</max_ast_depth>
<max_ast_elements>50000</max_ast_elements>
<max_expanded_ast_elements>500000</max_expanded_ast_elements>
<!-- Настройки для работы с временными данными -->
<tmp_path>/var/lib/clickhouse/tmp/</tmp_path>
<user_files_path>/var/lib/clickhouse/user_files/</user_files_path>
<format_schema_path>/var/lib/clickhouse/format_schemas/</format_schema_path>
<!-- Настройки для работы с репликацией -->
<distributed_ddl>
<path>/clickhouse/task_queue/ddl</path>
</distributed_ddl>
<!-- Настройки для работы с метриками системы -->
<system_log>
<database>system</database>
<table>query_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<system_log>
<database>system</database>
<table>query_thread_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<system_log>
<database>system</database>
<table>part_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<system_log>
<database>system</database>
<table>trace_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<system_log>
<database>system</database>
<table>metric_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<system_log>
<database>system</database>
<table>asynchronous_metric_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<system_log>
<database>system</database>
<table>session_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<system_log>
<database>system</database>
<table>text_log</table>
<partition_by>toYYYYMM(event_date)</partition_by>
<flush_interval_milliseconds>7500</flush_interval_milliseconds>
</system_log>
<!-- Настройки для работы с внешними источниками данных -->
<external_table_functions_whitelist>
<function>url</function>
<function>file</function>
<function>mysql</function>
<function>postgresql</function>
<function>odbc</function>
<function>jdbc</function>
<function>hdfs</function>
<function>s3</function>
</external_table_functions_whitelist>
<!-- Настройки для работы с Kafka -->
<kafka>
<broker_list>kafka:29092</broker_list>
<security_protocol>plaintext</security_protocol>
<topic_list>
<topic>sensus.metrics</topic>
</topic_list>
<consumer_group>clickhouse-consumer</consumer_group>
<num_consumers>1</num_consumers>
<max_block_size>1048576</max_block_size>
<max_poll_interval_ms>30000</max_poll_interval_ms>
<session_timeout_ms>30000</session_timeout_ms>
<auto_offset_reset>latest</auto_offset_reset>
<skip_broken_messages>100</skip_broken_messages>
</kafka>
</yandex>

View File

@ -0,0 +1,135 @@
<!-- Автор: Сергей Антропов, сайт: https://devops.org.ru -->
<!-- Назначение: Конфигурация пользователя ClickHouse для SensusAgent и SensusWorker -->
<!-- Определение пользователя sensus с необходимыми правами доступа -->
<yandex>
<!-- Пользователь sensus -->
<users>
<sensus>
<!-- Пароль (будет переопределен через переменную окружения) -->
<password_sha256_hex></password_sha256_hex>
<password></password>
<!-- Сетевые настройки -->
<networks>
<ip>::/0</ip>
</networks>
<!-- Настройки профиля -->
<profile>default</profile>
<!-- Настройки квот -->
<quota>default</quota>
<!-- Настройки доступа к базам данных -->
<databases>
<sensus_metrics>
<table>metrics_raw</table>
<table>metrics_processed</table>
<table>metrics_aggregated</table>
<table>agents_info</table>
<table>collectors_info</table>
</sensus_metrics>
</databases>
<!-- Настройки для работы с большими запросами -->
<max_memory_usage>10000000000</max_memory_usage>
<max_bytes_before_external_group_by>20000000000</max_bytes_before_external_group_by>
<max_bytes_before_external_sort>20000000000</max_bytes_before_external_sort>
<!-- Настройки для работы с временными данными -->
<max_temporary_data_size>10000000000</max_temporary_data_size>
<max_temporary_non_const_columns>1000</max_temporary_non_const_columns>
<!-- Настройки для работы с запросами -->
<max_query_size>268435456</max_query_size>
<max_ast_depth>1000</max_ast_depth>
<max_ast_elements>50000</max_ast_elements>
<max_expanded_ast_elements>500000</max_expanded_ast_elements>
<!-- Настройки для работы с репликацией -->
<distributed_ddl>
<path>/clickhouse/task_queue/ddl</path>
</distributed_ddl>
<!-- Настройки для работы с внешними источниками данных -->
<external_table_functions_whitelist>
<function>url</function>
<function>file</function>
<function>mysql</function>
<function>postgresql</function>
<function>odbc</function>
<function>jdbc</function>
<function>hdfs</function>
<function>s3</function>
</external_table_functions_whitelist>
<!-- Настройки для работы с Kafka -->
<kafka>
<broker_list>kafka:29092</broker_list>
<security_protocol>plaintext</security_protocol>
<topic_list>
<topic>sensus.metrics</topic>
</topic_list>
<consumer_group>clickhouse-consumer</consumer_group>
<num_consumers>1</num_consumers>
<max_block_size>1048576</max_block_size>
<max_poll_interval_ms>30000</max_poll_interval_ms>
<session_timeout_ms>30000</session_timeout_ms>
<auto_offset_reset>latest</auto_offset_reset>
<skip_broken_messages>100</skip_broken_messages>
</kafka>
</sensus>
</users>
<!-- Профиль по умолчанию -->
<profiles>
<default>
<!-- Настройки для работы с памятью -->
<max_memory_usage>10000000000</max_memory_usage>
<max_bytes_before_external_group_by>20000000000</max_bytes_before_external_group_by>
<max_bytes_before_external_sort>20000000000</max_bytes_before_external_sort>
<!-- Настройки для работы с временными данными -->
<max_temporary_data_size>10000000000</max_temporary_data_size>
<max_temporary_non_const_columns>1000</max_temporary_non_const_columns>
<!-- Настройки для работы с запросами -->
<max_query_size>268435456</max_query_size>
<max_ast_depth>1000</max_ast_depth>
<max_ast_elements>50000</max_ast_elements>
<max_expanded_ast_elements>500000</max_expanded_ast_elements>
<!-- Настройки для работы с репликацией -->
<distributed_ddl>
<path>/clickhouse/task_queue/ddl</path>
</distributed_ddl>
<!-- Настройки для работы с внешними источниками данных -->
<external_table_functions_whitelist>
<function>url</function>
<function>file</function>
<function>mysql</function>
<function>postgresql</function>
<function>odbc</function>
<function>jdbc</function>
<function>hdfs</function>
<function>s3</function>
</external_table_functions_whitelist>
</default>
</profiles>
<!-- Квоты по умолчанию -->
<quotas>
<default>
<interval>
<duration>3600</duration>
<queries>0</queries>
<errors>0</errors>
<result_rows>0</result_rows>
<read_rows>0</read_rows>
<execution_time>0</execution_time>
</interval>
</default>
</quotas>
</yandex>

270
docker-compose.yml Normal file
View File

@ -0,0 +1,270 @@
# Автор: Сергей Антропов, сайт: https://devops.org.ru
# Назначение: Инфраструктура для SensusAgent и SensusWorker
# Включает: Kafka, KafkaUI, PostgreSQL, ClickHouse (2 реплики)
version: "3.9"
services:
# Zookeeper для Kafka
zookeeper:
image: confluentinc/cp-zookeeper:7.6.0
container_name: sensus-zookeeper
environment:
ZOOKEEPER_CLIENT_PORT: ${ZOOKEEPER_CLIENT_PORT:-2181}
ZOOKEEPER_TICK_TIME: ${ZOOKEEPER_TICK_TIME:-2000}
volumes:
- zookeeper-data:/var/lib/zookeeper/data
- zookeeper-logs:/var/lib/zookeeper/log
networks:
- sensus-network
restart: unless-stopped
healthcheck:
test: ["CMD", "bash", "-c", "echo 'ruok' | nc localhost 2181"]
interval: 30s
timeout: 10s
retries: 3
# Kafka брокер
kafka:
image: confluentinc/cp-kafka:7.6.0
container_name: sensus-kafka
depends_on:
zookeeper:
condition: service_healthy
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT,SSL:SSL
KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:29092,PLAINTEXT_HOST://0.0.0.0:9092,SSL://0.0.0.0:9093
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://10.99.0.90:9092,SSL://10.99.0.90:9093
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_AUTO_CREATE_TOPICS_ENABLE: ${KAFKA_AUTO_CREATE_TOPICS_ENABLE:-true}
KAFKA_NUM_PARTITIONS: ${KAFKA_NUM_PARTITIONS:-3}
KAFKA_DEFAULT_REPLICATION_FACTOR: ${KAFKA_DEFAULT_REPLICATION_FACTOR:-1}
KAFKA_LOG_RETENTION_HOURS: ${KAFKA_LOG_RETENTION_HOURS:-168}
KAFKA_LOG_SEGMENT_BYTES: ${KAFKA_LOG_SEGMENT_BYTES:-1073741824}
KAFKA_LOG_RETENTION_CHECK_INTERVAL_MS: ${KAFKA_LOG_RETENTION_CHECK_INTERVAL_MS:-300000}
# SSL настройки
KAFKA_SSL_KEYSTORE_LOCATION: /var/ssl/private/kafka.server.keystore.jks
KAFKA_SSL_KEYSTORE_PASSWORD: ${KAFKA_SSL_KEYSTORE_PASSWORD:-kafka123}
KAFKA_SSL_KEY_PASSWORD: ${KAFKA_SSL_KEY_PASSWORD:-kafka123}
KAFKA_SSL_TRUSTSTORE_LOCATION: /var/ssl/private/kafka.server.truststore.jks
KAFKA_SSL_TRUSTSTORE_PASSWORD: ${KAFKA_SSL_TRUSTSTORE_PASSWORD:-kafka123}
KAFKA_SSL_CLIENT_AUTH: ${KAFKA_SSL_CLIENT_AUTH:-none}
KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM: ${KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM:-https}
volumes:
- kafka-data:/var/lib/kafka/data
- ./kafka-ssl:/var/ssl/private:ro
ports:
- "${KAFKA_EXTERNAL_PORT:-9092}:9092"
- "${KAFKA_SSL_PORT:-9093}:9093"
networks:
- sensus-network
restart: unless-stopped
healthcheck:
test: ["CMD", "kafka-broker-api-versions", "--bootstrap-server", "localhost:9092"]
interval: 30s
timeout: 10s
retries: 3
# Kafka UI для мониторинга
kafka-ui:
image: provectuslabs/kafka-ui:latest
container_name: sensus-kafka-ui
depends_on:
kafka:
condition: service_healthy
environment:
KAFKA_CLUSTERS_0_NAME: ${KAFKA_CLUSTERS_0_NAME:-sensus-cluster}
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: ${KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS:-kafka:29092}
KAFKA_CLUSTERS_0_ZOOKEEPER: ${KAFKA_CLUSTERS_0_ZOOKEEPER:-zookeeper:2181}
KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL: ${KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL:-PLAINTEXT}
KAFKA_CLUSTERS_0_PROPERTIES_SSL_TRUSTSTORE_LOCATION: ${KAFKA_CLUSTERS_0_PROPERTIES_SSL_TRUSTSTORE_LOCATION:-/var/ssl/private/kafka.server.truststore.jks}
KAFKA_CLUSTERS_0_PROPERTIES_SSL_TRUSTSTORE_PASSWORD: ${KAFKA_CLUSTERS_0_PROPERTIES_SSL_TRUSTSTORE_PASSWORD:-kafka123}
DYNAMIC_CONFIG_ENABLED: ${DYNAMIC_CONFIG_ENABLED:-true}
# Авторизация Kafka UI
AUTH_TYPE: ${KAFKA_UI_AUTH_TYPE:-LOGIN_FORM}
SPRING_SECURITY_USER_NAME: ${KAFKA_UI_USERNAME:-admin}
SPRING_SECURITY_USER_PASSWORD: ${KAFKA_UI_PASSWORD:-admin}
SPRING_SECURITY_USER_ROLES: ${KAFKA_UI_USER_ROLES:-ADMIN}
volumes:
- ./kafka-ssl:/var/ssl/private:ro
ports:
- "${KAFKA_UI_PORT:-8080}:8080"
networks:
- sensus-network
restart: unless-stopped
# PostgreSQL для хранения метаданных и конфигураций
postgres:
image: postgres:16-alpine
container_name: sensus-postgres
environment:
POSTGRES_DB: ${POSTGRES_DB:-sensus}
POSTGRES_USER: ${POSTGRES_USER:-sensus}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_INITDB_ARGS: ${POSTGRES_INITDB_ARGS:---encoding=UTF-8 --lc-collate=C --lc-ctype=C}
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d:ro
ports:
- "${POSTGRES_PORT:-5432}:5432"
networks:
- sensus-network
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-sensus} -d ${POSTGRES_DB:-sensus}"]
interval: 30s
timeout: 10s
retries: 3
# ClickHouse - первая реплика
clickhouse-1:
image: clickhouse/clickhouse-server:24.8-alpine
container_name: sensus-clickhouse-1
environment:
CLICKHOUSE_DB: ${CLICKHOUSE_DB:-sensus_metrics}
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-sensus}
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: ${CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:-1}
CLICKHOUSE_SECURE: ${CLICKHOUSE_SECURE:-true}
volumes:
- clickhouse-1-data:/var/lib/clickhouse
- ./clickhouse-config:/etc/clickhouse-server/config.d:ro
- ./clickhouse-users:/etc/clickhouse-server/users.d:ro
ports:
- "${CLICKHOUSE_1_PORT:-8123}:8123"
- "${CLICKHOUSE_1_HTTP_PORT:-9000}:9000"
networks:
- sensus-network
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8123/ping"]
interval: 30s
timeout: 10s
retries: 3
# ClickHouse - вторая реплика
clickhouse-2:
image: clickhouse/clickhouse-server:24.8-alpine
container_name: sensus-clickhouse-2
environment:
CLICKHOUSE_DB: ${CLICKHOUSE_DB:-sensus_metrics}
CLICKHOUSE_USER: ${CLICKHOUSE_USER:-sensus}
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD}
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: ${CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:-1}
CLICKHOUSE_SECURE: ${CLICKHOUSE_SECURE:-true}
volumes:
- clickhouse-2-data:/var/lib/clickhouse
- ./clickhouse-config:/etc/clickhouse-server/config.d:ro
- ./clickhouse-users:/etc/clickhouse-server/users.d:ro
ports:
- "${CLICKHOUSE_2_PORT:-8124}:8123"
- "${CLICKHOUSE_2_HTTP_PORT:-9001}:9000"
networks:
- sensus-network
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8123/ping"]
interval: 30s
timeout: 10s
retries: 3
# Nginx балансировщик нагрузки для ClickHouse
clickhouse-lb:
image: nginx:1.25-alpine
container_name: sensus-clickhouse-lb
depends_on:
clickhouse-1:
condition: service_healthy
clickhouse-2:
condition: service_healthy
volumes:
- ./nginx/clickhouse-lb.conf:/etc/nginx/nginx.conf:ro
ports:
- "${CLICKHOUSE_LB_HTTP_PORT:-8125}:80"
- "${CLICKHOUSE_LB_TCP_PORT:-9002}:9000"
networks:
- sensus-network
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:80/health"]
interval: 30s
timeout: 10s
retries: 3
# SensusAgent
sensus-agent:
build:
context: ../SensusAgent
dockerfile: Dockerfile
image: sensus/agent:latest
container_name: sensus-agent
depends_on:
kafka:
condition: service_healthy
environment:
CONFIG_PATH: /bin/agent/config.yaml
LOG_LEVEL: ${AGENT_LOG_LEVEL:-info}
KAFKA_BROKERS: kafka:29092
KAFKA_TOPIC: ${KAFKA_TOPIC:-sensus.metrics}
volumes:
- ../SensusAgent/bin/agent:/bin/agent:ro
networks:
- sensus-network
restart: unless-stopped
profiles:
- agent
# SensusWorker
sensus-worker:
build:
context: ../SensusWorker
dockerfile: Dockerfile
image: sensus/worker:latest
container_name: sensus-worker
depends_on:
kafka:
condition: service_healthy
postgres:
condition: service_healthy
clickhouse-1:
condition: service_healthy
environment:
LOG_LEVEL: ${WORKER_LOG_LEVEL:-info}
KAFKA_BROKERS: kafka:29092
KAFKA_TOPIC: ${KAFKA_TOPIC:-sensus.metrics}
KAFKA_GROUP_ID: ${KAFKA_GROUP_ID:-sensus-worker}
KAFKA_CLIENT_ID: ${KAFKA_CLIENT_ID:-sensus-worker}
POSTGRES_DSN: postgres://${POSTGRES_USER:-sensus}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-sensus}?sslmode=disable
CLICKHOUSE_DSN: http://${CLICKHOUSE_USER:-sensus}:${CLICKHOUSE_PASSWORD}@clickhouse-1:8123/${CLICKHOUSE_DB:-sensus_metrics}
networks:
- sensus-network
restart: unless-stopped
profiles:
- worker
volumes:
zookeeper-data:
driver: local
zookeeper-logs:
driver: local
kafka-data:
driver: local
postgres-data:
driver: local
clickhouse-1-data:
driver: local
clickhouse-2-data:
driver: local
networks:
sensus-network:
name: sensus-network
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16

97
env.example Normal file
View File

@ -0,0 +1,97 @@
# Автор: Сергей Антропов, сайт: https://devops.org.ru
# Назначение: Пример переменных окружения для инфраструктуры SensusAgent и SensusWorker
# ВНИМАНИЕ: Этот файл содержит примеры значений для настройки!
# =============================================================================
# ZOOKEEPER КОНФИГУРАЦИЯ
# =============================================================================
ZOOKEEPER_CLIENT_PORT=2181
ZOOKEEPER_TICK_TIME=2000
# =============================================================================
# KAFKA КОНФИГУРАЦИЯ
# =============================================================================
KAFKA_BROKER_ID=1
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT,SSL:SSL
KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:29092,PLAINTEXT_HOST://10.99.0.90:9092,SSL://10.99.0.90:9093
KAFKA_EXTERNAL_PORT=9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR=1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=1
KAFKA_AUTO_CREATE_TOPICS_ENABLE=true
KAFKA_NUM_PARTITIONS=3
KAFKA_DEFAULT_REPLICATION_FACTOR=1
KAFKA_LOG_RETENTION_HOURS=168
KAFKA_LOG_SEGMENT_BYTES=1073741824
KAFKA_LOG_RETENTION_CHECK_INTERVAL_MS=300000
# Kafka UI
KAFKA_UI_PORT=8080
KAFKA_CLUSTERS_0_NAME=sensus-cluster
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:29092
KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181
DYNAMIC_CONFIG_ENABLED=true
# Kafka UI авторизация
KAFKA_UI_AUTH_TYPE=LOGIN_FORM
KAFKA_UI_USERNAME=admin
KAFKA_UI_PASSWORD=admin
KAFKA_UI_USER_ROLES=ADMIN
# Kafka топики
KAFKA_TOPIC=sensus.metrics
KAFKA_GROUP_ID=sensus-worker
KAFKA_CLIENT_ID=sensus-worker
# Kafka SSL
KAFKA_SSL_PORT=9093
KAFKA_SSL_KEYSTORE_PASSWORD=kafka123
KAFKA_SSL_KEY_PASSWORD=kafka123
KAFKA_SSL_TRUSTSTORE_PASSWORD=kafka123
KAFKA_SSL_CLIENT_AUTH=none
KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM=https
# =============================================================================
# POSTGRESQL КОНФИГУРАЦИЯ
# =============================================================================
POSTGRES_DB=sensus
POSTGRES_USER=sensus
POSTGRES_PASSWORD=sensus_secure_password_2024
POSTGRES_PORT=5432
POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
# =============================================================================
# CLICKHOUSE КОНФИГУРАЦИЯ
# =============================================================================
CLICKHOUSE_DB=sensus_metrics
CLICKHOUSE_USER=sensus
CLICKHOUSE_PASSWORD=clickhouse_secure_password_2024
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1
CLICKHOUSE_SECURE=true
# ClickHouse реплика 1
CLICKHOUSE_1_PORT=8123
CLICKHOUSE_1_HTTP_PORT=9000
# ClickHouse реплика 2
CLICKHOUSE_2_PORT=8124
CLICKHOUSE_2_HTTP_PORT=9001
# ClickHouse Load Balancer
CLICKHOUSE_LB_HTTP_PORT=8125
CLICKHOUSE_LB_TCP_PORT=9002
# =============================================================================
# ПРИЛОЖЕНИЯ КОНФИГУРАЦИЯ
# =============================================================================
# SensusAgent
AGENT_LOG_LEVEL=info
# SensusWorker
WORKER_LOG_LEVEL=info
# =============================================================================
# СЕТЬ
# =============================================================================
# Docker network subnet для sensus-network
NETWORK_SUBNET=172.20.0.0/16

101
kafka-ssl/generate-ssl.sh Normal file
View File

@ -0,0 +1,101 @@
#!/bin/bash
# Автор: Сергей Антропов, сайт: https://devops.org.ru
# Назначение: Генерация SSL сертификатов для Kafka
set -e
# Переменные
KEYSTORE_PASSWORD=${KAFKA_SSL_KEYSTORE_PASSWORD:-kafka123}
TRUSTSTORE_PASSWORD=${KAFKA_SSL_TRUSTSTORE_PASSWORD:-kafka123}
KEY_PASSWORD=${KAFKA_SSL_KEY_PASSWORD:-kafka123}
CERT_VALIDITY_DAYS=${CERT_VALIDITY_DAYS:-365}
# Создание директории для сертификатов
mkdir -p /tmp/kafka-ssl
cd /tmp/kafka-ssl
echo "🔐 Генерация SSL сертификатов для Kafka..."
# 1. Создание CA (Certificate Authority)
echo "📋 Создание CA сертификата..."
keytool -keystore kafka.server.truststore.jks -alias CARoot -import -file ca-cert -storepass $TRUSTSTORE_PASSWORD -keypass $KEY_PASSWORD -noprompt || true
# Создание CA ключа и сертификата
openssl req -new -x509 -keyout ca-key -out ca-cert -days $CERT_VALIDITY_DAYS -subj "/C=RU/ST=Moscow/L=Moscow/O=Sensus/OU=IT/CN=ca.sensus.local"
# 2. Создание keystore для сервера
echo "🔑 Создание keystore для сервера..."
keytool -keystore kafka.server.keystore.jks -alias localhost -validity $CERT_VALIDITY_DAYS -genkey -keyalg RSA -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD -dname "CN=kafka.sensus.local, OU=IT, O=Sensus, L=Moscow, ST=Moscow, C=RU"
# 3. Создание Certificate Signing Request (CSR)
echo "📝 Создание CSR..."
keytool -keystore kafka.server.keystore.jks -alias localhost -certreq -file cert-file -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD
# 4. Подписание сертификата CA
echo "✍️ Подписание сертификата CA..."
openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days $CERT_VALIDITY_DAYS -CAcreateserial -passin pass:$KEY_PASSWORD
# 5. Импорт CA сертификата в keystore
echo "📥 Импорт CA сертификата в keystore..."
keytool -keystore kafka.server.keystore.jks -alias CARoot -import -file ca-cert -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD -noprompt
# 6. Импорт подписанного сертификата в keystore
echo "📥 Импорт подписанного сертификата в keystore..."
keytool -keystore kafka.server.keystore.jks -alias localhost -import -file cert-signed -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD -noprompt
# 7. Создание truststore
echo "🛡️ Создание truststore..."
keytool -keystore kafka.server.truststore.jks -alias CARoot -import -file ca-cert -storepass $TRUSTSTORE_PASSWORD -keypass $KEY_PASSWORD -noprompt
# 8. Создание клиентского keystore (для клиентов)
echo "👤 Создание клиентского keystore..."
keytool -keystore kafka.client.keystore.jks -alias localhost -validity $CERT_VALIDITY_DAYS -genkey -keyalg RSA -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD -dname "CN=client.sensus.local, OU=IT, O=Sensus, L=Moscow, ST=Moscow, C=RU"
# 9. Создание CSR для клиента
echo "📝 Создание CSR для клиента..."
keytool -keystore kafka.client.keystore.jks -alias localhost -certreq -file client-cert-file -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD
# 10. Подписание клиентского сертификата
echo "✍️ Подписание клиентского сертификата..."
openssl x509 -req -CA ca-cert -CAkey ca-key -in client-cert-file -out client-cert-signed -days $CERT_VALIDITY_DAYS -CAcreateserial -passin pass:$KEY_PASSWORD
# 11. Импорт CA в клиентский keystore
echo "📥 Импорт CA в клиентский keystore..."
keytool -keystore kafka.client.keystore.jks -alias CARoot -import -file ca-cert -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD -noprompt
# 12. Импорт подписанного клиентского сертификата
echo "📥 Импорт подписанного клиентского сертификата..."
keytool -keystore kafka.client.keystore.jks -alias localhost -import -file client-cert-signed -storepass $KEYSTORE_PASSWORD -keypass $KEY_PASSWORD -noprompt
# 13. Создание клиентского truststore
echo "🛡️ Создание клиентского truststore..."
keytool -keystore kafka.client.truststore.jks -alias CARoot -import -file ca-cert -storepass $TRUSTSTORE_PASSWORD -keypass $KEY_PASSWORD -noprompt
# 14. Копирование файлов в целевую директорию
echo "📁 Копирование сертификатов..."
cp kafka.server.keystore.jks /workspace/kafka-ssl/
cp kafka.server.truststore.jks /workspace/kafka-ssl/
cp kafka.client.keystore.jks /workspace/kafka-ssl/
cp kafka.client.truststore.jks /workspace/kafka-ssl/
cp ca-cert /workspace/kafka-ssl/
cp ca-key /workspace/kafka-ssl/
# 15. Установка правильных прав доступа
chmod 600 /workspace/kafka-ssl/*.jks
chmod 600 /workspace/kafka-ssl/ca-*
echo "✅ SSL сертификаты успешно созданы!"
echo "📋 Созданные файлы:"
echo " - kafka.server.keystore.jks (серверный keystore)"
echo " - kafka.server.truststore.jks (серверный truststore)"
echo " - kafka.client.keystore.jks (клиентский keystore)"
echo " - kafka.client.truststore.jks (клиентский truststore)"
echo " - ca-cert (CA сертификат)"
echo " - ca-key (CA ключ)"
echo ""
echo "🔐 Пароли:"
echo " - Keystore password: $KEYSTORE_PASSWORD"
echo " - Truststore password: $TRUSTSTORE_PASSWORD"
echo " - Key password: $KEY_PASSWORD"
echo ""
echo "⚠️ ВАЖНО: Измените пароли в production среде!"

174
nginx/clickhouse-lb.conf Normal file
View File

@ -0,0 +1,174 @@
# Автор: Сергей Антропов, сайт: https://devops.org.ru
# Назначение: Конфигурация Nginx для балансировки нагрузки ClickHouse
# Балансировка между двумя репликами ClickHouse
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
# HTTP балансировка для ClickHouse HTTP интерфейса
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Логирование
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# Основные настройки
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 100M;
# Gzip сжатие
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
# Upstream для ClickHouse HTTP интерфейса
upstream clickhouse_http {
# Балансировка по round-robin
least_conn;
# ClickHouse реплика 1
server clickhouse-1:8123 max_fails=3 fail_timeout=30s weight=1;
# ClickHouse реплика 2
server clickhouse-2:8123 max_fails=3 fail_timeout=30s weight=1;
# Резервные серверы (если основные недоступны)
keepalive 32;
}
# Upstream для ClickHouse Native протокола (TCP)
upstream clickhouse_native {
# ClickHouse реплика 1
server clickhouse-1:9000 max_fails=3 fail_timeout=30s weight=1;
# ClickHouse реплика 2
server clickhouse-2:9000 max_fails=3 fail_timeout=30s weight=1;
keepalive 32;
}
# Основной сервер для HTTP интерфейса ClickHouse
server {
listen 80;
server_name _;
# Health check endpoint
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# Статус балансировщика
location /status {
access_log off;
return 200 "ClickHouse Load Balancer is running\n";
add_header Content-Type text/plain;
}
# Проксирование всех запросов к ClickHouse HTTP интерфейсу
location / {
# Проксирование к ClickHouse
proxy_pass http://clickhouse_http;
# Заголовки для ClickHouse
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Настройки таймаутов
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Буферизация
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
proxy_busy_buffers_size 8k;
# Обработка ошибок
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 2;
proxy_next_upstream_timeout 10s;
# Поддержка WebSocket (если потребуется)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Специальный endpoint для ping
location /ping {
proxy_pass http://clickhouse_http/ping;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Endpoint для получения информации о сервере
location /info {
proxy_pass http://clickhouse_http/info;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
# TCP балансировка для ClickHouse Native протокола
stream {
# Логирование для stream
access_log /var/log/nginx/stream_access.log;
error_log /var/log/nginx/stream_error.log;
# Upstream для ClickHouse Native протокола
upstream clickhouse_native_backend {
# ClickHouse реплика 1
server clickhouse-1:9000 max_fails=3 fail_timeout=30s weight=1;
# ClickHouse реплика 2
server clickhouse-2:9000 max_fails=3 fail_timeout=30s weight=1;
}
# TCP сервер для ClickHouse Native протокола
server {
listen 9000;
proxy_pass clickhouse_native_backend;
proxy_timeout 1s;
proxy_responses 1;
proxy_bind $remote_addr transparent;
}
}