ما هو المشترك بين LVM و matryoshka؟

يوم جيد.
أريد أن أشارك المجتمع تجربة عملية في بناء نظام تخزين لـ KVM باستخدام md RAID + LVM.

سيقوم البرنامج:

  • قم ببناء md RAID 1 من NVMe SSD.
  • قم ببناء md RAID 6 من SATA SSD ومحركات الأقراص العادية.
  • ميزات TRIM / DISCARD على SSD RAID 1/6.
  • إنشاء صفيف md RAID 1/6 قابل للتمهيد على مجموعة مشتركة من الأقراص.
  • تثبيت النظام على NVMe RAID 1 إذا لم يكن هناك دعم NVMe في BIOS.
  • باستخدام مخبأ LVM ورقيقة LVM.
  • باستخدام لقطات BTRFS وإرسال / تلقي النسخ الاحتياطي.
  • استخدام لقطات رقيقة LVM و thin_delta للنسخ الاحتياطي بنمط BTRFS.

إذا كانت مهتمة ، من فضلك ، تحت القط.

بيان


لا يتحمل المؤلف أي مسؤولية عن عواقب استخدام أو عدم استخدام المواد / الأمثلة / الكود / النصائح / البيانات من هذه المقالة. من خلال قراءة أو استخدام هذه المواد بأي شكل من الأشكال ، فإنك تتحمل المسؤولية عن جميع عواقب هذه الإجراءات. تشمل العواقب المحتملة ما يلي:

  • NVMe SSD المقلية المقرمشة.
  • استخدام كامل لموارد التسجيل وفشل محركات الأقراص SSD.
  • فقدان كامل لجميع البيانات الموجودة على جميع محركات الأقراص ، بما في ذلك النسخ الاحتياطية.
  • أجهزة الكمبيوتر المعيبة.
  • أمضى الوقت والأعصاب والمال.
  • أي تأثيرات أخرى غير مدرجة أعلاه.

حديد


في المخزن كان:


اللوحة الأم حوالي عام 2013 على مجموعة شرائح Z87 كاملة مع Intel Core i7 / Haswell.

  • وحدة المعالجة المركزية 4 النوى ، 8 خيوط
  • 32 جيجا بايت من DDR3 RAM
  • 1 × 16 أو 2 × 8 فتحة PCIe 3.0
  • 1 × 4 + 1 × 1 فتحة PCIe 2.0
  • 6 × 6 جيجابايت / ثانية من موصلات SATA 3

تومض محول SAS LSI SAS9211-8I في وضع IT / HBA. تم استبدال البرامج الثابتة التي تدعم RAID عمدًا بالبرامج الثابتة HBA من أجل:

  1. كان من الممكن في أي وقت رمي ​​هذا المحول واستبداله بأي محول آخر.
  2. عمل TRIM / Discard بشكل طبيعي على الأقراص ، مثل في برامج RAID الثابتة ، لا يتم دعم هذه الأوامر على الإطلاق ، ولا يهتم HBA بشكل عام بالأوامر التي يجب إرسالها في الناقل.

الأقراص الصلبة - 8 قطع من HGST Travelstar 7K1000 بحجم 1 تيرابايت في شكل عامل 2.5 ، كما هو الحال بالنسبة لأجهزة الكمبيوتر المحمولة. كانت محركات الأقراص هذه في السابق في صفيف RAID 6. في النظام الجديد ، سيجدون أيضًا التطبيق. لتخزين النسخ الاحتياطية المحلية.

بالإضافة إلى ذلك تم إضافته:


6 قطع من طراز SATA SSD Samsung 860 QVO 2TB. تتطلب محركات الأقراص ذات الحالة الصلبة هذه كمية كبيرة ، ووجود ذاكرة تخزين مؤقت SLC ، والموثوقية أمر مرغوب فيه ، وسعر منخفض. كان إلزاميًا دعمًا للتجاهل / صفر والذي تم فحصه بواسطة سطر في dmesg:

kernel: ata1.00: Enabling discard_zeroes_data

قطعتان من طراز NVMe SSD Samsung SSD 970 EVO 500GB.

