Skip to content

Volume de produción de Docker ou Kubernetes eliminado: rescatando docker system prune --volumes, overlay2 Inodos, e etcd Instantáneas

Os números de emerxencia varían segundo o país. Esta páxina usa 911, o número dos Estados Unidos e Canadá. Moitos outros países usan 112, 999 ou outro número. Busca o número do teu país.

Correndo docker compose down -v, docker system prune -a --volumes, docker volume rm, ou kubectl delete pvc na pestana do terminal incorrecto en produción é unha das formas máis rápidas de borrar un volume de base de datos PostgreSQL, MySQL, MariaDB, Redis, MongoDB ou SQLite en directo. A diferenza das instantáneas de máquinas virtuais na nube que se moven a unha papeleira de reciclaxe de 7 días, o controlador de volume local de Docker (/var/lib/docker/volumes/<name>/_data) e Kubernetes local-path / hostPath os provedores emiten inmediatamente o estándar POSIX unlink() e rmdir() chama directamente ao sistema de ficheiros host Linux subxacente (ext4, XFS, ou Btrfs). Cada escritura que se produza nese servidor Linux despois de que remate o comando pode sobrescribir os bloques de base de datos liberados no disco. Se o disco do servidor se encheu ao 100 por cento (0 bytes free) antes de que alguén correse docker system prune --volumes en pánico, consultar o disco do servidor está cheo ao 100 %, o rexistro de WAL da base de datos está inflado e a recuperación de espazo cero; para a eliminación de ficheiros Linux fóra dos contedores, consulte rm -rf accidental ou Shift-Delete en ext4, XFS, APFS e NTFS: montaxe de só lectura e tallado de inodos e Corrupción da cadea de instantáneas de máquinas virtuales VMDK, VHDX e qcow2 e rescate do hipervisor. Se esta interrupción da produción afecta á atención do paciente hospitalario, ao envío de emerxencias ou aos sistemas de seguridade dos servizos públicos, chame ao número de emerxencia local (911 nos Estados Unidos e Canadá, 112 en toda a Unión Europea, 999 no Reino Unido) ou consulte o noso directorio de números de emerxencia.

Fai isto agora

  1. ** NON correr docker compose up -d, systemctl restart docker, ou volver a implantar o pod de Kubernetes**: ao volver crear o contedor ou reiniciar o daemon Docker, escribe megabytes de novos overlay2 metadatos, rexistros JSON do contedor e ficheiros de base de datos baleiros recén inicializados (initdb) directamente sobre o exacto ext4 ou XFS bloques nos que o teu volume eliminado estaba hai segundos.
  2. ** Comprobe en 5 segundos se o proceso do recipiente (postgres, mysqld, redis-server, node, python) aínda está en execución na memoria (ps aux e sudo lsof +L1)**: se alguén eliminou ficheiros dentro dun volume montado ou desvinculou un volume anónimo mentres o contedor aínda está en execución, o núcleo de Linux mantén vivos no disco o 100 por cento dos ficheiros de base de datos desvinculados mentres o ID de proceso do host do contenedor (PID) contén un descritor de ficheiro aberto (FD). Podes copiar eses ficheiros directamente fóra de /proc/<PID>/fd/ ou /proc/<PID>/root/ sen perda de datos antes de que o contedor pare.
  3. Se o contedor xa está parado e o volume foi eliminado (docker compose down -v ou docker system prune --volumes), conxela o disco host escribe inmediatamente: Detén o daemon Docker (sudo systemctl stop docker.socket docker.service containerd) polo que os contedores en segundo plano e as comprobacións de saúde deixan de escribir rexistros /var/lib/docker, entón ou remonta /var/lib/docker (ou a raíz / partición) só lectura (sudo mount -o remount,ro /) ou tome unha instantánea inmediata do volume da nube a nivel de bloque (AWS EBS Snapshot, GCP Persistent Disk Snapshot, DigitalOcean Volume Snapshot) antes de tocar nada.
  4. Se estás en Kubernetes (kubectl delete pvc ou kubectl delete namespace), verifique o PersistentVolume (PV) ReclaimPolicy (kubectl get pv) inmediatamente:
  5. Se o PV tiña persistentVolumeReclaimPolicy: Retain, os teus datos non se eliminan: o PV simplemente mudouse a Released estado e o teu disco na nube (EBS, Azure Disk, Ceph RBD, NFS) está 100 por cento intacto.
  6. Aínda que kubectl delete pvc está atrapado en Terminating, Kubernetes Finalizadores (kubernetes.io/pvc-protection) impide que o controlador CSI elimine o almacenamento subxacente sempre que algún Pod siga facendo referencia a ese PVC. Non elimine o Pod ata que copie os datos do Pod en execución.
  7. Imaxe da partición do bloque subxacente (dd / ddrescue a través de SSH) a un disco externo ou a un volume de nube separado antes de executalo ext4magic, extundelete, ou PhotoRec: Nunca execute os esculpidores de ficheiros que escriban ficheiros de saída na mesma partición de disco da que se está a recuperar /var/lib/docker/volumes.
  8. Para o estado do clúster de Kubernetes corrupto ou borrado accidentalmente (kubectl delete crd / namespace), parar kube-apiserver e restaura o teu último etcd instantánea (etcdctl snapshot restore): se o clúster está en etcd borrouse mentres aínda existen os volumes de almacenamento na nube subxacentes, restaurando etcd recupera todo PV, PVC, Secret, e ConfigMap obxectos simultaneamente.

