Profitând de faptul că micul meu router OPNsense s-a maturizat și s-a mutat la casa lui, într-un mini-PC Fujitsu dedicat, am decis că era momentul perfect pentru o reorganizare generală a serviciilor de acasă. Deși majoritatea rulau deja în Docker, în urma unei migrări anterioare, erau împrăștiate în mai multe containere LXC pe Proxmox. Multe dintre ele fuseseră create în grabă, cu gândul „mă ocup eu de ele mai târziu” – un „târziu” care, evident, s-a întins pe câțiva ani.

Container LXC pentru Docker in Proxmox

Vechea arhitectură complica inutil mentenanța. Înainte de orice actualizare, trebuia să fac snapshot-uri pentru fiecare LXC în parte. În plus, majoritatea comunicau între ele prin rețeaua locală, deși ar fi putut folosi eficient rețeaua virtuală Proxmox. Să fiu sincer, funcționam pe principiul: „Wow, un serviciu nou! Ia să-l probez”. Iar „probatul” la mine înseamnă instalare, configurare și utilizare câteva luni (Seafile sau Syncthing sunt exemple bune). Serviciile rămâneau acolo, iar cu cât trecea timpul, cu atât era mai greu să le mut.

De data asta, având la dispoziție trei zile (dintre care una fără „omuleți”, că erau la școală și grădiniță), am decis să fac curățenie generală. Am mutat totul pe un Proxmox mai modest (un i3-9100T cu 16GB RAM și un NVMe de 1TB) și am consolidat totul într-un singur container LXC optimizat. Dacă vă aflați într-o situație similară și vreți să reduceți uzura SSD-ului, iată pașii pe care i-am urmat și pe care îi puteți adapta.

Pasul 1: Crearea containerului LXC pentru Docker

Fișier de configurare container LXC pentru Docker

Primul pas este, evident, crearea unui nou container LXC pe care va rula Docker. Am folosit Debian, dar pașii sunt similari și pentru alte distribuții. Cheia este să activați opțiunile nesting și keyctl pentru ca Docker să funcționeze corect în interior. Acestea sunt setările pe care le-am folosit eu:

arch: amd64
cores: 4
features: nesting=1,keyctl=1
hostname: docker
memory: 4096
nameserver: 8.8.4.4
net0: name=eth0,bridge=vmbr0,firewall=1,gw=10.20.30.1,hwaddr=BC:24:11:DC:B5:1D,ip=10.20.30.106/24,type=veth
ostype: debian
rootfs: local-lvm:vm-106-disk-0,size=150G
searchdomain: 8.8.8.8
swap: 4096
unprivileged: 1
lxc.apparmor.profile: unconfined
lxc.cgroup2.devices.allow: a
lxc.cap.drop:
lxc.mount.auto: proc:rw sys:rw

Notă: Deși opțiuni precum nesting pot fi activate din interfața grafică Proxmox (sub Options > Features), majoritatea setărilor avansate (de exemplu, lxc.apparmor.profile) trebuie adăugate manual. Acestea se editează direct în fișierul de configurare al containerului, aflat pe nodul Proxmox, de obicei la locația /etc/pve/lxc/VMID.conf (unde VMID este ID-ul numeric al containerului, în acest caz 106.conf).

Am alocat 4 nuclee, 4GB RAM și un swap de 4GB, cu un disc de 150GB. Puteți ajusta aceste valori în funcție de resursele disponibile și de numărul de containere pe care plănuiți să le rulați.

Pasul 2: Instalarea și configurarea log2ram

Deoarece totul rulează acum pe un singur SSD NVMe, o preocupare majoră este uzura cauzată de scrierile frecvente (log-uri). Containerele Docker pot fi foarte „vorbărețe”. Soluția este log2ram, un utilitar simplu care mută directorul /var/log într-un RAM disk (tmpfs) și sincronizează periodic datele pe disc.

1. Instalarea log2ram

Pentru a instala cea mai recentă versiune stabilă, urmați acești pași direct în consola LXC-ului. Verificați întâi care e ultima versiune și adaptați comanda wget.

# 1. Verificați versiunile disponibile:
curl -s https://api.github.com/repos/azlux/log2ram/releases/latest | grep tag_name