بالنسبة لأقراص SSD هذه ، تعد سرعة القراءة / الكتابة العشوائية وموردًا لاحتياجاتك مهمة. المبرد لهم. إلزامي. الضرورة القصوى. خلاف ذلك ، قم بقليها حتى تصبح هشة أثناء مزامنة RAIDa الأولى.

محول StarTech PEX8M2E2 لقرصين NVMe SSD مع فتحة PCIe 3.0 8x. هذا ، مرة أخرى ، هو HBA فقط ، ولكن بالنسبة لـ NVMe. وهو يختلف عن المحولات الرخيصة في غياب متطلبات دعم التشعب PCIe من اللوحة الأم بسبب وجود مفتاح PCIe مدمج. ستعمل حتى في أقدم نظام يوجد به PCIe ، حتى لو كانت فتحة x1 PCIe 1.0. وبطبيعة الحال ، بالسرعة المناسبة. لا توجد RAIDs هناك. لا يوجد BIOS متكامل على اللوحة. لذلك ، لن يتعلم نظامك بطريقة سحرية التمهيد من NVMe ، ناهيك عن NVMe RAID بفضل هذا الجهاز.

كان هذا المكون ناتجًا فقط عن وجود قرص واحد مجاني 8x PCIe 3.0 في النظام ، وفي وجود فتحتين مجانيتين ، يمكن استبداله بسهولة بقطعتين PEX4M2E1 أو نظيرتين رخيصتين ، والتي يمكن شراؤها في أي مكان بسعر 600 روبل.

تم رفض جميع أنواع الأجهزة أو شرائح RAID / BIOS المدمجة بشكل متعمد ، حتى تتمكن من استبدال النظام بالكامل ، باستثناء SSD / HDD ، مما يحفظ جميع البيانات. من الناحية المثالية ، سيكون من الممكن الاحتفاظ حتى بنظام التشغيل المثبت عند الانتقال إلى جهاز جديد / مختلف تمامًا. الشيء الرئيسي هو أن هناك منافذ SATA و PCIe. إنه مثل قرص مضغوط مباشر أو محرك أقراص فلاش قابل للتشغيل ، فقط سريع جدًا وقليل الحجم قليلاً.

دعابة
, , — . . 5.25 .

حسنًا ، وبطبيعة الحال ، لتجربة طرق مختلفة للتخزين المؤقت SSD في Linux.
غارات الأجهزة ، إنها مملة. شغله. إما أنه يعمل أم لا. ومع mdadm هناك دائمًا خيارات.

ناعم


سابقًا ، تم تثبيت Debian 8 Jessie على الجهاز ، وهو قريب من موسوعة الحياة. تم إقران RAID 6 من الأقراص الصلبة المذكورة أعلاه مع LVM. كان يشغل آلات افتراضية في kvm / libvirt.

لان يمتلك المؤلف الخبرة المناسبة في إنشاء محركات أقراص محمولة قابلة للتشغيل SATA / NVMe محمولة ، وأيضًا ، حتى لا يتمزق قالب apt المعتاد ، تم اختيار Ubuntu 18.04 كنظام مستهدف ، والذي استقر بالفعل بما يكفي ، ولكن لا يزال لديه 3 سنوات من الدعم في المستقبل.

في النظام المذكور ، هناك جميع برامج تشغيل الأجهزة التي نحتاجها خارج الصندوق. لا نحتاج إلى أي برامج وبرامج تشغيل تابعة لجهات خارجية.

التحضير للتثبيت


لتثبيت النظام ، نحتاج إلى Ubuntu Desktop Image. يحتوي نظام الخادم على نوع من المثبتات القوية التي تظهر استقلالية مفرطة وغير قابلة للفصل ، مما يدفع دائمًا قسم نظام UEFI إلى أحد الأقراص التي تفسد كل الجمال. وفقًا لذلك ، يتم تثبيته فقط في وضع UEFI. لا تقدم خيارات.

هذا لا يناسبنا.

لماذا ا؟
, UEFI RAID, .. UEFI ESP . , ESP USB , , . mdadm RAID 1 0.9 UEFI BIOS , , BIOS - ESP .

, UEFI NVRAM, , .. .

, . , Legacy/BIOS boot, CSM UEFI- . , , .

