Skip to content
Back to skills

Backup Etcd

ASecurity

Create and manage etcd backups for OpenShift control plane disaster recovery, including automated backup procedures and verification.

  • 666 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 12, 2026
devopsbashnodekubernetesawsapisecuritydocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned June 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill backup-etcd --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Backup Etcd?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Backup Etcd
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-backup-etcd/badge)](https://www.skillsdirectory.com/skills/majiayu000-backup-etcd)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
name: backup-etcd
description: Create and manage etcd backups for OpenShift control plane disaster recovery, including automated backup procedures and verification.
---

# Backup etcd

This skill provides comprehensive guidance for backing up etcd, the critical key-value store for OpenShift/Kubernetes control plane data. Proper etcd backups are essential for cluster disaster recovery.

## When to Use This Skill

- **Before Major Changes**: Prior to cluster upgrades, configuration changes, or major updates
- **Regular Maintenance**: As part of routine backup procedures
- **Disaster Recovery Planning**: Setting up automated etcd backup schedules
- **Pre-Migration**: Before cluster migrations or infrastructure changes
- **Compliance**: Meeting backup retention requirements
- **Emergency Situations**: When cluster issues detected, capture current state

## What This Skill Does

1. **Validates Cluster Health**: Checks etcd cluster status before backup
2. **Creates etcd Snapshot**: Generates consistent etcd data snapshot
3. **Stores Backup Safely**: Copies snapshot to secure off-cluster location
4. **Verifies Backup**: Validates snapshot integrity and completeness
5. **Manages Retention**: Implements backup rotation and cleanup
6. **Documents Metadata**: Records backup metadata for recovery procedures

## How to Use

### Basic Usage

```
Create an etcd backup
```

```
Backup etcd and store in S3
```

### Automated Usage

```
Set up automated daily etcd backups
```

```
Create etcd backup CronJob with retention policy
```

### Emergency Usage

```
Create emergency etcd snapshot before cluster recovery
```

## Prerequisites

Before backing up etcd:

- [ ] Cluster admin access with oc CLI configured
- [ ] At least one healthy master node accessible
- [ ] Sufficient disk space on master nodes (typically 2-3x etcd data size)
- [ ] SSH access to master nodes (for manual backups)
- [ ] Off-cluster storage location configured (for backup copies)
- [ ] Understanding of etcd cluster topology

## Examples

### Example 1: Manual etcd Backup on Single Master

**User**: "Create manual etcd backup"

**Skill Actions**:

1. **Check etcd cluster health**:
   ```bash
   # Verify all etcd members are healthy
   oc get etcd -o=jsonpath='{range .items[0].status.conditions[?(@.type=="EtcdMembersAvailable")]}{.message}{"\n"}{.reason}{"\n"}{.status}{"\n"}{end}'

   # Check etcd pods
   oc get pods -n openshift-etcd -l app=etcd

   # Verify etcd endpoint health
   ETCD_POD=$(oc get pods -n openshift-etcd -l app=etcd -o jsonpath='{.items[0].metadata.name}')
   oc exec -n openshift-etcd $ETCD_POD -- etcdctl endpoint health -w table
   ```

2. **Access master node and create backup**:
   ```bash
   # Get first master node name
   MASTER_NODE=$(oc get nodes -l node-role.kubernetes.io/master -o jsonpath='{.items[0].metadata.name}')

   # Start debug session on master node
   oc debug node/$MASTER_NODE

   # Once in debug pod, run backup
   chroot /host

   # Create backup directory
   mkdir -p /home/core/etcd-backups

   # Run cluster backup script
   /usr/local/bin/cluster-backup.sh /home/core/etcd-backups

   # Exit chroot and debug pod
   exit
   exit
   ```

3. **Verify backup created**:
   ```bash
   # List backups on master node
   oc debug node/$MASTER_NODE -- chroot /host ls -lh /home/core/etcd-backups/
   ```

4. **Copy backup off cluster**:
   ```bash
   # Create local directory
   mkdir -p ./etcd-backups/$(date +%Y%m%d)

   # Copy backup files
   oc debug node/$MASTER_NODE -- chroot /host tar czf - /home/core/etcd-backups/ | tar xzf - -C ./etcd-backups/$(date +%Y%m%d)/

   # Verify files copied
   ls -lh ./etcd-backups/$(date +%Y%m%d)/
   ```

**Expected Output**:
```
Backup created at: /home/core/etcd-backups/snapshot_2025-11-17_152030.db
Static pod resources backed up to: /home/core/etcd-backups/static_kuberesources_2025-11-17_152030.tar.gz
```

**Success Indicators**:
- ✅ snapshot_*.db file created (etcd data)
- ✅ static_kuberesources_*.tar.gz created (static pod manifests)
- ✅ No errors in backup script output
- ✅ Backup files copied off cluster successfully

### Example 2: Automated etcd Backup with CronJob

**User**: "Set up automated daily etcd backups at 2 AM"

**Skill Actions**:

1. **Create etcd backup script ConfigMap**:
   ```yaml
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: etcd-backup-script
     namespace: openshift-etcd
   data:
     backup-etcd.sh: |
       #!/bin/bash
       set -euo pipefail

       BACKUP_DIR="/host/home/core/etcd-backups"
       BACKUP_DATE=$(date +%Y%m%d-%H%M%S)
       RETENTION_DAYS=7

       echo "Starting etcd backup at $BACKUP_DATE"

       # Create backup directory
       mkdir -p $BACKUP_DIR

       # Run backup
       /usr/local/bin/cluster-backup.sh $BACKUP_DIR

       echo "Backup completed successfully"

       # Clean up old backups
       find $BACKUP_DIR -name "snapshot_*.db" -mtime +$RETENTION_DAYS -delete
       find $BACKUP_DIR -name "static_kuberesources_*.tar.gz" -mtime +$RETENTION_DAYS -delete

       echo "Old backups cleaned up (retention: $RETENTION_DAYS days)"

       # List current backups
       echo "Current backups:"
       ls -lh $BACKUP_DIR/
   ```

2. **Create ServiceAccount with required permissions**:
   ```yaml
   apiVersion: v1
   kind: ServiceAccount
   metadata:
     name: etcd-backup
     namespace: openshift-etcd
   ---
   apiVersion: rbac.authorization.k8s.io/v1
   kind: ClusterRole
   metadata:
     name: etcd-backup
   rules:
     - apiGroups: [""]
       resources: ["nodes"]
       verbs: ["get", "list"]
     - apiGroups: [""]
       resources: ["pods"]
       verbs: ["get", "list"]
     - apiGroups: [""]
       resources: ["pods/log"]
       verbs: ["get"]
   ---
   apiVersion: rbac.authorization.k8s.io/v1
   kind: ClusterRoleBinding
   metadata:
     name: etcd-backup
   roleRef:
     apiGroup: rbac.authorization.k8s.io
     kind: ClusterRole
     name: etcd-backup
   subjects:
     - kind: ServiceAccount
       name: etcd-backup
       namespace: openshift-etcd
   ```

3. **Create CronJob for automated backups**:
   ```yaml
   apiVersion: batch/v1
   kind: CronJob
   metadata:
     name: etcd-backup
     namespace: openshift-etcd
   spec:
     schedule: "0 2 * * *"  # 2 AM daily
     concurrencyPolicy: Forbid
     successfulJobsHistoryLimit: 3
     failedJobsHistoryLimit: 3
     jobTemplate:
       spec:
         backoffLimit: 0
         template:
           metadata:
             labels:
               app: etcd-backup
           spec:
             serviceAccountName: etcd-backup
             hostNetwork: true
             hostPID: true
             nodeSelector:
               node-role.kubernetes.io/master: ""
             tolerations:
               - operator: "Exists"
             containers:
               - name: etcd-backup
                 image: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:... # Use cluster version
                 command:
                   - /bin/bash
                   - -c
                   - |
                     #!/bin/bash
                     set -euo pipefail

                     # Run backup script
                     /scripts/backup-etcd.sh

                     # Optional: Upload to S3/cloud storage
                     # aws s3 cp /host/home/core/etcd-backups/ s3://my-backups/etcd/ --recursive
                 volumeMounts:
                   - name: host
                     mountPath: /host
                   - name: backup-script
                     mountPath: /scripts
                 securityContext:
                   privileged: true
                   runAsUser: 0
             volumes:
               - name: host
                 hostPath:
                   path: /
                   type: Directory
               - name: backup-script
                 configMap:
                   name: etcd-backup-script
                   defaultMode: 0755
             restartPolicy: Never
   ```

4. **Apply resources**:
   ```bash
   oc apply -f etcd-backup-configmap.yaml
   oc apply -f etcd-backup-rbac.yaml
   oc apply -f etcd-backup-cronjob.yaml
   ```

5. **Test CronJob manually**:
   ```bash
   # Create manual job from CronJob
   oc create job --from=cronjob/etcd-backup etcd-backup-manual -n openshift-etcd

   # Watch job completion
   oc get jobs -n openshift-etcd -w

   # Check logs
   oc logs -n openshift-etcd job/etcd-backup-manual
   ```

**Success Indicators**:
- ✅ CronJob created and scheduled
- ✅ Manual test job completes successfully
- ✅ Backup files appear in /home/core/etcd-backups on master
- ✅ Old backups cleaned up based on retention policy

### Example 3: etcd Backup with S3 Upload

**User**: "Create etcd backup and upload to S3"

**Skill Actions**:

1. **Create AWS credentials secret**:
   ```bash
   cat <<EOF > aws-credentials
   [default]
   aws_access_key_id=<ACCESS_KEY>
   aws_secret_access_key=<SECRET_KEY>
   EOF

   oc create secret generic etcd-backup-aws-creds \
     --from-file=credentials=aws-credentials \
     -n openshift-etcd

   rm aws-credentials
   ```

2. **Create enhanced backup script with S3 upload**:
   ```yaml
   apiVersion: v1
   kind: ConfigMap
   metadata:
     name: etcd-backup-script-s3
     namespace: openshift-etcd
   data:
     backup-etcd.sh: |
       #!/bin/bash
       set -euo pipefail

       BACKUP_DIR="/host/home/core/etcd-backups"
       BACKUP_DATE=$(date +%Y%m%d-%H%M%S)
       S3_BUCKET="s3://my-etcd-backups"
       S3_PREFIX="openshift-cluster-1"
       RETENTION_DAYS=30

       echo "Starting etcd backup at $BACKUP_DATE"

       # Create backup directory
       mkdir -p $BACKUP_DIR

       # Run backup
       /usr/local/bin/cluster-backup.sh $BACKUP_DIR

       # Get backup files
       SNAPSHOT_FILE=$(ls -t $BACKUP_DIR/snapshot_*.db | head -1)
       STATIC_RESOURCES=$(ls -t $BACKUP_DIR/static_kuberesources_*.tar.gz | head -1)

       echo "Snapshot: $SNAPSHOT_FILE"
       echo "Static resources: $STATIC_RESOURCES"

       # Upload to S3
       echo "Uploading to S3..."
       aws s3 cp $SNAPSHOT_FILE $S3_BUCKET/$S3_PREFIX/$(basename $SNAPSHOT_FILE)
       aws s3 cp $STATIC_RESOURCES $S3_BUCKET/$S3_PREFIX/$(basename $STATIC_RESOURCES)

       # Create metadata file
       cat <<METADATA > $BACKUP_DIR/backup-metadata-$BACKUP_DATE.json
       {
         "timestamp": "$BACKUP_DATE",
         "snapshot_file": "$(basename $SNAPSHOT_FILE)",
         "static_resources": "$(basename $STATIC_RESOURCES)",
         "cluster_version": "$(oc version -o json | jq -r '.openshiftVersion')",
         "etcd_version": "$(oc exec -n openshift-etcd $ETCD_POD -- etcdctl version | head -1)"
       }
       METADATA

       # Upload metadata
       aws s3 cp $BACKUP_DIR/backup-metadata-$BACKUP_DATE.json \
         $S3_BUCKET/$S3_PREFIX/backup-metadata-$BACKUP_DATE.json

       echo "Upload completed successfully"

       # List S3 backups
       echo "Backups in S3:"
       aws s3 ls $S3_BUCKET/$S3_PREFIX/

       # Clean up local old backups
       find $BACKUP_DIR -name "snapshot_*.db" -mtime +7 -delete
       find $BACKUP_DIR -name "static_kuberesources_*.tar.gz" -mtime +7 -delete
       find $BACKUP_DIR -name "backup-metadata-*.json" -mtime +7 -delete

       echo "Backup process completed"
   ```

3. **Update CronJob with S3 credentials**:
   ```yaml
   # Add to CronJob container spec:
   env:
     - name: AWS_SHARED_CREDENTIALS_FILE
       value: /aws/credentials
     - name: AWS_DEFAULT_REGION
       value: us-east-1
   volumeMounts:
     - name: aws-credentials
       mountPath: /aws
       readOnly: true

   # Add to volumes:
   - name: aws-credentials
     secret:
       secretName: etcd-backup-aws-creds
   ```

**Verification**:
```bash
# Check S3 bucket
aws s3 ls s3://my-etcd-backups/openshift-cluster-1/

# Download and verify
aws s3 cp s3://my-etcd-backups/openshift-cluster-1/snapshot_latest.db ./
file snapshot_latest.db  # Should show: snapshot_latest.db: data
```

### Example 4: Pre-Upgrade etcd Backup

**User**: "Create etcd backup before cluster upgrade"

**Skill Actions**:

1. **Verify cluster health before backup**:
   ```bash
   # Check cluster operators
   oc get co

   # Check etcd cluster
   oc get etcd cluster -o jsonpath='{.status.conditions[?(@.type=="EtcdMembersAvailable")]}' | jq .

   # Verify no etcd leader elections happening
   oc logs -n openshift-etcd -l app=etcd --tail=100 | grep -i "leader"
   ```

2. **Create labeled backup**:
   ```bash
   UPGRADE_VERSION="4.14.8"
   BACKUP_DATE=$(date +%Y%m%d-%H%M%S)
   BACKUP_LABEL="pre-upgrade-$UPGRADE_VERSION"

   # Access master and create backup
   MASTER_NODE=$(oc get nodes -l node-role.kubernetes.io/master -o jsonpath='{.items[0].metadata.name}')

   oc debug node/$MASTER_NODE <<'BACKUP_EOF'
   chroot /host
   mkdir -p /home/core/etcd-backups/pre-upgrade-$UPGRADE_VERSION
   /usr/local/bin/cluster-backup.sh /home/core/etcd-backups/$BACKUP_LABEL
   exit
   exit
   BACKUP_EOF
   ```

3. **Document backup metadata**:
   ```bash
   # Create backup documentation
   cat <<EOF > etcd-backup-metadata-$BACKUP_DATE.yaml
   backup_type: pre-upgrade
   backup_date: $BACKUP_DATE
   cluster_version_before: $(oc version -o json | jq -r '.openshiftVersion')
   target_upgrade_version: $UPGRADE_VERSION
   cluster_name: $(oc get infrastructure cluster -o jsonpath='{.status.infrastructureName}')
   etcd_members: $(oc get pods -n openshift-etcd -l app=etcd -o jsonpath='{.items[*].metadata.name}')
   backup_location: /home/core/etcd-backups/$BACKUP_LABEL
   notes: "Pre-upgrade backup before upgrading to $UPGRADE_VERSION"
   EOF

   # Store metadata
   oc create configmap etcd-backup-metadata-$BACKUP_DATE \
     --from-file=metadata=etcd-backup-metadata-$BACKUP_DATE.yaml \
     -n openshift-etcd
   ```

4. **Copy and archive**:
   ```bash
   # Copy off cluster
   mkdir -p ./critical-backups/pre-upgrade-$UPGRADE_VERSION
   oc debug node/$MASTER_NODE -- chroot /host tar czf - /home/core/etcd-backups/$BACKUP_LABEL | \
     tar xzf - -C ./critical-backups/pre-upgrade-$UPGRADE_VERSION/

   # Create archive
   tar czf etcd-pre-upgrade-$UPGRADE_VERSION-$BACKUP_DATE.tar.gz \
     -C ./critical-backups pre-upgrade-$UPGRADE_VERSION

   echo "Backup archived: etcd-pre-upgrade-$UPGRADE_VERSION-$BACKUP_DATE.tar.gz"
   ```

**Post-Backup Verification**:
```bash
# Verify backup file integrity
tar tzf etcd-pre-upgrade-$UPGRADE_VERSION-$BACKUP_DATE.tar.gz | head -20

# Check backup size (should be several GB for production cluster)
ls -lh etcd-pre-upgrade-$UPGRADE_VERSION-$BACKUP_DATE.tar.gz
```

## Monitoring and Verification

### Check Backup Health

```bash
# Verify etcd snapshot integrity (basic check)
SNAPSHOT_FILE="/home/core/etcd-backups/snapshot_*.db"
file $SNAPSHOT_FILE  # Should show: data

# Check snapshot size (production clusters typically 1-10GB)
ls -lh $SNAPSHOT_FILE

# Verify static resources archive
tar tzf /home/core/etcd-backups/static_kuberesources_*.tar.gz | head -20
```

### Monitor Automated Backups

```bash
# Check CronJob status
oc get cronjobs -n openshift-etcd

# View recent job runs
oc get jobs -n openshift-etcd -l app=etcd-backup --sort-by=.metadata.creationTimestamp

# Check latest backup logs
LATEST_JOB=$(oc get jobs -n openshift-etcd -l app=etcd-backup --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}')
oc logs -n openshift-etcd job/$LATEST_JOB
```

## Troubleshooting

### Backup Script Fails

**Symptoms**: cluster-backup.sh fails with errors

**Common Causes**:
1. **Insufficient disk space**:
   ```bash
   # Check disk space on master
   oc debug node/$MASTER_NODE -- chroot /host df -h /home/core
   ```

2. **etcd unhealthy**:
   ```bash
   # Check etcd member health
   oc exec -n openshift-etcd $ETCD_POD -- etcdctl endpoint health -w table
   ```

3. **Permission issues**:
   ```bash
   # Verify running as root in debug pod
   oc debug node/$MASTER_NODE -- chroot /host whoami
   ```

### CronJob Not Running

**Symptoms**: No backup jobs created

**Diagnosis**:
```bash
# Check CronJob status
oc describe cronjob etcd-backup -n openshift-etcd

# Check for scheduling errors
oc get events -n openshift-etcd --field-selector involvedObject.name=etcd-backup
```

**Common Issues**:
- Node selector not matching (no master nodes)
- ServiceAccount permissions insufficient
- Image pull errors

### Cannot Access Master Node

**Symptoms**: oc debug fails to access master

**Solutions**:
```bash
# Try different master node
oc get nodes -l node-role.kubernetes.io/master
oc debug node/<different-master>

# Check SSH access (alternative method)
ssh core@<master-ip>
sudo /usr/local/bin/cluster-backup.sh /home/core/etcd-backups
```

## Best Practices

1. **Regular Schedule**
   - Daily backups minimum for production
   - Before/after major changes
   - Before cluster upgrades
   - Store at least 7 days of backups

2. **Off-Cluster Storage**
   - Always copy backups off cluster immediately
   - Use different storage system than cluster
   - Encrypt backups at rest and in transit
   - Test backup accessibility regularly

3. **Retention Policy**
   - Keep daily backups for 7 days
   - Weekly backups for 4 weeks
   - Monthly backups for 6-12 months
   - Pre-upgrade backups indefinitely until verified

4. **Backup Validation**
   - Test restore procedure quarterly
   - Verify backup file integrity
   - Document restore procedures
   - Train team on recovery process

5. **Monitoring**
   - Alert on backup failures
   - Monitor backup size trends
   - Track backup completion times
   - Alert on missing scheduled backups

6. **Documentation**
   - Record backup metadata (date, version, reason)
   - Document recovery procedures
   - Maintain inventory of backups
   - Note any special considerations

## Disaster Recovery Integration

### Combine with OADP

While etcd backups are separate from OADP, combine both for complete DR:

```bash
# 1. Create etcd backup
/usr/local/bin/cluster-backup.sh /home/core/etcd-backups

# 2. Create OADP namespace backup
velero backup create full-cluster-backup \
  --include-namespaces "*" \
  --exclude-namespaces "openshift-*,kube-*" \
  --snapshot-volumes

# 3. Store both backups together
tar czf complete-cluster-backup-$(date +%Y%m%d).tar.gz \
  etcd-backups/ \
  oadp-backup-metadata/
```

### Recovery Priority

In disaster recovery:
1. Restore etcd first (control plane)
2. Verify cluster comes up
3. Restore OADP backups (applications)
4. Verify application functionality

## Next Steps

After creating etcd backups:

1. **Test Restore**: Practice etcd restore in test environment
2. **Automate**: Set up CronJob for regular automated backups
3. **Monitor**: Configure alerts for backup failures
4. **Document**: Create runbook for disaster recovery
5. **Integrate**: Combine with OADP application backups

**Related Skills**:
- install-oadp - Install OADP operator
- create-backup - Create application backups
- diagnose-backup-issues - Troubleshoot backup problems

## Resources

- **OpenShift etcd Backup Documentation**: https://docs.openshift.com/container-platform/latest/backup_and_restore/control_plane_backup_and_restore/backing-up-etcd.html
- **Disaster Recovery**: https://docs.openshift.com/container-platform/latest/backup_and_restore/control_plane_backup_and_restore/disaster-recovery.html
- **etcd Documentation**: https://etcd.io/docs/

---

**Version**: 1.0
**Last Updated**: 2025-11-17
**Compatibility**: OpenShift 4.10+
**CRITICAL**: etcd backups are essential for cluster disaster recovery

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.