# 2. Instalare recomandată (exemplu cu versiunea 1.7.2):
cd /tmp
wget https://github.com/azlux/log2ram/archive/refs/tags/1.7.2.tar.gz
tar -xzf 1.7.2.tar.gz
cd log2ram-1.7.2
chmod +x install.sh
./install.sh

2. Configurarea log2ram

După instalare, trebuie să edităm fișierul de configurare pentru a aloca suficient spațiu și a seta calea corectă. Rulați nano /etc/log2ram.conf și ajustați valorile. Acestea sunt setările pe care le recomand pentru un LXC cu Docker, unde am crescut SIZE la 256M pentru a fi sigur că acoperă log-urile.

# Dimensiunea RAM disk-ului (ajustați în funcție de RAM-ul alocat LXC-ului)
SIZE=256M

# Calea către log-uri (standard e ok)
PATH_DISK="/var/log"

# Folosiți rsync (recomandat)
USE_RSYNC=true

# Notificări pe mail (opțional)
MAIL=false

# Algoritm de compresie
COMP_ALG=lz4

# Dimensiunea maximă a log-urilor păstrate pe disc
LOG_DISK_SIZE=512M

3. Pornirea și verificarea serviciului

Odată salvată configurarea, porniți și activați serviciul, apoi verificați dacă funcționează corect.

# Activare și pornire
systemctl enable log2ram
systemctl start log2ram

# Verificare status
systemctl status log2ram

# Verificare montare (ar trebui să vedeți log2ram pe /var/log)
df -h | grep log2ram

# Testare scriere forțată pe disc
log2ram write

Dacă totul este în regulă, comanda df -h ar trebui să vă arate /var/log montat ca log2ram (tmpfs) cu dimensiunea pe care ați setat-o (de ex. 256M).

Pasul 3: Optimizarea Docker pentru a reduce uzura SSD

Acum că log2ram se ocupă de /var/log, trebuie să-i spunem lui Docker să trimită log-urile acolo. În plus, putem optimiza și directoarele temporare ale Docker-ului, mutându-le tot în RAM. Am folosit un script simplu pentru a automatiza aceste setări.

Salvați următorul conținut ca optimize_docker.sh, faceți-l executabil (chmod +x) și rulați-l ca root:

#!/bin/bash
# ========================================
# Script optimizare Docker conștient de log2ram
# ========================================

set -e

echo "=== Script optimizare Docker (log2ram aware) ==="
echo ""

# 1. Configurare Docker daemon pentru a trimite log-urile la SYSLOG
# Acesta va fi interceptat de log2ram care rulează pe /var/log
echo "[1/3] Configurare Docker daemon pentru syslog..."
mkdir -p /etc/docker

cat > /etc/docker/daemon.json << 'EOF' { "log-driver": "syslog", "log-opts": { "tag": "docker/{{.Name}}" } } EOF echo "✓ daemon.json configurat să trimită log-urile la syslog (în RAM via log2ram)" # 2. Creare tmpfs pentru directoare temporare Docker echo "[2/3] Configurare tmpfs pentru /var/lib/docker/tmp..." mkdir -p /var/lib/docker/tmp if ! grep -q "/var/lib/docker/tmp" /etc/fstab; then echo "tmpfs /var/lib/docker/tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=1777,size=1G 0 0" >> /etc/fstab
    mount /var/lib/docker/tmp
    echo "✓ tmpfs adăugat în fstab și mount-at"
else
    # Asigură-te că e mount-at dacă fstab-ul exista deja dar nu era activ
    mount /var/lib/docker/tmp 2>/dev/null || true
    echo "✓ tmpfs deja configurat"
fi

# 3. Restart Docker daemon
echo "[3/3] Restart Docker daemon..."
systemctl restart docker
sleep 3
systemctl status docker --no-pager | head -n 5

echo ""
echo "=== Optimizare finalizată ==="
echo ""
echo "Verificări recomandate:"
echo "1. docker info | grep 'Logging Driver' (ar trebui să fie 'syslog')"
echo "2. df -h /var/lib/docker/tmp (ar trebui să fie tmpfs)"
echo "3. tail -f /var/log/syslog (ar trebui să vezi log-urile docker aici, în RAM)"
echo ""

