LVMずマトリョヌシカの共通点は䜕ですか?

今日は。
md RAID + LVM を䜿甚しお KVM 甚のデヌタ ストレヌゞ システムを構築した実際の経隓をコミュニティず共有したいず思いたす。

プログラムには以䞋が含たれたす:

  • NVMe SSD から md RAID 1 を構築したす。
  • SATA SSD ず通垞のドラむブから md RAID 6 を組み立おたす。
  • SSD RAID 1/6 での TRIM/DISCARD 操䜜の機胜。
  • 共通のディスク セット䞊にブヌト可胜な md RAID 1/6 アレむを䜜成したす。
  • BIOS で NVMe がサポヌトされおいない堎合に、NVMe RAID 1 にシステムをむンストヌルする。
  • LVM キャッシュず LVM シンの䜿甚。
  • BTRFS スナップショットを䜿甚し、バックアップのために送受信したす。
  • BTRFS スタむルのバックアップに LVM シン スナップショットず Thin_delta を䜿甚したす。

興味のある方は猫をご芧ください。

ЗаявлеМОе

著者は、この蚘事の資料/䟋/コヌド/ヒント/デヌタを䜿甚した堎合たたは䜿甚しなかった堎合の結果に぀いお、䞀切の責任を負いたせん。 䜕らかの圢でこの資料を読んだり䜿甚したりするこずにより、お客様はこれらの行為によるすべおの結果に察しお責任を負うこずになりたす。 考えられる圱響は次のずおりです。

  • サクサクしたNVMe SSD。
  • 録画リ゜ヌスを完党に䜿い果たし、SSD ドラむブが故障したした。
  • バックアップ コピヌを含む、すべおのドラむブ䞊のすべおのデヌタが完党に倱われたす。
  • コンピュヌタヌのハヌドりェアの故障。
  • 時間、神経、お金の無駄。
  • 䞊蚘に蚘茉されおいないその他の結果。

鉄

利甚可胜なものは次のずおりです。

Z2013チップセットを搭茉し、Intel Core i87 / Haswellを搭茉した7幎頃のマザヌボヌド。

  • プロセッサヌ 4 コア、8 スレッド
  • 32 GB DDR3 RAM
  • 1 x 16 たたは 2 x 8 PCIe 3.0
  • 1×4 + 1×1 PCIe 2.0
  • 6 x 6 GBps SATA 3 コネクタ

SAS アダプタヌ LSI SAS9211-8I が IT / HBA モヌドにフラッシュされたした。 RAID 察応ファヌムりェアは、次の目的で意図的に HBA ファヌムりェアに眮き換えられおいたす。

  1. このアダプタヌはい぀でも捚おお、他のアダプタヌず亀換できたす。
  2. TRIM/Discard はディスク䞊で正垞に機胜したした。なぜなら... RAID ファヌムりェアでは、これらのコマンドはたったくサポヌトされおおらず、HBA は䞀般に、バス䞊でどのようなコマンドが送信されるかを気にしたせん。

ハヌドドラむブ - ラップトップ甚ず同様、8 フォヌムファクタヌで 7 TB の容量を持぀ HGST Travelstar 1000K1 を 2.5 台。 これらのドラむブは、以前は RAID 6 アレむ内にありたした。 これらは新しいシステムでも䜿甚される予定です。 ロヌカルバックアップを保存するため。

さらに次のように远加されたした。

SATA SSD モデル Samsung 6 QVO 860TB 2 個。 これらの SSD は倧容量を必芁ずし、SLC キャッシュの存圚、信頌性、䜎䟡栌が求められおいたした。 Discard/zero のサポヌトが必芁でした。これは dmesg の行でチェックされたす。

kernel: ata1.00: Enabling discard_zeroes_data

NVMe SSDモデル Samsung SSD 2 EVO 970GB 500枚。

これらの SSD では、ニヌズに合わせたランダム読み取り/曞き蟌み速床ずリ゜ヌス容量が重芁です。 圌らのためのラゞ゚ヌタヌ。 必然的に。 絶察に。 それ以倖の堎合は、最初の RAID 同期䞭にカリカリになるたで揚げおください。

PCIe 8 2x スロットに取り付けられた 2 x NVMe SSD 甚の StarTech PEX2M3.0E8 アダプタ。 これも単なる HBA ですが、NVMe 甚です。 内蔵 PCIe スむッチの存圚により、マザヌボヌドからの PCIe 分岐サポヌトを必芁ずしないずいう点で、安䟡なアダプタヌずは異なりたす。 x1 PCIe 1.0 スロットであっおも、PCIe を備えた最も叀いシステムでも動䜜したす。 圓然、適切な速床で。 そこには RAID はありたせん。 ボヌドには BIOS が組み蟌たれおいたせん。 したがっお、システムは魔法のように NVMe で起動するこずを孊習するこずはなく、たしおやこのデバむスのおかげで NVMe RAID を孊習するこずはありたせん。

このコンポヌネントは、システム内に空き 8x PCIe 3.0 が 2 ぀だけ存圚するためであり、空きスロットが 4 ぀ある堎合は、2 ペニヌの PEX1M600EXNUMX たたは類䌌品 (XNUMX ドルでどこでも賌入できる) で簡単に眮き換えるこずができたす。ルヌブル。

すべおのデヌタを保持しながら、SSD/HDD 自䜓を陀くシステム党䜓を完党に亀換できるようにするために、あらゆる皮類のハヌドりェアたたは内蔵チップセット/BIOS RAID の拒吊が意図的に行われたした。 理想的には、たったく新しい/別のハヌドりェアに移行するずきに、むンストヌルされおいるオペレヌティング システムさえも保存できるようにしたす。 䞻なこずは、SATAずPCIeポヌトがあるこずです。 これはラむブ CD たたはブヌト可胜なフラッシュ ドラむブのようなものですが、非垞に高速で少しかさばるのみです。

ЮЌПрそうしないず、䜕が起こるかわかりたす。堎合によっおは、アレむ党䜓を緊急に持ち垰る必芁がある堎合がありたす。 でもデヌタは倱いたくないんです。 これを行うには、前述のすべおのメディアが暙準ケヌスの 5.25 ベむのスラむド䞊に配眮されおいるず䟿利です。

もちろん、Linux で SSD キャッシュのさたざたな方法を実隓するためでもありたす。

ハヌドりェアレむドは退屈だ。 それをオン。 それは機胜するか、機胜しないかのどちらかです。 そしお、mdadm には垞にオプションがありたす。

柔らかい

以前は、EOL に近い Debian 8 Jessie がハヌドりェアにむンストヌルされおいたした。 RAID 6 は、LVM ずペアになった䞊蚘の HDD から組み立おられたした。 kvm/libvirt で仮想マシンを実行したした。

なぜなら著者は、ポヌタブル起動可胜な SATA/NVMe フラッシュ ドラむブの䜜成においお適切な経隓を持っおいたす。たた、通垞の適切なテンプレヌトを壊さないようにするために、Ubuntu 18.04 をタヌゲット システムずしお遞択したした。これは、すでに十分に安定しおいたすが、ただ 3 幎の䜿甚期間がありたす。今埌のサポヌト。

前述のシステムには、すぐに䜿える必芁なハヌドりェア ドラむバヌがすべお含たれおいたす。 サヌドパヌティの゜フトりェアやドラむバヌは必芁ありたせん。

むンストヌルの準備

システムをむンストヌルするには、Ubuntu デスクトップ むメヌゞが必芁です。 サヌバヌ システムにはある皮の匷力なむンストヌラヌがあり、UEFI システム パヌティションをディスクの XNUMX ぀に抌し蟌んでも無効にできない過床の独立性を瀺し、すべおの矎しさを台無しにしたす。 したがっお、UEFI モヌドでのみむンストヌルされたす。 オプションは提䟛したせん。

私たちはこれに満足しおいたせん。

なぜですか残念ながら、UEFI ブヌトはブヌト ゜フトりェア RAID ずの互換性が非垞に悪いです。 誰も UEFI ESP パヌティションの予玄を提䟛したせん。 ESP パヌティションを USB ポヌトのフラッシュ ドラむブに配眮するこずを提案するオンラむンのレシピがありたすが、これは倱敗点です。 UEFI BIOS がこのパヌティションを認識するのを劚げない、メタデヌタ バヌゞョン 1 の゜フトりェア mdadm RAID 0.9 を䜿甚するレシピがありたすが、これは、BIOS たたは別のハヌドりェア OS が ESP に䜕かを曞き蟌み、それを他のハヌドりェアず同期するのを忘れる幞せな瞬間たで存続したす。鏡。

さらに、UEFI ブヌトは NVRAM に䟝存しおおり、NVRAM はディスクず䞀緒に新しいシステムに移動されたせん。 マザヌボヌドの䞀郚です。

したがっお、新しい車茪を再発明するこずはありたせん。 私たちはすでに、UEFI 互換システム䞊で CSM ずいう誇り高き名前を冠した、レガシヌ/BIOS ブヌトず呌ばれる、既補の実瞟のある祖父甚自転車を持っおいたす。 棚から取り出しお、泚油し、タむダに空気を入れお、湿らせた垃で拭きたす。

Ubuntuのデスクトップバヌゞョンもレガシヌブヌトロヌダヌでは正しくむンストヌルできたせんが、圌らが蚀うように、ここには少なくずもオプションがありたす。

そこで、ハヌドりェアを収集し、Ubuntu Live ブヌト可胜フラッシュ ドラむブからシステムをロヌドしたす。 パッケヌゞをダりンロヌドする必芁があるため、適切に機胜するネットワヌクをセットアップしたす。 それが機胜しない堎合は、必芁なパッケヌゞを事前にフラッシュ ドラむブにロヌドできたす。

デスクトップ環境に移動し、タヌミナル ゚ミュレヌタヌを起動しお、次の手順を実行したす。

#sudo bash

どうやっお 䞊の行は、sudo に関するホリワヌの暙準的なトリガヌです。 CbПより倧きなチャンスが到来し、Пより倧きな責任。 問題はそれを自分自身で匕き受けられるかどうかです。 倚くの人は、このように sudo を䜿甚するのは少なくずも泚意が必芁だず考えおいたす。 しかし

#apt-get install mdadm lvm2 thin-provisioning-tools btrfs-tools util-linux lsscsi nvme-cli mc

なぜ ZFS ではないのでしょうか...?私たちがコンピュヌタヌに゜フトりェアをむンストヌルするずき、私たちは基本的に、この゜フトりェアの開発者にハヌドりェアを貞しお運転しおもらうこずになりたす。
この゜フトりェアにデヌタの安党性を信頌するずき、私たちはこのデヌタを埩元する費甚ず同額のロヌンを組むこずになりたすが、それはい぀か返枈しなければなりたせん。

この芳点から芋るず、ZFS はフェラヌリであり、mdadm+lvm は自転車に䌌おいたす。

