notebook
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# SeaweedFS na Unraidu — S3-kompatibilní úložiště
|
||||
|
||||
Vyladěný Docker stack proti původnímu příkladu. Hlavní rozdíly a proč:
|
||||
|
||||
| Změna | Proč |
|
||||
|---|---|
|
||||
| Pin verze image `:4.32` místo `:latest` | reprodukovatelnost, žádné překvapení po `pull` |
|
||||
| Master má `-mdir=/data` + namapovaný volume | **metadata masteru** (kde co leží) jinak po restartu zmizí |
|
||||
| Filer má namapovaný `/data` | leveldb s metadaty souborů musí persistovat |
|
||||
| `-config=config_s3.json` u s3 | bez něj je S3 **bez autentizace, otevřené komukoliv** v síti |
|
||||
| `healthcheck` + `depends_on: service_healthy` | služby nestartují dřív, než je master skutečně nahoře |
|
||||
| `restart: unless-stopped` | přežije restart Unraidu |
|
||||
| `-ip.bind=0.0.0.0` | dostupnost z LAN, ne jen z kontejneru |
|
||||
| Data pod `/mnt/user/appdata/...` | zálohovatelné, ne v anonymním volume |
|
||||
|
||||
## Kam se ukládají data (DŮLEŽITÉ pro Unraid)
|
||||
|
||||
Klíčové pravidlo Unraidu: **cache není pod paritou** → patří tam jen to, co jde
|
||||
snadno obnovit. Rozhoduje tedy ne velikost, ale obnovitelnost:
|
||||
|
||||
| Co | Obnovitelné? | Kam | Cesta |
|
||||
|---|---|---|---|
|
||||
| volume (vlastní obsah) | ne (to jsou ta data) | **POLE (parita)** | `/mnt/user/seaweedfs/volume` |
|
||||
| **filer metadata** | **NE** — bez nich jsou bloby slepé | **externí DB** (Mongo/PG) | `filer.toml` |
|
||||
| master metadata | ano — poskládá se z heartbeatů | cache / appdata | `/mnt/user/appdata/seaweedfs/master` |
|
||||
| config_s3.json | trivální | vedle compose | `./config_s3.json` |
|
||||
|
||||
### Proč filer metadata nesmí na cache
|
||||
|
||||
filer drží mapu *název souboru → které chunky na kterém volume*. Volume servery ji
|
||||
**neumí zrekonstruovat** — bloby na poli přežijí, ale ztratíš informaci, co je co.
|
||||
Proto je dáváme do tvé existující DB na 192.168.1.76 (viz `filer.toml`):
|
||||
|
||||
- **MongoDB (doporučeno)** — kolekce v DB `seaweedfs` se vytvoří sama, žádné schéma.
|
||||
- **PostgreSQL** — vytvoř DB a tabulku:
|
||||
|
||||
```sql
|
||||
CREATE DATABASE seaweedfs;
|
||||
-- v DB seaweedfs:
|
||||
CREATE TABLE IF NOT EXISTS filemeta (
|
||||
dirhash BIGINT,
|
||||
name VARCHAR(65535),
|
||||
directory VARCHAR(65535),
|
||||
meta BYTEA,
|
||||
PRIMARY KEY (dirhash, name)
|
||||
);
|
||||
```
|
||||
|
||||
Master metadata na cache nechávám schválně — po ztrátě cache si je master poskládá
|
||||
z hlášení volume serverů, takže spadají do „snadno obnovitelné".
|
||||
|
||||
### Nejdřív založ share na poli
|
||||
|
||||
Settings → Shares → Add Share:
|
||||
- Název: `seaweedfs`
|
||||
- **Primary storage: Array** (NE cache), Secondary: none — jinak by data tekla zpět na cache a zaplnila ji
|
||||
- Allocation/split dle libosti
|
||||
|
||||
Tím vznikne `/mnt/user/seaweedfs`, kam míří volume vrstva. (Alternativa: napřímo na
|
||||
konkrétní ZFS disk, `/mnt/diskX/seaweedfs/volume`, když chceš obejít user share.)
|
||||
|
||||
> Pozn.: Disk 8 (sdd) má v poli **14 223 čtecích chyb** — než tam pustíš nová data,
|
||||
> mrkni na SMART / zvaž jeho vyřazení. Na takový disk bych volume dir nesměroval.
|
||||
|
||||
## Spuštění
|
||||
|
||||
```bash
|
||||
cd /boot/config/plugins/compose/... # nebo kamkoliv stack uložíš
|
||||
docker compose -p seaweedfs up -d
|
||||
docker compose -p seaweedfs ps
|
||||
```
|
||||
|
||||
## Endpoints (nahraď `UNRAID-IP`)
|
||||
|
||||
- Master UI: `http://UNRAID-IP:9333`
|
||||
- Filer/web: `http://UNRAID-IP:8888`
|
||||
- **S3 API:** `http://UNRAID-IP:8333`
|
||||
|
||||
## Před produkcí
|
||||
|
||||
1. **Změň klíče** v `config_s3.json` (admin i readonly). Dlouhé náhodné secret keys.
|
||||
2. Soubor `config_s3.json` drž s právy `600`.
|
||||
3. Zvaž reverzní proxy (SWAG/NPM) s TLS, pokud má být S3 dostupné mimo LAN.
|
||||
4. `defaultReplication=000` = bez replikace (1 kopie). Pro odolnost přes víc disků/serverů zvyš (např. `001`, `010`) a přidej volume servery.
|
||||
|
||||
## Test
|
||||
|
||||
```bash
|
||||
# AWS CLI
|
||||
S3=http://UNRAID-IP:8333 AK=admin SK=tajne ./test_s3.sh
|
||||
```
|
||||
|
||||
Nebo přes `s3cmd`, `rclone`, MinIO client (`mc`) — vše funguje proti `:8333`.
|
||||
|
||||
## Škálování později
|
||||
|
||||
Tohle je single-node setup (test / menší nasazení). Pro distribuovaný cluster přidej
|
||||
další `volume` servery (klidně na jiných strojích) mířící na stejný master a zvyš
|
||||
replikaci. Master + filer mohou zůstat, volume vrstva se škáluje horizontálně.
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"identities": [
|
||||
{
|
||||
"name": "admin",
|
||||
"credentials": [
|
||||
{
|
||||
"accessKey": "ZMEN_ME_admin",
|
||||
"secretKey": "ZMEN_ME_tajny_klic_dlouhy_nahodny"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
"Admin",
|
||||
"Read",
|
||||
"Write",
|
||||
"List",
|
||||
"Tagging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "readonly",
|
||||
"credentials": [
|
||||
{
|
||||
"accessKey": "ZMEN_ME_readonly",
|
||||
"secretKey": "ZMEN_ME_tajny_klic_readonly"
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
"Read",
|
||||
"List"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
# =============================================================================
|
||||
# SeaweedFS — S3-kompatibilní úložiště na Unraidu (Docker)
|
||||
# Vyladěná verze: persistence VŠECH dat, S3 přihlášení, healthcheck, restart.
|
||||
#
|
||||
# Spuštění:
|
||||
# docker compose -p seaweedfs up -d
|
||||
# (na starším Unraidu: docker-compose -f docker-compose.yml -p seaweedfs up -d)
|
||||
#
|
||||
# Endpoints (nahraď UNRAID-IP IP adresou serveru):
|
||||
# Master UI : http://UNRAID-IP:9333
|
||||
# Filer/web : http://UNRAID-IP:8888
|
||||
# S3 API : http://UNRAID-IP:8333
|
||||
# Volume : http://UNRAID-IP:8080 (interní, kvůli debugu)
|
||||
#
|
||||
# DŮLEŽITÉ: před produkčním použitím změň klíče v config_s3.json!
|
||||
# =============================================================================
|
||||
|
||||
x-image: &swimg chrislusf/seaweedfs:4.32 # pin verze (ne :latest) kvůli reprodukovatelnosti
|
||||
|
||||
services:
|
||||
seaweed-master:
|
||||
image: *swimg
|
||||
container_name: seaweed-master
|
||||
command: >
|
||||
master -ip=seaweed-master -ip.bind=0.0.0.0
|
||||
-mdir=/data -volumeSizeLimitMB=1024 -defaultReplication=000
|
||||
ports:
|
||||
- "9333:9333"
|
||||
volumes:
|
||||
# metadata masteru — cache OK: po ztrátě se poskládá z heartbeatů volume serverů
|
||||
- /mnt/user/appdata/seaweedfs/master:/data
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://localhost:9333/cluster/status"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
seaweed-volume:
|
||||
image: *swimg
|
||||
container_name: seaweed-volume
|
||||
command: >
|
||||
volume -mserver=seaweed-master:9333 -ip=seaweed-volume -ip.bind=0.0.0.0
|
||||
-dir=/data -max=0
|
||||
ports:
|
||||
- "8080:8080"
|
||||
volumes:
|
||||
# POZOR: vlastní obsah (roste do TB) -> na POLE, NE do appdata/cache!
|
||||
# Vyžaduje share "seaweedfs" s primary storage = Array (cache=No).
|
||||
- /mnt/user/seaweedfs/volume:/data
|
||||
depends_on:
|
||||
seaweed-master:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
|
||||
seaweed-filer:
|
||||
image: *swimg
|
||||
container_name: seaweed-filer
|
||||
command: >
|
||||
filer -master=seaweed-master:9333 -ip=seaweed-filer -ip.bind=0.0.0.0
|
||||
ports:
|
||||
- "8888:8888"
|
||||
volumes:
|
||||
# filer metadata -> externí DB dle filer.toml (Mongo/Postgres) = chráněné.
|
||||
- ./filer.toml:/etc/seaweedfs/filer.toml:ro
|
||||
# Jen pokud ve filer.toml zvolíš variantu C (leveldb2): odkomentuj a dej na POLE
|
||||
# - /mnt/user/seaweedfs/filermeta:/data
|
||||
depends_on:
|
||||
seaweed-master:
|
||||
condition: service_healthy
|
||||
seaweed-volume:
|
||||
condition: service_started
|
||||
restart: unless-stopped
|
||||
|
||||
seaweed-s3:
|
||||
image: *swimg
|
||||
container_name: seaweed-s3
|
||||
command: >
|
||||
s3 -filer=seaweed-filer:8888 -ip.bind=0.0.0.0
|
||||
-config=/etc/seaweedfs/config_s3.json
|
||||
ports:
|
||||
- "8333:8333"
|
||||
volumes:
|
||||
- ./config_s3.json:/etc/seaweedfs/config_s3.json:ro # S3 přihlašovací údaje (read-only)
|
||||
depends_on:
|
||||
seaweed-filer:
|
||||
condition: service_started
|
||||
restart: unless-stopped
|
||||
@@ -0,0 +1,38 @@
|
||||
# =============================================================================
|
||||
# SeaweedFS filer — kde se ukládají METADATA (název -> chunky, stromová struktura)
|
||||
#
|
||||
# POZOR: filer metadata NEJDOU rekonstruovat z volume serverů. Když se ztratí,
|
||||
# data na poli sice přežijí, ale ztratíš mapu, co je co. Proto NESMÍ ležet na
|
||||
# nechráněné cache. Tři varianty (zapni právě JEDNU sekci enabled=true):
|
||||
#
|
||||
# A) mongodb (DOPORUČENO u tebe) — metadata do tvého Monga (192.168.1.76),
|
||||
# kolekce se vytvoří sama. Chrání je, co chrání Mongo (zálohy/replica).
|
||||
# B) postgres — metadata do tvého Postgresu; vyžaduje ručně založit tabulku
|
||||
# (CREATE TABLE viz README).
|
||||
# C) leveldb2 — embedded soubor; pak ho MUSÍŠ mapovat na POLE (parita), ne cache.
|
||||
# =============================================================================
|
||||
|
||||
# --- A) MongoDB (doporučeno) -------------------------------------------------
|
||||
[mongodb]
|
||||
enabled = true
|
||||
uri = "mongodb://192.168.1.76:27017"
|
||||
option_pool_size = 0
|
||||
database = "seaweedfs"
|
||||
|
||||
# --- B) PostgreSQL -----------------------------------------------------------
|
||||
[postgres]
|
||||
enabled = false
|
||||
hostname = "192.168.1.76"
|
||||
port = 5432
|
||||
username = "seaweedfs"
|
||||
password = "ZMEN_ME"
|
||||
database = "seaweedfs"
|
||||
sslmode = "disable"
|
||||
connection_max_idle = 5
|
||||
connection_max_open = 30
|
||||
|
||||
# --- C) leveldb2 (embedded) — jen když chceš zůstat bez DB --------------------
|
||||
# Pak v compose mapuj /data na POLE: /mnt/user/seaweedfs/filermeta:/data
|
||||
[leveldb2]
|
||||
enabled = false
|
||||
dir = "/data/filerldb2"
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# Rychlý test SeaweedFS S3 API přes AWS CLI.
|
||||
# Předpoklad: nainstalované awscli (pip install awscli / apt install awscli)
|
||||
#
|
||||
# Použití:
|
||||
# ./test_s3.sh # použije defaulty níže
|
||||
# S3=http://192.168.1.50:8333 AK=admin SK=tajne ./test_s3.sh
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
S3="${S3:-http://UNRAID-IP:8333}"
|
||||
AK="${AK:-ZMEN_ME_admin}"
|
||||
SK="${SK:-ZMEN_ME_tajny_klic_dlouhy_nahodny}"
|
||||
BUCKET="${BUCKET:-test-bucket}"
|
||||
|
||||
export AWS_ACCESS_KEY_ID="$AK"
|
||||
export AWS_SECRET_ACCESS_KEY="$SK"
|
||||
export AWS_DEFAULT_REGION="us-east-1"
|
||||
AWS=(aws --endpoint-url "$S3")
|
||||
|
||||
echo "== 1) vytvoření bucketu =="
|
||||
"${AWS[@]}" s3 mb "s3://$BUCKET" || true
|
||||
|
||||
echo "== 2) upload souboru =="
|
||||
echo "ahoj ze SeaweedFS $(date)" > /tmp/sw_test.txt
|
||||
"${AWS[@]}" s3 cp /tmp/sw_test.txt "s3://$BUCKET/hello.txt"
|
||||
|
||||
echo "== 3) výpis bucketu =="
|
||||
"${AWS[@]}" s3 ls "s3://$BUCKET/"
|
||||
|
||||
echo "== 4) stažení zpět a kontrola =="
|
||||
"${AWS[@]}" s3 cp "s3://$BUCKET/hello.txt" /tmp/sw_back.txt
|
||||
diff /tmp/sw_test.txt /tmp/sw_back.txt && echo "OK: obsah sedí"
|
||||
|
||||
echo "== 5) úklid =="
|
||||
"${AWS[@]}" s3 rm "s3://$BUCKET/hello.txt"
|
||||
echo "Hotovo."
|
||||
Reference in New Issue
Block a user