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

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

368 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🌐 Удаленные клиенты 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 <token>
```
**Ответ:**
```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 <token>
```
#### Получение статистики логов
```http
GET /api/logs/stats/{container_id}
Authorization: Bearer <token>
```
## Мониторинг и отладка
### Логи клиента
```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*