䞻芳的には、著者はフェラヌリではなく、芋知らぬ個人にクレゞットで自転車を貞すこずを奜みたす。 そこでは、この問題の䟡栌は高くありたせん。 暩利など必芁ありたせん。 亀通ルヌルよりも簡単です。 駐車堎は無料です。 クロスカントリヌ胜力が向䞊したす。 自転車はい぀でも脚を取り付けるこずができ、自分の手で自転車を修理するこずができたす。

ではなぜBTRFS...?オペレヌティング システムを起動するには、レガシヌ/BIOS GRUB ですぐにサポヌトされ、同時にラむブ スナップショットをサポヌトするファむル システムが必芁です。 これを /boot パヌティションに䜿甚したす。 さらに、䜜成者はこの FS を / (ルヌト) に䜿甚するこずを奜みたすが、他の゜フトりェアの堎合は LVM 䞊に個別のパヌティションを䜜成し、必芁なディレクトリにマりントできるこずにも留意しおください。

この FS には仮想マシンやデヌタベヌスのむメヌゞは保存されたせん。
この FS は、システムの電源をオフにするこずなくシステムのスナップショットを䜜成し、送信/受信を䜿甚しおこれらのスナップショットをバックアップ ディスクに転送するためにのみ䜿甚されたす。

さらに、著者は通垞、最小限の゜フトりェアをハヌドりェア䞊に盎接保持し、GPU や PCI-USB ホスト コントロヌラヌを IOMMU 経由で KVM に転送するなどの手段を䜿甚しお、他のすべおの゜フトりェアを仮想マシンで実行するこずを奜みたす。

ハヌドりェア䞊に残るのは、デヌタ ストレヌゞ、仮想化、バックアップだけです。

ZFS をより信頌する堎合は、原則ずしお、指定されたアプリケヌションに぀いおは亀換可胜です。

ただし、著者は、ZFS、BRTFS、および LVM が備えおいる組み蟌みのミラヌリング/RAID および冗長性機胜を意図的に無芖しおいたす。

远加の議論ずしお、BTRFS にはランダムな曞き蟌みをシヌケンシャルな曞き蟌みに倉換する機胜があり、これは HDD 䞊のスナップショット/バックアップの同期速床に非垞に良い圱響を䞎えたす。

すべおのデバむスを再スキャンしおみたしょう。

#udevadm control --reload-rules && udevadm trigger

呚りを芋回しおみたしょう:

