Depolama İleri Düzey
TEKNİK REHBER DEPOLAMA LVM THIN PROVISIONING 2026

LVM Thin Provisioning —
Snapshot & dm-verity.

Gömülü ve sunucu sistemlerde gelişmiş depolama yönetimi: LVM thin pool oluşturma, thin LV, anlık görüntüler (snapshot), yeniden boyutlandırma, Docker depolama sürücüsü, dm-verity ile bütünlük zinciri ve üretim en iyi pratikleri.

00 LVM mimarisi — PV, VG, LV, thin pool

LVM (Logical Volume Manager), blok cihaz yönetiminde esneklik katmanı sağlar. Thin provisioning, fiziksel disk alanı talep esasına (on-demand) tahsis ederek aşırı commit sağlar.

LVM Katman Mimarisi
Fiziksel Disk (HDD/SSD/NVMe)
       │
       ▼
PV (Physical Volume) — pvcreate ile işaretlenir
       │  (/dev/sda2, /dev/nvme0n1p3 ...)
       ▼
VG (Volume Group) — bir veya birden fazla PV'yi birleştirir
       │
       ├── Thick LV — klasik, alan hemen tahsis edilir
       │
       └── Thin Pool LV — havuz (metadata LV + data LV)
                 │
                 ├── Thin LV 1 — sanal boyut ≥ gerçek kullanım
                 ├── Thin LV 2
                 └── Thin LV N (snapshot dahil)
Physical Volume (PV)
Blok cihazın (disk bölümü, disk, SSD) LVM'e tanıtılmış hali. pvcreate ile oluşturulur, LVM metadata'sı PV başlığına yazılır.
Volume Group (VG)
Bir veya birden fazla PV'yi tek depolama havuzunda birleştirir. PE (Physical Extent, varsayılan 4 MB) birimleriyle adresler.
Thin Pool
Gerçek veri ve metadata için iki LV içerir. Thin LV'lerin talep ettikçe kullanacağı fiziksel alanı barındırır.
Thin LV
Beyan edilen boyuttan büyük sanal birim. İlk yazıya kadar disk alanı tahsis edilmez (lazy allocation). Snapshot'lar da thin LV'dir.

01 Thin pool oluşturma ve yapılandırma

Thin pool'u doğru boyutlandırmak kritiktir: metadata LV'si toplam thin LV boyutuna göre hesaplanmalıdır. Aşırı tahsis (overcommit) dikkatli izleme gerektirir.

bash — sıfırdan thin pool kurulumu
## 1. Physical Volume oluştur
pvcreate /dev/sdb
# Physical volume "/dev/sdb" successfully created.

## 2. Volume Group oluştur
vgcreate vg_data /dev/sdb
# Volume group "vg_data" successfully created

## 3. Thin pool LV oluştur
# Toplam 100 GB pool, metadata için %1 = 1 GB
lvcreate --type thin-pool \
         --size 100G \
         --poolmetadatasize 1G \
         --name pool0 \
         vg_data

# Veya tek komutla (lvm2 >= 2.02.112)
lvcreate -L 100G --thinpool vg_data/pool0

## 4. Chunk size ve zero mode ayarla
lvchange --zero n vg_data/pool0     # yeni yazımda sıfırlama yapma
lvchange --discards passdown vg_data/pool0  # TRIM/DISCARD SSD'ye ilet

Pool metadata boyutlandırma formülü

Metadata Boyut Hesabı
Metadata boyutu = (2 × chunk_count × 64 byte) + 128 MB

Chunk size varsayılan: 64 KB
100 GB pool için chunk sayısı = 100 × 1024 × 1024 KB / 64 KB = 1.638.400

Metadata = (2 × 1.638.400 × 64 byte) + 128 MB
          = 200 MB + 128 MB = 328 MB → 512 MB tahsis etmek güvenli

# Metadata kullanımını kontrol et:
lvs -o+metadata_percent vg_data/pool0

/etc/lvm/lvm.conf — otomatik genişleme

lvm.conf
activation {
    thin_pool_autoextend_threshold = 80  # %80 dolunca tetikle
    thin_pool_autoextend_percent   = 20  # %20 büyüt
}

02 Thin LV oluşturma ve kullanım

Thin LV, pool'dan sanal alan tahsis eder. Fiziksel boyutu başlangıçta 0'dır; yazıldıkça chunk'lar tahsis edilir. Bu davranış SSD ve flash tabanlı depolamada avantajlıdır.

bash — thin LV oluşturma ve kullanım
## Thin LV oluştur (sanal boyut: 50 GB, gerçek tahsis: 0)
lvcreate --thin --name lv_app \
         --virtualsize 50G \
         vg_data/pool0

## Dosya sistemi oluştur
mkfs.ext4 /dev/vg_data/lv_app