لا يعرف إصدار سطح المكتب من Ubuntu أيضًا كيفية التثبيت بشكل طبيعي مع Legoot bootloader ، ولكن هنا ، كما يقولون ، على الأقل هناك خيارات.

لذا ، قم بتجميع الأجهزة وتحميل النظام من محرك أقراص Ubuntu Live القابل للتمهيد. سنحتاج إلى تنزيل الحزم ، لذا قمنا بإعداد الشبكة ، والتي أكسبتك. إذا لم يفلح ذلك ، يمكنك تنزيل الحزم الضرورية على محرك أقراص USB المحمول مسبقًا.

نذهب إلى بيئة سطح المكتب ، ونشغل محاكي الطرفية ، ودعونا نذهب:

#sudo bash

كيف...؟
sudo. . , . sudo , . :


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

لماذا لا ZFS ...؟
, — , .
, — , - .

ZFS — , mdadm+lvm .

. . . . . . , .

ثم لماذا BTRFS ...؟
Legacy/BIOS GRUB , , , -. /boot . , / () , LVM .

, .
send/recieve.

, GPU PCI-USB Host- KVM IOMMU.

— , .

ZFS, , , .

, / RAID ZFS, BRTFS LVM.

, 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. لن نقوم حتى بإنشاء أقسام هناك. إذا كنت تريد وفقًا "للشريعة" أو "المبدأ" - قم بإنشاء قسم واحد كبير ، مثل محرك الأقراص الثابتة.

SATA HDD


لا يوجد شيء خاص للاختراع. سنقوم بإنشاء قسم واحد لكل شيء. سنقوم بإنشاء القسم لأن 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


هنا لدينا الأكثر إثارة للاهتمام.

أولاً ، لدينا محركي أقراص TB. هذا ضمن الحدود المسموح بها لـ MBR ، والتي سنستخدمها. إذا لزم الأمر ، يمكن استبداله بـ GPT. تحتوي أقراص GPT على طبقة توافق تسمح للأنظمة المتوافقة مع MBR برؤية الأقسام الأربعة الأولى إذا كانت موجودة ضمن أول 2 تيرابايت. الشيء الرئيسي هو أن قسم التمهيد وقسم bios_grub على هذه الأقراص يجب أن يكون في البداية. هذا يسمح لك بالتمهيد حتى من محرك GPT Legacy / BIOS.

لكن ، هذه ليست قضيتنا.

هنا سنقوم بإنشاء قسمين. سيكون الأول بحجم 1 جيجا بايت ويستخدم لـ RAID 1 / boot.

سيتم استخدام الثاني لـ RAID 6 وسيشغل كل المساحة الخالية المتبقية باستثناء منطقة صغيرة غير مخصصة في نهاية محرك الأقراص.

ما هي المساحة غير المخصصة؟
SATA SSD SLC 6 78 . 6 «» «» «» . 72 .

, SLC, 4 bit MLC. , 4 1 SLC .

72 4 288 . , SLC .

, 312 SLC . 2 RAID .

, . QLC , — . , , , SSD TBW .

#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. TRIM/DISCARD SSD «».

SSD RAID 1 DISCARD .

SSD RAID 6 DISCARD .

, SSD 4/5/6 discard_zeroes_data. , , , -, , . , , . DISCARD - RAID 6.

انتباه ، الأمر التالي سوف يدمر جميع البيانات الموجودة على محركات أقراص 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

لماذا كبير جدا ...؟
chunk-size chunk-size . , . , IOPS . 99% IO 512K.

RAID 6 IOPS IOPS . IOPS , .
RAID 6 by-design , RAID 6 .
RAID 6 NVMe thin-provisioning.

لم نقم بعد بتمكين DISCARD لـ RAID 6. لذا ، لن نقوم "بتهيئة" هذا الصفيف بعد. سنفعل ذلك لاحقًا ، بعد تثبيت نظام التشغيل.

SATA HDD


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

LVM على NVMe RAID


