version: 1
id: kubernetes-etcd-snapshot
title: Practice etcd Snapshot Runbooks
summary: Inspect a real control-plane etcd snapshot from k3d, author the restore runbook, and keep an application-consistent companion backup.
difficulty: advanced
estimatedMinutes: 40
prerequisites: [kubernetes-backup-restore]
image: alpine/k8s:1.31.4
shell: /bin/bash
runtime:
  type: k3d
  addons: [etcd-snapshot]
setup:
  - "mkdir -p /workspace/backup/etcd /workspace/docs /workspace/bin"
  - "kubectl create namespace payments >/dev/null"
  - "kubectl -n payments create configmap cluster-meta --from-literal=cluster=payments-prod --from-literal=region=eu-west-1"
  - "curl -fsSL https://github.com/etcd-io/etcd/releases/download/v3.5.16/etcd-v3.5.16-linux-amd64.tar.gz | tar -xz -C /tmp && cp /tmp/etcd-v3.5.16-linux-amd64/etcdctl /workspace/bin/etcdctl && chmod +x /workspace/bin/etcdctl"
  - "export PATH=/workspace/bin:$PATH"
tasks:
  - id: inspect-live-snapshot
    title: Inspect the live etcd snapshot
    description: 'A real snapshot from this cluster control plane is mounted at /workspace/backup/etcd/snapshot.db. Using /workspace/bin/etcdctl, run snapshot status and write the output to /workspace/backup/etcd/SNAPSHOT_STATUS.txt. The file must mention hash or revision or snapshot_bytes.'
    hints:
      - 'Tip code ETCD_STATUS: ETCDCTL_API=3 /workspace/bin/etcdctl snapshot status /workspace/backup/etcd/snapshot.db'
      - 'Redirect stdout to SNAPSHOT_STATUS.txt'
      - 'Host also left snapshot-status.host.txt as a reference.'
    checks:
      - type: command
        name: Live snapshot present
        command: test -s /workspace/backup/etcd/snapshot.db
      - type: file
        name: Status file present
        path: /workspace/backup/etcd/SNAPSHOT_STATUS.txt
      - type: command
        name: Status has etcd fields
        command: "grep -Eqi 'hash|revision|snapshot_bytes|total key' /workspace/backup/etcd/SNAPSHOT_STATUS.txt"
  - id: snapshot-runbook
    title: Companion backup and recovery runbook
    description: 'Export cluster-meta ConfigMap to /workspace/backup/etcd/snapshot-manifests.yaml. Create /workspace/backup/etcd/SNAPSHOT.sha256 with a sha256 of snapshot.db (the live artifact). Write /workspace/docs/etcd-runbook.md with headings Snapshot, Restore, and Validation that mention etcdctl snapshot save, etcdctl snapshot restore, and testing restores.'
    hints:
      - kubectl get configmap cluster-meta -n payments -o yaml > backup/etcd/snapshot-manifests.yaml
      - 'sha256sum /workspace/backup/etcd/snapshot.db | awk ''{print $1}'' > SNAPSHOT.sha256'
      - Runbook must mention etcdctl snapshot save and restore.
    checks:
      - type: file
        name: Manifest snapshot saved
        path: /workspace/backup/etcd/snapshot-manifests.yaml
        value: cluster-meta
      - type: command
        name: Checksum file present
        command: test -s /workspace/backup/etcd/SNAPSHOT.sha256
      - type: command
        name: Checksum matches live snapshot
        command: "test \"$(sha256sum /workspace/backup/etcd/snapshot.db | awk '{print $1}')\" = \"$(tr -d '[:space:]' < /workspace/backup/etcd/SNAPSHOT.sha256)\""
      - type: file
        name: Snapshot section
        path: /workspace/docs/etcd-runbook.md
        value: Snapshot
      - type: file
        name: Restore section
        path: /workspace/docs/etcd-runbook.md
        value: Restore
      - type: file
        name: Validation section
        path: /workspace/docs/etcd-runbook.md
        value: Validation
      - type: file
        name: Mentions snapshot save
        path: /workspace/docs/etcd-runbook.md
        value: etcdctl snapshot save
      - type: file
        name: Mentions snapshot restore
        path: /workspace/docs/etcd-runbook.md
        value: etcdctl snapshot restore
      - type: command
        name: Mentions testing restores
        command: "grep -Eqi 'test' /workspace/docs/etcd-runbook.md"
limits: {cpus: "1.0", memory: 512m, pids: 256, timeout: 3600, network: true}