## Mount et
mkdir -p /mnt/app
mount /dev/vg_data/lv_app /mnt/app

## /etc/fstab kaydı
echo "/dev/vg_data/lv_app  /mnt/app  ext4  defaults,discard  0 2" \
  >> /etc/fstab

## Gerçek kullanımı göster
lvs -o name,vg_name,lv_size,data_percent,pool_lv vg_data
# LV     VG       LSize  Data%  Pool
# lv_app vg_data  50.00g  8.00  pool0
# pool0  vg_data 100.00g 12.00

Aşırı tahsis (overcommit) senaryosu

bash — 100 GB pool'da 300 GB sanal LV
## 100 GB fiziksel pool, toplam 300 GB sanal tahsis
lvcreate --thin -n lv_prod   -V 100G vg_data/pool0
lvcreate --thin -n lv_test   -V 100G vg_data/pool0
lvcreate --thin -n lv_backup -V 100G vg_data/pool0

## Gerçek yazım yapılmadıkça fiziksel yer tüketilmez
lvs -o name,lv_size,data_percent vg_data
# lv_prod   100.00g  0.00
# lv_test   100.00g  0.00
# lv_backup 100.00g  0.00
# pool0     100.00g  0.00

03 Snapshot — anlık görüntü alma ve geri yükleme

LVM thin snapshot'ları, kaynak LV ile aynı veri bloklarını paylaşır (Copy-on-Write). Alınması neredeyse anlık olup disk alanı yalnızca değişen bloklar için tüketilir.

bash — snapshot alma ve yönetimi
## Snapshot al (kaynak: lv_app)
lvcreate --snapshot --name lv_app_snap1 \
         /dev/vg_data/lv_app
# Thin snapshot: ek alan gerekmez, anında oluşur

## Snapshot listesi
lvs -o name,origin,lv_size,data_percent vg_data | grep snap

## Snapshot'ı mount et (salt okunur veya yazılabilir)
mkdir -p /mnt/snap1
mount -o ro /dev/vg_data/lv_app_snap1 /mnt/snap1

## Snapshot'ı birleştir (geri yükle) — kaynak mount'u çıkar
umount /mnt/app
lvconvert --merge /dev/vg_data/lv_app_snap1
# Eğer LV kullanımdaysa birleştirme sonraki mount'ta otomatik gerçekleşir

## Anlık görüntü kaldır
lvremove /dev/vg_data/lv_app_snap1

Otomatik düzenli snapshot (systemd timer)

/etc/systemd/system/lvm-snapshot.service
[Unit]
Description=LVM Thin Snapshot — lv_app
After=local-fs.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c '\
  SNAP="lv_app_$(date +%%Y%%m%%d_%%H%%M)"; \
  lvcreate --snapshot --name "$SNAP" /dev/vg_data/lv_app; \
  echo "Snapshot alındı: $SNAP"; \
  # 7 günden eski snapshot'ları sil: \
  lvs --noheadings -o lv_name vg_data | \
    grep lv_app_snap | sort | head -n -7 | \
    xargs -r -I {} lvremove -f /dev/vg_data/{}'
/etc/systemd/system/lvm-snapshot.timer
[Unit]
Description=Günlük LVM snapshot

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
bash
systemctl enable --now lvm-snapshot.timer

04 Thin LV ve pool yeniden boyutlandırma

Thin LV boyutu çevrimiçi (online) olarak artırılabilir. Pool kapasitesi dolmaya yaklaştığında yeni PV ekleyerek genişletme yapılır.

bash — yeniden boyutlandırma
## Thin LV sanal boyutunu artır (çevrimiçi)
lvextend -L +20G /dev/vg_data/lv_app
resize2fs /dev/vg_data/lv_app    # ext4 için
# veya: xfs_growfs /mnt/app      # XFS için

## Pool'a fiziksel disk ekle
pvcreate /dev/sdc
vgextend vg_data /dev/sdc
lvextend -L +50G vg_data/pool0   # pool'u genişlet

## Thin LV küçültme (dikkat: çevrimdışı gerektirebilir)
umount /mnt/app
e2fsck -f /dev/vg_data/lv_app
resize2fs /dev/vg_data/lv_app 30G
lvreduce -L 30G /dev/vg_data/lv_app

Otomatik genişleme izleme script'i

pool_monitor.sh
#!/bin/bash
POOL="vg_data/pool0"
THRESHOLD=85  # %85 eşiği
EXTEND_GB=20

while true; do
    DATA_PCT=$(lvs --noheadings -o data_percent "$POOL" | tr -d ' ')
    DATA_PCT=${DATA_PCT%.*}  # ondalık kısım at

    if [ "${DATA_PCT:-0}" -ge "$THRESHOLD" ]; then
        echo "UYARI: Pool doluluk $DATA_PCT% — genişletiliyor"
        lvextend -L "+${EXTEND_GB}G" /dev/vg_data/pool0
        logger -t lvm-monitor "Pool genişletildi +${EXTEND_GB}GB (was ${DATA_PCT}%)"
    fi
    sleep 60
