logboard/docs/remote-clients.md
Сергей Антропов 011d460a38 feat: добавлено сворачивание секций и периодическое обновление контейнеров
- Добавлена функция сворачивания/разворачивания секций локальных и удаленных контейнеров
- Реализовано периодическое обновление списка контейнеров каждые 30 секунд
- Добавлена автоматическая фильтрация остановленных контейнеров
- Обновлены обработчики событий для корректной работы в свернутом sidebar
- Добавлены функции обновления счетчиков контейнеров
- Обновлена документация с описанием новых функций
- Добавлены тестовые скрипты для проверки функциональности

Автор: Сергей Антропов
Сайт: https://devops.org.ru
2025-08-20 20:06:33 +03:00

13 KiB
Raw Blame History

🌐 Удаленные клиенты 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. Создайте директорию для клиента:
mkdir logboard-client
cd logboard-client
  1. Создайте docker-compose.yml:
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
  1. Создайте 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"]
  1. Создайте requirements.txt:
aiohttp==3.9.1
docker==6.1.3
urllib3==2.1.0
requests==2.31.0
  1. Создайте app/main.py:
#!/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())
  1. Запустите клиент:
docker-compose up -d

Использование

Web интерфейс

После настройки клиентов, в веб-интерфейсе LogBoard+ вы увидите:

📍 Локальные контейнеры

  • Контейнеры с текущего сервера
  • Обычное отображение без дополнительных индикаторов

🌐 Удаленные контейнеры

  • Контейнеры с удаленных серверов
  • Визуальное разделение по хостам
  • Индикаторы удаленного доступа (глобус 🌐)
  • Время последнего обновления
  • Статистика по хостам

Функции интерфейса

🔽 Сворачивание секций

  • Секции контейнеров: Можно сворачивать/разворачивать секции "Локальные контейнеры" и "Удаленные контейнеры"
  • Секции хостов: Каждый хост в удаленных контейнерах можно сворачивать отдельно
  • Кнопки управления: Стрелки для сворачивания/разворачивания
  • Сохранение состояния: Состояние сворачивания сохраняется между сессиями

Периодическое обновление

  • Автоматическое обновление: Список контейнеров обновляется каждые 30 секунд
  • Фильтрация остановленных: Остановленные контейнеры автоматически скрываются из интерфейса
  • Обновление счетчиков: Количество контейнеров в секциях обновляется в реальном времени
  • Логирование изменений: В консоли браузера отображается информация об изменениях

📱 Адаптивный интерфейс

  • Свернутый sidebar: Миникарточки контейнеров с иконками статуса
  • Развернутый sidebar: Полная информация о контейнерах с возможностью сворачивания секций
  • Мобильная поддержка: Адаптивный дизайн для мобильных устройств

API эндпоинты

Получение контейнеров

GET /api/containers/services
Authorization: Bearer <token>

Ответ:

[
  {
    "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
  }
]

Получение логов удаленного контейнера

GET /api/logs/{container_id}
Authorization: Bearer <token>

Получение статистики логов

GET /api/logs/stats/{container_id}
Authorization: Bearer <token>

Мониторинг и отладка

Логи клиента

docker-compose logs -f logboard-client

Проверка здоровья

curl http://localhost:8080/health

Тестирование API

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