للسرعة ، نريد وضع الجذر FS على NVMe RAID 1 وهو / dev / md0.
ومع ذلك ، ما زلنا بحاجة إلى هذا الصفيف السريع للاحتياجات الأخرى ، مثل المبادلة والبيانات الوصفية وذاكرة التخزين المؤقت LVM وبيانات التعريف الرقيقة LVM ، وبالتالي ، في هذا الصفيف ، سننشئ LVM VG. إنشاء قسم للجذر FS. قم بإنشاء قسم لتبديل حجم ذاكرة الوصول العشوائي.

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




#lvcreate -L 128G --name root root



#lvcreate -L 32G --name swap root

تثبيت نظام التشغيل


في المجموع ، لدينا كل ما يلزم لتثبيت النظام.

قم بتشغيل معالج التثبيت من بيئة Ubuntu Live. التثبيت العادي. فقط في مرحلة تحديد محركات الأقراص للتثبيت ، تحتاج إلى تحديد ما يلي:

  • / dev / md1 ، - نقطة تحميل / تمهيد ، FS - BTRFS
  • / dev / root / root (aka / dev / mapper / root-root) ، - نقطة تحميل / (root) ، FS - BTRFS
  • / dev / root / swap (aka / dev / mapper / root-swap) ، - استخدم كقسم تبديل
  • تثبيت برنامج Bootloader على / dev / sda

إذا قمت بتحديد BTRFS كجذر FS ، فسيقوم المثبت تلقائيًا بإنشاء مجلدين BTRFS بأسماء "@" لـ / (root) و "home" لـ / home.

نبدأ التثبيت ...

سينتهي التثبيت بمربع حوار مشروط للإبلاغ عن خطأ تثبيت محمل التمهيد. لسوء الحظ ، سيفشل الخروج من هذا الحوار بالوسائل العادية ومواصلة التثبيت. نقوم بتسجيل الخروج من النظام وتسجيل الدخول مرة أخرى ، والوصول إلى سطح مكتب Ubuntu Live النظيف. افتح الوحدة الطرفية ، ومرة ​​أخرى:

#sudo bash

قم بإنشاء بيئة chroot لمواصلة التثبيت: قم بإعداد الشبكة واسم المضيف في chroot: انتقل إلى بيئة 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



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



#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 قبل ذلك. دعنا نغير معلمات وحدة RAID 6 لتمكين TRIM / DISCARD: سنقوم بتعديل صفائفنا قليلاً:

#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=="sd[a-z]", ATTR{queue/rotational}=="0", RUN+="/sbin/blockdev --setra 0 /dev/%k"
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="nvme[0-9]n1", RUN+="/sbin/blockdev --setra 0 /dev/%k"
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="dm-*", ATTR{queue/rotational}=="0", RUN+="/sbin/blockdev --setra 0 /dev/%k"
SUBSYSTEM=="block", ACTION=="add|change", KERNEL=="md*", RUN+="/sbin/blockdev --setra 0 /dev/%k"

EOF

ماذا كان ..؟
udev :

  • 2020- RAID 6. -, , Linux, .
  • / IO. , .
  • / IO. , / SSD RAID- . NVMe. ( ? . )
  • APM (HDD) 7 . APM (-B 255). - . , , , -. . - . , , - «», -, RAID- mini-MAID-.
  • readahead () 1 — /chunk RAID 6
  • readahead SATA SSD
  • readahead NVMe SSD
  • readahead LVM SSD.
  • readahead RAID .


تحرير / 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 .. .

LVM /dev/mapper/vg-lv, .. .

UUID LVM .. UUID LVM .
مرتين نحن جبل / ديف / مخطط / الجذر الجذر ..؟
. . BTRFS. subvol.

- LVM BTRFS . .

نقوم بتجديد تكوين mdadm: قم بتصحيح إعدادات LVM:

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



#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

ماذا كان ..؟
LVM thin 90% 5% .

LVM cache.

LVM LVM (PV) :

  • LVM cache (cdata)
  • LVM cache (<lv_name>_corig). ( <lv_name>).
  • LVM cache (cmeta)
  • VG images. , , LVM .
  • VG backup. .
  • «gpv» ( guest physical volume )

DISCARD LVM VG. . LV SSD . SSD RAID 6. , , thin provisioning, , .

تحديث صورة initramfs:

#update-initramfs -u -k all

تثبيت وتكوين اليرقة:

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


ما يدفع للاختيار؟
sd*. SATA SSD.

