נפח הפקה של Docker או Kubernetes נמחק: הצלה docker system prune --volumes, overlay2 אינודס, ו etcd תצלומים¶
מספרי חירום שונים לפי מדינה. דף זה משתמש ב-911, המספר של ארצות הברית וקנדה. מדינות רבות אחרות משתמשות ב-112, 999 או מספר אחר. מצא את המספר עבור המדינה שלך.
ריצה docker compose down -v, docker system prune -a --volumes, docker volume rm, או kubectl delete pvc בכרטיסיית הטרמינל הלא נכונה בייצור היא אחת הדרכים המהירות ביותר למחוק נפח מסד נתונים חי של PostgreSQL, MySQL, MariaDB, Redis, MongoDB או SQLite. בניגוד לצילומי מצב של מכונות וירטואליות בענן שעוברות לפח מיחזור של 7 ימים, מנהל התקן הנפח המקומי של Docker (/var/lib/docker/volumes/<name>/_data) ו-Kubernetes local-path / hostPath ספקי אספקה מנפיקים מיד את התקן POSIX unlink() ו rmdir() שיחות ישירות מול מערכת הקבצים המארח הבסיסית של לינוקס (ext4, XFS, או Btrfs). כל כתיבה שמתרחשת באותו מארח לינוקס לאחר סיום הפקודה יכולה לדרוס את בלוקי מסד הנתונים המשוחררים בדיסק. אם דיסק השרת שלך התמלא עד 100 אחוז (0 bytes free) לפני שמישהו רץ docker system prune --volumes בבהלה, התייעצו דיסק שרת מלא ב-100%, התנפחות יומן WAL של מסד הנתונים ושחזור שטח אפס; למחיקת קבצי Linux ממתכת חשופה מחוץ לקונטיינרים, ראה rm -rf בשוגג או Shift-Delete ב-ext4, XFS, APFS ו-NTFS: רכיבה מחדש לקריאה בלבד וגילוף אינוד ו מכונה וירטואלית VMDK, VHDX ו-qcow2 שחיתות שרשרת צילומי מצב והצלת hypervisor. אם הפסקת ייצור זו משפיעה על טיפול בחולים בבית החולים, על שיגור חירום או על מערכות בטיחות של שירותים ציבוריים, התקשר למספר החירום המקומי שלך (911 בארצות הברית ובקנדה, 112 ברחבי האיחוד האירופי, 999 בבריטניה) או עיין במדריך שלנו של מספרי חירום.
תעשה את זה עכשיו¶
- לא לרוץ
docker compose up -d,systemctl restart docker, או לפרוס מחדש את הפוד של Kubernetes: יצירה מחדש של המיכל או הפעלה מחדש של הדמון Docker כותב מגה-בייט של חדשoverlay2מטא נתונים, יומני JSON של מיכל וקבצי מסד נתונים ריקים שזה עתה אתחולו (initdb) ישירות מעל המדויקext4אוXFSחוסם היכן עוצמת הקול שנמחקה שלך ישבה לפני שניות. - בדוק תוך 5 שניות אם תהליך המכולה (
postgres,mysqld,redis-server,node,python) עדיין פועל בזיכרון (ps auxוsudo lsof +L1): אם מישהו מחק קבצים בתוך אמצעי אחסון מותקן או ביטל קישור של אמצעי אחסון אנונימי בזמן שהמכולה עדיין פועל, ליבת לינוקס שומר 100 אחוז מקבצי מסד הנתונים הלא מקושרים בחיים בדיסק כל עוד מזהה התהליך המארח של המארח (PID) מכיל מתאר קובץ פתוח (FD). אתה יכול להעתיק את הקבצים האלה ישירות החוצה/proc/<PID>/fd/או/proc/<PID>/root/עם אפס אובדן נתונים לפני שהמכולה נעצרת. - אם המכולה כבר נעצרה ועוצמת הקול נמחקה (
docker compose down -vאוdocker system prune --volumes), הקפאת דיסק מארח כותב מיד: עצור את דמון ה-Docker (sudo systemctl stop docker.socket docker.service containerd) כך שמיכלי רקע ובדיקות בריאות מפסיקים לכתוב לתוכו יומנים/var/lib/docker, ואז או טען מחדש/var/lib/docker(או השורש/מחיצה) לקריאה בלבד (sudo mount -o remount,ro /) או צלם תמונת מצב מיידית של עוצמת הקול בענן ברמת הבלוק (AWS EBS Snapshot,GCP Persistent Disk Snapshot,DigitalOcean Volume Snapshot) לפני שנוגעים במשהו. - אם אתה ב-Kubernetes (
kubectl delete pvcאוkubectl delete namespace), בדוק את ה-PeristentVolume (PV)ReclaimPolicy(kubectl get pv) מיד: - אם ה
PVהיהpersistentVolumeReclaimPolicy: Retain, הנתונים שלך לא נמחקו: הPVפשוט עבר לReleasedסטטוס ודיסק הענן שלך (EBS,Azure Disk,Ceph RBD,NFS) הוא 100 אחוז שלם. - גם אם
kubectl delete pvcתקוע בTerminating, Kubernetes מסיימים (kubernetes.io/pvc-protection) חוסם את מנהל ההתקן של ה-CSI ממחיקת האחסון הבסיסי כל עוד כל Pod עדיין מפנה לאותו PVC. אל תמחק את הפוד עד שתעתיק את הנתונים מה-Pod הפועל. - תמונה את מחיצת הבלוק הבסיסית (
dd/ddrescueמעל SSH) לדיסק חיצוני או אמצעי אחסון נפרד בענן לפני ההפעלהext4magic,extundelete, אוPhotoRec: לעולם אל תפעיל חוצבי קבצים שכותבים קבצי פלט על אותה מחיצת דיסק שממנה אתה מתאושש/var/lib/docker/volumes. - עבור מצב אשכול Kubernetes פגום או שנמחק בטעות (
kubectl delete crd/namespace), לעצורkube-apiserverולשחזר את הגרסה האחרונה שלךetcdתמונת מצב (etcdctl snapshot restore): אם האשכול מופיע בetcdנמחק בזמן שנפחי האחסון הבסיסיים בענן עדיין קיימים, ומשחזרetcdמשחזר הכלPV,PVC,Secret, וConfigMapחפצים בו זמנית.
Danger
לעולם אל תסיר את kubernetes.io/pvc-protection או kubernetes.io/pv-protection מסיים עם kubectl patch ... -p '{"metadata":{"finalizers":null}}' כאשר PVC תקוע פנימה Terminating: הגמר הזה הוא הדבר היחיד ששומר על מנהל התקן CSI בענן (aws-ebs-csi-driver, pd.csi.storage.gke.io, Longhorn, Rook-Ceph) מהנפקת חומרה DeleteVolume קריאת API להרוס את דיסק הייצור שלך. בעוד ה-PVC תקוע פנימה Terminating, הפוד עדיין פועל ועוצמת הקול עדיין מותקנת: הפעל kubectl exec או kubectl cp (או pg_dump / mysqldump) מיד כדי להציל 100 אחוז ממסד הנתונים שלך לפני שה-Pod יסתיים.
עץ ההחלטות: נמחק כרך Docker, overlay2 שכבה, או משולש PVC של Kubernetes¶
השתמש בתרשים זרימה זה כדי לבחור את הנתיב המהיר ביותר לשחזור אפס אובדן בהתבסס על אם תהליך המכולה עדיין חי, אם אמצעי האחסון היה מגובה על ידי דיסק מקומי או אחסון CSI בענן, ואיזו מערכת קבצים מארח /var/lib/docker:
flowchart TD
Start["נתוני הפקה חסרים לאחר פקודת המחיקה של Docker או Kubernetes"] --> WhichEnv{"איזו פלטפורמה ופיקוד גרמו להפסד?"}
WhichEnv -->|"Docker: מיכל עדיין פועל (קבצים לא מקושרים בתוך אמצעי אחסון/מיכל)"| ProcRescue["הצלת מתארי קבצים לא מקושרים באמצעות sudo lsof +L1 ו-/proc/PID/fd/N או /proc/PID/root/"]
WhichEnv -->|"Docker: Container Stop & Volume Deleted (compose down -v / prune --volumes)"| StopDocker["הפעל מיד: sudo systemctl stop docker.socket docker containerd"]
WhichEnv -->|"Kubernetes: kubectl מחק pvc / pv / statefulset / מרחב שמות"| K8sCheck{"האם הפוד עדיין פועל או ש-PVC תקוע בסיומה?"}
K8sCheck -->|"כן: הפוד עדיין פועל (הגמר חוסם מחיקת CSI)"| K8sExec["אל תמחק Pod -> הפעל את kubectl exec / pg_dump / tar על stdout לדיסק המקומי באופן מיידי"]
K8sCheck -->|"לא: Pod Gone -> בדוק kubectl get pv"| ReclaimCheck{"מה הייתה מדיניות PV Reclaim?"}
ReclaimCheck -->|"שמור (סטטוס PV = פורסם)"| ClearClaimRef["100% נתונים שלמים -> ערוך PV כדי להסיר spec.claimRef.uid -> התחבר מחדש ל-PVC חדש"]
ReclaimCheck -->|"מחק (ענן EBS / PD / Longhorn / Local-Path)"| CloudOrLocal{"נפח CSI בענן או דיסק מארח מקומי?"}
CloudOrLocal -->|"Cloud CSI (AWS EBS / GCP / Azure / Ceph)"| CloudSnap["בדוק את סל המיחזור של קונסולת הענן / תמונות Snapshot אוטומטיות של EBS / אשפה של Ceph RBD (rbd trash ls)"]
CloudOrLocal -->|"דיסק צומת מקומי (local-path / hostPath)"| StopDocker
StopDocker --> RemountRO["התקן מחדש מחיצת מארח לקריאה בלבד (mount -o remount,ro) או הזרם תמונת בלוק על SSH"]
RemountRO --> HostFS{"איזה מערכת קבצים מארח /var/lib/docer?"}
HostFS -->|"ext4"| Ext4Rec["השתמש ב-debugfs / ext4magic Journal Inode Rollback Transaction (-חותמת זמן)"]
HostFS -->|"XFS / Btrfs"| CarveRec["השתמש ב-Btrfs Roots / xfs_irecover / גילוף חתימות מותאם אישית עבור SQLite, Postgres Heap או InnoDB .ibd"]
שלב 1: כיצד Docker ו-Kubernetes למעשה מוחקים אמצעי אחסון בדיסק¶
לפני הפעלת פקודת שחזור כלשהי, הבן היכן הנתונים שלך חיים פיזית במארח לינוקס ובמה בעצם נגעה פקודת המחיקה:
| סוג אחסון ופקודת מחיקה | נתיב מערכת קבצים מארח ב- Linux Node | מה בעצם עשתה פקודת המחיקה | שיטת שחזור מיידית |
|---|---|---|---|
בשם Docker Volume (docker volume rm או docker compose down -v) |
/var/lib/docker/volumes/<vol_name>/_data |
ביטל את הקישור של הקבצים בפנים _data/ והסיר את ערך הספרייה מ /var/lib/docker/volumes/metadata.db (boltdb). |
עצור את דוקר מיד, עלה מחדש /var/lib/docker לקריאה בלבד, ושחזור אינודות לא מקושרות באמצעות ext4magic / debugfs או גילוף חתימה. |
** נפח דוקר אנונימי (docker run -v /var/lib/mysql + docker rm -v או docker system prune --volumes)** |
/var/lib/docker/volumes/<64-char-hex-id>/_data |
docker system prune --volumes מוחק כל כרך אנונימי ועם שם שאין לו הפניה כרגע על ידי מיכל קיים אחד לפחות. |
עצור את Docker מיד; אם היו לך מכולות אחרות עצורות שנפחן לא גזום, סמן את השאריות /var/lib/docker/volumes/*/_data תחילה תיקיות לפני גילוף בלוקים לא מוקצים. |
** שכבה לכתיבה של מיכל (docker rm <container> כאשר הנתונים נכתבו מחוץ לנפח)** |
/var/lib/docker/overlay2/<layer-id>/diff/ |
ביטל את הקישור העליון של המכולה diff/ ספרייה בתוך overlay2 מנהל התקן אחסון. |
עצור את Docker מיד ושחזר את עץ הספריות הלא מקושר מה- ext4 יומן או XFS בלוקים. |
Docker Desktop ב-macOS או Windows (docker system prune --volumes) |
בתוך תמונת דיסק של מכונה וירטואלית אחת: -/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw (macOS) או %LocalAppData%\Docker\wsl\disk\docker_data.vhdx (Windows WSL2). |
נשלח unlink() בתוך ה-Linux VM, ואם discard/TRIM פעיל ב Docker.raw / docker_data.vhdx, נקבו חורים דלילים בקובץ המארח. |
צא מ-Docker Desktop תוך 5 שניות, העתק Docker.raw או docker_data.vhdx לכונן חיצוני, ולהפעיל ext4magic / PhotoRec כנגד תמונת הדיסק הוירטואלית. |
Kubernetes PVC עם Delete ReclaimPolicy על Ceph RBD (Rook-Ceph) או לונגהורן |
Ceph OSD בריכת (rbd) או /var/lib/longhorn/replicas/. |
אם csi-rbdplugin יש trash מופעל (rbd trash), תמונת RBD מועברת לפח האשפה של Ceph; אחרת בלוקים אינם ממופים. |
רוץ rbd trash ls --pool <pool> בתוך ה rook-ceph-tools תרמיל ולשחזר עם rbd trash restore. |
שלב 2: הצלת קבצי מסד נתונים פתוחים ממיכל שעדיין פועל (/proc/<pid>/fd/)¶
רגע: האם המכולה עדיין פועלת עכשיו?
לעתים קרובות, מהנדס מפעיל סקריפט העברת יישומים, עבודת cron ניקוי או מדריך rm -rf /var/lib/postgresql/data/* או rm /app/data/production.sqlite3 בתוך מיכל פועל, או מוחק את תיקיית ה-bind-mount המארח הבסיסית /opt/app/data בעוד המיכל עצמו (postgres, mysqld, mariadbd, redis-server, mongod, gunicorn, node) עדיין פועל.
בלינוקס, קובץ לא נמחק מהדיסק כאשר rm או unlink() נקרא. בלוקי הדיסק והאינוד שלו נשארים 100 אחוז הוקצו וקריא עד לתהליך האחרון המחזיק מתאר קובץ פתוח (FD) לאינוד זה סוגר אותו או יוצא.
שלב 1: מצא את מזהה התהליך המארח (PID) של תהליך המכולה¶
בצומת המארח של לינוקס (לא בתוך הקונטיינר), מצא את המארח PID של מסד הנתונים או תהליך הבקשה שלך:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
mysqld 18492 999 14u REG 259,1 482344960 0 1849201 /var/lib/mysql/app_prod/users.ibd (deleted)
mysqld 18492 999 15u REG 259,1 125829120 0 1849202 /var/lib/mysql/app_prod/orders.ibd (deleted)
mysqld 18492 999 16u REG 259,1 79691776 0 1849190 /var/lib/mysql/ibdata1 (deleted)
python3 22104 1000 4u REG 259,1 89128960 0 3102944 /data/production.sqlite3 (deleted)
NLINK: כתוב 0, ושם הקובץ מסתיים ב-(deleted). הקובץ נעלם לחלוטין ls /var/lib/docker/volumes/..., ובכל זאת כל בייט בודד (482 MB ב users.ibd, 89 MB ב production.sqlite3) עדיין חי בפנים /proc/<PID>/fd/<FD>.
שלב 2: העתק את קבצי מסד הנתונים הלא מקושרים ישר החוצה /proc/<PID>/fd/¶
אל תפסיק או תפעיל מחדש את המיכל. בזמן שהתהליך עדיין פועל, העתק את מתארי הקובץ הגולמי ישירות לתיקיה בטוחה במארח שלך:
sudo mkdir -p /root/proc_emergency_rescue
# Example 1: Rescuing an unlinked SQLite3 database (PID 22104, FD 4)
sudo cp /proc/22104/fd/4 /root/proc_emergency_rescue/production.sqlite3
# Check if PID 22104 also holds the -wal file open (e.g. FD 5) and copy it too:
sudo cp /proc/22104/fd/5 /root/proc_emergency_rescue/production.sqlite3-wal
# Example 2: Automatically rescuing ALL open (deleted) MySQL/Postgres files for PID 18492
for fd in /proc/18492/fd/*; do
target=$(sudo readlink "$fd" 2>/dev/null)
if echo "$target" | grep -q "(deleted)"; then
fd_num=$(basename "$fd")
clean_name=$(echo "$target" | sed 's/ (deleted)//; s/\//_/g')
echo "Rescuing FD $fd_num -> $clean_name"
sudo cp "$fd" "/root/proc_emergency_rescue/${fd_num}${clean_name}"
fi
done
שלב 3: אפילו טוב יותר: הפעל dump לוגי חי (pg_dump / mysqldump / .backup) לפני שהמכל סוגר את ה-FDs¶
אם postgres או mysqld עדיין פועל עם קבצי הנתונים שלו פתוחים בזיכרון ו /proc/<PID>/fd/, נסה להריץ תחילה dump לוגי חי מעל שקע ה-Unix או חיבור TCP הקיים:
# If the database engine can still read its open file descriptors:
docker exec <container_name> pg_dumpall -U postgres > /root/proc_emergency_rescue/live_dump.sql
# Or for MySQL:
docker exec <container_name> mysqldump -u root -p --all-databases --single-transaction > /root/proc_emergency_rescue/live_mysql.sql
.1, .2 לפלח קבצים על פני תהליכי עבודה באופן דינמי, כך pg_dump עלול להיכשל בטבלאות לא מאוחסנות במטמון; שילוב שאילתת SQL חיה עם העתקת כל פתיחה /proc/<pid>/fd/* על פני הכל postgres PIDs backend של ילדים שומר את נתוני ערימת הטבלה המקסימלית האפשרית.)
שלב 3: שחזור אמצעי אחסון של Docker שנמחק מופעל ext4 או XFS לאחר שהמיכל נעצר¶
מה אם אתה רץ docker compose down -v או docker system prune --volumes, אז המכולה כבר נעצרה והכל /proc/<pid>/fd/ המתארים סגורים? עכשיו אתה במרוץ נגד כתיבת דיסק ברקע על מארח לינוקס.
שלב 1: הקפיא את מערכת הקבצים המארח של לינוקס תוך 10 שניות¶
- עצור מיד את Docker, containerd, kubelet ו-cron כך שאף מיכל, בדיקת בריאות או מסובב יומנים לא כותב בית נוסף ל
/var/lib/docker: - בדוק איזה מכשיר חסימה ומערכת קבצים מחזיקים
/var/lib/docker: - התקן מחדש את המחיצה לקריאה בלבד (או הזרמת תמונת מחיצה גולמית על גבי SSH למחשב אחר):
- אם
/var/lib/dockerנמצא על מחיצה ייעודית משלו או אמצעי אחסון LVM (לדוגמה/dev/nvme0n1p2או/dev/mapper/vg0-docker), התקן אותו מיד לקריאה בלבד: - אם
/var/lib/dockerנמצא על השורש/מחיצה (/), נסה לאלץ את מחיצת השורש לקריאה בלבד באמצעות הטריגר של הליבה Magic SysRq (echo u | sudo tee /proc/sysrq-trigger) אוsudo mount -o remount,ro /. - אם אתה נמצא ב-VPS בענן (AWS EC2, GCP, DigitalOcean, Hetzner, Linode): עבור מייד לקונסולת האינטרנט בענן שלך ולחץ על צור תמונת מצב בנפח החסימה של השרת (או הזרם את התקן החסימה הגולמית דרך SSH לשרת שני:
sudo dd if=/dev/nvme0n1p1 bs=4M status=progress | gzip -1 | ssh user@backup-server "cat > /mnt/storage/docker_host_raw.img.gz").
שלב 2: בדוק אם הנתונים שלך עדיין נמצאים בנפח אחר לא גזום או overlay2 שכבה¶
לפני גילוף בלוקים של דיסקים לא מוקצים, ודא שמסד הנתונים שלך לא היה מאוחסן בפועל ב-bind mount או באמצעי אחסון בעל שם אחר ששרד:
# Search the entire /var/lib/docker tree read-only for any surviving database files:
sudo find /var/lib/docker -name "PG_VERSION" -o -name "ibdata1" -o -name "*.sqlite*" -o -name "*.db" -o -name "dump.rdb" -o -name "WiredTiger" 2>/dev/null
docker volume rm app_db_data, רק כדי לגלות עם find /var/lib/docker זאת docker-compose.yml יצר למעשה projectname_app_db_data (שעדיין שלם ב-100 אחוז בדיסק) בעוד app_db_data היה כרך ישן שאינו בשימוש מלפני שישה חודשים.
שלב 3: שחזור ספריות אמצעי אחסון לא מקושרות של Docker ext4 באמצעות ext4 יומן (ext4magic ו debugfs)¶
מתי docker volume rm מוחק /var/lib/docker/volumes/<vol_name>/_data על א ext4 מערכת קבצים, ext4 מאפס את מצביעי הבלוק הישירים (i_block / שורש עץ במידה) בטבלת האינדה החיה. עם זאת, הext4 יומן (inode <8>, בדרך כלל 128 MB ל 1024 MB חיץ טבעות מעגלי) עדיין מחזיק עותקים היסטוריים של טבלאות האינוד המדויקות ובלוקי הספריות ממש לפני docker compose down -v הוצא להורג.
+-------------------------------------------------------------------------+
| HOW ext4magic RECOVERS A DELETED DOCKER VOLUME FROM THE EXT4 JOURNAL |
| |
| Live Inode Table on Disk (After docker volume rm): |
| Inode #918402 (users.ibd): [Size = 0, Extent Pointers = ZEROED] |
| |
| Ext4 Journal Ring Buffer (Inode <8> on Disk): |
| Transaction #41902 (10 mins ago): |
| Inode #918402 (users.ibd): [Size = 482MB, Extents = Blocks 9000..9999]|
| |
| -> ext4magic reads the old Inode Copy from Journal Transaction #41902 |
| and extracts Blocks 9000..9999 directly to your rescue drive. |
+-------------------------------------------------------------------------+
רוץ ext4magic כנגד המחיצה לקריאה בלבד (או ה .img עותק תמונת מצב בשרת שני), תוך ציון חותמת זמן (-a) מ5 דקות לפני רצתם docker compose down -v או docker system prune --volumes:
# Install ext4magic on your rescue machine (never on the affected partition)
sudo apt-get install -y ext4magic e2fsprogs
# Dump the ext4 journal from the frozen partition / image to a file in RAM (/dev/shm)
sudo debugfs -R "dump <8> /dev/shm/ext4_journal.copy" /dev/nvme0n1p1
# Recover all files deleted under var/lib/docker/volumes after (Current Time - 15 minutes)
sudo mkdir -p /mnt/external_rescue/docker_recovered
sudo ext4magic /dev/nvme0n1p1 \
-j /dev/shm/ext4_journal.copy \
-f var/lib/docker/volumes \
-a $(date -d "-15 minutes" +%s) \
-r -d /mnt/external_rescue/docker_recovered
-j /dev/shm/ext4_journal.copy: קורא את תמונת היומן ששמרת ב-RAM מיד לאחר הפסקת Docker.
- -f var/lib/docker/volumes: ממקד לעץ ספריות הכרכים המדויק של Docker (הערה: השמט את הקוד המוביל / ב ext4magic נתיבים יחסיים).
- -a $(date -d "-15 minutes" +%s): מספר ext4magic לשחזר את עץ הספריות באמצעות עותקי inode שתקפו לפני 15 דקות (ממש לפני המחיקה בשוגג).
- -r: משחזר ספריות שלמות שבהן לא הוחלפו בלוקים; אם -r מפספס קבצים שהוחלפו חלקית, הפעל מעבר שני להחליף -r עם -m (גילוף קסם + מצב היברידי יומן).
שלב 4: גילוף קבצי SQLite, PostgreSQL או MySQL InnoDB גולמיים כאשר היומן עטוף (XFS או ext4)¶
Warning
למה XFS אינו תומך ext4magic ודורש ביטול קריאה בלבד מיידית: לא דומה ext4, שכותבת עותקי אינוד מלאים של 256 בתים ביומן שלו, XFS רושם דלתות של כוונת מטא נתונים ומשתמש חוזר באגרסיביות בעצי האינוד המשוחררים (agi). אם /var/lib/docker יושב על א XFS מחיצה (ברירת מחדל ב-RHEL, Rocky Linux, AlmaLinux ואמזון לינוקס), ביטול הרכבה /var/lib/docker או עלייה מחדש / קריאה בלבד תוך שניות הוא השלב החשוב ביותר לפני הגילוף.
אם המארח משתמש בXFS או אם ה ext4 יומן כבר עטוף על מצביעי האינודה, השתמש בחתימה ובגילוף מבנה כנגד תמונת הדיסק הגולמית (docker_host_raw.img):
- עבור מסדי נתונים של SQLite3 (
.sqlite,.db- למשל, Vaultwarden, Nextcloud, Home Assistant, Gitea, Grafana): כל מסד נתונים של SQLite3 מתחיל עם כותרת ASCII של 16 בתים שאין לטעות בה בבתים 0 של הדף הראשון של 4 קילובייט:53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00("SQLite format 3\0"), ומאחסן את גודל עמוד מסד הנתונים המדויק (Bytes 16..17, בדרך כלל4096) וגודל מסד הנתונים הכולל בדפים (Bytes 28..31, מספר שלם של 32 סיביות גדול) ממש בתוך אותה כותרת. - רוץ
PhotoRecעם[File Opt]->[x] sqliteמופעלת, או סרוק את המחיצה ישירות באמצעותgrep -ab "SQLite format 3"כדי למצוא את היסט הבתים המדויק של קובץ SQLite שנמחק ולחלץ אותו באמצעותוdd:לאחר החילוץ, הרץ# Find the exact byte offsets of every "SQLite format 3" header on the partition: sudo grep -ab "SQLite format 3" /dev/nvme0n1p1sqlite3 carved.db ".recover" | sqlite3 repaired.dbלשחזר כל דף עלה עץ B שלם.
Tip
איך לחשב את המדויק dd גודל בתים של קובץ SQLite3 לא מקושר מהכותרת שלו: פעם אחת grep -ab "SQLite format 3" נותן לך את היסט הבתים ההתחלתי OFFSET של מסד הנתונים של SQLite שנמחק, קרא בתים 16..17 (גודל עמוד uint16 big-endian, למשל, 0x1000 = 4096 בתים) ובייטים 28..31 (Uint32 big-endian Page Count, למשל, 25000 דפים) באמצעות hexdump -C -s OFFSET -n 32. הכפלה Page Size x Page Count נותן לך את אורך הבתים המדויק לעבור אליו dd (iflag=skip_bytes,count_bytes) כאשר הקובץ רציף בדיסק.
- עבור MySQL / MariaDB InnoDB (
.ibdקבצי טבלה): כל InnoDB.ibdהטבלה מורכבת מרצף16 KB(16,384byte) דפים המכילים אתFIL_PAGE_INDEX(0x45BF) הכותרת והטבלה הייחודיתspace_id. השתמש ב-Percona / TwinDBundrop-for-innodb(stream_parser+c_parser) ערכת כלים לסריקה/dev/nvme0n1p1עבור כולם16 KBאינדקס דפי InnoDB ותשליך כל שורה ישירות לקבצי TSV/SQL לייבוא מחדש. - עבור קבצי PostgreSQL Heap (
$PGDATA/base/<db_oid>/<relfilenode>): PostgreSQL מאחסן כל שולחן כרצף8 KB(8,192byte) ערימת דפים המכיליםPageHeaderData(pd_lower,pd_upper,pd_special). השתמש בpg_filedumpאוpglazarus/pduלסריקת אזורי דיסק לא מוקצים עבורם8 KBדפים התואמים את פריסת העמודות של הטבלה שלך (HeapTupleHeaderData) ובנה מחדש את השורות.
שלב 4: Kubernetes PVC, PV, ו etcd שחזור חירום של תמונת מצב¶
ב-Kubernetes (EKS, GKE, AKS, k3s, RKE2, kubeadm, OpenShift), מחיקת בטעות PersistentVolumeClaim (kubectl delete pvc), StatefulSet או מרחב שמות שלם (kubectl delete ns prod) עוקב אחר ארכיטקטורה שונה מאוד מזו של Docker העצמאי.
תרחיש א': ה-PVC מראה Terminating (מציל הגמר)¶
הרץ:
אם הSTATUS בעמודה כתוב Terminating, נשמו לרווחה: הנתונים שלך עדיין לא נמחקו.
- מַדוּעַ? כל PVC של Kubernetes שנוצר מאז Kubernetes 1.9 כולל אוטומטית finalizers: [kubernetes.io/pvc-protection].
- כל עוד Pod עדיין מתקין את ה-PVC הזה, בקר Kubernetes מסרב להשלים את מחיקת ה-PVC ולעולם לא קורא לדרייבר ה-CSI DeleteVolume RPC.
- פעולה מיידית: האם לא מחק או הפעל מחדש את הפוד, ועשה לא מתקן את הגמר. העתק מיד את כל הנתונים מה-Pod הפועל למחשב המקומי שלך או לדלי S3:
# Stream a compressed tar backup or pg_dump out of the still-running pod immediately:
kubectl exec -n <namespace> <pod-name> -- pg_dumpall -U postgres > ./rescued_k8s_db.sql
# Or tar an entire mounted volume directory out over stdout:
kubectl exec -n <namespace> <pod-name> -- tar czf - /var/lib/postgresql/data > ./rescued_pvc_files.tar.gz
תרחיש ב': ה-PVC נמחק, ו kubectl get pv מציג את ה-PeristentVolume ב Released מדינה (ReclaimPolicy: Retain)¶
הרץ:
אם הנפח המתמשך שלך (pv-prod-postgres) עדיין מופיע עם STATUS: Released (בגלל שהשימוש ב- StorageClass שלו reclaimPolicy: Retain), 100 אחוז מהנתונים שלך עדיין לא נגועים בדיסק הבסיסי. עם זאת, Kubernetes מסרב לתת ל-PVC חדש להיקשר ל-a Released PV כי ה-PV עדיין מכיל א spec.claimRef מצביע על ה-PVC הישנים שנמחקו UID.
איך מכינים א Released PV Available שוב תוך 10 שניות עם אפס אובדן נתונים:
1. ערוך את האובייקט PersistentVolume ומחק את ה- spec.claimRef חסום:
kubectl get pv שוב: הסטטוס משתנה מיד מReleased עד Available.
3. צור מחדש את שלך PersistentVolumeClaim (מפרט volumeName: <your-pv-name> והתאמה של קיבולת/storageClassName). זה ייקשר ל-PV הקיים באופן מיידי עם כל הקבצים שלמים.
תרחיש C: שחזור מצב אשכול Kubernetes שנמחק מ-an etcd תמונת מצב (etcdctl snapshot restore)¶
מה אם מישהו רץ kubectl delete namespace prod או helm uninstall ומחק 200 מניפסטים Kubernetes, סודות, ConfigMaps והגדרות PV בניהול עצמי kubeadm, k3s, או RKE2 מטוס שליטה?
- אתר את האחרון שלך
etcdתמונת מצב (כברירת מחדל ב/var/lib/rancher/k3s/server/db/snapshots/,/var/lib/rancher/rke2/server/db/snapshots/, או המתוכנן שלך/var/backups/etcd/snapshot.db). - אמת את תקינות תמונת המצב לפני נגיעה באשכול החי:
- עצור
kube-apiserverוetcdבצמתים במישור הבקרה: - ב-
kubeadm(תרמילים סטטיים): הזז/etc/kubernetes/manifests/kube-apiserver.yamlו/etc/kubernetes/manifests/etcd.yamlזמנית ל/root/manifests_hold/כךkubeletעוצר את שני המיכלים בצורה נקייה, ואז מגבה/var/lib/etcdל/var/lib/etcd.bak. - ב-
k3s: רוץsudo systemctl stop k3sוsudo k3s server --cluster-reset --cluster-reset-restore-path=/path/to/snapshot. - שחזר את
etcdספריית הנתונים פועלתkubeadm: - זז
etcd.yamlוkube-apiserver.yamlחזרה לתוך/etc/kubernetes/manifests/. תוך 30 שניות,kube-apiserverמתחבר מחדש למשוחזרetcdstore וכל אובייקט Namespace, Secret, ConfigMap ו-PersistentVolume שנמחק מופיעים שוב.
שלב 5: הקשחת נפחי Docker ו-Kubernetes מפני מחיקה בשוגג¶
לאחר שחזור מסד הנתונים של הייצור שלך, יישם את ארבעת מעקות הבטיחות הארכיטקטוניים האלה כך ששגיאת הקלדה אחת של CLI לא תוכל למחוק שוב כרך חי:
- שנה כל ייצור Kubernetes
StorageClassמreclaimPolicy: DeleteלreclaimPolicy: Retain: כברירת מחדל, StorageClasses מובנות בענן (gp2,gp3,standard-rwo) ברירת מחדל לreclaimPolicy: Delete, כלומר מחיקת PVC הורסת את דיסק הענן. צור אStorageClassעםreclaimPolicy: Retain(או תיקון PVs קיימים עםkubectl patch pv <pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}') כך שמחיקת PVC או מרחב שמות לעולם לא מוחקת את נפח הבלוק הבסיסי. - הפעל את סל המיחזור של AWS EBS / לוחות זמנים של תמונת מצב של GCP / Velero עם צילומי CSI: הפעלת סל המיחזור של AWS EBS שומרת על כל אמצעי אחסון EBS שנמחק למשך 7 עד 30 ימים גם אם מנהל ההתקן של CSI מתקשר
DeleteVolume. - לעולם אל תשתמש
docker system prune --volumesבסקריפטים אוטומטיים של ניקוי או ברצי CI/CD: אם מיכל מסד נתונים ייצור קורס לזמן קצר (Exited (1)) ברגע המדויק של עבודת cron פועלתdocker system prune -a --volumes -f, Docker מחשיב את הכרכים האנונימיים שלה "לא בשימוש" ומוחק אותם לצמיתות. רצועה--volumesמכל תסריטי הניקוי. - השתמש ברכיבי חיבור מארח מפורשים (
/srv/prod_data/postgres:/var/lib/postgresql/data) או מסדי נתונים מנוהלים חיצוניים לעומסי עבודה של ייצור סטטיסטיים: לא דומה/var/lib/docker/volumes/, מארח ספריות חיבור לחיבור בחוץ/var/lib/docker/מעולם לא נגעו בהםdocker compose down -v,docker volume rm, אוdocker system prune --volumes.
מספרי חירום אזוריים ופרוטוקולי סוכנות¶
כאשר מחיקת מיכל או אחסון Kubernetes משפיעה על הפעילות הקלינית של בית החולים, על שליחת בטיחות הציבור או על נתונים אישיים מוסדרים, הסלמה מיד:
- ארצות הברית וקנדה: חייגו
911אם כשל באשכול מיכל משבית ניטור מטופל קליני, מערכות EHR או שיגור חירום. דווח על מחיקת תשתית מכולה זדונית או תקריות סייבר ל-CISA (1-844-Say-CISA/cisa.gov/report) או המרכז הקנדי לאבטחת סייבר (1-833-CYBER-88). - בריטניה: חייגו
999לאיומי חיים או תשתית NHS קריטית. תחת ה-GDPR של בריטניה, הרס קבוע או אובדן זמינות של נתונים אישיים ללא גיבוי הניתן לשחזור מחייב הערכה של הודעת הפרה של 72 שעות ל-ICO (0303 123 1113). - האיחוד האירופי: חייגו
112בכל המדינות החברות באיחוד האירופי. ישויות תחת הדירקטיבה NIS2 חייבות להגיש אזהרה מוקדמת ל-CSIRT הלאומי שלהם בתוך 24 שעות מהפסקת שירות חמורה, ואובדן נתונים אישיים לצמיתות גורם לדיווח של GDPR סעיף 33 תוך 72 שעות. - אוסטרליה וניו זילנד: חייגו
000באוסטרליה או111בניו זילנד; דווח על תקריות תשתית קריטיות ל-ACSC (1300 CYBER1). - הודו ואסיה-פסיפיק: חייגו
112בהודו לתגובת חירום; דווח על אירועי אבטחה בענן או מיכל ל-CERT-In (incident@cert-in.org.in) בתוך חלון החובה של 6 שעות.
שאלות נפוצות¶
עושה docker compose down -v מחק מארח חיבור mounts (./data:/var/lib/mysql) או רק כרכים Named and Anonymous Docker?¶
`docker compose down -v` מוחק רק כרכים בעלי שם שהוצהר ב- `volumes:` סעיף של `docker-compose.yml` וכרכים אנונימיים המצורפים למכולות; זה לעולם לא מוחק קבצים בתוך חיבור מארח (כגון `- /opt/mysql_data:/var/lib/mysql` או `- ./postgres_data:/var/lib/postgresql/data`). אם קובץ הכתיבה שלך השתמש בנתיב מארח שמתחיל ב `/` או `./`, בדוק את התיקיה במארח עכשיו: הקבצים שלך עדיין שלמים ב-100 אחוז.
למה עשה docker system prune --volumes למחוק את נפח מסד הנתונים שלי כאשר עצרתי את המיכל רק ל-2 דקות כדי לעדכן משתנה סביבה?¶
המתן בזהירות להבחנה בין `docker stop` ו `docker rm`: אם מיכל הוא רק `Stopped / Exited` (נראה ב `docker ps -a`), `docker system prune --volumes` עושה לא מחק את אמצעי האחסון שלו מכיוון שהמכל שנעצר עדיין מפנה אליהם. עם זאת, אם רצתם `docker rm
האם אוכל לשחזר נפח Docker שנמחק בתוך Docker Desktop ב-Mac (Apple Silicon / Intel) או Windows (WSL2)?¶
כן, אם תעזוב את Docker Desktop מיד כדי שהמכונה הוירטואלית תפסיק לפעול `fstrim` כנגד הדיסק הוירטואלי. ב-macOS, Docker מאחסן את כל אמצעי האחסון של לינוקס בפנים `-/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw`; ב-Windows WSL2, בפנים `%LocalAppData%\Docker\wsl\disk\docker_data.vhdx`. תעתיק את זה `.raw` או `.vhdx` קובץ ל-SSD חיצוני מיד, צרף אותו לקריאה בלבד בלינוקס (באמצעות `losetup -Pr` עבור `.raw` או `qemu-nbd -r` עבור `.vhdx`), ורוץ `ext4magic` או `PhotoRec` נגד הוירטואלי `ext4` מחיצה בפנים.
מה אם מחקתי Kubernetes StatefulSet עם kubectl delete statefulset postgres? זה מחק גם את ה-PVC שלי?¶
לא. כברירת מחדל ב-Kubernetes (אלא אם כן `persistentVolumeClaimRetentionPolicy.whenDeleted: Delete` הוגדר במפורש ב-Kubernetes 1.27+), פועל `kubectl delete statefulset` מוחק את בקר ה-StatefulSet וה-Pods שלו, עוזב את הכל `PersistentVolumeClaims` (`data-postgres-0`, `data-postgres-1`) והנתונים הבסיסיים שלהם 100 אחוז שלמים. פשוט החל מחדש את שלך `StatefulSet` מניפסט YAML עם אותו שם ו `volumeClaimTemplates`, וה-Pods החדשים יתחברו אוטומטית מחדש לקיים `data-postgres-0` PVCs.
כיצד אוכל לגשת לקבצים בתוך Docker overlay2 ספרייה כאשר המיכל מסרב להתחיל (CrashLoopBackOff / Exited (1))?¶
אל תמחק את המכולה שהתרסקה. כל עוד המיכל שנעצר עדיין קיים ב `docker ps -a`, השכבה הניתנת לכתיבה ורכיבי הנפח שלו שלמים לחלוטין בדיסק. אתה יכול להעתיק קבצים ישירות מתוך המכולה שהופסקה באמצעות `docker cp
מה אם מישהו מחק Kubernetes Namespace (kubectl delete ns prod) ולכל PVC היה reclaimPolicy: Delete ב-AWS EBS או GCP?¶
אם מנהל התקן CSI בענן (`ebs.csi.aws.com` או `pd.csi.storage.gke.io`) כבר בוצע `DeleteVolume` כי `reclaimPolicy` היה `Delete`, בדוק מיד שלוש רשתות ביטחון ברמת הענן: (1) סמן את **סל המיחזור AWS עבור נפחי EBS** בקונסולת AWS EC2 (אם כלל שמירה היה פעיל בחשבון/תגיות, אמצעי האחסון של EBS שנמחק יושב בסל המיחזור וניתן לשחזר אותו בלחיצה אחת); (2) בדוק את **AWS Backup / DLM / GCP Snapshot Schedules** עבור תמונת המצב האוטומטית האחרונה של עוצמת הקול; ו (3) בדוק אם מסד הנתונים שלך הזרם WAL/binlogs (`WAL-G`, `pgBackRest`, `Litestream`) לדלי S3/GCS.
מדריכים קשורים¶
- דיסק שרת מלא ב-100% (0 בתים פנויים): התנפחות יומן WAL של מסד הנתונים, עץ B פגום ושחזור שטח אפס
- 'rm -rf' או 'Shift+Delete' בשוגג ב-Linux, macOS או Windows: הרכבה מיידית לקריאה בלבד וגילוף אינוד
- מכונה וירטואלית VMDK, VHDX, ו-qcow2 שחיתות שרשרת צילומי מצב והצלת hypervisor
- התחייבות Git בשוגג של מפתחות AWS, קובץ '.env' או מפתח SSH פרטי לריפו ציבורי של GitHub
- משבר אירוח אתרים, הגירה ושחזור גיבוי
- גיבוי מחשבים, אסטרטגיית 3-2-1, והתאוששות מאסון
- מספרי חירום לפי מדינה
מקורות והדרכה רשמית¶
- תיעוד רשמי של Kubernetes (
kubernetes.io/ Cloud Native Computing Foundation): הגנה על אובייקט אחסון בשימוש (kubernetes.io/pvc-protectionמסיימים), Reclaiming PersistentVolumes (RetainלעומתDelete), והפעלהetcdאשכולות עבור Kubernetes (etcdctl snapshot restore). - Docker Inc. (
docs.docker.com): נהל נתונים ב-Docker: נפחים, חיבורי חיבור,overlay2ארכיטקטורת מנהלי התקן לאחסון, והפניה לגזם. - ארגון ליבת לינוקס (
kernel.org): ה/procמערכת קבצים (procfsפתח את שחזור מתאר קבצים באמצעות/proc/<pid>/fd/) ומפרט יומן Ext4. ext4magicתיעוד הפרויקט (ext4magic.sourceforge.net): שחזור עסקאות אינודות ויומן משפטי במערכות קבצים Ext3/Ext4.- המכון הלאומי לתקנים וטכנולוגיה (
NIST) (ארצות הברית): פרסום מיוחד 800-190: Application Container Security Guide & Incident Recovery.