282 lines
8.0 KiB
Markdown
282 lines
8.0 KiB
Markdown
# Синхронизация `config.toml` между `mtg.ivx.su`, `gt1.ivx.su`, `gt2.ivx.su` и `gt3.ivx.su`
|
||
|
||
Целевая схема:
|
||
- **A (primary, запись):** `mtg.ivx.su`
|
||
- **B (replica, только чтение):** `gt1.ivx.su`, `gt2.ivx.su`, `gt3.ivx.su`
|
||
|
||
Изменения вносятся только на A (через API/бот), затем автоматически синхронизируются на все B.
|
||
|
||
## 1) Подготовка `telemt-data` на каждом B-сервере
|
||
|
||
```bash
|
||
cd /opt/telemt-plus
|
||
docker compose stop telemt
|
||
mkdir -p telemt-data/cache
|
||
```
|
||
|
||
Если ранее использовались отдельные файлы рядом с compose:
|
||
|
||
```bash
|
||
mkdir -p backup-telemt-$(date +%F-%H%M%S)
|
||
cp -a config.toml proxy-secret cache docker-compose.yml backup-telemt-$(date +%F-%H%M%S)/ 2>/dev/null || true
|
||
|
||
[ -f config.toml ] && cp -f config.toml telemt-data/config.toml
|
||
[ -f proxy-secret ] && cp -f proxy-secret telemt-data/proxy-secret
|
||
[ -d cache ] && cp -a cache/. telemt-data/cache/
|
||
```
|
||
|
||
Права под пользователя контейнера Telemt (`uid/gid = 999`):
|
||
|
||
```bash
|
||
chown -R 999:999 telemt-data
|
||
find telemt-data -type d -exec chmod 750 {} \;
|
||
find telemt-data -type f -exec chmod 640 {} \;
|
||
chmod 660 telemt-data/config.toml 2>/dev/null || true
|
||
chmod 770 telemt-data/cache 2>/dev/null || true
|
||
```
|
||
|
||
## 2) Compose-настройка (A и B)
|
||
|
||
Для сервиса `telemt` должен быть volume директории:
|
||
|
||
```yaml
|
||
volumes:
|
||
- ./telemt-data:/run/telemt
|
||
```
|
||
|
||
Убрать:
|
||
- `./config.toml:/run/telemt/config.toml`
|
||
- `tmpfs: /run/telemt`
|
||
|
||
## 3) Настройка API в `config.toml`
|
||
|
||
### A (`mtg.ivx.su`)
|
||
|
||
```toml
|
||
[server.api]
|
||
enabled = true
|
||
read_only = false
|
||
```
|
||
|
||
### B (`gt1.ivx.su`, `gt2.ivx.su`, `gt3.ivx.su`)
|
||
|
||
```toml
|
||
[server.api]
|
||
enabled = true
|
||
read_only = true
|
||
```
|
||
|
||
## 4) SSH-доступ A -> B без пароля
|
||
|
||
Выполняется на `mtg.ivx.su`:
|
||
|
||
```bash
|
||
ssh-keygen -t ed25519 -N "" -f ~/.ssh/telemt_sync
|
||
ssh-copy-id -i ~/.ssh/telemt_sync.pub [email protected]
|
||
ssh-copy-id -i ~/.ssh/telemt_sync.pub [email protected]
|
||
ssh-copy-id -i ~/.ssh/telemt_sync.pub [email protected]
|
||
ssh -i ~/.ssh/telemt_sync [email protected] "echo ok"
|
||
ssh -i ~/.ssh/telemt_sync [email protected] "echo ok"
|
||
ssh -i ~/.ssh/telemt_sync [email protected] "echo ok"
|
||
```
|
||
|
||
## 5) Установка `lsyncd` на A (`mtg.ivx.su`)
|
||
|
||
```bash
|
||
apt update && apt install -y lsyncd rsync
|
||
mkdir -p /etc/lsyncd
|
||
```
|
||
|
||
Создать файл `/etc/lsyncd/lsyncd.conf.lua`:
|
||
|
||
```lua
|
||
settings {
|
||
logfile = "/var/log/lsyncd.log",
|
||
statusFile = "/var/log/lsyncd.status",
|
||
nodaemon = false,
|
||
}
|
||
|
||
-- B1: gt1.ivx.su
|
||
sync {
|
||
default.rsyncssh,
|
||
source = "/opt/telemt-plus/telemt-data/",
|
||
host = "[email protected]",
|
||
targetdir = "/opt/telemt-plus/telemt-data/",
|
||
delay = 1,
|
||
exclude = { "cache/" },
|
||
rsync = {
|
||
archive = true,
|
||
compress = true,
|
||
_extra = {
|
||
"--delete",
|
||
"--chown=65532:65532",
|
||
"--chmod=Du=rwx,Dg=rx,Do=,Fu=rw,Fg=r,Fo=",
|
||
"-e", "ssh -i /root/.ssh/telemt_sync -o StrictHostKeyChecking=accept-new"
|
||
}
|
||
}
|
||
}
|
||
|
||
-- B2: gt2.ivx.su
|
||
sync {
|
||
default.rsyncssh,
|
||
source = "/opt/telemt-plus/telemt-data/",
|
||
host = "[email protected]",
|
||
targetdir = "/opt/telemt-plus/telemt-data/",
|
||
delay = 1,
|
||
exclude = { "cache/" },
|
||
rsync = {
|
||
archive = true,
|
||
compress = true,
|
||
_extra = {
|
||
"--delete",
|
||
"--chown=65532:65532",
|
||
"--chmod=Du=rwx,Dg=rx,Do=,Fu=rw,Fg=r,Fo=",
|
||
"-e", "ssh -i /root/.ssh/telemt_sync -o StrictHostKeyChecking=accept-new"
|
||
}
|
||
}
|
||
}
|
||
|
||
-- B3: gt3.ivx.su
|
||
sync {
|
||
default.rsyncssh,
|
||
source = "/opt/telemt-plus/telemt-data/",
|
||
host = "[email protected]",
|
||
targetdir = "/opt/telemt-plus/telemt-data/",
|
||
delay = 1,
|
||
exclude = { "cache/" },
|
||
rsync = {
|
||
archive = true,
|
||
compress = true,
|
||
_extra = {
|
||
"--delete",
|
||
"--chown=65532:65532",
|
||
"--chmod=Du=rwx,Dg=rx,Do=,Fu=rw,Fg=r,Fo=",
|
||
"-e", "ssh -i /root/.ssh/telemt_sync -o StrictHostKeyChecking=accept-new"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 6) Первичная синхронизация (один раз)
|
||
|
||
**Важно:** на каждом B (`gt1.ivx.su`, `gt2.ivx.su`, `gt3.ivx.su`) должен быть установлен `rsync`:
|
||
|
||
```bash
|
||
# Выполнить на каждом B-сервере:
|
||
apt update && apt install -y rsync
|
||
```
|
||
|
||
На `mtg.ivx.su`:
|
||
|
||
```bash
|
||
# B1: gt1.ivx.su
|
||
rsync -az --delete \
|
||
--chown=65532:65532 \
|
||
--chmod=Du=rwx,Dg=rx,Do=,Fu=rw,Fg=r,Fo= \
|
||
-e "ssh -i /root/.ssh/telemt_sync -o StrictHostKeyChecking=accept-new" \
|
||
/opt/telemt-plus/telemt-data/ \
|
||
[email protected]:/opt/telemt-plus/telemt-data/
|
||
|
||
# B2: gt2.ivx.su
|
||
rsync -az --delete \
|
||
--chown=65532:65532 \
|
||
--chmod=Du=rwx,Dg=rx,Do=,Fu=rw,Fg=r,Fo= \
|
||
-e "ssh -i /root/.ssh/telemt_sync -o StrictHostKeyChecking=accept-new" \
|
||
/opt/telemt-plus/telemt-data/ \
|
||
[email protected]:/opt/telemt-plus/telemt-data/
|
||
|
||
# B3: gt3.ivx.su
|
||
rsync -az --delete \
|
||
--chown=65532:65532 \
|
||
--chmod=Du=rwx,Dg=rx,Do=,Fu=rw,Fg=r,Fo= \
|
||
-e "ssh -i /root/.ssh/telemt_sync -o StrictHostKeyChecking=accept-new" \
|
||
/opt/telemt-plus/telemt-data/ \
|
||
[email protected]:/opt/telemt-plus/telemt-data/
|
||
```
|
||
|
||
## 7) Запуск `lsyncd`
|
||
|
||
На A:
|
||
|
||
```bash
|
||
systemctl enable lsyncd
|
||
systemctl restart lsyncd
|
||
systemctl status lsyncd --no-pager
|
||
```
|
||
|
||
Если ошибка пути конфигурации:
|
||
|
||
```bash
|
||
systemctl cat lsyncd
|
||
```
|
||
|
||
## 8) Проверка работы
|
||
|
||
На каждом B (`gt1.ivx.su`, `gt2.ivx.su`, `gt3.ivx.su`):
|
||
|
||
```bash
|
||
cd /opt/telemt-plus
|
||
docker compose up -d --force-recreate telemt
|
||
docker logs --tail=100 telemt
|
||
```
|
||
|
||
На B проверить режим read-only:
|
||
|
||
```bash
|
||
curl -s http://127.0.0.1:9091/v1/health
|
||
```
|
||
|
||
В ответе ожидается `read_only: true`.
|
||
|
||
## 8.1) Перенастройка существующих B (slave) на новый `uid/gid` и повторный запуск синхронизации
|
||
|
||
Если B-серверы уже были настроены со старым `--chown=999:999`, выполните эти шаги, чтобы синхронизация снова применялась корректно.
|
||
|
||
1. На A (`mtg.ivx.su`) обновить конфиг `lsyncd` и перезапустить демон (выполнять на `mtg.ivx.su` от root; желательно сначала остановить `telemt` на всех B по шагу 2, затем вставить блок целиком):
|
||
|
||
```bash
|
||
sed -i.bak 's/--chown=999:999/--chown=65532:65532/g' /etc/lsyncd/lsyncd.conf.lua
|
||
systemctl restart lsyncd
|
||
systemctl status lsyncd --no-pager
|
||
```
|
||
|
||
2. На каждом B (`gt1.ivx.su`, `gt2.ivx.su`, `gt3.ivx.su`) остановить `telemt` и выставить права под новый `uid/gid`:
|
||
|
||
```bash
|
||
cd /opt/telemt-plus
|
||
docker compose stop telemt
|
||
chown -R 65532:65532 telemt-data
|
||
find telemt-data -type d -exec chmod 750 {} \;
|
||
find telemt-data -type f -exec chmod 640 {} \;
|
||
chmod 660 telemt-data/config.toml 2>/dev/null || true
|
||
chmod 770 telemt-data/cache 2>/dev/null || true
|
||
```
|
||
|
||
3. На A выполнить повторную полную синхронизацию на все B (команды из шага 6 с `--chown=65532:65532`).
|
||
|
||
4. На A перезапустить `lsyncd`:
|
||
|
||
```bash
|
||
systemctl restart lsyncd
|
||
systemctl status lsyncd --no-pager
|
||
```
|
||
|
||
5. На каждом B поднять контейнер и проверить, что узел в режиме read-only:
|
||
|
||
```bash
|
||
cd /opt/telemt-plus
|
||
docker compose up -d --force-recreate telemt
|
||
curl -s http://127.0.0.1:9091/v1/health
|
||
```
|
||
|
||
Ожидаемо:
|
||
- контейнер `telemt` стартует без ошибок прав доступа;
|
||
- в health-ответе `read_only: true`;
|
||
- после изменения `config.toml` на A файл автоматически обновляется на всех B.
|
||
|
||
## 9) Правило эксплуатации
|
||
|
||
- Мутации (`POST/PATCH/DELETE`) делать только на A (`mtg.ivx.su`).
|
||
- Бота направлять на API A.
|
||
- B (`gt1.ivx.su`, `gt2.ivx.su`, `gt3.ivx.su`) держать как реплики только для чтения.
|