Danger

Nunca retire o kubernetes.io/pvc-protection ou kubernetes.io/pv-protection finalizador con kubectl patch ... -p '{"metadata":{"finalizers":null}}' cando un PVC está pegado Terminating: Ese finalizador é o único que mantén o controlador CSI da nube (aws-ebs-csi-driver, pd.csi.storage.gke.io, Longhorn, Rook-Ceph) de emitir un hardware DeleteVolume Chamada á API para destruír o teu disco de produción. Mentres o PVC está pegado Terminating, o Pod segue funcionando e o volume aínda está montado: executa kubectl exec ou kubectl cp (ou pg_dump / mysqldump) inmediatamente para rescatar o 100 por cento da súa base de datos antes de que finalice o Pod.


Árbore de decisións: volume de Docker eliminado, overlay2 capa ou triaxe de PVC de Kubernetes

Use este diagrama de fluxo para escoller a ruta de recuperación máis rápida sen perdas cero en función de se o proceso do contedor aínda está activo, se o volume estaba apoiado por un disco local ou un almacenamento CSI na nube e o sistema de ficheiros que hospeda. /var/lib/docker:

flowchart TD
    Start["Faltan datos de produción despois do comando Eliminar de Docker ou Kubernetes"] --> WhichEnv{"Que plataforma e comando provocaron a perda?"}

    WhichEnv -->|"Docker: o contedor segue en execución (ficheiros desvinculados dentro do volume/contedor)"| ProcRescue["Rescatar os descritores de ficheiros desvinculados abertos mediante sudo lsof +L1 e /proc/PID/fd/N ou /proc/PID/root/"]

    WhichEnv -->|"Docker: Contedor detido e volume eliminado (compor -v / prune --volumes)"| StopDocker["Executar inmediatamente: sudo systemctl stop docker.socket docker containerd"]

    WhichEnv -->|"Kubernetes: kubectl delete pvc / pv / statefulset / namespace"| K8sCheck{"A vaina segue funcionando ou está o PVC atascado ao finalizar?"}

    K8sCheck -->|"Si: o pod segue en execución (eliminar CSI bloqueando o finalizador)"| K8sExec["NON elimine Pod -> Executa kubectl exec / pg_dump / tar sobre stdout no disco local inmediatamente"]
    K8sCheck -->|"Non: Pod Gone -> Comproba kubectl get pv"| ReclaimCheck{"Que era PV ReclaimPolicy?"}

    ReclaimCheck -->|"Conservar (estado PV = liberado)"| ClearClaimRef["Datos 100% intactos -> Editar PV para eliminar spec.claimRef.uid -> Volver vincular a novo PVC"]
    ReclaimCheck -->|"Eliminar (Cloud EBS / PD / Longhorn / Local-Path)"| CloudOrLocal{"Volume CSI na nube ou disco anfitrión local?"}

    CloudOrLocal -->|"Cloud CSI (AWS EBS/GCP/Azure/Ceph)"| CloudSnap["Comproba a papeleira de reciclaxe de Cloud Console / Instantáneas automatizadas de EBS / Ceph RBD Trash (rbd trash ls)"]
    CloudOrLocal -->|"Disco de nodo local (local-path / hostPath)"| StopDocker

    StopDocker --> RemountRO["Remontar partición de host de só lectura (mount -o remount,ro) OU transmitir a imaxe do bloque a través de SSH"]
    RemountRO --> HostFS{"Que sistema de ficheiros alberga /var/lib/docker?"}
    HostFS -->|"ext4"| Ext4Rec["Use debugfs/ext4magic Journal Inode Transaction Rollback (-a marca de tempo)"]
    HostFS -->|"XFS / Btrfs"| CarveRec["Use Btrfs Roots / xfs_irecover / Custom Signature Carving para SQLite, Postgres Heap ou InnoDB .ibd"]