#lsscsi && nvme list
[0:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sda
[1:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdb
[2:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdc
[3:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdd
[4:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sde
[5:0:0:0] disk ATA Samsung SSD 860 2B6Q /dev/sdf
[6:0:0:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdg
[6:0:1:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdh
[6:0:2:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdi
[6:0:3:0] disk ATA HGST HTS721010A9 A3B0 /dev/sdj
[6:0:4:0] disk ATA HGST HTS721010A9 A3B0 /dev/sdk
[6:0:5:0] disk ATA HGST HTS721010A9 A3B0 /dev/sdl
[6:0:6:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdm
[6:0:7:0] disk ATA HGST HTS721010A9 A3J0 /dev/sdn
Node SN Model Namespace Usage Format FW Rev
---------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1 S466NXXXXXXX15L Samsung SSD 970 EVO 500GB 1 0,00 GB / 500,11 GB 512 B + 0 B 2B2QEXE7
/dev/nvme1n1 S5H7NXXXXXXX48N Samsung SSD 970 EVO 500GB 1 0,00 GB / 500,11 GB 512 B + 0 B 2B2QEXE7

ディスクレむアりト

NVMe SSD

しかし、私たちはそれらをいかなる方法でもマヌクしたせん。 それでも、BIOS はこれらのドラむブを認識したせん。 したがっお、完党に゜フトりェア RAID に移行するこずになりたす。 そこにセクションを䜜成するこずもありたせん。 「芏範」たたは「原則」に埓いたい堎合は、HDD などの倧きなパヌティションを XNUMX ぀䜜成したす。

SATA HDD

ここで特別なこずを考え出す必芁はありたせん。 すべおに察しお XNUMX ぀のセクションを䜜成したす。 BIOS はこれらのディスクを認識し、そこから起動しようずする堎合もあるため、パヌティションを䜜成したす。 埌でこれらのディスクに GRUB をむンストヌルしお、システムが突然これを実行できるようにしたす。

#cat >hdd.part << EOF
label: dos
label-id: 0x00000000
device: /dev/sdg
unit: sectors

/dev/sdg1 : start= 2048, size= 1953523120, type=fd, bootable
EOF
#sfdisk /dev/sdg < hdd.part
#sfdisk /dev/sdh < hdd.part
#sfdisk /dev/sdi < hdd.part
#sfdisk /dev/sdj < hdd.part
#sfdisk /dev/sdk < hdd.part
#sfdisk /dev/sdl < hdd.part
#sfdisk /dev/sdm < hdd.part
#sfdisk /dev/sdn < hdd.part

SATA SSD

ここが私たちにずっお興味深いずころです。

たず、ドラむブのサむズは 2 TB です。 これは MBR の蚱容範囲内であり、これを䜿甚したす。 必芁に応じお GPT に眮き換えるこずができたす。 GPT ディスクには互換性レむダヌがあり、MBR 互換システムは最初の 4 ぀のパヌティションが最初の 2 テラバむト内にある堎合にそれを認識できたす。 重芁なこずは、これらのディスク䞊のブヌト パヌティションず bios_grub パヌティションが先頭にある必芁があるこずです。 これにより、GPT レガシヌ/BIOS ドラむブから起動するこずもできたす。

しかし、これは私たちの堎合ではありたせん。

ここでは 1 ぀のセクションを䜜成したす。 最初のサむズは 1 GB で、RAID XNUMX /ブヌトに䜿甚されたす。

6 ぀目は RAID XNUMX に䜿甚され、ドラむブの端にある小さな未割り圓お領域を陀いお、残りの空き領域をすべお占有したす。

このマヌクのない領域は䜕ですか?ネットワヌク䞊の情報源によるず、圓瀟の SATA SSD には、6  78 GB のサむズの動的に拡匵可胜な SLC キャッシュが搭茉されおいたす。 ドラむブのデヌタシヌトにある「ギガバむト」ず「ギビバむト」の違いにより、6 ギガバむトを「無料」で取埗できたす。 残りの 72 GB は未䜿甚のスペヌスから割り圓おられたす。

ここでは、SLC キャッシュがあり、そのスペヌスが 4 ビット MLC モヌドで占有されおいるこずに泚意しおください。 これは事実䞊、4 GB の空き領域ごずに 1 GB の SLC キャッシュしか取埗できないこずを意味したす。

72 ギガバむトを 4 で乗算するず、288 ギガバむトになりたす。 これは、ドラむブが SLC キャッシュを最倧限に掻甚できるようにするためにマヌクアりトしない空き領域です。

したがっお、合蚈 312 台のドラむブから最倧 2 GB の SLC キャッシュを効果的に取埗するこずになりたす。 すべおのドラむブのうち XNUMX 台は冗長性を確保するために RAID で䜿甚されたす。

この量のキャッシュにより、実際には曞き蟌みがキャッシュに行かない状況に遭遇するこずはほずんどなくなりたす。 これは、QLC メモリの最も残念な欠点、぀たりキャッシュをバむパスしおデヌタを曞き蟌むずきの曞き蟌み速床が非垞に遅いこずを非垞にうたく補いたす。 負荷がこれに圓おはたらない堎合は、デヌタシヌトの TBW を考慮しお、そのような負荷の䞋で SSD がどのくらい持続するかをよく考えるこずをお勧めしたす。

#cat >ssd.part << EOF
label: dos
label-id: 0x00000000
device: /dev/sda
unit: sectors

/dev/sda1 : start= 2048, size= 2097152, type=fd, bootable
/dev/sda2 : start= 2099200, size= 3300950016, type=fd
EOF
#sfdisk /dev/sda < ssd.part
#sfdisk /dev/sdb < ssd.part
#sfdisk /dev/sdc < ssd.part
#sfdisk /dev/sdd < ssd.part
#sfdisk /dev/sde < ssd.part
#sfdisk /dev/sdf < ssd.part

配列の䜜成

たず、マシンの名前を倉曎する必芁がありたす。 これが必芁なのは、ホスト名が mdadm 内のどこかにある配列名の䞀郚であり、どこかに圱響を䞎えるためです。 もちろん、配列の名前は埌で倉曎できたすが、これは䞍芁な手順です。

#mcedit /etc/hostname
#mcedit /etc/hosts
#hostname
vdesk0

NVMe SSD

#mdadm --create --verbose --assume-clean /dev/md0 --level=1 --raid-devices=2 /dev/nvme[0-1]n1

なぜ - クリヌンだず仮定するのですか...?配列の初期化を避けるため。 これは RAID レベル 1 ず 6 の䞡方で有効です。 新しい配列の堎合は、初期化なしですべおが機胜したす。 さらに、SSD アレむの䜜成時に初期化するず、TBW リ゜ヌスが無駄になりたす。 組み立おられた SSD アレむに察しお可胜な限り TRIM/DISCARD を䜿甚しお「初期化」したす。

SSD アレむの堎合、RAID 1 DISCARD はすぐにサポヌトされたす。

SSD RAID 6 DISCARD アレむの堎合は、カヌネル モゞュヌル パラメヌタで有効にする必芁がありたす。

これは、このシステムのレベル 4/5/6 アレむで䜿甚されおいるすべおの SSD が、discard_zeroes_data を有効にサポヌトしおいる堎合にのみ実行する必芁がありたす。 この機胜がサポヌトされおいるずカヌネルに通知する奇劙なドラむブに遭遇するこずがありたすが、実際にはサポヌトされおいないか、機胜が垞に動䜜するずは限りたせん。 珟時点では、サポヌトはほがどこでも利甚できたすが、叀いドラむブやファヌムりェアにぱラヌが発生しおいたす。 このため、RAID 6 では DISCARD サポヌトはデフォルトで無効になっおいたす。

次のコマンドは、アレむを「れロ」で「初期化」するこずにより、NVMe ドラむブ䞊のすべおのデヌタを砎壊するこずに泚意しおください。

#blkdiscard /dev/md0

䜕か問題が発生した堎合は、ステップを指定しおみおください。

#blkdiscard --step 65536 /dev/md0

SATA SSD

#mdadm --create --verbose --assume-clean /dev/md1 --level=1 --raid-devices=6 /dev/sd[a-f]1
#blkdiscard /dev/md1
#mdadm --create --verbose --assume-clean /dev/md2 --chunk-size=512 --level=6 --raid-devices=6 /dev/sd[a-f]2

なぜこんなに倧きいのか チャンク サむズを増やすず、チャンク サむズたでのブロックでのランダム読み取りの速床にプラスの効果がありたす。 これは、適切なサむズ以䞋の 99 ぀の操䜜が単䞀のデバむス䞊で完党に完了できるために発生したす。 したがっお、すべおのデバむスからの IOPS が合蚈されたす。 統蚈によるず、IO の 512% は XNUMXK を超えたせん。

曞き蟌みあたりの RAID 6 IOPS 垞に XNUMX ぀のドラむブの IOPS 以䞋です。 ランダム読み取りの堎合、IOPS が XNUMX 台のドラむブの IOPS よりも数倍倧きくなる可胜性があり、ここではブロック サむズが重芁になりたす。
著者は、蚭蚈䞊 RAID 6 で苊手なパラメヌタを最適化しようずする意味を理解しおおらず、代わりに RAID 6 が埗意ずするパラメヌタを最適化しおいたす。
NVMe キャッシュずシンプロビゞョニングのトリックで、RAID 6 の貧匱なランダム曞き蟌みを補いたす。

RAID 6 の DISCARD をただ有効にしおいないため、珟時点ではこのアレむを「初期化」したせん。 これは、OS をむンストヌルした埌で行いたす。

SATA HDD

#mdadm --create --verbose --assume-clean /dev/md3 --chunk-size=512 --level=6 --raid-devices=8 /dev/sd[g-n]1

NVMe RAID 䞊の LVM

速床を高めるために、ルヌト ファむル システムを NVMe RAID 1 (/dev/md0) に配眮したす。
ただし、スワップ、メタデヌタ、LVM キャッシュおよび LVM シン メタデヌタなどの他のニヌズにはこの高速アレむが䟝然ずしお必芁ずなるため、このアレむ䞊に LVM VG を䜜成したす。

#pvcreate /dev/md0
#vgcreate root /dev/md0

ルヌト ファむル システムのパヌティションを䜜成したしょう。

#lvcreate -L 128G --name root root

RAMのサむズに応じおスワップ甚のパヌティションを䜜成したしょう。

#lvcreate -L 32G --name swap root

OSのむンストヌル

合蚈するず、システムのむンストヌルに必芁なものがすべお揃っおいたす。

Ubuntu Live 環境からシステム むンストヌル りィザヌドを起動したす。 通垞のむンストヌル。 むンストヌルするディスクを遞択する段階でのみ、以䞋を指定する必芁がありたす。

  • /dev/md1、 - マりントポむント /boot、FS - BTRFS
  • /dev/root/root (別名 /dev/mapper/root-root)、 - マりント ポむント / (ルヌト)、FS - BTRFS
  • /dev/root/swap (別名 /dev/mapper/root-swap) - スワップ パヌティションずしお䜿甚したす
  • ブヌトロヌダヌを /dev/sda にむンストヌルしたす

ルヌト ファむル システムずしお BTRFS を遞択するず、むンストヌラヌは / (ルヌト) を衚す「@」ず /home を衚す「@home」ずいう名前の XNUMX ぀の BTRFS ボリュヌムを自動的に䜜成したす。

むンストヌルを開始したしょう...

むンストヌルは終了し、ブヌトロヌダヌのむンストヌル䞭に゚ラヌが発生したこずを瀺すモヌダル ダむアログ ボックスが衚瀺されたす。 残念ながら、暙準的な方法ではこのダむアログを終了しおむンストヌルを続行するこずはできたせん。 システムからログアりトしお再床ログむンするず、最終的にはクリヌンな Ubuntu Live デスクトップが衚瀺されたす。 タヌミナルを開き、もう䞀床次のようにしたす。

#sudo bash

むンストヌルを続行するには、chroot 環境を䜜成したす。

#mkdir /mnt/chroot
#mount -o defaults,space_cache,noatime,nodiratime,discard,subvol=@ /dev/mapper/root-root /mnt/chroot
#mount -o defaults,space_cache,noatime,nodiratime,discard,subvol=@home /dev/mapper/root-root /mnt/chroot/home
#mount -o defaults,space_cache,noatime,nodiratime,discard /dev/md1 /mnt/chroot/boot
#mount --bind /proc /mnt/chroot/proc
#mount --bind /sys /mnt/chroot/sys
#mount --bind /dev /mnt/chroot/dev

chroot でネットワヌクずホスト名を蚭定したしょう。

#cat /etc/hostname >/mnt/chroot/etc/hostname
#cat /etc/hosts >/mnt/chroot/etc/hosts
#cat /etc/resolv.conf >/mnt/chroot/etc/resolv.conf

chroot 環境に入っおみたしょう。

#chroot /mnt/chroot

たず、パッケヌゞを配送したす。

apt-get install --reinstall mdadm lvm2 thin-provisioning-tools btrfs-tools util-linux lsscsi nvme-cli mc debsums hdparm

システムのむンストヌルが䞍完党なために誀っおむンストヌルされたすべおのパッケヌゞを確認しお修正しおみたしょう。

#CORRUPTED_PACKAGES=$(debsums -s 2>&1 | awk '{print $6}' | uniq)
#apt-get install --reinstall $CORRUPTED_PACKAGES

䜕かがうたくいかない堎合は、最初に /etc/apt/sources.list を線集する必芁があるかもしれたせん。

TRIM/DISCARD を有効にするために RAID 6 モゞュヌルのパラメヌタを調敎したしょう。

#cat >/etc/modprobe.d/raid456.conf << EOF
options raid456 devices_handle_discard_safely=1
EOF

配列を少し調敎しおみたしょう。

#cat >/etc/udev/rules.d/60-md.rules << EOF
SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/stripe_cache_size", ATTR{md/stripe_cache_size}="32768"
SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/sync_speed_min", ATTR{md/sync_speed_min}="48000"
SUBSYSTEM=="block", KERNEL=="md*", ACTION=="change", TEST=="md/sync_speed_max", ATTR{md/sync_speed_max}="300000"
EOF
#cat >/etc/udev/rules.d/62-hdparm.rules << EOF
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="/sbin/hdparm -B 254 /dev/%k"
EOF
#cat >/etc/udev/rules.d/63-blockdev.rules << EOF
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", RUN+="/sbin/blockdev --setra 1024 /dev/%k"
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="md*", RUN+="/sbin/blockdev --setra 0 /dev/%k"
EOF

それが䜕だった..以䞋を実行する䞀連の udev ルヌルを䜜成したした。

  • RAID 2020 のブロック キャッシュ サむズを 6 幎に適切な倀に蚭定したす。デフォルト倀は、Linux の䜜成以来倉曎されおいないようで、長い間適切ではありたせんでした。
  • アレむのチェック/同期の間、最小限の IO を予玄したす。 これは、アレむが負荷の䞋で氞遠の同期状態に陥るのを防ぐためです。
  • アレむのチェック/同期䞭の最倧 IO を制限したす。 これは、SSD RAID の同期/チェックによっおドラむブがパンクしないようにするために必芁です。 これは特に NVMe に圓おはたりたす。 (ラゞ゚ヌタヌのこずを芚えおいたすか?冗談ではありたせん。)
  • APM を介しおディスクがスピンドル回転 (HDD) を停止するこずを犁止し、ディスク コントロヌラヌのスリヌプ タむムアりトを 7 時間に蚭定したす。 ドラむブで APM が可胜な堎合は、APM を完党に無効にするこずができたす (-B 255)。 デフォルト倀では、ドラむブは XNUMX 秒埌に停止したす。 その埌、OS はディスク キャッシュをリセットしようずし、ディスクが再び回転し、すべおが最初からやり盎しになりたす。 ディスクにはスピンドルの最倧回転数が制限されおいたす。 このような単玔なデフォルト サむクルでは、数幎でディスクが簡単に壊れおしたう可胜性がありたす。 すべおのディスクがこの問題に悩たされるわけではありたせんが、私たちのディスクは「ラップトップ」ディスクであり、適切なデフォルト蚭定があり、RAID がミニ MAID のように芋えたす。
  • ディスク (回転) 1 メガバむトに先読みをむンストヌル - 6 ぀の連続ブロック/チャンク RAID XNUMX
  • アレむ自䜓の先読みを無効にしたす。

/etc/fstab を線集したしょう。

#cat >/etc/fstab << EOF
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
# file-system mount-point type options dump pass
/dev/mapper/root-root / btrfs defaults,space_cache,noatime,nodiratime,discard,subvol=@ 0 1
UUID=$(blkid -o value -s UUID /dev/md1) /boot btrfs defaults,space_cache,noatime,nodiratime,discard 0 2
/dev/mapper/root-root /home btrfs defaults,space_cache,noatime,nodiratime,discard,subvol=@home 0 2
/dev/mapper/root-swap none swap sw 0 0
EOF

䜕故ですか../boot パヌティションを UUID で怜玢したす。 配列の名前は理論的には倉曎される可胜性がありたす。

残りのセクションは、/dev/mapper/vg-lv 衚蚘の LVM 名で怜玢したす。 これらはパヌティションを非垞に䞀意に識別したす。

LVM には UUID を䜿甚したせん。 LVM ボリュヌムずそのスナップショットの UUID は同じであっおもかたいたせん。/dev/mapper/root-root.. を XNUMX 回マりントしたすか?はい。 その通り。 BTRFSの特城。 このファむル システムは、異なるサブボリュヌムを䜿甚しお耇数回マりントできたす。

これず同じ機胜のため、アクティブな BTRFS ボリュヌムの LVM スナップショットを䜜成しないこずをお勧めしたす。 再起動するず驚くかもしれたせん。

mdadm 構成を再生成したしょう。

#/usr/share/mdadm/mkconf | sed 's/#DEVICE/DEVICE/g' >/etc/mdadm/mdadm.conf

LVM 蚭定を調敎したしょう。

#cat >>/etc/lvm/lvmlocal.conf << EOF

activation {
thin_pool_autoextend_threshold=90
thin_pool_autoextend_percent=5
}
allocation {
cache_pool_max_chunks=2097152
}
devices {
global_filter=["r|^/dev/.*_corig$|","r|^/dev/.*_cdata$|","r|^/dev/.*_cmeta$|","r|^/dev/.*gpv$|","r|^/dev/images/.*$|","r|^/dev/mapper/images.*$|","r|^/dev/backup/.*$|","r|^/dev/mapper/backup.*$|"] issue_discards=1
}
EOF

それが䜕だった..占有スペヌスの 90%、ボリュヌムの 5% に達するず、LVM シン プヌルの自動拡匵が可胜になりたした。

LVM キャッシュのキャッシュ ブロックの最倧数が増加したした。

LVM が以䞋の LVM ボリュヌム (PV) を怜玢できないようにしたした。

  • LVM キャッシュ (cdata) を含むデバむス
  • LVM キャッシュを䜿甚しおキャッシュされたデバむスは、キャッシュをバむパスしたす ( _コリグ。 この堎合、キャッシュされたデバむス自䜓は匕き続きキャッシュを通じおスキャンされたす単に。
  • LVM キャッシュ メタデヌタ (cmeta) を含むデバむス
  • VG 内のむメヌゞずいう名前のすべおのデバむス。 ここでは仮想マシンのディスク むメヌゞを䜿甚したすが、ホスト䞊の LVM がゲスト OS に属するボリュヌムをアクティブ化する必芁はありたせん。
  • VG 内のバックアップずいう名前のすべおのデバむス。 ここでは、仮想マシン むメヌゞのバックアップ コピヌを䜜成したす。
  • 名前が「gpv」で終わるすべおのデバむス (ゲスト物理ボリュヌム)

LVM VG の空き領域を解攟するずきに DISCARD サポヌトを有効にしたした。 気を぀けお。 これにより、SSD 䞊の LV の削陀に非垞に時間がかかりたす。 これは特に SSD RAID 6 に圓おはたりたす。ただし、蚈画によれば、シン プロビゞョニングを䜿甚する予定ですので、これはたったく支障はありたせん。

initramfs むメヌゞを曎新したしょう。

#update-initramfs -u -k all

grub をむンストヌルしお構成したす。

#apt-get install grub-pc
#apt-get purge os-prober
#dpkg-reconfigure grub-pc

どのディスクを遞択すればよいでしょうか?SD*な皆さん。 システムは、動䜜しおいる SATA ドラむブたたは SSD から起動できる必芁がありたす。

なぜ os-prober を远加したのでしょうか?過床の独立性ず遊び心のある手のために。

RAID の XNUMX ぀が劣化状態にある堎合、正しく動䜜したせん。 このハヌドりェア䞊で実行されおいる仮想マシンで䜿甚されおいるパヌティション䞊の OS を怜玢しようずしたす。

必芁な堎合はそのたたにしおおいおも構いたせんが、䞊蚘のすべおに留意しおください。 いたずら手を取り陀くためのレシピをオンラむンで探すこずをお勧めしたす。

これで初期むンストヌルが完了したした。 新しくむンストヌルした OS で再起動したす。 ブヌタブル Live CD/USB を忘れずに取り倖しおください。

#exit
#reboot

いずれかの SATA SSD をブヌト デバむスずしお遞択したす。

SATA SSD 䞊の LVM

この時点で、すでに新しい OS を起動し、ネットワヌクず apt を蚭定し、タヌミナル ゚ミュレヌタヌを開いお次のコマンドを実行しおいたす。

#sudo bash

続けたす。

SATA SSD からアレむを「初期化」したす。

#blkdiscard /dev/md2

うたくいかない堎合は、次のこずを詊しおください。

#blkdiscard --step 65536 /dev/md2
SATA SSD 䞊に LVM VG を䜜成したす。

#pvcreate /dev/md2
#vgcreate data /dev/md2

なぜ別の VG が...?実際、root ずいう名前の VG がすでにありたす。 すべおを XNUMX ぀の VG に远加しおみたせんか?

VG 内に耇数の PV がある堎合、VG が正しくアクティブ化されるためには、すべおの PV が存圚する (オンラむン) 必芁がありたす。 䟋倖は LVM RAID ですが、これは意図的に䜿甚したせん。

RAID 6 アレむのいずれかで障害 (読み取りデヌタの損倱) が発生した堎合、オペレヌティング システムが通垞どおり起動し、問題を解決する機䌚が䞎えられるこずが本圓に望たしいのです。

これを行うために、抜象化の最初のレベルで、各タむプの物理「メディア」を個別の VG に分離したす。

科孊的に蚀えば、異なる RAID アレむは異なる「信頌性ドメむン」に属したす。 XNUMX ぀の VG にそれらを詰め蟌んで、さらに共通の障害点を䜜成すべきではありたせん。

「ハヌドりェア」レベルでの LVM の存圚により、さたざたな方法で組み合わせるこずにより、さたざたな RAID アレむの断片を任意に切り出すこずができたす。 たずえば、実行したす 同時に bcache + LVM Thin、bcache + BTRFS、LVM キャッシュ + LVM Thin、キャッシュを備えた耇雑な ZFS 構成、たたはその他の地獄のような組み合わせをすべお詊しお比范したす。

「ハヌドりェア」レベルでは、叀き良き「シック」LVM ボリュヌム以倖は䜿甚したせん。 この芏則の䟋倖は、バックアップ パヌティションである堎合がありたす。

この時点で、倚くの読者はすでに入れ子人圢に぀いお䜕かを疑い始めおいたず思いたす。

SATA HDD 䞊の LVM

#pvcreate /dev/md3
#vgcreate backup /dev/md3

たた新しいVG デヌタのバックアップに䜿甚するディスク アレむに障害が発生した堎合でも、バックアップ以倖のデヌタぞのアクセスを通垞どおり維持しながら、オペレヌティング システムが正垞に動䜜し続けるこずを本圓に望んでいたす。 したがっお、VG アクティベヌションの問題を回避するために、別の VG を䜜成したす。

LVMキャッシュの蚭定

NVMe RAID 1 䞊に LV を䜜成しお、キャッシュ デバむスずしお䜿甚したしょう。

#lvcreate -L 70871154688B --name cache root

なんでこんなに少ないんだろう 実際、圓瀟の NVMe SSD には SLC キャッシュも搭茉されおいたす。 4 ビット MLC で占有される空きスペヌスにより、18 ギガバむトの「フリヌ」スペヌスず 3 ギガバむトのダむナミック スペヌスが発生したす。 このキャッシュが䜿い果たされるず、NVMe SSD はキャッシュ付きの SATA SSD よりもそれほど高速ではなくなりたす。 実際には、このような理由から、LVM キャッシュ パヌティションを NVMe ドラむブの SLC キャッシュのサむズの 32 倍より倧きくするこずは意味がありたせん。 䜿甚する NVMe ドラむブに぀いおは、64  XNUMX GB のキャッシュを䜜成するのが劥圓であるず著者は考えおいたす。

64 GB のキャッシュ、キャッシュ メタデヌタ、およびメタデヌタ バックアップを線成するには、指定されたパヌティション サむズが必芁です。

さらに、ダヌティ システムのシャットダりン埌、LVM はキャッシュ党䜓をダヌティずしおマヌクし、再床同期するこずに泚意しおください。 さらに、システムが再床リブヌトされるたで、このデバむスで lvchange が䜿甚されるたびにこれが繰り返されたす。 したがっお、適切なスクリプトを䜿甚しおキャッシュをすぐに再䜜成するこずをお勧めしたす。

SATA RAID 6 䞊に LV を䜜成しお、キャッシュされたデバむスずしお䜿甚したしょう。

#lvcreate -L 3298543271936B --name cache data

なぜ XNUMX テラバむトしかないのですか?そのため、必芁に応じお、他のニヌズに SATA SSD RAID 6 を䜿甚できたす。 キャッシュされたスペヌスのサむズは、システムを停止するこずなく、その堎で動的に増加できたす。 これを行うには、キャッシュを䞀時的に停止しお再床有効にする必芁がありたすが、たずえば bcache に察する LVM キャッシュの際立った利点は、これを実行䞭に実行できるこずです。

キャッシュ甚の新しい VG を䜜成したしょう。

#pvcreate /dev/root/cache
#pvcreate /dev/data/cache
#vgcreate cache /dev/root/cache /dev/data/cache

キャッシュされたデバむス䞊に LV を䜜成したしょう。

#lvcreate -L 3298539077632B --name cachedata cache /dev/data/cache

ここでは、/dev/data/cache 䞊のすべおの空きスペヌスを即座に䜿甚し、他のすべおの必芁なパヌティションが /dev/root/cache 䞊に即座に䜜成されるようにしたした。 間違った堎所に䜕かを䜜成した堎合は、pvmove を䜿甚しお移動できたす。

キャッシュを䜜成しお有効にしおみたしょう。

#lvcreate -y -L 64G -n cache cache /dev/root/cache
#lvcreate -y -L 1G -n cachemeta cache /dev/root/cache
#lvconvert -y --type cache-pool --cachemode writeback --chunksize 64k --poolmetadata cache/cachemeta cache/cache
#lvconvert -y --type cache --cachepool cache/cache cache/cachedata

なぜそのようなチャンクサむズ...?実際の実隓を通じお、著者は、LVM キャッシュ ブロックのサむズが LVM シン ブロックのサむズず䞀臎する堎合に最良の結果が埗られるこずを発芋するこずができたした。 さらに、サむズが小さいほど、構成のランダム蚘録でのパフォヌマンスが向䞊したす。

64k は、LVM Thin に蚱可される最小ブロック サむズです。

ラむトバックには泚意しおください...!はい。 このタむプのキャッシュでは、キャッシュされたデバむスぞの曞き蟌み同期が延期されたす。 ぀たり、キャッシュが倱われるず、キャッシュされたデバむス䞊のデヌタが倱われる可胜性がありたす。 このリスクを補うために、NVMe RAID 1 以倖にどのような察策を講じるこずができるかに぀いおは、埌ほど説明したす。

このキャッシュ タむプは、RAID 6 の貧匱なランダム曞き蟌みパフォヌマンスを補うために意図的に遞択されたした。

䜕が埗られたかを確認しおみたしょう:

#lvs -a -o lv_name,lv_size,devices --units B cache
LV LSize Devices
[cache] 68719476736B cache_cdata(0)
[cache_cdata] 68719476736B /dev/root/cache(0)
[cache_cmeta] 1073741824B /dev/root/cache(16384)
cachedata 3298539077632B cachedata_corig(0)
[cachedata_corig] 3298539077632B /dev/data/cache(0)
[lvol0_pmspare] 1073741824B /dev/root/cache(16640)

[cachedata_corig] のみを /dev/data/cache に配眮する必芁がありたす。 䜕か問題がある堎合は、pvmove を䜿甚しおください。

必芁に応じお、XNUMX ぀のコマンドでキャッシュを無効にするこずができたす。

#lvconvert -y --uncache cache/cachedata

これはオンラむンで行われたす。 LVM は単玔にキャッシュをディスクに同期しお削陀し、cachedata_corig の名前を cachedata に戻したす。

LVM シンのセットアップ

LVM シン メタデヌタに必芁なスペヌスを倧たかに芋積もっおみたしょう。

#thin_metadata_size --block-size=64k --pool-size=6terabytes --max-thins=100000 -u bytes
thin_metadata_size - 3385794560 bytes estimated metadata area size for "--block-size=64kibibytes --pool-size=6terabytes --max-thins=100000"

4 ギガバむトに切り䞊げ: 4294967296B

LVM PV メタデヌタの堎合、4194304 を掛けお 8594128896B を远加したす: XNUMXB
NVMe RAID 1 䞊に別のパヌティションを䜜成しお、LVM シン メタデヌタずそのバックアップ コピヌをそこに配眮したしょう。

#lvcreate -L 8594128896B --name images root

䜕のために..ここで、LVM シン メタデヌタが NVMe にキャッシュされお高速に動䜜するのに、なぜ LVM シン メタデヌタを別に配眮する必芁があるのか​​ずいう疑問が生じるかもしれたせん。

ここでは速床が重芁ですが、それは䞻な理由からは皋遠いです。 問題は、キャッシュが障害点になるずいうこずです。 䜕かが起こった可胜性があり、LVM シン メタデヌタがキャッシュされおいる堎合、すべおが完党に倱われたす。 完党なメタデヌタがなければ、シン ボリュヌムを組み立おるこずはほが䞍可胜になりたす。

メタデヌタを別の非キャッシュの高速ボリュヌムに移動するこずで、キャッシュの損倱や砎損が発生した堎合でもメタデヌタの安党性が保蚌されたす。 この堎合、キャッシュ損倱によっお匕き起こされるすべおの損傷はシン ボリュヌム内で局所的に発生するため、回埩手順が倧幅に簡玠化されたす。 高い確率で、これらの損傷は FS ログを䜿甚しお埩元されたす。

さらに、シン ボリュヌムのスナップショットが以前に䜜成されおおり、その埌キャッシュが少なくずも XNUMX 回完党に同期されおいる堎合、LVM シンの内郚蚭蚈により、キャッシュが倱われた堎合でもスナップショットの敎合性が保蚌されたす。 。

シンプロビゞョニングを担圓する新しい VG を䜜成したしょう。

#pvcreate /dev/root/images
#pvcreate /dev/cache/cachedata
#vgcreate images /dev/root/images /dev/cache/cachedata

プヌルを䜜成したしょう。

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T images/thin-pool
なぜ -Z yこのモヌドの実際の目的 (スペヌスを再配分するずきに、ある仮想マシンからのデヌタが別の仮想マシンに挏掩するのを防ぐこず) に加えお、れロ化は、64k 未満のブロックでのランダム曞き蟌みの速床を䞊げるためにさらに䜿甚されたす。 シン ボリュヌムの以前に割り圓おられおいない領域ぞの 64K 未満の曞き蟌みは、キャッシュ内で 64K の゚ッゞに揃えられたす。 これにより、キャッシュされたデバむスをバむパスし、キャッシュを通じお操䜜を完党に実行できるようになりたす。

LV を察応する PV に移動したしょう。

#pvmove -n images/thin-pool_tdata /dev/root/images /dev/cache/cachedata
#pvmove -n images/lvol0_pmspare /dev/cache/cachedata /dev/root/images
#pvmove -n images/thin-pool_tmeta /dev/cache/cachedata /dev/root/images

小切手

#lvs -a -o lv_name,lv_size,devices --units B images
LV LSize Devices
[lvol0_pmspare] 4294967296B /dev/root/images(0)
thin-pool 274877906944B thin-pool_tdata(0)
[thin-pool_tdata] 274877906944B /dev/cache/cachedata(0)
[thin-pool_tmeta] 4294967296B /dev/root/images(1024)

テスト甚のシン ボリュヌムを䜜成したしょう。

#lvcreate -V 64G --thin-pool thin-pool --name test images

テストず監芖甚のパッケヌゞをむンストヌルしたす。

#apt-get install sysstat fio

これは、ストレヌゞ構成の動䜜をリアルタむムで芳察する方法です。

#watch 'lvs --rows --reportformat basic --quiet -ocache_dirty_blocks,cache_settings cache/cachedata && (lvdisplay cache/cachedata | grep Cache) && (sar -p -d 2 1 | grep -E "sd|nvme|DEV|md1|md2|md3|md0" | grep -v Average | sort)'

構成をテストする方法は次のずおりです。

#fio --loops=1 --size=64G --runtime=4 --filename=/dev/images/test --stonewall --ioengine=libaio --direct=1
--name=4kQD32read --bs=4k --iodepth=32 --rw=randread
--name=8kQD32read --bs=8k --iodepth=32 --rw=randread
--name=16kQD32read --bs=16k --iodepth=32 --rw=randread
--name=32KQD32read --bs=32k --iodepth=32 --rw=randread
--name=64KQD32read --bs=64k --iodepth=32 --rw=randread
--name=128KQD32read --bs=128k --iodepth=32 --rw=randread
--name=256KQD32read --bs=256k --iodepth=32 --rw=randread
--name=512KQD32read --bs=512k --iodepth=32 --rw=randread
--name=4Kread --bs=4k --rw=read
--name=8Kread --bs=8k --rw=read
--name=16Kread --bs=16k --rw=read
--name=32Kread --bs=32k --rw=read
--name=64Kread --bs=64k --rw=read
--name=128Kread --bs=128k --rw=read
--name=256Kread --bs=256k --rw=read
--name=512Kread --bs=512k --rw=read
--name=Seqread --bs=1m --rw=read
--name=Longread --bs=8m --rw=read
--name=Longwrite --bs=8m --rw=write
--name=Seqwrite --bs=1m --rw=write
--name=512Kwrite --bs=512k --rw=write
--name=256write --bs=256k --rw=write
--name=128write --bs=128k --rw=write
--name=64write --bs=64k --rw=write
--name=32write --bs=32k --rw=write
--name=16write --bs=16k --rw=write
--name=8write --bs=8k --rw=write
--name=4write --bs=4k --rw=write
--name=512KQD32write --bs=512k --iodepth=32 --rw=randwrite
--name=256KQD32write --bs=256k --iodepth=32 --rw=randwrite
--name=128KQD32write --bs=128k --iodepth=32 --rw=randwrite
--name=64KQD32write --bs=64k --iodepth=32 --rw=randwrite
--name=32KQD32write --bs=32k --iodepth=32 --rw=randwrite
--name=16KQD32write --bs=16k --iodepth=32 --rw=randwrite
--name=8KQD32write --bs=8k --iodepth=32 --rw=randwrite
--name=4kQD32write --bs=4k --iodepth=32 --rw=randwrite
| grep -E 'read|write|test' | grep -v ioengine

気を぀けお リ゜ヌスこのコヌドは 36 の異なるテストを実行し、それぞれのテストを 4 秒間実行したす。 テストの半分は蚘録甚です。 NVMe では 4 秒で倧量の録画が可胜です。 毎秒最倧 3 ギガバむト。 したがっお、曞き蟌みテストを実行するたびに、最倧 216 GB の SSD リ゜ヌスが消費される可胜性がありたす。

読み曞きが混圚しおいたすかはい。 読み取りテストず曞き蟌みテストを別々に実行するのが合理的です。 さらに、以前に行われた曞き蟌みが読み取りに圱響しないように、すべおのキャッシュが同期されおいるこずを確認するこずは理にかなっおいたす。

結果は、最初の起動時ずその埌の起動時にキャッシュずシン ボリュヌムがいっぱいになるに぀れお倧きく異なりたす。たた、システムが最埌の起動時にいっぱいになったキャッシュを同期できたかどうかによっおも異なりたす。

ずりわけ、スナップショットを䜜成したばかりの、すでにいっぱいになっおいるシン ボリュヌムの速床を枬定するこずをお勧めしたす。 著者は、最初のスナップショットを䜜成した盎埌、特にキャッシュがただ完党にいっぱいになっおいないずきに、ランダム曞き蟌みがどのように急激に加速するかを芳察する機䌚がありたした。 これは、コピヌオンラむト曞き蟌みセマンティクス、キャッシュずシン ボリュヌム ブロックの配眮、および RAID 6 ぞのランダム曞き蟌みが RAID 6 からのランダム読み取りずその埌のキャッシュぞの曞き蟌みに倉わるずいう事実により発生したす。 この構成では、RAID 6 からのランダム読み取りは曞き蟌みよりも最倧 6 倍 (アレむ内の SATA SSD の数) 高速です。 なぜならCoW のブロックはシン プヌルから順番に割り圓おられ、蚘録もほずんどの堎合順次になりたす。

これらの機胜は䞡方ずも有利に䜿甚できたす。

「䞀貫性のある」スナップショットをキャッシュする

キャッシュの損傷/損倱が発生した堎合のデヌタ損倱のリスクを軜枛するために、著者は、この堎合にスナップショットをロヌテヌションしお敎合性を保蚌する方法を導入するこずを提案しおいたす。

たず、シン ボリュヌムのメタデヌタはキャッシュされおいないデバむス䞊に存圚するため、メタデヌタの䞀貫性が保たれ、損倱の可胜性はデヌタ ブロック内で分離されたす。

次のスナップショット ロヌテヌション サむクルにより、キャッシュ損倱が発生した堎合にスナップショット内のデヌタの敎合性が保蚌されたす。

  1. <name> ずいう名前のシン ボリュヌムごずに、<name>.cached ずいう名前のスナップショットを䜜成したす。
  2. 移行のしきい倀を適切な高い倀に蚭定したしょう。 #lvchange --quiet --cachesettings "migration_threshold=16384" cache/cachedata
  3. ルヌプ内で、キャッシュ内のダヌティ ブロックの数をチェックしたす。 #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' れロになるたで。 れロが長期間欠萜しおいる堎合は、キャッシュを䞀時的にラむトスルヌ モヌドに切り替えるこずでれロを䜜成できたす。 ただし、SATA および NVMe SSD アレむの速床特性ずその TBW リ゜ヌスを考慮するず、キャッシュ モヌドを倉曎せずにその瞬間を玠早く捉えるこずができるか、ハヌドりェアがそのリ゜ヌス党䜓を完党に消費しおしたうかのどちらかになりたす。数日。 リ゜ヌスの制限により、システムは原則ずしお、垞に 100% の曞き蟌み負荷を䞋回るこずができたせん。 圓瀟の NVMe SSD は 100% の曞き蟌み負荷にさらされるず、リ゜ヌスを完党に䜿い果たしおしたいたす。 3-4日。 SATA SSD は XNUMX 倍しか寿呜がありたせん。 したがっお、負荷の倧郚分が読み取りに圓おられ、比范的短期間の非垞に高いアクティビティず曞き蟌みの平均負荷の䜎さのバヌストが発生するず仮定したす。
  4. れロをキャッチ (たたはれロを䜜成) したらすぐに、<name>.cached の名前を <name>.committed に倉曎したす。 叀い <name>.committed は削陀されたす。
  5. オプションで、キャッシュが 100% いっぱいの堎合は、スクリプトによっおキャッシュを再䜜成し、キャッシュをクリアできたす。 キャッシュが半分空の堎合、システムは曞き蟌み時にはるかに高速に動䜜したす。
  6. 移行しきい倀をれロに蚭定したす。 #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata これにより、キャッシュがメむン メディアず䞀時的に同期できなくなりたす。
  7. かなり倚くの倉曎がキャッシュに蓄積されるたで埅機したす #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' たたはタむマヌがオフになりたす。
  8. もう䞀床繰り返したす。

移行しきい倀が難しいのはなぜですか...?実際には、「ランダム」録音は完党にランダムではないずいうこずです。 サむズが 4 キロバむトのセクタヌに䜕かを曞き蟌んだ堎合、次の数分以内に、同じセクタヌたたは隣接する (+- 32K) セクタヌの XNUMX ぀にレコヌドが䜜成される可胜性が高くなりたす。

移行しきい倀をれロに蚭定するこずで、SATA SSD での曞き蟌み同期を延期し、いく぀かの倉曎をキャッシュ内の 64 ぀の XNUMXK ブロックに集玄したす。 これにより、SATA SSD のリ゜ヌスが倧幅に節玄されたす。

コヌドはどこにありたすか?残念ながら、著者は 100% 独孊で「Google」䞻導の開発を実践しおいるため、bash スクリプトの開発胜力が䞍十分であるず考えおおり、そのため、自分の手から生み出されたひどいコヌドは誰にも䜿甚されるべきではないず考えおいたす。それ以倖。

この分野の専門家であれば、必芁に応じお䞊蚘のロゞックをすべお独立しお衚珟でき、おそらく著者が詊みたように、システム化されたサヌビスずしお矎しく蚭蚈するこずもできるず思いたす。

このようなシンプルなスナップショット ロヌテヌション スキヌムにより、XNUMX ぀のスナップショットを垞に SATA SSD 䞊で完党に同期させるこずができるだけでなく、thin_delta ナヌティリティを䜿甚しお、䜜成埌にどのブロックが倉曎されたかを芋぀けお、損傷を局所的に特定するこずもできたす。メむン ボリュヌムが削陀され、リカバリが倧幅に簡玠化されたす。

libvirt/KVM での TRIM/DISCARD

なぜならデヌタ ストレヌゞは libvirt を実行する KVM に䜿甚されるため、空き領域を占有するだけでなく、䞍芁になったものを解攟するように VM に教えるこずをお勧めしたす。

これは、仮想ディスク䞊で TRIM/DISCARD サポヌトを゚ミュレヌトするこずによっお行われたす。 これを行うには、コントロヌラヌのタむプを virtio-scsi に倉曎し、xml を線集する必芁がありたす。

#virsh edit vmname
<disk type='block' device='disk'>
<driver name='qemu' type='raw' cache='writethrough' io='threads' discard='unmap'/>
<source dev='/dev/images/vmname'/>
<backingStore/>
<target dev='sda' bus='scsi'/>
<alias name='scsi0-0-0-0'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>

<controller type='scsi' index='0' model='virtio-scsi'>
<alias name='scsi0'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</controller>

ゲスト OS からのこのような DISCARD は LVM によっお正しく凊理され、ブロックはキャッシュずシン プヌルの䞡方で正しく解攟されたす。 私たちの堎合、これは䞻に次のスナップショットを削陀するずきに遅延しお発生したす。

BTRFSバックアップ

既補のスクリプトを䜿甚しお、 крайМей 泚意ず 自己責任で。 このコヌドは䜜者が自分自身のために、そしお自分のためだけに曞きたした。 経隓豊富な Linux ナヌザヌの倚くが同様のツヌルを持っおいるず思いたす。他の人のツヌルをコピヌする必芁はありたせん。

バックアップ デバむス䞊にボリュヌムを䜜成したしょう。

#lvcreate -L 256G --name backup backup

BTRFS でフォ​​ヌマットしたしょう。

#mkfs.btrfs /dev/backup/backup

マりント ポむントを䜜成し、ファむル システムのルヌト サブセクションをマりントしたしょう。

#mkdir /backup
#mkdir /backup/btrfs
#mkdir /backup/btrfs/root
#mkdir /backup/btrfs/back
#ln -s /boot /backup/btrfs
# cat >>/etc/fstab << EOF

/dev/mapper/root-root /backup/btrfs/root btrfs defaults,space_cache,noatime,nodiratime 0 2
/dev/mapper/backup-backup /backup/btrfs/back btrfs defaults,space_cache,noatime,nodiratime 0 2
EOF
#mount -a
#update-initramfs -u
#update-grub

バックアップ甚のディレクトリを䜜成したしょう。

#mkdir /backup/btrfs/back/remote
#mkdir /backup/btrfs/back/remote/root
#mkdir /backup/btrfs/back/remote/boot

バックアップ スクリプト甚のディレクトリを䜜成したしょう。

#mkdir /root/btrfs-backup

スクリプトをコピヌしたしょう。

恐ろしいbashコヌドがたくさんありたす。 自己責任。 著者に怒りの手玙を曞かないでください...#cat >/root/btrfs-backup/btrfs-backup.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

LOCK_FILE="/dev/shm/$SCRIPT_NAME.lock"
DATE_PREFIX='%Y-%m-%d'
DATE_FORMAT=$DATE_PREFIX'-%H-%M-%S'
DATE_REGEX='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
BASE_SUFFIX=".@base"
PEND_SUFFIX=".@pend"
SNAP_SUFFIX=".@snap"
MOUNTS="/backup/btrfs/"
BACKUPS="/backup/btrfs/back/remote/"

function terminate ()
{
echo "$1" >&2
exit 1
}

function wait_lock()
{
flock 98
}

function wait_lock_or_terminate()
{
echo "Wating for lock..."
wait_lock || terminate "Failed to get lock. Exiting..."
echo "Got lock..."
}

function suffix()
{
FORMATTED_DATE=$(date +"$DATE_FORMAT")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function filter()
{
FORMATTED_DATE=$(date --date="$1" +"$DATE_PREFIX")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function backup()
{
SOURCE_PATH="$MOUNTS$1"
TARGET_PATH="$BACKUPS$1"
SOURCE_BASE_PATH="$MOUNTS$1$BASE_SUFFIX"
TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
TARGET_BASE_DIR="$(dirname $TARGET_BASE_PATH)"
SOURCE_PEND_PATH="$MOUNTS$1$PEND_SUFFIX"
TARGET_PEND_PATH="$BACKUPS$1$PEND_SUFFIX"
if [ -d "$SOURCE_BASE_PATH" ] then
echo "$SOURCE_BASE_PATH found"
else
echo "$SOURCE_BASE_PATH File not found creating snapshot of $SOURCE_PATH to $SOURCE_BASE_PATH"
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_BASE_PATH
sync
if [ -d "$TARGET_BASE_PATH" ] then
echo "$TARGET_BASE_PATH found out of sync with source... removing..."
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
fi
fi
if [ -d "$TARGET_BASE_PATH" ] then
echo "$TARGET_BASE_PATH found"
else
echo "$TARGET_BASE_PATH not found. Synching to $TARGET_BASE_DIR"
btrfs send $SOURCE_BASE_PATH | btrfs receive $TARGET_BASE_DIR
sync
fi
if [ -d "$SOURCE_PEND_PATH" ] then
echo "$SOURCE_PEND_PATH found removing..."
btrfs subvolume delete -c $SOURCE_PEND_PATH
sync
fi
btrfs subvolume snapshot -r $SOURCE_PATH $SOURCE_PEND_PATH
sync
if [ -d "$TARGET_PEND_PATH" ] then
echo "$TARGET_PEND_PATH found removing..."
btrfs subvolume delete -c $TARGET_PEND_PATH
sync
fi
echo "Sending $SOURCE_PEND_PATH to $TARGET_PEND_PATH"
btrfs send -p $SOURCE_BASE_PATH $SOURCE_PEND_PATH | btrfs receive $TARGET_BASE_DIR
sync
TARGET_DATE_SUFFIX=$(suffix)
btrfs subvolume snapshot -r $TARGET_PEND_PATH "$TARGET_PATH$TARGET_DATE_SUFFIX"
sync
btrfs subvolume delete -c $SOURCE_BASE_PATH
sync
btrfs subvolume delete -c $TARGET_BASE_PATH
sync
mv $SOURCE_PEND_PATH $SOURCE_BASE_PATH
mv $TARGET_PEND_PATH $TARGET_BASE_PATH
sync
}

function list()
{
LIST_TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
LIST_TARGET_BASE_DIR="$(dirname $LIST_TARGET_BASE_PATH)"
LIST_TARGET_BASE_NAME="$(basename -s .$BASE_SUFFIX $LIST_TARGET_BASE_PATH)"
find "$LIST_TARGET_BASE_DIR" -maxdepth 1 -mindepth 1 -type d -printf "%fn" | grep "${LIST_TARGET_BASE_NAME/$BASE_SUFFIX/$SNAP_SUFFIX}.$DATE_REGEX"
}

function remove()
{
REMOVE_TARGET_BASE_PATH="$BACKUPS$1$BASE_SUFFIX"
REMOVE_TARGET_BASE_DIR="$(dirname $REMOVE_TARGET_BASE_PATH)"
btrfs subvolume delete -c $REMOVE_TARGET_BASE_DIR/$2
sync
}

function removeall()
{
DATE_OFFSET="$2"
FILTER="$(filter "$DATE_OFFSET")"
while read -r SNAPSHOT ; do
remove "$1" "$SNAPSHOT"
done < <(list "$1" | grep "$FILTER")

}

(
COMMAND="$1"
shift

case "$COMMAND" in
"--help")
echo "Help"
;;
"suffix")
suffix
;;
"filter")
filter "$1"
;;
"backup")
wait_lock_or_terminate
backup "$1"
;;
"list")
list "$1"
;;
"remove")
wait_lock_or_terminate
remove "$1" "$2"
;;
"removeall")
wait_lock_or_terminate
removeall "$1" "$2"
;;
*)
echo "None.."
;;
esac
) 98>$LOCK_FILE

EOF

それは䞀䜓䜕をするのでしょうか...?BTRFS スナップショットを䜜成し、BTRFS 送受信を䜿甚しお別の FS にコピヌするための簡単なコマンドのセットが含たれおいたす。

最初の起動は比范的時間がかかるこずがありたす。なぜなら... 最初はすべおのデヌタがコピヌされたす。 それ以降の起動は非垞に高速になりたす。なぜなら... 倉曎のみがコピヌされたす。

cron に远加する別のスクリプト:

もう少しバッシュコヌドを远加#cat >/root/btrfs-backup/cron-daily.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

BACKUP_SCRIPT="$SCRIPT_DIR/btrfs-backup.sh"
RETENTION="-60 day"
$BACKUP_SCRIPT backup root/@
$BACKUP_SCRIPT removeall root/@ "$RETENTION"
$BACKUP_SCRIPT backup root/@home
$BACKUP_SCRIPT removeall root/@home "$RETENTION"
$BACKUP_SCRIPT backup boot/
$BACKUP_SCRIPT removeall boot/ "$RETENTION"
EOF

それは䜕をするためのものか..リストされた BTRFS ボリュヌムの増分スナップショットをバックアップ FS 䞊に䜜成し、同期したす。 その埌、60 日前に䜜成されたすべおの写真が削陀されたす。 起動埌、リストされたボリュヌムの日付付きスナップショットが /backup/btrfs/back/remote/ サブディレクトリに衚瀺されたす。

コヌドに実行暩限を䞎えたしょう。

#chmod +x /root/btrfs-backup/cron-daily.sh
#chmod +x /root/btrfs-backup/btrfs-backup.sh

それを確認しお cron に入れおみたしょう。

#/usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/btrfs-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t btrfs-backup
#cat /var/log/syslog | grep btrfs-backup
#crontab -e
0 2 * * * /usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/btrfs-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t btrfs-backup

LVMシンバックアップ

バックアップ デバむス䞊にシン プヌルを䜜成したしょう。

#lvcreate -L 274877906944B --poolmetadataspare y --poolmetadatasize 4294967296B --chunksize 64k -Z y -T backup/thin-pool

ddrescue をむンストヌルしたしょう。なぜなら... スクリプトはこのツヌルを䜿甚したす。

#apt-get install gddrescue

スクリプト甚のディレクトリを䜜成したしょう。

#mkdir /root/lvm-thin-backup

スクリプトをコピヌしたしょう。

内郚ではたくさんのバッシュが...#cat >/root/lvm-thin-backup/lvm-thin-backup.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

LOCK_FILE="/dev/shm/$SCRIPT_NAME.lock"
DATE_PREFIX='%Y-%m-%d'
DATE_FORMAT=$DATE_PREFIX'-%H-%M-%S'
DATE_REGEX='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
BASE_SUFFIX=".base"
PEND_SUFFIX=".pend"
SNAP_SUFFIX=".snap"
BACKUPS="backup"
BACKUPS_POOL="thin-pool"

export LVM_SUPPRESS_FD_WARNINGS=1

function terminate ()
{
echo "$1" >&2
exit 1
}

function wait_lock()
{
flock 98
}

function wait_lock_or_terminate()
{
echo "Wating for lock..."
wait_lock || terminate "Failed to get lock. Exiting..."
echo "Got lock..."
}

function suffix()
{
FORMATTED_DATE=$(date +"$DATE_FORMAT")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function filter()
{
FORMATTED_DATE=$(date --date="$1" +"$DATE_PREFIX")
echo "$SNAP_SUFFIX.$FORMATTED_DATE"
}

function read_thin_id {
lvs --rows --reportformat basic --quiet -othin_id "$1/$2" | awk '{print $2}'
}

function read_pool_lv {
lvs --rows --reportformat basic --quiet -opool_lv "$1/$2" | awk '{print $2}'
}

function read_lv_dm_path {
lvs --rows --reportformat basic --quiet -olv_dm_path "$1/$2" | awk '{print $2}'
}

function read_lv_active {
lvs --rows --reportformat basic --quiet -olv_active "$1/$2" | awk '{print $2}'
}

function read_lv_chunk_size {
lvs --rows --reportformat basic --quiet --units b --nosuffix -ochunk_size "$1/$2" | awk '{print $2}'
}

function read_lv_size {
lvs --rows --reportformat basic --quiet --units b --nosuffix -olv_size "$1/$2" | awk '{print $2}'
}

function activate_volume {
lvchange -ay -Ky "$1/$2"
}

function deactivate_volume {
lvchange -an "$1/$2"
}

function read_thin_metadata_snap {
dmsetup status "$1" | awk '{print $7}'
}

function thindiff()
{
DIFF_VG="$1"
DIFF_SOURCE="$2"
DIFF_TARGET="$3"
DIFF_SOURCE_POOL=$(read_pool_lv $DIFF_VG $DIFF_SOURCE)
DIFF_TARGET_POOL=$(read_pool_lv $DIFF_VG $DIFF_TARGET)

if [ "$DIFF_SOURCE_POOL" == "" ] then
(>&2 echo "Source LV is not thin.")
exit 1
fi

if [ "$DIFF_TARGET_POOL" == "" ] then
(>&2 echo "Target LV is not thin.")
exit 1
fi

if [ "$DIFF_SOURCE_POOL" != "$DIFF_TARGET_POOL" ] then
(>&2 echo "Source and target LVs belong to different thin pools.")
exit 1
fi

DIFF_POOL_PATH=$(read_lv_dm_path $DIFF_VG $DIFF_SOURCE_POOL)
DIFF_SOURCE_ID=$(read_thin_id $DIFF_VG $DIFF_SOURCE)
DIFF_TARGET_ID=$(read_thin_id $DIFF_VG $DIFF_TARGET)
DIFF_POOL_PATH_TPOOL="$DIFF_POOL_PATH-tpool"
DIFF_POOL_PATH_TMETA="$DIFF_POOL_PATH"_tmeta
DIFF_POOL_METADATA_SNAP=$(read_thin_metadata_snap $DIFF_POOL_PATH_TPOOL)

if [ "$DIFF_POOL_METADATA_SNAP" != "-" ] then
(>&2 echo "Thin pool metadata snapshot already exist. Assuming stale one. Will release metadata snapshot in 5 seconds.")
sleep 5
dmsetup message $DIFF_POOL_PATH_TPOOL 0 release_metadata_snap
fi

dmsetup message $DIFF_POOL_PATH_TPOOL 0 reserve_metadata_snap
DIFF_POOL_METADATA_SNAP=$(read_thin_metadata_snap $DIFF_POOL_PATH_TPOOL)

if [ "$DIFF_POOL_METADATA_SNAP" == "-" ] then
(>&2 echo "Failed to create thin pool metadata snapshot.")
exit 1
fi

#We keep output in variable because metadata snapshot need to be released early.
DIFF_DATA=$(thin_delta -m$DIFF_POOL_METADATA_SNAP --snap1 $DIFF_SOURCE_ID --snap2 $DIFF_TARGET_ID $DIFF_POOL_PATH_TMETA)

dmsetup message $DIFF_POOL_PATH_TPOOL 0 release_metadata_snap

echo $"$DIFF_DATA" | grep -E 'different|left_only|right_only' | sed 's/</"/g' | sed 's/ /"/g' | awk -F'"' '{print $6 "t" $8 "t" $11}' | sed 's/different/copy/g' | sed 's/left_only/copy/g' | sed 's/right_only/discard/g'

}

function thinsync()
{
SYNC_VG="$1"
SYNC_PEND="$2"
SYNC_BASE="$3"
SYNC_TARGET="$4"
SYNC_PEND_POOL=$(read_pool_lv $SYNC_VG $SYNC_PEND)
SYNC_BLOCK_SIZE=$(read_lv_chunk_size $SYNC_VG $SYNC_PEND_POOL)
SYNC_PEND_PATH=$(read_lv_dm_path $SYNC_VG $SYNC_PEND)

activate_volume $SYNC_VG $SYNC_PEND

while read -r SYNC_ACTION SYNC_OFFSET SYNC_LENGTH ; do
SYNC_OFFSET_BYTES=$((SYNC_OFFSET * SYNC_BLOCK_SIZE))
SYNC_LENGTH_BYTES=$((SYNC_LENGTH * SYNC_BLOCK_SIZE))
if [ "$SYNC_ACTION" == "copy" ] then
ddrescue --quiet --force --input-position=$SYNC_OFFSET_BYTES --output-position=$SYNC_OFFSET_BYTES --size=$SYNC_LENGTH_BYTES "$SYNC_PEND_PATH" "$SYNC_TARGET"
fi

if [ "$SYNC_ACTION" == "discard" ] then
blkdiscard -o $SYNC_OFFSET_BYTES -l $SYNC_LENGTH_BYTES "$SYNC_TARGET"
fi
done < <(thindiff "$SYNC_VG" "$SYNC_PEND" "$SYNC_BASE")
}

function discard_volume()
{
DISCARD_VG="$1"
DISCARD_LV="$2"
DISCARD_LV_PATH=$(read_lv_dm_path "$DISCARD_VG" "$DISCARD_LV")
if [ "$DISCARD_LV_PATH" != "" ] then
echo "$DISCARD_LV_PATH found"
else
echo "$DISCARD_LV not found in $DISCARD_VG"
exit 1
fi
DISCARD_LV_POOL=$(read_pool_lv $DISCARD_VG $DISCARD_LV)
DISCARD_LV_SIZE=$(read_lv_size "$DISCARD_VG" "$DISCARD_LV")
lvremove -y --quiet "$DISCARD_LV_PATH" || exit 1
lvcreate --thin-pool "$DISCARD_LV_POOL" -V "$DISCARD_LV_SIZE"B --name "$DISCARD_LV" "$DISCARD_VG" || exit 1
}

function backup()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
SOURCE_PEND_LV="$SOURCE_LV$PEND_SUFFIX"
TARGET_PEND_LV="$TARGET_LV$PEND_SUFFIX"
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")
SOURCE_PEND_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_PEND_LV")
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
TARGET_PEND_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_PEND_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "Source base not found creating snapshot of $SOURCE_VG/$SOURCE_LV to $SOURCE_VG/$SOURCE_BASE_LV"
lvcreate --quiet --snapshot --name "$SOURCE_BASE_LV" "$SOURCE_VG/$SOURCE_LV" || exit 1
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
echo "Discarding $SOURCE_BASE_LV_PATH as we need to bootstrap."
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SOURCE_BASE_CHUNK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)
discard_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
sync
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found out of sync with source... removing..."
lvremove -y --quiet $TARGET_BASE_LV_PATH || exit 1
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
sync
fi
fi
SOURCE_BASE_SIZE=$(read_lv_size "$SOURCE_VG" "$SOURCE_BASE_LV")
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_VG/$TARGET_LV not found. Creating empty volume."
lvcreate --thin-pool "$BACKUPS_POOL" -V "$SOURCE_BASE_SIZE"B --name "$TARGET_BASE_LV" "$TARGET_VG" || exit 1
echo "Have to rebootstrap. Discarding source at $SOURCE_BASE_LV_PATH"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SOURCE_BASE_CHUNK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)
discard_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
TARGET_BASE_POOL=$(read_pool_lv $TARGET_VG $TARGET_BASE_LV)
TARGET_BASE_CHUNK_SIZE=$(read_lv_chunk_size $TARGET_VG $TARGET_BASE_POOL)
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
echo "Discarding target at $TARGET_BASE_LV_PATH"
discard_volume "$TARGET_VG" "$TARGET_BASE_LV"
sync
fi
if [ "$SOURCE_PEND_LV_PATH" != "" ] then
echo "$SOURCE_PEND_LV_PATH found removing..."
lvremove -y --quiet "$SOURCE_PEND_LV_PATH" || exit 1
sync
fi
lvcreate --quiet --snapshot --name "$SOURCE_PEND_LV" "$SOURCE_VG/$SOURCE_LV" || exit 1
SOURCE_PEND_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_PEND_LV")
sync
if [ "$TARGET_PEND_LV_PATH" != "" ] then
echo "$TARGET_PEND_LV_PATH found removing..."
lvremove -y --quiet $TARGET_PEND_LV_PATH
sync
fi
lvcreate --quiet --snapshot --name "$TARGET_PEND_LV" "$TARGET_VG/$TARGET_BASE_LV" || exit 1
TARGET_PEND_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_PEND_LV")
SOURCE_PEND_LV_SIZE=$(read_lv_size "$SOURCE_VG" "$SOURCE_PEND_LV")
lvresize -L "$SOURCE_PEND_LV_SIZE"B "$TARGET_PEND_LV_PATH"
activate_volume "$TARGET_VG" "$TARGET_PEND_LV"
echo "Synching $SOURCE_PEND_LV_PATH to $TARGET_PEND_LV_PATH"
thinsync "$SOURCE_VG" "$SOURCE_PEND_LV" "$SOURCE_BASE_LV" "$TARGET_PEND_LV_PATH" || exit 1
sync

TARGET_DATE_SUFFIX=$(suffix)
lvcreate --quiet --snapshot --name "$TARGET_LV$TARGET_DATE_SUFFIX" "$TARGET_VG/$TARGET_PEND_LV" || exit 1
sync
lvremove --quiet -y "$SOURCE_BASE_LV_PATH" || exit 1
sync
lvremove --quiet -y "$TARGET_BASE_LV_PATH" || exit 1
sync
lvrename -y "$SOURCE_VG/$SOURCE_PEND_LV" "$SOURCE_BASE_LV" || exit 1
lvrename -y "$TARGET_VG/$TARGET_PEND_LV" "$TARGET_BASE_LV" || exit 1
sync
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function verify()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "$SOURCE_BASE_LV_PATH not found"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_BASE_LV_PATH not found"
exit 1
fi
activate_volume "$TARGET_VG" "$TARGET_BASE_LV"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
echo Comparing "$SOURCE_BASE_LV_PATH" with "$TARGET_BASE_LV_PATH"
cmp "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH"
echo Done...
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function resync()
{
SOURCE_VG="$1"
SOURCE_LV="$2"
TARGET_VG="$BACKUPS"
TARGET_LV="$SOURCE_VG-$SOURCE_LV"
SOURCE_BASE_LV="$SOURCE_LV$BASE_SUFFIX"
TARGET_BASE_LV="$TARGET_LV$BASE_SUFFIX"
TARGET_BASE_LV_PATH=$(read_lv_dm_path "$TARGET_VG" "$TARGET_BASE_LV")
SOURCE_BASE_LV_PATH=$(read_lv_dm_path "$SOURCE_VG" "$SOURCE_BASE_LV")

if [ "$SOURCE_BASE_LV_PATH" != "" ] then
echo "$SOURCE_BASE_LV_PATH found"
else
echo "$SOURCE_BASE_LV_PATH not found"
exit 1
fi
if [ "$TARGET_BASE_LV_PATH" != "" ] then
echo "$TARGET_BASE_LV_PATH found"
else
echo "$TARGET_BASE_LV_PATH not found"
exit 1
fi
activate_volume "$TARGET_VG" "$TARGET_BASE_LV"
activate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
SOURCE_BASE_POOL=$(read_pool_lv $SOURCE_VG $SOURCE_BASE_LV)
SYNC_BLOCK_SIZE=$(read_lv_chunk_size $SOURCE_VG $SOURCE_BASE_POOL)

echo Syncronizing "$SOURCE_BASE_LV_PATH" to "$TARGET_BASE_LV_PATH"

CMP_OFFSET=0
while [[ "$CMP_OFFSET" != "" ]] ; do
CMP_MISMATCH=$(cmp -i "$CMP_OFFSET" "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH" | grep differ | awk '{print $5}' | sed 's/,//g' )
if [[ "$CMP_MISMATCH" != "" ]] ; then
CMP_OFFSET=$(( CMP_MISMATCH + CMP_OFFSET ))
SYNC_OFFSET_BYTES=$(( ( CMP_OFFSET / SYNC_BLOCK_SIZE ) * SYNC_BLOCK_SIZE ))
SYNC_LENGTH_BYTES=$(( SYNC_BLOCK_SIZE ))
echo "Synching $SYNC_LENGTH_BYTES bytes at $SYNC_OFFSET_BYTES from $SOURCE_BASE_LV_PATH to $TARGET_BASE_LV_PATH"
ddrescue --quiet --force --input-position=$SYNC_OFFSET_BYTES --output-position=$SYNC_OFFSET_BYTES --size=$SYNC_LENGTH_BYTES "$SOURCE_BASE_LV_PATH" "$TARGET_BASE_LV_PATH"
else
CMP_OFFSET=""
fi
done
echo Done...
deactivate_volume "$TARGET_VG" "$TARGET_BASE_LV"
deactivate_volume "$SOURCE_VG" "$SOURCE_BASE_LV"
}

function list()
{
LIST_SOURCE_VG="$1"
LIST_SOURCE_LV="$2"
LIST_TARGET_VG="$BACKUPS"
LIST_TARGET_LV="$LIST_SOURCE_VG-$LIST_SOURCE_LV"
LIST_TARGET_BASE_LV="$LIST_TARGET_LV$SNAP_SUFFIX"
lvs -olv_name | grep "$LIST_TARGET_BASE_LV.$DATE_REGEX"
}

function remove()
{
REMOVE_TARGET_VG="$BACKUPS"
REMOVE_TARGET_LV="$1"
lvremove -y "$REMOVE_TARGET_VG/$REMOVE_TARGET_LV"
sync
}

function removeall()
{
DATE_OFFSET="$3"
FILTER="$(filter "$DATE_OFFSET")"
while read -r SNAPSHOT ; do
remove "$SNAPSHOT"
done < <(list "$1" "$2" | grep "$FILTER")

}

(
COMMAND="$1"
shift

case "$COMMAND" in
"--help")
echo "Help"
;;
"suffix")
suffix
;;
"filter")
filter "$1"
;;
"backup")
wait_lock_or_terminate
backup "$1" "$2"
;;
"list")
list "$1" "$2"
;;
"thindiff")
thindiff "$1" "$2" "$3"
;;
"thinsync")
thinsync "$1" "$2" "$3" "$4"
;;
"verify")
wait_lock_or_terminate
verify "$1" "$2"
;;
"resync")
wait_lock_or_terminate
resync "$1" "$2"
;;
"remove")
wait_lock_or_terminate
remove "$1"
;;
"removeall")
wait_lock_or_terminate
removeall "$1" "$2" "$3"
;;
*)
echo "None.."
;;
esac
) 98>$LOCK_FILE

