# 🌐 Удаленные клиенты LogBoard+ ## Обзор LogBoard+ поддерживает сбор логов с удаленных серверов через специальные клиенты. Это позволяет централизованно мониторить логи контейнеров с нескольких машин. ## Архитектура ``` ┌─────────────────┐ HTTP API ┌─────────────────┐ │ Удаленный │ ──────────────► │ LogBoard+ │ │ сервер │ │ Сервер │ │ │ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ Клиент │ │ │ │ Web UI │ │ │ │ LogBoard+ │ │ │ │ │ │ │ └─────────────┘ │ │ └─────────────┘ │ └─────────────────┘ └─────────────────┘ ``` ## Компоненты ### 1. Серверная часть (LogBoard+ Server) - **API эндпоинты**: Прием логов от удаленных клиентов - **Хранение логов**: Сохранение в файловой системе - **Web интерфейс**: Отображение локальных и удаленных контейнеров - **Визуальное разделение**: Четкое различие между локальными и удаленными контейнерами ### 2. Клиентская часть (LogBoard+ Client) - **Сбор логов**: Чтение логов Docker контейнеров - **Отправка данных**: HTTP POST запросы на сервер - **Автоматизация**: Docker Compose для простого развертывания ## Установка и настройка ### На сервере LogBoard+ 1. Убедитесь, что сервер LogBoard+ запущен и доступен 2. Получите API ключ для аутентификации клиентов ### На удаленном сервере 1. Создайте директорию для клиента: ```bash mkdir logboard-client cd logboard-client ``` 2. Создайте `docker-compose.yml`: ```yaml version: '3.8' services: logboard-client: build: . container_name: logboard-client environment: - LOGBOARD_SERVER_URL=http://your-logboard-server:9001 - API_KEY=your-api-key - HOSTNAME=your-server-name volumes: - /var/run/docker.sock:/var/run/docker.sock - ./logs:/app/logs restart: unless-stopped user: 0:0 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 # Тестовый контейнер для демонстрации test-nginx: image: nginx:alpine container_name: test-nginx ports: - "8080:80" restart: unless-stopped ``` 3. Создайте `Dockerfile`: ```dockerfile FROM python:3.11-slim RUN apt-get update && apt-get install -y \ curl \ && rm -rf /var/lib/apt/lists/* RUN groupadd -r logboard && useradd -r -g logboard logboard RUN mkdir -p /app /var/log WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app/ ./app/ RUN mkdir -p /var/log && \ chown -R logboard:logboard /app /var/log USER logboard CMD ["python", "app/main.py"] ``` 4. Создайте `requirements.txt`: ``` aiohttp==3.9.1 docker==6.1.3 urllib3==2.1.0 requests==2.31.0 ``` 5. Создайте `app/main.py`: ```python #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ LogBoard+ Client - Клиент для отправки логов на сервер LogBoard+ Автор: Сергей Антропов Сайт: https://devops.org.ru """ import asyncio import aiohttp import docker import os import logging from datetime import datetime # Настройка логирования logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) class LogBoardClient: def __init__(self): self.server_url = os.getenv('LOGBOARD_SERVER_URL', 'http://localhost:9001') self.api_key = os.getenv('API_KEY', 'default-key') self.hostname = os.getenv('HOSTNAME', 'unknown') # Инициализация Docker клиента try: self.docker_client = docker.from_env() logger.info("Docker клиент инициализирован успешно") except Exception as e: logger.error(f"Ошибка инициализации Docker клиента: {e}") self.docker_client = None async def send_logs(self, container_name, logs_data): """Отправка логов на сервер LogBoard+""" try: async with aiohttp.ClientSession() as session: url = f"{self.server_url}/api/logs/remote" data = { 'container_name': container_name, 'hostname': self.hostname, 'logs': logs_data, 'api_key': self.api_key } async with session.post(url, json=data) as response: if response.status == 200: logger.info(f"Логи контейнера {container_name} отправлены успешно") else: logger.error(f"Ошибка отправки логов: {response.status}") except Exception as e: logger.error(f"Ошибка при отправке логов: {e}") def get_container_logs(self, container_name, tail=100): """Получение логов контейнера""" try: if not self.docker_client: return [] container = self.docker_client.containers.get(container_name) logs = container.logs(tail=tail, timestamps=True).decode('utf-8') return logs.split('\n')[:-1] # Убираем пустую строку в конце except Exception as e: logger.error(f"Ошибка получения логов контейнера {container_name}: {e}") return [] async def collect_and_send_logs(self): """Сбор и отправка логов всех контейнеров""" try: if not self.docker_client: logger.error("Docker клиент недоступен") return containers = self.docker_client.containers.list() logger.info(f"Найдено {len(containers)} контейнеров") for container in containers: try: logs = self.get_container_logs(container.name) if logs: await self.send_logs(container.name, logs) except Exception as e: logger.error(f"Ошибка обработки контейнера {container.name}: {e}") except Exception as e: logger.error(f"Ошибка сбора логов: {e}") async def run(self): """Основной цикл работы клиента""" logger.info(f"LogBoard+ Client запущен для хоста: {self.hostname}") logger.info(f"Сервер: {self.server_url}") while True: try: await self.collect_and_send_logs() await asyncio.sleep(30) # Пауза 30 секунд except Exception as e: logger.error(f"Критическая ошибка: {e}") await asyncio.sleep(60) # Увеличенная пауза при ошибке async def main(): client = LogBoardClient() await client.run() if __name__ == "__main__": asyncio.run(main()) ``` 6. Запустите клиент: ```bash docker-compose up -d ``` ## Использование ### Web интерфейс После настройки клиентов, в веб-интерфейсе LogBoard+ вы увидите: #### 📍 Локальные контейнеры - Контейнеры с текущего сервера - Обычное отображение без дополнительных индикаторов #### 🌐 Удаленные контейнеры - Контейнеры с удаленных серверов - Визуальное разделение по хостам - Индикаторы удаленного доступа (глобус 🌐) - Время последнего обновления - Статистика по хостам ### Функции интерфейса #### 🔽 Сворачивание секций - **Секции контейнеров**: Можно сворачивать/разворачивать секции "Локальные контейнеры" и "Удаленные контейнеры" - **Секции хостов**: Каждый хост в удаленных контейнерах можно сворачивать отдельно - **Кнопки управления**: Стрелки для сворачивания/разворачивания - **Сохранение состояния**: Состояние сворачивания сохраняется между сессиями #### ⚡ Периодическое обновление - **Автоматическое обновление**: Список контейнеров обновляется каждые 30 секунд - **Фильтрация остановленных**: Остановленные контейнеры автоматически скрываются из интерфейса - **Обновление счетчиков**: Количество контейнеров в секциях обновляется в реальном времени - **Логирование изменений**: В консоли браузера отображается информация об изменениях #### 📱 Адаптивный интерфейс - **Свернутый sidebar**: Миникарточки контейнеров с иконками статуса - **Развернутый sidebar**: Полная информация о контейнерах с возможностью сворачивания секций - **Мобильная поддержка**: Адаптивный дизайн для мобильных устройств ### API эндпоинты #### Получение контейнеров ```http GET /api/containers/services Authorization: Bearer ``` **Ответ:** ```json [ { "id": "container-id", "name": "container-name", "status": "running", "is_remote": false, "hostname": "localhost", "project": "project-name", "service": "service-name" }, { "id": "remote-hostname-container", "name": "remote-container", "status": "running", "is_remote": true, "hostname": "remote-host", "last_modified": "2025-08-20T16:30:00", "size": 1024 } ] ``` #### Получение логов удаленного контейнера ```http GET /api/logs/{container_id} Authorization: Bearer ``` #### Получение статистики логов ```http GET /api/logs/stats/{container_id} Authorization: Bearer ``` ## Мониторинг и отладка ### Логи клиента ```bash docker-compose logs -f logboard-client ``` ### Проверка здоровья ```bash curl http://localhost:8080/health ``` ### Тестирование API ```bash python3 test_interface.py ``` ## Безопасность - **API ключи**: Обязательная аутентификация клиентов - **HTTPS**: Рекомендуется использовать HTTPS для передачи данных - **Сетевая изоляция**: Клиенты должны иметь доступ только к необходимым портам ## Устранение неполадок ### Клиент не подключается 1. Проверьте URL сервера в переменной `LOGBOARD_SERVER_URL` 2. Убедитесь, что API ключ правильный 3. Проверьте сетевое подключение ### Логи не отображаются 1. Проверьте права доступа к Docker socket 2. Убедитесь, что контейнеры запущены 3. Проверьте логи клиента ### Интерфейс не обновляется 1. Откройте консоль браузера (F12) 2. Проверьте наличие ошибок JavaScript 3. Убедитесь, что WebSocket соединения работают ## Автор **Сергей Антропов** 🌐 Сайт: https://devops.org.ru 📧 Email: contact@devops.org.ru --- *Документация обновлена: 2025-08-20*