done

05 Docker storage driver olarak LVM thin

Docker'ın devicemapper sürücüsü, LVM thin provisioning üzerine inşa edilmiştir. Her container ve image, ayrı thin LV olarak depolanır. Özellikle RHEL/CentOS tabanlı sistemlerde tercih edilir.

bash — Docker LVM thin kurulumu
## Docker için ayrı VG
pvcreate /dev/sdd
vgcreate docker_vg /dev/sdd

## /etc/docker/daemon.json
cat > /etc/docker/daemon.json <<'EOF'
{
  "storage-driver": "devicemapper",
  "storage-opts": [
    "dm.thinpooldev=/dev/mapper/docker_vg-thinpool",
    "dm.use_deferred_removal=true",
    "dm.use_deferred_deletion=true",
    "dm.fs=ext4",
    "dm.basesize=20G"
  ]
}
EOF

## Thin pool oluştur (Docker için)
lvcreate --type thin-pool \
         --size 80G \
         --poolmetadatasize 512M \
         --zero n \
         -n thinpool docker_vg

systemctl restart docker
docker info | grep -A5 "Storage Driver"

devicemapper performans notları

direct-lvm modu
loop-lvm (geliştirme) yerine her zaman direct-lvm (gerçek disk) kullanın. loop-lvm üretim için desteklenmez.
Chunk size
Varsayılan 64 KB container iş yükleri için uygundur. Büyük dosyalar için 512 KB daha iyi olabilir.
DISCARD etkin
dm.use_deferred_removal + dm.use_deferred_deletion ile silinen container'ların alanı geri verilir.

06 dm-verity — blok cihaz bütünlük doğrulama

dm-verity, bir blok cihazın her bloğunu okuma sırasında hash ile doğrular. Android, Chrome OS ve gömülü Linux'ta rootfs değişmezliği garantisi için kullanılır. Merkle ağacı (hash tree) yapısı üzerine kuruludur.

dm-verity Yapısı
Veri Bloğu 0   Veri Bloğu 1  ...  Veri Bloğu N
     │               │                   │
     ▼               ▼                   ▼
  Hash(0)         Hash(1)   ...      Hash(N)        — Level 0
     │               │                   │
     └───────┬────────────────────────────┘
             ▼
       Hash(Hash(0..K))  ...  Hash(Hash(...))       — Level 1
             │
             └─── ... ─── Root Hash (32 byte, SHA-256)

Root hash → kernel komut satırında veya bootloader'da sabit tutulur
Her okumada: veri hash == beklenen hash → ERR veya panic

veritysetup ile dm-verity hash ağacı oluşturma

bash — veritysetup
## veritysetup kurulum
sudo apt install cryptsetup-bin

## 1. Salt okunur dosya sistemi görüntüsü oluştur
# (önceden ext4/squashfs ile doldurulmuş)
dd if=/dev/zero of=rootfs.img bs=1M count=512
mkfs.ext4 rootfs.img
# ... rootfs içeriğini kopyala ...

## 2. Hash ağacını oluştur
veritysetup format rootfs.img verity_hash.img
# VERITY header information for rootfs.img
#   UUID:                   a1b2c3d4-...
#   Hash type:              1
#   Data block size:        4096
#   Hash block size:        4096
#   Data blocks:            131072
#   Salt:                   aabbccdd...
#   Root hash:              7f3e2a1b...  ← bu hash kritik

ROOT_HASH=$(veritysetup format rootfs.img verity_hash.img | \
            grep "Root hash:" | awk '{print $3}')
echo "Root hash: $ROOT_HASH"

dm-verity cihazını aktifleştir

bash
## dm-verity cihazını oluştur
veritysetup open rootfs.img verity_root \
    verity_hash.img "$ROOT_HASH"
# /dev/mapper/verity_root oluştu

## Salt okunur mount et
mount -o ro /dev/mapper/verity_root /mnt/rootfs

## Bütünlük doğrulama (manuel)
veritysetup verify rootfs.img verity_hash.img "$ROOT_HASH"
# Verification is successful.

07 dm-verity ile salt okunur rootfs

Gömülü sistemlerde rootfs'i dm-verity ile korumak, fiziksel erişim olan saldırganların bile dosya sistemi değiştirmesini imkansız kılar. Kernel panigi yerine yazılabilir overlay ile üretim esnekliği sağlanabilir.

Kernel komut satırı ile dm-verity