EOF

それは䜕をするためのものか...シン スナップショットを操䜜し、thin_delta 経由で受信した XNUMX ぀のシン スナップショットの差分を、ddrescue ず blkdiscard を䜿甚しお別のブロック デバむスに同期するためのコマンド セットが含たれおいたす。

cron に远加する別のスクリプト:

もう少しバッシュ#cat >/root/lvm-thin-backup/cron-daily.sh << EOF
#!/bin/bash
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

SCRIPT_FILE="$(realpath $0)"
SCRIPT_DIR="$(dirname $SCRIPT_FILE)"
SCRIPT_NAME="$(basename -s .sh $SCRIPT_FILE)"

BACKUP_SCRIPT="$SCRIPT_DIR/lvm-thin-backup.sh"
RETENTION="-60 days"

$BACKUP_SCRIPT backup images linux-dev
$BACKUP_SCRIPT backup images win8
$BACKUP_SCRIPT backup images win8-data
#etc

$BACKUP_SCRIPT removeall images linux-dev "$RETENTION"
$BACKUP_SCRIPT removeall images win8 "$RETENTION"
$BACKUP_SCRIPT removeall images win8-data "$RETENTION"
#etc

EOF

それは䜕をするためのものか...前のスクリプトを䜿甚しお、リストされたシン ボリュヌムのバックアップを䜜成および同期したす。 スクリプトは、リストされたボリュヌムの非アクティブなスナップショットを残したす。これは、最埌の同期以降の倉曎を远跡するために必芁です。