لماذا مسمر os-prober ..؟
.

RAID- . , .

, , , . .

بهذا أكملنا التثبيت الأولي. حان الوقت لإعادة التشغيل في نظام التشغيل المثبت حديثًا. تذكر إزالة قرص CD / USB المباشر القابل للتمهيد. كجهاز للتشغيل ، حدد أيًا من SATA SSD.

#exit
#reboot




LVM إلى SATA SSD


في هذه المرحلة ، قمنا بالفعل بالتمهيد إلى نظام التشغيل الجديد ، وقمنا بتهيئة الشبكة ، وفتح ، ومحاكي الطرفية ، وبدأنا:

#sudo bash

متابعة.

"تهيئة" صفيف من SATA SSD:

#blkdiscard /dev/md2

إذا لم يحدث ذلك ، فحاول:

#blkdiscard --step 65536 /dev/md2
إنشاء LVM VG على SATA SSD:

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


لماذا آخر vg ..؟
, VG root. VG?

VG PV, VG PV (online). LVM RAID, .

, ( ) RAID 6 .

, «» VG.

-, RAID « ». , VG.

LVM «» RAID - . , — bcache + LVM thin, bcache + BTRFS, LVM cache + LVM thin, ZFS , .

«» , - «» LVM-, . , , .

, , - .

LVM إلى SATA HDD


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


مرة أخرى VG الجديد ..؟
, , , , - . , - VG, — VG.

تكوين ذاكرة التخزين المؤقت LVM


قم بإنشاء LV على NVMe RAID 1 لاستخدامه كجهاز تخزين مؤقت.

#lvcreate -L 70871154688B --name cache root

لماذا القليل جدا ...؟
, NVMe SSD SLC . 4 «» 18 3-bit MLC. - NVMe SSD SATA SSD . , LVM cache SLC NVMe . NVMe 32-64 .

64 , .

, LVM . , lvchange . , .

لنقم بإنشاء LV على SATA RAID 6 لاستخدامه كجهاز مخبأ.

#lvcreate -L 3298543271936B --name cache data

لماذا فقط ثلاثة تيرابايت ..؟
, , SATA SSD RAID 6 - . , , . , , LVM-cache , , bcache, , .

إنشاء VG جديد للتخزين المؤقت. قم بإنشاء LV على الجهاز المخزن مؤقتًا. هنا أخذنا على الفور كل المساحة الحرة على / dev / data / cache حتى يتم إنشاء جميع الأقسام الضرورية الأخرى على الفور على / dev / root / cache. إذا كان لديك شيء لم يتم إنشاؤه هناك ، يمكنك نقله باستخدام pvmove. إنشاء وتمكين ذاكرة التخزين المؤقت:

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




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





#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 cache LVM thin. , , .

64 — LVM thin.

تحذير رد ..!
. . , , , . , , NVMe RAID 1 , .

, RAID 6 .

دعنا نتحقق من نجاحنا: يجب وضع [cachedata_corig] فقط على / dev / data / cache. إذا كان هناك شيء خاطئ ، فاستخدم pvmove. إذا لزم الأمر ، يمكنك تعطيل ذاكرة التخزين المؤقت بأمر واحد: يتم ذلك عبر الإنترنت. يقوم LVM ببساطة بمزامنة ذاكرة التخزين المؤقت على القرص وحذفها وإعادة تسمية cachedata_corig إلى البيانات المخزنة مؤقتًا.

#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)





#lvconvert -y --uncache cache/cachedata



إعداد LVM رفيع


سنقدّر تقريبًا مقدار المساحة التي سنحتاجها للبيانات الوصفية الرقيقة LVM: تقريب ما يصل إلى 4 غيغابايت: 4294967296B اضرب في اثنين وأضف 4194304B للبيانات الوصفية LVM PV: 8594128896B أنشئ قسمًا منفصلاً على NVMe RAID 1 لوضع علامة على البيانات الوصفية الرقيقة 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"







#lvcreate -L 8594128896B --name images root

لماذا..؟
, LVM thin , NVMe .

, . , , . - , , LVM thin , . .

- -, , , . , . .

, , , , , , LVM thin, .

قم بإنشاء 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
, , — , — zeroing 64k. 64k 64K . .

