Новости:

SMF - Just Installed!

Главное меню

Последние сообщения

#11
Что делаем дальше?Теперь у вас полностью готовы:Сеть GlusterFS со всеми нужными каталогами и правами пользователей (Шаг 1 и Шаг 5).Внешний отказоустойчивый кластер Galera на хостах (Шаг 2).Инициализированный Docker Swarm и сеть cloudlife_net (Шаг 3).Конфигурационный файл Caddyfile (Шаг 6).Все компоненты собраны. Вы можете смело возвращаться к файлу prod-stack.yml из предыдущего сообщения и запускать команду:bashsudo docker stack deploy -c prod-stack.yml hub
Используйте код с осторожностью.Дайте знать, когда запустите команду деплоя. Нам останется выполнить финальную проверку: посмотреть, как hub_onlyoffice распределился по вашим новым трем нодам. Стек успешно стартовал?Error: adapting config using caddyfile: parsing caddyfile tokens for 'reverse_proxy': unrecognized subdirective read_buffer_size, at /etc/caddy/Caddyfile:13 какая-то директива не поддерживается  cat Caddyfile
# --- НАСТРОЙКИ КЛАССТЕРА ONLYOFFICE ---
docs.cloud-life.site {
    # Проксируем запросы на встроенный балансировщик Swarm
    # Имя 'hub_onlyoffice' сформировано из имени стека и имени сервиса
    reverse_proxy hub_onlyoffice:80 {
        # Передаем реальные заголовки, чтобы OnlyOffice понимал, откуда идет тра                                                                                                             фик
        header_up X-Forwarded-Host {host}
        header_up X-Forwarded-Proto {scheme}

        # Настройки таймаутов для 1000 пользователей (чтобы тяжелые документы не                                                                                                              отваливались при открытии)
        transport http {
            dial_timeout 10s
            read_buffer_size 4096
        }
    }

    # Включаем сжатие ответов (ускоряет загрузку интерфейса редактора у клиентов                                                                                                             )
    encode gzip zstd
}

# --- ПРОВЕРКА ЖИВУЧЕСТИ ДЛЯ ВНЕШНЕГО БАЛАНСИРОВЩИКА (Если используете HAProxy/K                                                                                                             eepalived) ---
:8080 {
    respond /health "OK" 200
}Моя ошибка. В Caddy внутри блока transport http директива read_buffer_size отсутствует в таком виде. Настройка буферов в Caddy управляется глобально или через другие механизмы, а для стабильности тяжелых соединений в transport http достаточно стандартных параметров таймаутов.Давайте уберем проблемную строку, чтобы Caddy успешно запустился.Исправленный вариант CaddyfileОткройте файл /mnt/gluster-storage/Caddyfile и замените блок transport http на этот (строка с ошибкой удалена):caddy# --- НАСТРОЙКИ КЛАССТЕРА ONLYOFFICE ---
docs.cloud-life.site {
    # Проксируем запросы на встроенный балансировщик Swarm
    # Имя 'hub_onlyoffice' сформировано из имени стека и имени сервиса
    reverse_proxy hub_onlyoffice:80 {
        # Передаем реальные заголовки, чтобы OnlyOffice понимал, откуда идет трафик
        header_up X-Forwarded-Host {host}
        header_up X-Forwarded-Proto {scheme}

        # Настройки таймаутов для стабильной работы под нагрузкой
        transport http {
            dial_timeout 10s
        }
    }

    # Включаем сжатие ответов (ускоряет загрузку интерфейса редактора у клиентов)
    encode gzip zstd
}

# --- ПРОВЕРКА ЖИВУЧЕСТИ ДЛЯ ВНЕШНЕГО БАЛАНСИРОВЩИКА (Если используете HAProxy/Keepalived) ---
:8080 {
    respond /health "OK" 200
}
Используйте код с осторожностью.Как применить изменения:После сохранения файла отправьте Caddy команду на перечитку конфига:bashdocker exec -it $(docker ps -q -f name=hub_caddy | head -n 1) caddy reload --config /etc/caddy/Caddyfile
Используйте код с осторожностью.Конфигурация должна примениться без ошибок. Сообщите, если Caddy успешно запустился, и мы сможем проверить статус сервиса OnlyOffice через docker stack ps hub.root@onlyoffice-stack-1:/mnt/gluster-storage# docker exec -it $(docker ps -q -f name=hub_caddy | head -n 1) caddy reload --config /etc/caddy/Caddyfile
2026/05/16 20:11:09.046 INFO    using config from file  {"file": "/etc/caddy/Caddyfile"}
2026/05/16 20:11:09.049 WARN    caddyfile       Unnecessary header_up X-Forwarded-Host: the reverse proxy's default behavior is to pass headers to the upstream
2026/05/16 20:11:09.049 WARN    caddyfile       Unnecessary header_up X-Forwarded-Proto: the reverse proxy's default behavior is to pass headers to the upstream
2026/05/16 20:11:09.052 INFO    adapted config to JSON  {"adapter": "caddyfile"}
2026/05/16 20:11:09.052 WARN    Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies    {"adapter": "caddyfile", "file": "/etc/caddy/Caddyfile", "line": 3}
root@onlyoffice-stack-1:/mnt/gluster-storage# давай поправим до конца, это все-таки продПрекрасный подход. В продакшене логи должны быть идеально чистыми, без предупреждений (WARN), чтобы в случае реальной аварии сразу заметить важные сообщения.Варнинги говорят о двух вещах:Современный Caddy по умолчанию сам передает заголовки X-Forwarded-Host и X-Forwarded-Proto на бэкенд. Дублировать их вручную больше не нужно.Файл конфигурации имеет неидеальные отступы/пробелы с точки зрения встроенного линтера Caddy.Давайте сделаем конфиг безупречным.Шаг 1. Идеальный Caddyfile без лишних опцийОткройте ваш файл /mnt/gluster-storage/Caddyfile и приведите его к следующему чистому виду:caddy# --- НАСТРОЙКИ КЛАССТЕРА ONLYOFFICE ---
docs.cloud-life.site {
   # Проксируем запросы на встроенный балансировщик Swarm
   reverse_proxy hub_onlyoffice:80 {
      # Настройки таймаутов для стабильной работы под нагрузкой
      transport http {
         dial_timeout 10s
      }
   }

   # Включаем сжатие ответов (ускоряет работу интерфейса)
   encode gzip zstd
}