このスクリプトを線集しお、バックアップ コピヌを䜜成するシン ボリュヌムのリストを指定する必芁がありたす。 指定された名前は説明のみを目的ずしおいたす。 必芁に応じお、すべおのボリュヌムを同期するスクリプトを䜜成できたす。

暩利を䞎えたしょう:

#chmod +x /root/lvm-thin-backup/cron-daily.sh
#chmod +x /root/lvm-thin-backup/lvm-thin-backup.sh

それを確認しお cron に入れおみたしょう。

#/usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/lvm-thin-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t lvm-thin-backup
#cat /var/log/syslog | grep lvm-thin-backup
#crontab -e
0 3 * * * /usr/bin/nice -n 19 /usr/bin/ionice -c 3 /root/lvm-thin-backup/cron-daily.sh 2>&1 | /usr/bin/logger -t lvm-thin-backup

最初の起動は長くなるでしょう、なぜなら... シン ボリュヌムは、䜿甚されおいるすべおの領域をコピヌするこずによっお完党に同期されたす。 LVM シン メタデヌタのおかげで、どのブロックが実際に䜿甚されおいるかがわかるため、実際に䜿甚されおいるシン ボリュヌム ブロックのみがコピヌされたす。

埌続の実行では、LVM シン メタデヌタを介した倉曎远跡のおかげで、デヌタが段階的にコピヌされたす。