Fase 1: como Docker e Kubernetes eliminan realmente volumes do disco

Antes de executar calquera comando de recuperación, comprenda onde vivían fisicamente os seus datos no servidor Linux e o que tocou realmente o comando de eliminación:

Tipo de almacenamento e comando Eliminar Ruta do sistema de ficheiros do host no nodo de Linux O que realmente fixo o comando Eliminar Método de recuperación inmediata
Volum Docker denominado (docker volume rm ou docker compose down -v) /var/lib/docker/volumes/<vol_name>/_data Desvinculáronse os ficheiros do interior _data/ e eliminou a entrada do directorio /var/lib/docker/volumes/metadata.db (boltdb). Detén Docker inmediatamente, volve montar /var/lib/docker só lectura e recupere os inodos desvinculados mediante ext4magic / debugfs ou talla de sinatura.
** Volume docker anónimo (docker run -v /var/lib/mysql + docker rm -v ou docker system prune --volumes)** /var/lib/docker/volumes/<64-char-hex-id>/_data docker system prune --volumes elimina todos os volumes anónimos e con nome aos que non se fai referencia actualmente polo menos un contedor existente. Detén Docker inmediatamente; se tivese outros recipientes parados cuxos volumes foron non podados, comprobe o resto /var/lib/docker/volumes/*/_data cartafoles primeiro antes de tallar bloques sen asignar.
** Capa escribible do contedor (docker rm <container> cando os datos foron escritos fóra dun volume)** /var/lib/docker/overlay2/<layer-id>/diff/ Desvinculouse a parte superior do contedor diff/ directorio dentro do overlay2 controlador de almacenamento. Detén Docker inmediatamente e recupera a árbore de directorios desvinculada do ficheiro ext4 xornal ou XFS bloques.
Docker Desktop en macOS ou Windows (docker system prune --volumes) Dentro dunha única imaxe de disco da máquina virtual: -/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw (macOS) ou %LocalAppData%\Docker\wsl\disk\docker_data.vhdx (Windows WSL2). Enviado unlink() dentro da máquina virtual Linux, e se discard/TRIM está activo Docker.raw / docker_data.vhdx, fixo buracos escasos no ficheiro host. Saia de Docker Desktop en 5 segundos, copia Docker.raw ou docker_data.vhdx a unha unidade externa e execute ext4magic / PhotoRec contra a imaxe do disco virtual.
Kubernetes PVC con Delete ReclaimPolicy en Ceph RBD (Rook-Ceph) ou Longhorn Grupo Ceph OSD (rbd) ou /var/lib/longhorn/replicas/. Se csi-rbdplugin ten trash activado (rbd trash), a imaxe RBD móvese ao lixo de Ceph; se non, os bloques non se asignan. Corre rbd trash ls --pool <pool> dentro do rook-ceph-tools pod e restaurar con rbd trash restore.

Fase 2: Rescatar ficheiros de base de datos abertos dun contedor aínda en execución (/proc/<pid>/fd/)

Agarda: o contedor segue funcionando agora mesmo? Con frecuencia, un enxeñeiro executa un script de migración de aplicacións, un traballo cron de limpeza ou un manual rm -rf /var/lib/postgresql/data/* ou rm /app/data/production.sqlite3 dentro dun contenedor en execución ou elimina o cartafol de montaxe de enlace do host subxacente /opt/app/data mentres que o propio recipiente (postgres, mysqld, mariadbd, redis-server, mongod, gunicorn, node) está aínda en funcionamento.

En Linux, un ficheiro non se elimina do disco cando rm ou unlink() chámase. Os seus bloques de disco e inodo permanecen 100 por cento asignados e lexibles ata que o último proceso contén un descritor de ficheiro aberto (FD) a ese inodo péchao ou sae.

Paso 1: busque o ID de proceso do host (PID) do proceso de contedores

No nodo de host de Linux (non dentro do contedor), busque o host PID da súa base de datos ou proceso de solicitude:

sudo lsof +L1 | grep -E "postgres|mysqld|mariadbd|sqlite|redis|mongo|node|python|java"
Mira a saída:
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)
Mira a columna NLINK: di 0, e o nome do ficheiro remata con (deleted). O ficheiro desapareceu por completo ls /var/lib/docker/volumes/..., pero cada byte (482 MB en users.ibd, 89 MB en production.sqlite3) aínda está vivo dentro /proc/<PID>/fd/<FD>.

Paso 2: copie directamente os ficheiros da base de datos desvinculados /proc/<PID>/fd/

Non pare ou reinicie o contedor. Mentres o proceso aínda estea en execución, copie os descritores dos ficheiros en bruto directamente nun cartafol seguro do seu servidor:

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

Paso 3: aínda mellor: executa un volcado lóxico en directo (pg_dump / mysqldump / .backup) antes de que o recipiente peche os FD

Se postgres ou mysqld segue funcionando cos seus ficheiros de datos abertos na memoria e /proc/<PID>/fd/, intente executar primeiro un volcado lóxico en directo sobre o socket Unix existente ou a conexión 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
(Nota: PostgreSQL ábrese e péchase .1, .2 segmenta os ficheiros en procesos de traballo de forma dinámica, polo tanto pg_dump pode fallar nas táboas sen caché; combinando unha consulta SQL en directo coa copia de cada aberta /proc/<pid>/fd/* en todos postgres Os PID de backend fillos gardan o máximo de datos de montón de táboas posibles.)


Fase 3: Recuperación dun volume Docker eliminado activado ext4 ou XFS despois de que o recipiente parase

E se correches docker compose down -v ou docker system prune --volumes, polo que o recipiente está xa parado e todo /proc/<pid>/fd/ os descriptores están pechados? Agora estás nunha carreira contra as escrituras de disco en segundo plano no servidor Linux.

Paso 1: Conxela o sistema de ficheiros host Linux nun prazo de 10 segundos

  1. Detén Docker, containerd, kubelet e cron inmediatamente polo que ningún contenedor, comprobación de saúde ou rotador de rexistros escribe outro byte para /var/lib/docker:
    sudo systemctl stop docker.socket docker.service containerd.service cron.service
    
  2. Comproba que dispositivo de bloque e sistema de ficheiros contén /var/lib/docker:
    df -Th /var/lib/docker
    
    Filesystem     Type  Size  Used Avail Use% Mounted on
    /dev/nvme0n1p1 ext4  100G   42G   58G  42% /
    
  3. Volver a montar a partición de só lectura (ou transmitir unha imaxe de partición en bruto a través de SSH a outra máquina):
  4. Se /var/lib/docker está na súa propia partición dedicada ou volume LVM (por exemplo /dev/nvme0n1p2 ou /dev/mapper/vg0-docker), volva a montar de só lectura inmediatamente:
    sudo mount -o remount,ro /var/lib/docker
    
  5. Se /var/lib/docker está na raíz / partición (/), proba a forzar a partición raíz de só lectura usando o disparador Magic SysRq do núcleo (echo u | sudo tee /proc/sysrq-trigger) ou sudo mount -o remount,ro /.
  6. Se estás nun VPS na nube (AWS EC2, GCP, DigitalOcean, Hetzner, Linode): vai inmediatamente á túa consola web na nube e fai clic en Crear instantánea no volume de bloques do servidor (ou transmite o dispositivo de bloques en bruto a través de SSH a un segundo servidor: sudo dd if=/dev/nvme0n1p1 bs=4M status=progress | gzip -1 | ssh user@backup-server "cat > /mnt/storage/docker_host_raw.img.gz").

Paso 2: comproba se os teus datos aínda están en OUTRO volume sen podar ou overlay2 capa

Antes de esculpir bloques de disco sen asignar, verifique que a súa base de datos non se almacenou realmente nunha montaxe de enlace ou nun volume con nome diferente que sobreviviu:

# 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
Cada semana, os administradores entran en pánico despois de executar docker volume rm app_db_data, só para descubrir con find /var/lib/docker iso docker-compose.yml realmente creara projectname_app_db_data (que aínda está 100 por cento intacto no disco) mentres app_db_data era un vello volume sen uso de hai seis meses.

Paso 3: Recuperando os directorios de volume de Docker desvinculados ext4 usando o ext4 Xornal (ext4magic e debugfs)

Cando docker volume rm elimina /var/lib/docker/volumes/<vol_name>/_data nun ext4 sistema de ficheiros, ext4 elimina a cero os punteiros de bloque directo (i_block / raíz da árbore de extensión) na táboa de inodos en directo. Non obstante, o ext4 diario (inode <8>, normalmente 128 MB a 1024 MB búfer de anel circular) aínda contén copias históricas das táboas de inodos exactas e dos bloques de directorios de antes docker compose down -v foi executado.

+-------------------------------------------------------------------------+
| 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.        |
+-------------------------------------------------------------------------+

Corre ext4magic contra a súa partición de só lectura (ou o .img copia de instantánea nun segundo servidor), especificando unha marca de tempo (-a) desde 5 minutos antes que correches docker compose down -v ou 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: Le a instantánea do diario que gardou na RAM inmediatamente despois de deter Docker. - -f var/lib/docker/volumes: Diríxese á árbore de directorios de volumes Docker exacta (nota: omita o inicio / en ext4magic camiños relativos). - -a $(date -d "-15 minutes" +%s): Conta ext4magic para reconstruír a árbore de directorios usando copias do inodo válidas hai 15 minutos (xusto antes da eliminación accidental). - -r: recupera os directorios completos onde non se sobrescribiu ningún bloque; se -r perde ficheiros parcialmente sobrescritos, realice unha segunda pasada substituíndo -r con -m (escultura máxica + modo híbrido diario).

Paso 4: gravar ficheiros SQLite, PostgreSQL ou MySQL InnoDB en bruto cando a revista estea envuelta (XFS ou ext4)

Warning

Por que XFS non soporta ext4magic e require un desmontaxe inmediato de só lectura: A diferenza ext4, que escribe copias completas de inodo de 256 bytes no seu diario, XFS rexistra deltas de intención de metadatos e reutiliza agresivamente as árbores B de inodos liberados (agi). Se /var/lib/docker senta nun XFS partición (predeterminada en RHEL, Rocky Linux, AlmaLinux e Amazon Linux), desmontando /var/lib/docker ou remontando / só lectura en segundos é o paso máis importante antes de tallar.

Se o host usa XFS ou se o ext4 Diario xa envolto sobre os punteiros do inodo, use a sinatura e a estrutura de tallado contra a imaxe do disco en bruto (docker_host_raw.img):

  1. Para bases de datos SQLite3 (.sqlite, .db - por exemplo, Vaultwarden, Nextcloud, Home Assistant, Gitea, Grafana): Cada base de datos SQLite3 comeza cunha cabeceira ASCII inconfundible de 16 bytes no byte 0 da súa primeira páxina de 4 kilobytes: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 ("SQLite format 3\0"), e almacena o tamaño exacto da páxina da base de datos (Bytes 16..17, normalmente 4096) e o tamaño total da base de datos en páxinas (Bytes 28..31, enteiro big-endian de 32 bits) xusto dentro da mesma cabeceira.
  2. Corre PhotoRec con [File Opt] -> [x] sqlite activado, ou escanear a partición directamente con grep -ab "SQLite format 3" para atopar a compensación de bytes exacta do ficheiro SQLite eliminado e extraeo con dd:
    # Find the exact byte offsets of every "SQLite format 3" header on the partition:
    sudo grep -ab "SQLite format 3" /dev/nvme0n1p1
    
    Unha vez extraído, corre sqlite3 carved.db ".recover" | sqlite3 repaired.db para reconstruír todas as páxinas de follas da árbore B intactas.

Tip

Como calcular o exacto dd tamaño de bytes dun ficheiro SQLite3 desvinculado da súa cabeceira: Unha vez grep -ab "SQLite format 3" ofrécelle a compensación de byte inicial OFFSET da súa base de datos SQLite eliminada, ler bytes 16..17 (uint16 big-endian Tamaño da páxina, por exemplo, 0x1000 = 4096 bytes) e bytes 28..31 (uint32 big-endian Page Count, por exemplo, 25000 páxinas) utilizando hexdump -C -s OFFSET -n 32. Multiplicando Page Size x Page Count dálle a lonxitude exacta de bytes á que pasar dd (iflag=skip_bytes,count_bytes) cando o ficheiro é contiguo no disco.

  1. Para MySQL/MariaDB InnoDB (.ibd ficheiros de táboa): Cada InnoDB .ibd táboa consiste en secuencial 16 KB (16,384 byte) páxinas que conteñen o FIL_PAGE_INDEX (0x45BF) cabeceira e única da táboa space_id. Use o Percona / TwinDB undrop-for-innodb (stream_parser + c_parser) kit de ferramentas para escanear /dev/nvme0n1p1 para todos 16 KB Páxinas de índice de InnoDB e volcar cada fila directamente en ficheiros TSV/SQL para volver importar.
  2. Para ficheiros de montón PostgreSQL ($PGDATA/base/<db_oid>/<relfilenode>): PostgreSQL almacena cada táboa como contigua 8 KB (8,192 byte) páxinas de pila que conteñen PageHeaderData (pd_lower, pd_upper, pd_special). Usar pg_filedump ou pglazarus / pdu para analizar rexións de disco non asignadas 8 KB páxinas que coinciden co deseño da tupla de columnas da túa táboa (HeapTupleHeaderData) e reconstruír as filas.

Fase 4: Kubernetes PVC, PV e etcd Recuperación de emerxencia instantánea

En Kubernetes (EKS, GKE, AKS, k3s, RKE2, kubeadm, OpenShift), eliminando accidentalmente un PersistentVolumeClaim (kubectl delete pvc), un StatefulSet ou un espazo de nomes completo (kubectl delete ns prod) segue unha arquitectura moi diferente á do Docker autónomo.

Escenario A: mostra o PVC Terminating (The Finalizer Lifesaver)

Executar:

kubectl get pvc -n <namespace>
Se o STATUS columna di Terminating, respira aliviado: os teus datos aínda NON foron eliminados. - Por que? Cada PVC de Kubernetes creado desde Kubernetes 1.9 inclúe automaticamente finalizers: [kubernetes.io/pvc-protection]. - Mentres un Pod siga montando ese PVC, o controlador de Kubernetes négase a completar a eliminación do PVC e nunca chama ao controlador CSI. DeleteVolume RPC. - Acción inmediata: NON elimine ou reinicie o Pod e NON parchee o finalizador. Copie inmediatamente todos os datos do Pod en execución na súa máquina local ou nun bucket 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

Escenario B: eliminouse o PVC e kubectl get pv mostra o volume persistente en Released estado (ReclaimPolicy: Retain)

Executar:

kubectl get pv
Se o teu volume persistente (pv-prod-postgres) aínda está listado con STATUS: Released (porque a súa StorageClass usada reclaimPolicy: Retain), O 100 por cento dos teus datos aínda está intacto no disco subxacente. Non obstante, Kubernetes négase a que un novo PVC se una a un Released PV porque o PV aínda contén a spec.claimRef sinalando os antigos PVC eliminados UID.

Como facer un Released PV Available de novo en 10 segundos sen perda de datos: 1. Edite o obxecto PersistentVolume e elimine o spec.claimRef bloque:

kubectl patch pv <your-pv-name> --type json -p '[{"op": "remove", "path": "/spec/claimRef"}]'
2. Corre kubectl get pv de novo: o estado cambia inmediatamente de Released a Available. 3. Recrea o teu PersistentVolumeClaim (especificando volumeName: <your-pv-name> e capacidade coincidente/storageClassName). Enlazarase ao PV existente inmediatamente con todos os ficheiros intactos.

Escenario C: restaurar un estado de clúster de Kubernetes borrado desde un etcd instantánea (etcdctl snapshot restore)

E se alguén correse kubectl delete namespace prod ou helm uninstall e eliminou 200 manifestos de Kubernetes, segredos, ConfigMaps e definicións PV nun sistema autoxestionado. kubeadm, k3s, ou RKE2 avión de control?

  1. Busca o teu último etcd instantánea (por defecto en /var/lib/rancher/k3s/server/db/snapshots/, /var/lib/rancher/rke2/server/db/snapshots/, ou o teu programado /var/backups/etcd/snapshot.db).
  2. Verifica a integridade da instantánea antes de tocar o clúster activo:
    ETCDCTL_API=3 etcdctl snapshot status /path/to/snapshot.db --write-out=table
    
  3. Para kube-apiserver e etcd no nodo(s) do plano de control:
  4. En kubeadm (vainas estáticas): Mover /etc/kubernetes/manifests/kube-apiserver.yaml e /etc/kubernetes/manifests/etcd.yaml temporalmente a /root/manifests_hold/ así kubelet detén os dous recipientes limpamente e, a continuación, fai unha copia de seguridade /var/lib/etcd a /var/lib/etcd.bak.
  5. En k3s: Corre sudo systemctl stop k3s e sudo k3s server --cluster-reset --cluster-reset-restore-path=/path/to/snapshot.
  6. Restaurar etcd directorio de datos activado kubeadm:
    sudo ETCDCTL_API=3 etcdctl snapshot restore /path/to/snapshot.db \
      --data-dir=/var/lib/etcd \
      --name=<control-plane-node-name> \
      --initial-cluster=<node-name>=https://<node-ip>:2380 \
      --initial-advertise-peer-urls=https://<node-ip>:2380
    
  7. Mover etcd.yaml e kube-apiserver.yaml volta a /etc/kubernetes/manifests/. Dentro de 30 segundos, kube-apiserver reconecta ao restaurado etcd almacena e reaparece cada obxecto eliminado Namespace, Secret, ConfigMap e PersistentVolume.

Fase 5: Endurecemento dos volumes de Docker e Kubernetes contra a eliminación accidental

Unha vez que se restaure a base de datos de produción, implementa estes catro protectores arquitectónicos para que un único erro tipográfico da CLI non poida volver a eliminar un volume en directo:

  • Cambiar todos os Kubernetes de produción StorageClass dende reclaimPolicy: Delete a reclaimPolicy: Retain: Por defecto, StorageClasses na nube incorporado (gp2, gp3, standard-rwo) por defecto reclaimPolicy: Delete, é dicir, eliminar un PVC destrúe o disco da nube. Crear un StorageClass con reclaimPolicy: Retain (ou parchear os PV existentes con kubectl patch pv <pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}') polo que eliminar un PVC ou un espazo de nomes nunca elimina o volume do bloque subxacente.
  • Activar a papeleira de reciclaxe de AWS EBS/programacións de instantáneas de GCP/Velero con instantáneas de CSI: habilitar a papeleira de reciclaxe de AWS EBS conserva calquera volume de EBS eliminado durante 7 a 30 días aínda que o controlador de CSI chame DeleteVolume.
  • Nunca use docker system prune --volumes en scripts de limpeza automatizados ou corredores de CI/CD: se un contenedor de base de datos de produción falla brevemente (Exited (1)) no momento exacto en que se executa un traballo cron docker system prune -a --volumes -f, Docker considera os seus volumes anónimos "sen utilizar" e elimínaos permanentemente. Tira --volumes de todos os scripts de limpeza.
  • Usar montaxes de enlace de host explícitos (/srv/prod_data/postgres:/var/lib/postgresql/data) ou bases de datos xestionadas externas para cargas de traballo de produción con estado: A diferenza /var/lib/docker/volumes/, host directorios de montaxe de enlace fóra /var/lib/docker/ son nunca tocados por docker compose down -v, docker volume rm, ou docker system prune --volumes.

Números de emerxencia rexionais e protocolos da axencia

Cando un contedor ou a eliminación do almacenamento de Kubernetes afectan ás operacións clínicas do hospital, ao envío de seguridade pública ou aos datos persoais regulados, escala inmediatamente:

  • Estados Unidos e Canadá: Marque 911 se un fallo do clúster de contedores desactiva o seguimento clínico do paciente, os sistemas EHR ou o envío de emerxencia. Informe a eliminación de infraestruturas de contenedores maliciosos ou incidentes cibernéticos a CISA (1-844-Say-CISA / cisa.gov/report) ou o Centro Canadiense de Seguridade Cibernética (1-833-CYBER-88).
  • Reino Unido: Marque 999 para ameazas á vida ou infraestruturas críticas do NHS. Segundo o GDPR do Reino Unido, a destrución permanente ou a perda de dispoñibilidade de datos persoais sen unha copia de seguridade recuperable require avaliar unha notificación de incumprimento de 72 horas ao ICO (0303 123 1113).
  • Unión Europea: Marque 112 en todos os estados membros da UE. As entidades baixo a Directiva NIS2 deben enviar un aviso anticipado ao seu CSIRT nacional nun prazo de 24 horas despois dunha interrupción grave do servizo e a perda permanente de datos persoais desencadea o informe Artigo 33 do RGPD nun prazo de 72 horas.
  • Australia e Nova Zelanda: Marque 000 en Australia ou 111 en Nova Zelanda; informar incidentes de infraestruturas críticas ao ACSC (1300 CYBER1).
  • India e Asia-Pacífico: Marque 112 na India para a resposta de emerxencia; informe de incidentes de seguridade na nube ou en contedores a CERT-In (incident@cert-in.org.in) dentro da xanela obrigatoria de 6 horas.

Preguntas frecuentes

Fai docker compose down -v eliminar montaxes de enlace de host (./data:/var/lib/mysql) ou só volumes Docker con nome e anónimo?

`docker compose down -v` SÓ elimina os volumes con nome declarados no `volumes:` sección de `docker-compose.yml` e Volumes anónimos adheridos aos contedores; iso nunca elimina ficheiros dentro dunha montaxe de enlace de host (como `- /opt/mysql_data:/var/lib/mysql` ou `- ./postgres_data:/var/lib/postgresql/data`). Se o teu ficheiro de redacción utilizaba unha ruta do servidor que comezaba por `/` ou `./`, comproba ese cartafol no host agora mesmo: os teus ficheiros aínda están 100 por cento intactos.

Por que fixo docker system prune --volumes eliminar o meu volume de base de datos cando só parei o contedor durante 2 minutos para actualizar unha variable de ambiente?

Agarde coidadosamente pola distinción entre `docker stop` e `docker rm`: se un recipiente é meramente `Stopped / Exited` (visible en `docker ps -a`), `docker system prune --volumes` fai non eliminar os seus volumes porque o contedor detido aínda fai referencia a eles. Porén, se correches `docker rm ` (para recrear o contedor con bandeiras novas) ou se pasaches `docker system prune -a --volumes` (que primeiro elimina todos os contedores parados e entón elimina todos os volumes que xa non están conectados a ningún recipiente), o volume quedou "colgando" ao milisegundo no que se eliminou o recipiente parado e limpouse inmediatamente despois.

Podo recuperar un volume de Docker eliminado dentro de Docker Desktop nunha Mac (Apple Silicon / Intel) ou Windows (WSL2)?

Si, se saes de Docker Desktop inmediatamente para que a máquina virtual deixe de funcionar `fstrim` contra o disco virtual. En macOS, Docker almacena todos os volumes de Linux dentro `-/Library/Containers/com.docker.docker/Data/vms/0/data/Docker.raw`; en Windows WSL2, dentro `%LocalAppData%\Docker\wsl\disk\docker_data.vhdx`. Copia iso `.raw` ou `.vhdx` ficheiro a un SSD externo inmediatamente, adxúntalo de só lectura en Linux (usando `losetup -Pr` para `.raw` ou `qemu-nbd -r` para `.vhdx`), e corre `ext4magic` ou `PhotoRec` contra o virtual `ext4` partición por dentro.

E se elimino un StatefulSet de Kubernetes con kubectl delete statefulset postgres? Iso tamén eliminou os meus PVC?

Non. Por defecto en Kubernetes (a menos que `persistentVolumeClaimRetentionPolicy.whenDeleted: Delete` configurouse explícitamente en Kubernetes 1.27+), en execución `kubectl delete statefulset` elimina o controlador StatefulSet e os seus Pods, deixando todo `PersistentVolumeClaims` (`data-postgres-0`, `data-postgres-1`) e os seus datos subxacentes 100 por cento intactos. Só ten que volver a aplicar o seu `StatefulSet` Manifesto YAML co mesmo nome e `volumeClaimTemplates`, e os novos Pods volverán conectarse automaticamente aos existentes `data-postgres-0` PVC.

Como acceder aos ficheiros dentro dun Docker overlay2 directorio cando o contedor se nega a iniciar (CrashLoopBackOff / Exited (1))?

Non elimines o contedor que fallou. Sempre que o contedor detido aínda exista `docker ps -a`, a súa capa escribible e os soportes de volume están completamente intactos no disco. Podes copiar ficheiros directamente fóra do contedor detido usando `docker cp :/var/lib/postgresql/data /root/rescued_data`, ou atopar o seu host exacto `overlay2` camiño correndo `docker inspect --format '{{.GraphDriver.Data.UpperDir}}'` e lendo ese directorio directamente como `root`.

E se alguén eliminou un Kubernetes Namespace (kubectl delete ns prod) e todos os PVC tiñan reclaimPolicy: Delete en AWS EBS ou GCP?

Se o controlador CSI da nube (`ebs.csi.aws.com` ou `pd.csi.storage.gke.io`) xa executado `DeleteVolume` porque `reclaimPolicy` foi `Delete`, verifique de inmediato tres redes de seguridade a nivel de nube: (1) marque **Papeleira de reciclaxe de AWS para volumes EBS** na consola AWS EC2 (se unha regra de retención estaba activa na conta/etiquetas, o volume EBS eliminado sitúase na papeleira e pódese restaurar con 1 clic); (2) verifique **Copia de seguranza de AWS / DLM / Programacións de instantáneas de GCP** para obter a instantánea de volume automatizada máis recente; e (3) verifique se a súa base de datos estaba transmitindo WAL/binlogs (`WAL-G`, `pgBackRest`, `Litestream`) a un bucket S3/GCS.


Guías relacionadas


Fontes e orientacións oficiais

  • Documentación oficial de Kubernetes (kubernetes.io / Cloud Native Computing Foundation): Protección de obxectos de almacenamento en uso (kubernetes.io/pvc-protection Finalizadores), Recuperando Volumes Persistentes (Retain vs. Delete), e en funcionamento etcd Clústeres para Kubernetes (etcdctl snapshot restore).
  • Docker Inc. (docs.docker.com): Xestionar datos en Docker: volumes, montaxes de enlace, overlay2 Arquitectura do controlador de almacenamento e referencia de Prune.
  • Organización do núcleo de Linux (kernel.org): O /proc Sistema de ficheiros (procfs Abrir File Descriptor Recovery mediante /proc/<pid>/fd/) e Ext4 Journal Specification.
  • ext4magic Documentación do proxecto (ext4magic.sourceforge.net): Forensic Inode e Recuperación de transaccións de diario en sistemas de ficheiros Ext3/Ext4.
  • Instituto Nacional de Estándares e Tecnoloxía (NIST) (Estados Unidos): Publicación especial 800-190: Application Container Security Guide & Incident Recovery.