# --- ПРОВЕРКА ЖИВУЧЕСТИ ДЛЯ ВНЕШНЕГО БАЛАНСИРОВЩИКА ---
:8080 {
   respond /health "OK" 200
}
Используйте код с осторожностью.Шаг 2. Автоматическое форматирование (убираем последний WARN)Чтобы у Caddy вообще не было претензий к синтаксису, выполните команду автоматического форматирования прямо через контейнер. Она исправит все табы и отступы в файле на GlusterFS:bashdocker exec -it $(docker ps -q -f name=hub_caddy | head -n 1) caddy fmt --overwrite /etc/caddy/Caddyfile
Используйте код с осторожностью.Шаг 3. Финальная проверкаТеперь примените конфигурацию заново:bashdocker exec -it $(docker ps -q -f name=hub_caddy | head -n 1) caddy reload --config /etc/caddy/Caddyfile
Используйте код с осторожностью.Теперь в выводе должны остаться только чистые строки INFO о том, что конфиг успешно адаптирован и применен. Никаких WARN быть не должно.Вывод стал чистым? Если да, давайте проверим, как чувствуют себя контейнеры OnlyOffice, командой docker stack ps hub — все три ноды успешно запустились?Error: reading config from file: open /etc/caddy/Caddyfile: stale file handleОшибка stale file handle (устаревший дескриптор файла) — это специфическая и очень частая проблема распределенной файловой системы GlusterFS.Она возникает, когда утилита caddy fmt --overwrite перезаписала файл с одной ноды, создав новый дескриптор (inode) в системе, а контейнер Caddy на другой ноде (или системный кэш) всё ещё пытается прочитать старый идентификатор файла, которого физически больше нет на диске.Поскольку GlusterFS потерял связь с этим конкретным файлом, обычный caddy reload не сработает, пока операционная система не обновит кэш тома.Как это исправить прямо сейчас (в прод-кластере)Шаг 1. Сброс кэша GlusterFS на нодах хостаЧтобы вылечить stale file handle, нужно заставить операционную систему перечитать содержимое сетевой папки. Выполните на всех трех нодах хоста команду принудительного обновления атрибутов каталога:bashsudo ls -la /mnt/gluster-storage/
Используйте код с осторожностью.(Простой вызов ls -la внутри общей папки заставляет GlusterFS синхронизировать индексы файлов по сети и чинит эту ошибку в 99% случаев).Шаг 2. Перезапуск сервиса Caddy (если ls не помог)Если контейнеры Caddy намертво «залипли» на старом дескрипторе файла и продолжают выдавать ошибку, самый быстрый и безопасный способ для Swarm — это заставить кластер поочередно пересоздать контейнеры Caddy (с нулевым простоем / Zero Downtime):bashsudo docker service update --force hub_caddy
Используйте код с осторожностью.Docker Swarm по очереди перезапустит Caddy на каждой ноде. Новые контейнеры гарантированно прочитают свежий Caddyfile с GlusterFS уже без ошибок.⚠️ Прод-совет на будущееУтилиты автоматического форматирования или редактирования (вроде sed -i или caddy fmt --overwrite), которые удаляют старый файл и создают на его месте новый с тем же именем, противопоказаны для использования напрямую внутри контейнеров поверх сетевых папок (GlusterFS/NFS).В будущем на продакшене меняйте Caddyfile классическим способом: отредактировали через nano /mnt/gluster-storage/Caddyfile на хосте -> сделали docker service update --force hub_caddy или caddy reload.
#12
Шаг 5. Подготовка остальных каталогов в GlusterFS (Выполнить на любой ОДНОЙ ноде)Помимо документов, нам нужно создать папки для баз данных Redis, а также для конфигурации и SSL-сертификатов Caddy.Создаем папки для Redis и Caddy:bashsudo mkdir -p /mnt/gluster-storage/onlyoffice_redis_data
sudo mkdir -p /mnt/gluster-storage/caddy_data
sudo mkdir -p /mnt/gluster-storage/caddy_config
Используйте код с осторожностью.Назначаем права для Redis:В официальном alpine-образе Redis работает под пользователем redis (UID 999, GID 999).bashsudo chown -R 999:999 /mnt/gluster-storage/onlyoffice_redis_data
Используйте код с осторожностью.Назначаем права для Caddy:Caddy в контейнере работает от пользователя caddy (UID 1000, GID 1000).bashsudo chown -R 1000:1000 /mnt/gluster-storage/caddy_data
sudo chown -R 1000:1000 /mnt/gluster-storage/caddy_config
Используйте код с осторожностью.теперь права распределены изолированно и безопасно.Шаг 6. Создание отказоустойчивого CaddyfileТак как Caddy у нас работает в режиме global (на всех 3 нодах), они будут одновременно читать один файл конфигурации из GlusterFS. Благодаря тому, что папка /data (где Caddy хранит SSL-сертификаты Let's Encrypt) тоже вынесена в GlusterFS, ноды Caddy будут делить сертификаты между собой автоматически и не заблокируют лимиты Let's Encrypt.Создайте файл конфигурации:bashsudo nano /mnt/gluster-storage/Caddyfile
Используйте код с осторожностью.Вставьте в него следующий продакшен-конфиг. Я добавил туда оптимизацию для работы 1000 человек, долгоживущие веб-сокеты и проксирование на ваш новый кластер OnlyOffice:caddy# --- НАСТРОЙКИ КЛАССТЕРА ONLYOFFICE ---
docs.cloud-life.site {
    # Проксируем запросы на встроенный балансировщик Swarm
    # Имя 'hub_onlyoffice' сформировано из имени стека и имени сервиса
    reverse_proxy hub_onlyoffice:80 {
        # Передаем реальные заголовки, чтобы OnlyOffice понимал, откуда идет трафик
        header_up X-Forwarded-Host {host}
        header_up X-Forwarded-Proto {scheme}
       
        # Настройки таймаутов для 1000 пользователей (чтобы тяжелые документы не отваливались при открытии)
        transport http {
            dial_timeout 10s
            read_buffer_size 4096
        }
    }

    # Включаем сжатие ответов (ускоряет загрузку интерфейса редактора у клиентов)
    encode gzip zstd
}

# --- ПРОВЕРКА ЖИВУЧЕСТИ ДЛЯ ВНЕШНЕГО БАЛАНСИРОВЩИКА (Если используете HAProxy/Keepalived) ---
:8080 {
    respond /health "OK" 200
}


Шагу 4: Создание конфигурации продакшен-стека.



Мы собираем всё в один файл docker-compose.yml, который развернет Caddy, OnlyOffice, Redis и RabbitMQ на всех трех новых нодах Ubuntu 24.04.Поскольку Galera работает на хостах, мы настроим OnlyOffice на отказоустойчивое циклическое подключение. Мы передадим ему IP-адреса всех трех серверов (10.10.1.36, 10.10.1.37, 10.10.1.38). Если одна нода базы данных упадет, OnlyOffice автоматически переключится на выжившую.Настройка параметров лимитов на хостах (Выполнить на ВСЕХ 3 нодах)Перед запуском OnlyOffice на 1000 человек нужно увеличить лимиты операционной системы на максимальное количество открытых файлов (иначе пользователи упрутся в системный потолок):bashsudo sysctl -w fs.file-max=100000
Используйте код с осторожностью.(Чтобы сохранить настройку после перезагрузки, добавьте строку fs.file-max = 100000 в конец файла /etc/sysctl.conf).Создание файла prod-stack.ymlСоздайте на мастер-ноде файл конфигурации стека:bashnano prod-stack.yml
Используйте код с осторожностью.Вставьте в него следующий продакшен-конфиг:yamlversion: '3.8'

services:

  # --- ФРОНТЕНД / ПРОКСИ (ЗАПУЩЕН НА КАЖДОЙ НОДЕ) ---
  caddy:
    image: caddy:latest
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /mnt/gluster-storage/Caddyfile:/etc/caddy/Caddyfile
      - /mnt/gluster-storage/caddy_data:/data
      - /mnt/gluster-storage/caddy_config:/config
    networks:
      - cloudlife_net
    deploy:
      mode: global
      restart_policy:
        condition: on-failure

  # --- ОЧЕРЕДЬ ЗАДАЧ ДЛЯ ONLYOFFICE ---
  onlyoffice-rabbitmq:
    image: rabbitmq:3-management-alpine
    environment:
      - RABBITMQ_DEFAULT_USER=onlyoffice
      - RABBITMQ_DEFAULT_PASS=SuperSecretRabbitPass  # Используйте ваш пароль
    networks:
      - cloudlife_net
    deploy:
      mode: replicated
      replicas: 1
      restart_policy:
        condition: on-failure

  # --- КЭШ И КООРДИНАЦИЯ СЕССИЙ РЕДАКТИРОВАНИЯ ---
  onlyoffice-redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - /mnt/gluster-storage/onlyoffice_redis_data:/data
    networks:
      - cloudlife_net
    deploy:
      mode: replicated
      replicas: 1
      restart_policy:
        condition: on-failure

  # --- КЛАССТЕР ONLYOFFICE DOCUMENT SERVER ---
  onlyoffice:
    image: onlyoffice/documentserver:latest
    environment:
      - JWT_ENABLED=true
      - JWT_SECRET=3e4b7f484b9304066de217c5315f586f
      - JWT_HEADER=AuthorizationJwt
      - USE_UNAUTHORIZED_STORAGE=true
     
      # Подключение к внешней распределенной Galera (Указываем все три IP хостов через запятую)
      - DB_TYPE=mysql
      - DB_HOST=10.10.1.36,10.10.1.37,10.10.1.38
      - DB_PORT=3306
      - DB_NAME=onlyoffice
      - DB_USER=onlyoffice
      - DB_PASSWORD=SuperSecretDBPass               # Пароль из Шага 2
     
      # Подключение к брокеру сообщений Swarm
      - AMQP_URI=amqp://onlyoffice:SuperSecretRabbitPass@onlyoffice-rabbitmq:5672/%2f
     
      # Подключение к кэшу Swarm
      - REDIS_SERVER_HOST=onlyoffice-redis
      - REDIS_SERVER_PORT=6379
    volumes:
      - /mnt/gluster-storage/onlyoffice_data:/var/www/onlyoffice/Data
    networks:
      - cloudlife_net
    deploy:
      mode: global  # Разворачиваем OnlyOffice на ВСЕ 3 ноды параллельно!
      resources:
        limits:
          memory: 4G # Запас памяти для 1000 активных пользователей
      update_config:
        parallelism: 1
        order: stop-first
        delay: 10s

networks:
  cloudlife_net:
    external: true  # Используем созданную нами на Шаге 3 сеть attachable
Используйте код с осторожностью.Запуск стекаЗапустите деплой созданной конфигурации (назовем стек hub, чтобы имена сервисов совпадали с вашими логами):bashsudo docker stack deploy -c prod-stack.yml hub
Используйте код с осторожностью.Как проверить, что всё запустилось успешно?Проверьте статус развертывания контейнеров по всему кластеру:bashsudo docker stack ps hub
Используйте код с осторожностью.Посмотрите логи OnlyOffice, чтобы убедиться, что он успешно подключился к внешней Galera, Redis и RabbitMQ и не выдал ошибок инициализации структуры БД:bashsudo docker service logs hub_onlyoffice --tail 50
Используйте код с осторожностью.Сохраняйте файл и запускайте деплой.
#13
Шагу 3: Сборка кластера Docker Swarm и организация связи из контейнеров во внешнюю сеть хостов.Основная сложность здесь в том, что контейнеры OnlyOffice будут запущены внутри изолированной overlay-сети Docker, а MariaDB Galera работает прямо на операционной системе (на хосте). Нам нужно сделать так, чтобы контейнеры гарантированно достучались до IP-адресов хостов (10.10.1.36, 37, 38).Часть 1. Инициализация Docker Swarm кластераНам нужно объединить три ноды Ubuntu 24.04 в единый Swarm. Делать все три ноды Менеджерами (Managers) — идеальное решение для трехнодового кластера. Если упадет одна любая нода, оставшиеся две сохранят кворум и продолжат управлять стеком.3.1. Инициализация кластера (Выполнить ТОЛЬКО на NODE 1 — 10.10.1.36)Запускаем Swarm на первом сервере и явно указываем IP для межведомственной связи кластера:bashsudo docker swarm init --advertise-addr 10.10.1.36
Используйте код с осторожностью.В ответ команда выведет длинную строку подключения, которая выглядит примерно так:docker swarm join --token SWMTKN-1-XXXXX 10.10.1.36:23773.2. Получение токена для Менеджеров (Выполнить ТОЛЬКО на NODE 1)По умолчанию Docker генерирует токен для добавления Воркеров (рабочих нод). Но нам нужны Менеджеры. Получите правильную команду подключения:bashsudo docker swarm join-token manager
Используйте код с осторожностью.Скопируйте сгенерированную команду docker swarm join --token ... из вывода.3.3. Подключение остальных нод (Выполнить на NODE 2 и NODE 3)Вставьте скопированную команду на втором (10.10.1.37) и третьем (10.10.1.38) серверах:bashsudo docker swarm join --token SWMTKN-1-ПРАВИЛЬНЫЙ_ТОКЕН_МЕНЕДЖЕРА 10.10.1.36:2377
Используйте код с осторожностью.Терминал должен ответить: This node has joined a swarm as a manager.3.4. Проверка статуса кластера (Выполнить на ЛЮБОЙ ноде)bashsudo docker node ls
Используйте код с осторожностью.Вы должны увидеть список из трех нод. В колонке STATUS должно быть Ready, а в колонке AVAILABILITY — Active. Все три должны иметь статус Leader или Reachable в графе MANAGER STATUS.Часть 2. Прокидывание «моста» во внешнюю GaleraВ Docker Swarm контейнеры по умолчанию изолированы. Чтобы OnlyOffice мог достучаться до Galera на хосте, мы создадим общую overlay-сеть для стека с включенным параметром attachable.3.5. Создание overlay-сети (Выполнить ТОЛЬКО на NODE 1)Создаем сеть, в которой будут жить Caddy, OnlyOffice, Redis и RabbitMQ:bashsudo docker network create --driver overlay --attachable cloudlife_net
Используйте код с осторожностью.3.6. Проверка доступности хоста из сети Docker (Важный тест безопасности)Контейнеры внутри cloudlife_net по умолчанию могут достучаться до хост-машин по их реальным IP-адресам, ЕСЛИ это не заблокировано файрволом Ubuntu 24.04 (UFW).Давайте создадим временный контейнер в нашей новой сети и попробуем проверить доступ к порту MariaDB (3306) на хосте:bashsudo docker run --rm --network cloudlife_net alpine nc -zv 10.10.1.36 3306
Используйте код с осторожностью.Если вывод: 10.10.1.36 (10.10.1.36:3306) open — Всё супер! Связь есть, мост работает.Если выдает ошибку или зависает: Файрволл ufw на Ubuntu блокирует запросы из подсети Docker. В этом случае выполните на ВСЕХ трех нодах команду, разрешающую подсетям Docker доступ к хосту:bashsudo ufw allow from 10.0.0.0/8 to any port 3306 proto tcp
Используйте код с осторожностью.(И повторите тест с nc -zv еще раз, чтобы убедиться в успехе).Docker Swarm собран в отказоустойчивый треугольник, сеть настроена, доступ к внешней Galera проверен.Проверьте, прошел ли тест nc -zv к порту 3306.
#14
Шаг 2: Установка и настройка Galera Cluster на Ubuntu 24.042.1. Установка MariaDB (Выполнить на ВСЕХ трех нодах)Устанавливаем актуальную версию MariaDB Server:bashsudo apt update
sudo apt install -y mariadb-server mariadb-client
Используйте код с осторожностью.После установки сразу останавливаем службу, чтобы настроить конфигурацию кластера:bashsudo systemctl stop mariadb
Используйте код с осторожностью.2.2. Настройка конфигурации GaleraСоздаем чистый файл конфигурации кластера. Удалите всё содержимое старого файла, если оно там есть.На NODE 1 (10.10.1.36)bashsudo nano /etc/mysql/mariadb.conf.d/60-galera.cnf
Используйте код с осторожностью.Вставьте следующий конфиг:ini[mysqld]
binlog_format=ROW
default-storage-engine=innodb
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0

# Настройки Galera
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_cluster_name="cloudlife_galera"
wsrep_cluster_address="gcomm://10.10.1.36,10.10.1.37,10.10.1.38"
wsrep_sst_method=rsync

# Уникальные настройки для NODE 1
node_id=1
wsrep_node_address="10.10.1.36"
wsrep_node_name="node1"
Используйте код с осторожностью.На NODE 2 (10.10.1.37)bashsudo nano /etc/mysql/mariadb.conf.d/60-galera.cnf
Используйте код с осторожностью.Вставьте (изменен IP и имя ноды):ini[mysqld]
binlog_format=ROW
default-storage-engine=innodb
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0

# Настройки Galera
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_cluster_name="cloudlife_galera"
wsrep_cluster_address="gcomm://10.10.1.36,10.10.1.37,10.10.1.38"
wsrep_sst_method=rsync

# Уникальные настройки для NODE 2
node_id=2
wsrep_node_address="10.10.1.37"
wsrep_node_name="node2"
Используйте код с осторожностью.На NODE 3 (10.10.1.38)bashsudo nano /etc/mysql/mariadb.conf.d/60-galera.cnf
Используйте код с осторожностью.Вставьте (изменен IP и имя ноды):ini[mysqld]
binlog_format=ROW
default-storage-engine=innodb
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0

# Настройки Galera
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_cluster_name="cloudlife_galera"
wsrep_cluster_address="gcomm://10.10.1.36,10.10.1.37,10.10.1.38"
wsrep_sst_method=rsync

# Уникальные настройки для NODE 3
node_id=3
wsrep_node_address="10.10.1.38"
wsrep_node_name="node3"
Используйте код с осторожностью.2.3. Запуск кластера (Внимание, строгий порядок!)Кластер Galera нельзя запускать обычной командой systemctl start на первом сервере, так как ему не к кому подключаться. Первую ноду нужно «инициализировать».Шаг А: Инициализация на NODE 1 (10.10.1.36)Выполните специальную команду создания нового кластера:bashsudo galera_new_cluster
Используйте код с осторожностью.Чтобы проверить, что нода запустилась в режиме кластера, выполните:bashsudo mysql -e "SHOW STATUS LIKE 'wsrep_cluster_size';"
Используйте код с осторожностью.Вывод должен показать Value: 1.Шаг Б: Запуск на NODE 2 (10.10.1.37)Теперь, когда первая нода ждет подключений, запускаем вторую ноду в обычном режиме:bashsudo systemctl start mariadb
Используйте код с осторожностью.Она автоматически свяжется с первой нодой по rsync и заберет структуру. Проверяем размер кластера на любом из двух серверов: wsrep_cluster_size должен стать 2.Шаг В: Запуск на NODE 3 (10.10.1.38)Запускаем последнюю ноду:bashsudo systemctl start mariadb
sudo systemctl enable mariadb  # Добавляем в автозагрузку на будущее
Используйте код с осторожностью.Теперь на всех трех нодах wsrep_cluster_size должен показать 3. Кластер Galera успешно собран на чистой системе.2.4. Первичная безопасность и создание базы OnlyOfficeНа любой одной ноде запустите базовую настройку безопасности (задайте root-пароль, удалите анонимов):bashsudo mysql_secure_installation
Используйте код с осторожностью.Зайдите в консоль MySQL (mysql -u root -p) и создайте базу данных и пользователя, которые понадобятся OnlyOffice:sqlCREATE DATABASE onlyoffice CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'onlyoffice'@'%' IDENTIFIED BY 'SuperSecretDBPass';
GRANT ALL PRIVILEGES ON onlyoffice.* TO 'onlyoffice'@'%';
FLUSH PRIVILEGES;
Используйте код с осторожностью.Благодаря Galera, эта база мгновенно появится на остальных двух серверах.Жду команду. Как только Galera статус покажет размер 3 и база будет создана — пишите.Следующий Шаг 3: Инициализация Docker Swarm кластера на этих нодах и прокидывание "моста" из Docker во внешнюю Galera. Переходим?а ты не ошибся? не вот так должен быть конфиг? [mysqld]
binlog_format=ROW
default-storage-engine=innodb
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0

[galera]

# Настройки Galera
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_cluster_name="cloudlife_galera"
wsrep_cluster_address="gcomm://10.10.1.36,10.10.1.37,10.10.1.38"
wsrep_sst_method=rsync

# Уникальные настройки для NODE 3
node_id=3
wsrep_node_address="10.10.1.38"
wsrep_node_name="node3"Вы правы, вынеся настройки в отдельную секцию [galera], вы сделали синтаксически более чистый и красивый конфиг. Но технической ошибки в моём варианте нет.Дело в том, как MariaDB внутри себя парсит конфигурационные файлы. Секция [galera] — это просто подгруппа (alias). Все переменные, начинающиеся с wsrep_, сервер MariaDB прекрасно понимает и считывает, даже если они находятся внутри основной секции [mysqld].Однако ваш вариант с явным разделением на [mysqld] и [galera] считается лучшей практикой (best practice), так как он гораздо легче читается человеком. Использовать нужно именно его.Единственный момент: в MariaDB параметр node_id не существует (он используется в MaxScale или MySQL Cluster). Для идентификации ноды в Galera используются параметры wsrep_node_address и wsrep_node_name. Строчку node_id=3 можно безопасно удалить, чтобы сервер не ругался в логи на неизвестную переменную.Итоговый идеальный конфиг для NODE 1 (10.10.1.36):ini[mysqld]
binlog_format=ROW
default-storage-engine=innodb
innodb_autoinc_lock_mode=2
bind-address=0.0.0.0

[galera]
wsrep_on=ON
wsrep_provider=/usr/lib/galera/libgalera_smm.so
wsrep_cluster_name="cloudlife_galera"
wsrep_cluster_address="gcomm://10.10.1.36,10.10.1.37,10.10.1.38"
wsrep_sst_method=rsync

wsrep_node_address="10.10.1.36"
wsrep_node_name="node1"
Используйте код с осторожностью.(Для второй и третьей ноды просто меняем две последние строчки на их IP и имена node2/node3).Прописывайте эти конфиги, запускайте кластер через sudo galera_new_cluster на первой ноде и systemctl start mariadb на остальных
#15
Шаг 1: Развертывание GlusterFS на Ubuntu 24.041.1. Настройка hosts (Выполнить на ВСЕХ трех нодах)Откройте файл:bashsudo nano /etc/hosts
Используйте код с осторожностью.Добавьте ваши реальные IP-адреса в самый конец файла:text10.10.1.36 node1
10.10.1.37 node2
10.10.1.38 node3
Используйте код с осторожностью.1.2. Установка GlusterFS (Выполнить на ВСЕХ трех нодах)bashsudo apt update
sudo apt install -y glusterfs-server
sudo systemctl enable --now glusterd
Используйте код с осторожностью.1.3. Объединение нод в пул (Выполнить ТОЛЬКО на первой ноде — 10.10.1.36)Связываем сервера в единый кластер хранения:bashsudo gluster peer probe node2
sudo gluster peer probe node3
Используйте код с осторожностью.Убедиться, что ноды увидели друг друга, можно командой sudo gluster peer status.1.4. Подготовка директорий для данных (Выполнить на ВСЕХ трех нодах)Создаем локальную папку («кирпич»), где GlusterFS будет физически хранить реплики:bashsudo mkdir -p /gluster/brick1
Используйте код с осторожностью.1.5. Создание и запуск общего тома (Выполнить ТОЛЬКО на первой ноде — 10.10.1.36)Создаем распределенный том shared-vol с тройной репликацией:bashsudo gluster volume create shared-vol replica 3 node1:/gluster/brick1 node2:/gluster/brick1 node3:/gluster/brick1 force
sudo gluster volume start shared-vol
Используйте код с осторожностью.Статус созданного тома проверяется командой sudo gluster volume info.1.6. Монтирование тома (Выполнить на ВСЕХ трех нодах)Подключаем сетевое хранилище в систему в папку /mnt/gluster-storage.Создаем точку монтирования:bashsudo mkdir -p /mnt/gluster-storage
Используйте код с осторожностью.Открываем файл автозапуска дисков:bashsudo nano /etc/fstab
Используйте код с осторожностью.Добавляем в самый конец строку для автоматического монтирования (через localhost, чтобы при падении сети нода не зависала):textlocalhost:/shared-vol /mnt/gluster-storage glusterfs defaults,_netdev,x-systemd.automount 0 0
Используйте код с осторожностью.Монтируем прямо сейчас:bashsudo mount -a
Используйте код с осторожностью.1.7. Создание директории OnlyOffice (Выполнить на ЛЮБОЙ одной ноде)Создаем папку внутри Gluster и сразу выставляем права пользователя OnlyOffice (104:104):bashsudo mkdir -p /mnt/gluster-storage/onlyoffice_data
sudo chown -R 104:104 /mnt/gluster-storage/onlyoffice_data
Используйте код с осторожностью.Базовый уровень хранения на этих трех IP-адресах готов.
#16
mysql (Mariadb) / От: Создание БД и удаленного п...
Последний ответ от George - Май 16, 2026, 11:40
Способ удалить пользователей «в одну строчку» (через Bash)Если у вас есть доступ к терминалу сервера, самый быстрый и безопасный способ — сгенерировать SQL-запросы на удаление и сразу передать их обратно в MariaDB.Выполните эту команду в терминале Linux (замените root и пароль при необходимости):
Код: bash
mysql -u root -p -e "SELECT CONCAT('DROP USER \'', user, '\'@\'', host, '\';') FROM mysql.user WHERE user LIKE 'isp%';" -B -N | mysql -u root -p
Как это работает: Первая часть команды находит всех пользователей, чье имя начинается на isp, и превращает их в строки вида DROP USER 'isp_user'@'localhost';. Вторая часть (после знака |) выполняет эти строки как готовые команды.
#17
mysql (Mariadb) / От: Создание БД и удаленного п...
Последний ответ от George - Май 15, 2026, 08:19
Код: bash
CREATE USER 'ispconfig'@'localhost' IDENTIFIED BY 'пароль';
Принудительно удаляем старого пользователя, если он мешает установке
Код: bash
DROP USER IF EXISTS 'ispconfig'@'localhost';
DROP USER IF EXISTS 'ispconfig'@'10.10.1.%';
DROP USER IF EXISTS 'ispconfig'@'%';
-- Даем пользователю root максимальные права с возможностью делегирования (GRANT OPTION)
Код: bash
GRANT ALL PRIVILEGES ON *.* TO 'root'@'10.10.1.%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Используйте код с осторожностью.
#18
0. Архитектура (важно понять перед началом)

Instant Clone = каждая VM одноразовая, поэтому:

профили → только через FSLogix (Profile Container)
локальный диск → мусор, не используем
обязательна сеть-хранилище (SMB)

Минимум:

File Server (SMB шарa)
AD (у тебя уже есть)
Golden Image (template)
OU для VDI машин
1. Файловая шара под профили
Создаёшь папку

Например:

\\fileserver\FSLogixProfiles
NTFS права (критично!)

На корень:

SYSTEM — Full
Domain Admins — Full
Users (или Domain Users) — Create Folder / Append Data + List
CREATOR OWNER — Full (Subfolders only)
Самый важный момент:

👉 Пользователь должен создавать свою папку, но не видеть чужие.

Share permissions:

Проще всего:

Everyone — Full

(контроль через NTFS)

2. Установка FSLogix в Golden Image

Ставишь FSLogix Apps:

👉 качается с Microsoft

Устанавливаешь:

FSLogixAppsSetup.exe /install /quiet

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

C:\Program Files\FSLogix
3. Настройка через реестр (основа)

ВСЁ управление через:

HKLM\SOFTWARE\FSLogix\Profiles
Минимально необходимое:
[HKLM\SOFTWARE\FSLogix\Profiles]
Enabled=1
VHDLocations=\\fileserver\FSLogixProfiles
DeleteLocalProfileWhenVHDShouldApply=1
FlipFlopProfileDirectoryName=1
Объяснение (важное)
Enabled=1 — включает FSLogix
VHDLocations — путь к шаре
DeleteLocalProfileWhenVHDShouldApply=1
→ убирает локальные профили (must-have для Instant Clone)

FlipFlopProfileDirectoryName=1
→ делает папки вида:

username_SID

(это правильно для Horizon)

4. Формат контейнера

Рекомендуется:

VolumeType=VHDX
SizeInMBs=30000
IsDynamic=1

👉 30GB — норм старт, потом регулируешь

5. Исключения (чтобы не раздулся профиль)

Добавь:

RedirectionsXML=C:\Program Files\FSLogix\redirections.xml

Создаёшь файл:

Код: bash
<?xml version="1.0" encoding="UTF-8"?>
<FrxProfileFolderRedirection ExcludeCommonFolders="0">
    <Excludes>
        <Exclude Copy="0">AppData\Local\Temp</Exclude>
        <Exclude Copy="0">AppData\Local\Microsoft\Windows\INetCache</Exclude>
        <Exclude Copy="0">AppData\Local\Google\Chrome\User Data\Default\Cache</Exclude>
    </Excludes>
</FrxProfileFolderRedirection>

👉 Это реально спасает от мусора

📌 Куда класть redirections.xml

Файл создаётся на Golden Image:

C:\Program Files\FSLogix\redirections.xml

👉 именно локально в системе, не на шаре
👉 он читается агентом FSLogix при логине

📌 Нужно ли прописывать в GPO?

👉 ДА, обязательно

Сам файл просто лежит, но FSLogix должен знать, что его использовать.

🚀 Как правильно через GPO

Открываешь:

Computer Configuration
 → Administrative Templates
   → FSLogix
     → Profile Containers
Включаешь параметр:
Redirection XML source folder

И указываешь:

C:\Program Files\FSLogix

👉 FSLogix автоматически найдёт там:

redirections.xml
⚠️ ВАЖНО

❗ Не надо указывать полный путь к файлу
❗ Только папку

📌 Альтернатива (если без GPO)

Можно через реестр:

HKLM\SOFTWARE\FSLogix\Profiles
RedirectionsXML = C:\Program Files\FSLogix\redirections.xml

👉 но ты же делаешь прод → лучше через GP

6. GPO (лучше чем руками)

Импортируешь ADMX:

C:\Program Files\FSLogix\Apps\frx.admx

И настраиваешь:

Computer Configuration
  → FSLogix
    → Profiles

Включаешь:

Enable FSLogix Profile Container
VHD Locations
Delete local profile
7. Golden Image (важные моменты)

Перед snapshot:

НЕ логинься доменным юзером

очисти:

C:\Users\*

проверь:

fslogix services running

Сервисы:

FSLogix Apps Services
8. Horizon Pool (Instant Clone)

В VMware Horizon:

тип: Instant Clone
floating pool (обычно)
refresh on logoff — включить
9. Первый логин (как проверить)

После входа пользователя:

На файловом сервере должно появиться:

\\fileserver\FSLogixProfiles\username_SID\
   Profile_username.vhdx
Проверка внутри VM:
C:\Users\username

👉 должен быть mounted VHD, а не локальный профиль

Логи FSLogix:
C:\ProgramData\FSLogix\Logs\Profiles

Если что-то не работает — это первое место смотреть.

10. Частые проблемы (сразу)
❌ Профиль не монтируется
права NTFS
DNS / UNC путь
пользователь не может создать папку
❌ Временный профиль
VHD не создался
блокировка файла
#19
ВАРИАНТ 2. Использование нативного драйвера Docker local (Рекомендуется для Swarm)
Этот способ правильнее для Docker Swarm, так как Docker сам управляет монтированием к GlusterFS в момент старта контейнера на любой ноде кластера.
2.1. Создание Volume через Docker CLI:
Код: bash
docker volume create --driver local --opt type=glusterfs --opt o=addr=10.10.1.42,rw --opt device=:webdata shared_gluster_vol
Где 10.10.1.42 — IP одной из рабочих нод GlusterFS, а :webdata — имя созданного ранее тома GlusterFS.
2.2. Использование в Docker Compose / Swarm Stack:Создайте файл docker-compose-swarm.yml.
Опишите в секции volumes подключение к GlusterFS напрямую. При деплое стек сам создаст нужные именованные волюмы на всех нодах.
Код: bash
version: '3.8'
services:
wordpress:
image: wordpress:latestports:- "8080:80"
volumes:- gluster_wp_data:/var/www/htmldeploy
:replicas: 3
placement:constraints:
- node.role == workervolumes
:gluster_wp_data
:driver
: localdriver_opts
:type: "glusterfs"
o: "addr=10.10.1.42,rw,network.ping-timeout=5"
device: ":webdata"
Запустите этот стек в Swarm-кластере одной командой:
Код: bash
docker stack deploy -c docker-compose-swarm.yml my_web_stack
#20
Развертывание контейнеров поверх распределенной файловой системы GlusterFS позволяет контейнерам на разных нодах одновременно читать и писать в одну и ту же директорию. Если контейнер упадет на Node 1 и перезапустится на Node 2, он мгновенно продолжит работу со своими данными.Существует два основных подхода к такой интеграции: прямое монтирование через локальный волюм и использование специализированного плагина.

ВАРИАНТ 1.
Прямое монтирование (Bind Mount) — Самый простой и надежный способ
Поскольку вы уже смонтировали GlusterFS в общую локальную папку /var/www на Web-нодах (в Шаге 7 предыдущей инструкции), вы можете использовать обычный проброс путей.

1.1. Запуск одиночного контейнера (Docker CLI):
Код: bash
docker run -d --name app-web -v /var/www/my-site:/usr/share/nginx/html -p 80:80 nginx:latest
1.2. Описание в Docker Compose:
Код: bash
version: '3.8'services:web:image: nginx:latestports:- "80:80"volumes:- /var/www/my-site:/usr/share/nginx/html
🡱 🡳

Отметьте интересные вам фрагменты текста и они станут доступны по уникальной ссылке в адресной строке браузера.