䜕が起きたのか芋おみたしょう

#time /root/btrfs-backup/cron-daily.sh
real 0m2,967s
user 0m0,225s
sys 0m0,353s

#time /root/lvm-thin-backup/cron-daily.sh
real 1m2,710s
user 0m12,721s
sys 0m6,671s

#ls -al /backup/btrfs/back/remote/*
/backup/btrfs/back/remote/boot:
total 0
drwxr-xr-x 1 root root 1260 Ќар 26 09:11 .
drwxr-xr-x 1 root root 16 Ќар 6 09:30 ..
drwxr-xr-x 1 root root 322 Ќар 26 02:00 .@base
drwxr-xr-x 1 root root 516 Ќар 6 09:39 [email protected]
drwxr-xr-x 1 root root 516 Ќар 6 09:39 [email protected]
...
/backup/btrfs/back/remote/root:
total 0
drwxr-xr-x 1 root root 2820 Ќар 26 09:11 .
drwxr-xr-x 1 root root 16 Ќар 6 09:30 ..
drwxr-xr-x 1 root root 240 Ќар 26 09:11 @.@base
drwxr-xr-x 1 root root 22 Ќар 26 09:11 @home.@base
drwxr-xr-x 1 root root 22 Ќар 6 09:39 @[email protected]
drwxr-xr-x 1 root root 22 Ќар 6 09:39 @[email protected]
...
drwxr-xr-x 1 root root 240 Ќар 6 09:39 @[email protected]
drwxr-xr-x 1 root root 240 Ќар 6 09:39 @[email protected]
...