bootloader/extlinux.conf
LABEL linux
  KERNEL /boot/Image
  FDT /boot/imx8qm.dtb
  APPEND console=ttyLP0,115200 \
         root=/dev/mapper/verity_rootfs ro \
         rootfstype=ext4 \
         dm-mod.create="verity_rootfs,,,ro,\
           0 1048576 verity \
           1 /dev/mmcblk0p2 /dev/mmcblk0p3 \
           4096 4096 131072 131072 sha256 \
           7f3e2a1b4c5d6e7f8a9b0c1d2e3f4a5b \
           aabbccdd1122334455667788"

Overlay ile yazılabilir katman

bash — overlayfs üst katman
## tmpfs veya ayrı bölümde üst katman
mount -t tmpfs tmpfs /overlay
mkdir -p /overlay/upper /overlay/work

## overlayfs: dm-verity (salt okunur) + tmpfs (yazılabilir)
mount -t overlay overlay \
    -o lowerdir=/mnt/verity_root,\
       upperdir=/overlay/upper,\
       workdir=/overlay/work \
    /newroot

## /tmp, /var, /etc gibi yazılabilir alanlar upperdir'de saklanır
## Yeniden başlatmada upperdir temizlenir → deterministik durum

08 LVM metadata yönetimi ve izleme

LVM thin pool'da metadata LV dolması, data LV dolmasından daha kritiktir. Metadata dolduğunda tüm I/O durdurulur; proaktif izleme zorunludur.

İzleme komutları

bash — LVM izleme
## Detaylı LV durumu
lvs -o name,lv_size,data_percent,metadata_percent,\
       pool_lv,origin,lv_attr vg_data

## Pool ve thin LV özeti
lvdisplay /dev/vg_data/pool0
# --- Logical volume ---
# LV Size               100.00 GiB
# Allocated pool data   45.23%
# Allocated metadata    12.07%

## Sürekli izleme (her 5 saniyede)
watch -n5 "lvs -o name,data_percent,metadata_percent vg_data"

## dmeventd ile otomatik izleme aktif et
lvchange --monitor y vg_data/pool0

Prometheus ile LVM metrik toplama

lvm_exporter.sh — textfile collector için
#!/bin/bash
# /etc/prometheus/node_exporter_textfile/lvm.prom

OUTPUT="/var/lib/node_exporter/textfile_collector/lvm.prom"
TMPFILE=$(mktemp)

echo "# HELP lvm_thin_data_percent LVM thin pool data percent" > "$TMPFILE"
echo "# TYPE lvm_thin_data_percent gauge" >> "$TMPFILE"

lvs --noheadings -o vg_name,lv_name,data_percent \
    --select 'lv_is_thin_pool=1' | while read vg lv pct; do
    pct=${pct:-0}
    echo "lvm_thin_data_percent{vg=\"$vg\",lv=\"$lv\"} $pct" >> "$TMPFILE"
done

mv "$TMPFILE" "$OUTPUT"

09 Üretim en iyi pratikleri ve sorun giderme

LVM thin provisioning güçlü bir araçtır; yanlış yapılandırılmış pool'lar veri kaybına yol açabilir. Aşağıdaki pratikler üretim ortamı için temel rehberdir.

Üretim kontrol listesi

Metadata büyüklüğü
Metadata LV'si toplam thin LV boyutunun en az %0.5'i olmalıdır. Küçük metadata = veri kaybı riski.
Overcommit sınırı
Toplam thin LV boyutu pool kapasitesinin %150'sini geçmemeli. Ani dolma durumunda I/O suspend oluşur.
Pool doluluk alarmı
%80 data, %70 metadata dolulukta alarm üretilmeli. dmeventd veya Prometheus alertmanager ile yapılandırın.
Yedekleme stratejisi
Snapshot alıp vg_data'yı yedeğe transfer edin. lvmpolld hizmetinin çalıştığından emin olun.
fstrim zamanlaması
SSD tabanlı ortamda haftalık fstrim ile thin pool'a geri DISCARD bildirin.

Yaygın sorunlar ve çözümler

Sorun Giderme
## Sorun: "No space left" hatası (pool doldu)
# Hızlı çözüm: yeni PV ekle
pvcreate /dev/sde
vgextend vg_data /dev/sde
lvextend -l +100%FREE vg_data/pool0

## Sorun: Metadata %100 (KRİTİK)
# Cihazlar askıya alınır. Acil genişletme:
lvextend --poolmetadatasize +512M vg_data/pool0

## Sorun: Thin LV "error" durumunda
lvs -o name,lv_health_status vg_data
# eğer "partial" → bazı PE'ler kayıp
# Yedekten geri yükleme gerekebilir

## Pool sağlık kontrolü
lvdisplay vg_data/pool0 | grep -E "health|active|status"

## Metadata dump (teşhis amaçlı)
dmsetup status vg_data-pool0
# 0 204800000 thin-pool 0/20480 408/4096 - rw no_discard_passdown queue_if_no_space