Acest script face două lucruri esențiale: 1. Setează driver-ul de log-uri al Docker la syslog (care scrie în /var/log, acum interceptat de log2ram) și 2. Creează un tmpfs (RAM disk) separat de 1GB pentru /var/lib/docker/tmp. După rularea scriptului, toate log-urile containerelor vor fi direcționate în RAM, reducând drastic scrierile pe SSD.

Pasul 4: Consolidarea serviciilor cu Docker Compose

Odată ce containerul LXC este pregătit și optimizat, ultimul pas al migrării mele a fost definirea tuturor serviciilor într-un singur fișier docker-compose.yml. Această abordare centralizată simplifică enorm managementul: actualizările, backup-urile și pornirea/oprirea serviciilor se fac dintr-o singură comandă.

Crearea containerelor Docker

În loc să am fișiere separate pentru fiecare serviciu sau, mai rău, comenzi docker run salvate în notițe, acum totul este într-un singur loc. Acest fișier docker-compose.yml definește rețelele virtuale, volumele persistente și dependențele dintre containere.

Pasul 5: Adaptarea containerelor „încăpățânate”

Configurarea globală din daemon.json care trimite log-urile la syslog funcționează perfect pentru stdout și stderr. Totuși, unele servicii, în special bazele de date precum MariaDB sau aplicații complexe, sunt configurate să scrie și log-uri interne în fișiere proprii, de obicei în interiorul volumelor lor persistente (de ex. în /var/lib/mysql). Aceste log-uri nu ajung în /var/log și, prin urmare, log2ram nu le vede, continuând să uzeze SSD-ul.

Soluția este să forțați aceste aplicații să-și scrie log-urile la stderr sau stdout. Putem face asta direct în docker-compose.yml suprascriind comanda de pornire a containerului.

Să luăm exemplul unui container mariadb. O definiție standard, care nu specifică nimic despre log-uri, ar arăta așa:

  mariadb:
    image: mariadb:latest
    container_name: mariadb
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: clsb
    volumes:
      - ./mysql-db:/var/lib/mysql
    restart: unless-stopped
    command: --max_allowed_packet=256M

Pentru a forța MariaDB să trimită log-ul său de erori la stderr (de unde Docker îl va prelua și trimite la syslog), trebuie să adăugăm un argument suplimentar la command:

  mariadb:
    image: mariadb:latest
    container_name: mariadb
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: clsb
    volumes:
      - ./mysql-db:/var/lib/mysql
    restart: unless-stopped
    command: 
      - --max_allowed_packet=256M
      - --log-error=/dev/stderr

Aplicând această modificare, log-ul de erori al MariaDB va fi tratat ca orice alt log Docker și va ajunge în RAM prin log2ram. Va trebui să verificați documentația fiecărui container pe care îl folosiți (de ex. Nextcloud, Postgres, etc.) pentru a găsi argumentul echivalent de redirectare a log-urilor.

Pasul 6: Concluzie – De ce acest efort?

Poate părea o optimizare minoră, dar beneficiile utilizării log2ram într-un LXC pentru Docker sunt clare, mai ales dacă rulați pe un SSD:

  • Reduce I/O pe stocarea Proxmox: Log-urile Docker pot genera mii de scrieri frecvente, mai ales la pornirea sau oprirea containerelor.
  • Protejează SSD-ul: Scăderea numărului de cicluri de scriere prelungește durata de viață a discului.
  • Performanță mai bună: Scrierea log-urilor în RAM este aproape instantanee.

Câteva lucruri de reținut:

  • Nu exagerați cu valoarea SIZE din log2ram.conf. Lăsați suficient RAM pentru containerele Docker.
  • La restartul sau oprirea LXC-ului, log2ram salvează automat log-urile din RAM pe disc.
  • Puteți forța oricând o salvare manuală cu comanda log2ram write.
  • Monitorizați utilizarea RAM-ului (free -h) și a RAM disk-ului (df -h | grep log2ram).

În cazul meu, am mai făcut un pas suplimentar și am configurat individual serviciile (cele care permit asta) să păstreze log-uri doar pe o zi. Având deja alerte configurate pe Telegram, dacă ceva crapă, aflu imediat și nu am nevoie de un istoric stufos.

Spune-ți părerea!

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *

Acest site folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.