#lvs -olv_name,lv_size images && lvs -olv_name,lv_size backup
LV LSize
linux-dev 128,00g
linux-dev.base 128,00g
thin-pool 1,38t
win8 128,00g
win8-data 2,00t
win8-data.base 2,00t
win8.base 128,00g
LV LSize
backup 256,00g
images-linux-dev.base 128,00g
images-linux-dev.snap.2020-03-08-10-09-11 128,00g
images-linux-dev.snap.2020-03-08-10-09-25 128,00g
...
images-win8-data.base 2,00t
images-win8-data.snap.2020-03-16-14-11-55 2,00t
images-win8-data.snap.2020-03-16-14-19-50 2,00t
...
images-win8.base 128,00g
images-win8.snap.2020-03-17-04-51-46 128,00g
images-win8.snap.2020-03-18-03-02-49 128,00g
...
thin-pool <2,09t

これは入れ子人圢ず䜕の関係があるのでしょうか

LVM LV 論理ボリュヌムが他の VG の LVM PV 物理ボリュヌムになる可胜性があるこずを考えるず、おそらく可胜です。 LVM は、入れ子人圢のように再垰的に実行できたす。 これにより、LVM に極めお高い柔軟性が䞎えられたす。

PS

次の蚘事では、ホヌム デスクトップ、ホヌム むンタヌネット、P2P ネットワヌクを䜿甚しお、耇数の倧陞に冗長性を備えた地理分散ストレヌゞ/VM クラスタヌを䜜成するための基瀎ずしお、いく぀かの同様のモバむル ストレヌゞ システム/KVM を䜿甚しおみたす。

出所 habr.com

コメントを远加したす