دعنا ننقل LV إلى PVs المقابلة: تحقق: إنشاء حجم صغير للاختبارات: ضع حزمًا للاختبارات والملاحظات: هذه هي الطريقة التي يمكنك من خلالها ملاحظة سلوك تكوين التخزين لدينا في الوقت الفعلي: هذه هي الطريقة التي يمكنك بها اختبار التكوين لدينا:

#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=256Kwrite --bs=256k --rw=write \
--name=128Kwrite --bs=128k --rw=write \
--name=64Kwrite --bs=64k --rw=write \
--name=32Kwrite --bs=32k --rw=write \
--name=16Kwrite --bs=16k --rw=write \
--name=8Kwrite --bs=8k --rw=write \
--name=4Kwrite --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 . . 4 NVMe . 3 . , 216 SSD.

القراءة والكتابة المراوغة؟
. . , , , .

ستختلف النتائج بشكل كبير في البداية الأولى واللاحقة بعد ذلك ، حيث تمتلئ ذاكرة التخزين المؤقت والحجم الرقيق ، وأيضًا اعتمادًا على ما إذا كان النظام تمكن من مزامنة ذاكرة التخزين المؤقت المملوءة في البداية الأخيرة.

من بين أمور أخرى ، أوصي بقياس السرعة على الحجم الرقيق المملوء بالفعل الذي تم عمل اللقطة منه للتو. أتيحت للمؤلف فرصة ملاحظة كيف يتسارع التسجيل العشوائي بشكل حاد بعد إنشاء اللقطة الأولى ، خاصة عندما لا تكون ذاكرة التخزين المؤقت ممتلئة بعد. ويرجع ذلك إلى دلالات الكتابة عند الكتابة ، ومحاذاة كتل التخزين المؤقت والأحجام الرقيقة ، وحقيقة أن الكتابة العشوائية إلى RAID 6 تتحول إلى قراءة عشوائية من RAID 6 ثم الكتابة إلى ذاكرة التخزين المؤقت. في تكويننا ، تكون القراءة العشوائية من RAID 6 حتى 6 مرات (عدد SATA SSDs في الصفيف) أسرع من الكتابة. لان نظرًا لأن كتل 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}' . , writethrough . , SATA NVMe SSD, , TBW, , . - 100% . NVMe SSD 100% 3-4 . SATA SSD - . , , , , — .
  4. ( ) — <>.cached <>.committed. <>.committed .
  5. , 100%, , . .
  6. migration threshold : #lvchange --quiet --cachesettings "migration_threshold=0" cache/cachedata .
  7. , #lvs --rows --reportformat basic --quiet -ocache_dirty_blocks cache/cachedata | awk '{print $2}' .
  8. .

migration threshold...?
, «» . - 4 , , - (+- 32K) .

migration threshold SATA SSD 64K . SATA SSD.

..?
, bash 100% «google»-driven development, , , , .

, , , , systemd , .

سيسمح لنا نظام التدوير البسيط هذا للقطات ليس فقط الحصول على لقطة واحدة متزامنة تمامًا على SATA SSD ، ولكن أيضًا بمساعدة الأداة المساعدة thin_delta لمعرفة الكتل التي تم تغييرها بعد إنشائها ، وبالتالي تحديد موقع الضرر على المجلدات الرئيسية ، مما يجعل من الأسهل بكثير الاستعادة .

تريم / تجاهل في libvirt / KVM


لان نظرًا لأنه سيتم استخدام مخزن البيانات لتشغيل KVM libvirt ، فسيكون من الجيد تعليم أجهزة VM لدينا ليس فقط لشغل مساحة خالية ، ولكن أيضًا لتحرير ما لم يعد مطلوبًا.

يتم ذلك عن طريق محاكاة دعم TRIM / DISCARD على الأقراص الافتراضية. للقيام بذلك ، قم بتغيير نوع وحدة التحكم إلى Virtio-scsi وتحرير xml. تتم معالجة DISCARDs المماثلة من أنظمة تشغيل الضيف بشكل صحيح بواسطة LVM ، ويتم تحرير الكتل بشكل صحيح في ذاكرة التخزين المؤقت وفي التجمع الرقيق. في حالتنا ، يحدث هذا ، بشكل رئيسي ، مؤجل ، عندما تحذف اللقطة التالية.

#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>



النسخ الاحتياطي BTRFS


استخدام البرامج النصية الجاهزة مع المدقع الحذر و على مسؤوليتك الخاصة، والمخاطر . كتب المؤلف هذا الرمز بنفسه وحصريا لنفسه. أنا متأكد من أن العديد من مستخدمي Linux ذوي الخبرة لديهم مثل هذه العكازات من الخبرة ، ولن يحتاج نسخ الآخرين.

إنشاء وحدة تخزين على جهاز النسخ الاحتياطي:

#lvcreate -L 256G --name backup backup

تهيئتها في BTRFS:

#mkfs.btrfs /dev/backup/backup

إنشاء نقاط تحميل وتثبيت مفاتيح الجذر الفرعية لـ FS: إنشاء أدلة للنسخ الاحتياطية: إنشاء دليل للبرامج النصية للنسخ الاحتياطي: نسخ البرنامج النصي:

#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



الكثير من كود باش مخيف. استخدام على مسؤوليتك الخاصة. المؤلف لا يكتب رسائل غاضبة ...
#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 "%f\n" | 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 send/recieve.

يمكن أن يكون الإطلاق الأول طويلًا نسبيًا ، لأنه في البداية سيتم نسخ جميع البيانات. المزيد من عمليات الإطلاق ستكون سريعة جدًا ، لأن سيتم نسخ التغييرات فقط.

سيناريو آخر في كرون:

المزيد من كود باش
#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


ماذا يفعل ..؟
backup BTRFS-. 60 . /backup/btrfs/back/remote/ .

دعونا نعطي الرمز الحق في التنفيذ: تحقق واكتظ في التيجان:

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



#/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, ddrescue blkdiscard.

نص آخر سنضعه في التيجان:

المزيد من باش
#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


ماذا يفعل ...؟
, . , .

يجب تعديل هذا النص البرمجي ، مما يشير إلى قائمة المجلدات الرقيقة التي تتطلب نسخًا احتياطية لها. الأسماء المعطاة هي لأغراض التوضيح فقط. إذا كنت ترغب في ذلك ، يمكنك كتابة برنامج نصي يقوم بمزامنة جميع المجلدات.

دعونا نعطي الحقوق: تحقق وتكدس في التيجان: سيكون الإطلاق الأول طويلًا ، لأنه ستتم مزامنة وحدات التخزين الرفيعة بشكل كامل عن طريق نسخ المساحة المستخدمة بالكامل. بفضل البيانات الوصفية الرقيقة LVM ، نحن نعرف الكتل المستخدمة بالفعل ، لذلك لن يتم نسخ سوى الكتل الفعلية للأحجام الرقيقة فقط. ستقوم عمليات الإطلاق اللاحقة بنسخ البيانات بشكل تدريجي من خلال تتبع التغييرات من خلال بيانات التعريف الرقيقة LVM.

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




#/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





دعونا نرى ما حدث:


#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 .@snap.2020-03-06-09-39-37
drwxr-xr-x 1 root root 516 6 09:39 .@snap.2020-03-06-09-39-57
...
/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 @home.@snap.2020-03-06-09-39-35
drwxr-xr-x 1 root root 22 6 09:39 @home.@snap.2020-03-06-09-39-57
...
drwxr-xr-x 1 root root 240 6 09:39 @.@snap.2020-03-06-09-39-26
drwxr-xr-x 1 root root 240 6 09:39 @.@snap.2020-03-06-09-39-56
...

#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 يمكن أن تكون أحجام LVM PV المادية لـ VGs أخرى. يمكن أن تكون LVM عودية ، مثل دمى التعشيش. هذا يمنح LVM مرونة قصوى.

ملاحظة


في المقالة التالية ، سنحاول استخدام العديد من أنظمة التخزين المحمولة / KVMs المتشابهة كأساس لإنشاء مجموعة تخزين / vm موزعة جغرافيًا مع التكرار في عدة قارات من خلال أجهزة الكمبيوتر المكتبية المنزلية والإنترنت المنزلي وشبكات P2P.

All Articles