Adds more to wild-backup.
This commit is contained in:
195
bin/wild-backup
195
bin/wild-backup
@@ -4,6 +4,72 @@
|
|||||||
set -e
|
set -e
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
|
# Parse command line flags
|
||||||
|
BACKUP_HOME=true
|
||||||
|
BACKUP_APPS=true
|
||||||
|
BACKUP_CLUSTER=true
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
echo "Usage: $0 [OPTIONS]"
|
||||||
|
echo "Backup components of your wild-cloud infrastructure"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " --home-only Backup only WC_HOME (wild-cloud configuration)"
|
||||||
|
echo " --apps-only Backup only applications (databases and PVCs)"
|
||||||
|
echo " --cluster-only Backup only Kubernetes cluster resources"
|
||||||
|
echo " --no-home Skip WC_HOME backup"
|
||||||
|
echo " --no-apps Skip application backups"
|
||||||
|
echo " --no-cluster Skip cluster resource backup"
|
||||||
|
echo " -h, --help Show this help message"
|
||||||
|
echo ""
|
||||||
|
echo "Default: Backup all components (home, apps, cluster)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process command line arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--home-only)
|
||||||
|
BACKUP_HOME=true
|
||||||
|
BACKUP_APPS=false
|
||||||
|
BACKUP_CLUSTER=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--apps-only)
|
||||||
|
BACKUP_HOME=false
|
||||||
|
BACKUP_APPS=true
|
||||||
|
BACKUP_CLUSTER=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--cluster-only)
|
||||||
|
BACKUP_HOME=false
|
||||||
|
BACKUP_APPS=false
|
||||||
|
BACKUP_CLUSTER=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--no-home)
|
||||||
|
BACKUP_HOME=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--no-apps)
|
||||||
|
BACKUP_APPS=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--no-cluster)
|
||||||
|
BACKUP_CLUSTER=false
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
show_help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
# Initialize Wild Cloud environment
|
# Initialize Wild Cloud environment
|
||||||
if [ -z "${WC_ROOT}" ]; then
|
if [ -z "${WC_ROOT}" ]; then
|
||||||
echo "WC_ROOT is not set."
|
echo "WC_ROOT is not set."
|
||||||
@@ -46,18 +112,25 @@ else
|
|||||||
echo "Repository initialized successfully."
|
echo "Repository initialized successfully."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Backup entire WC_HOME.
|
# Backup entire WC_HOME
|
||||||
restic --verbose --tag wild-cloud --tag wc-home --tag "$(date +%Y-%m-%d)" backup $WC_HOME
|
if [ "$BACKUP_HOME" = true ]; then
|
||||||
# TODO: Ignore wild cloud cache?
|
echo "Backing up WC_HOME..."
|
||||||
|
restic --verbose --tag wild-cloud --tag wc-home --tag "$(date +%Y-%m-%d)" backup $WC_HOME
|
||||||
|
echo "WC_HOME backup completed."
|
||||||
|
# TODO: Ignore wild cloud cache?
|
||||||
|
else
|
||||||
|
echo "Skipping WC_HOME backup."
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p "$STAGING_DIR"
|
mkdir -p "$STAGING_DIR"
|
||||||
|
|
||||||
# Run backup for all apps at once
|
# Run backup for all apps at once
|
||||||
echo "Running backup for all apps..."
|
if [ "$BACKUP_APPS" = true ]; then
|
||||||
wild-app-backup --all
|
echo "Running backup for all apps..."
|
||||||
|
wild-app-backup --all
|
||||||
|
|
||||||
# Upload each app's backup to restic individually
|
# Upload each app's backup to restic individually
|
||||||
for app_dir in "$STAGING_DIR"/apps/*; do
|
for app_dir in "$STAGING_DIR"/apps/*; do
|
||||||
if [ ! -d "$app_dir" ]; then
|
if [ ! -d "$app_dir" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
@@ -65,14 +138,108 @@ for app_dir in "$STAGING_DIR"/apps/*; do
|
|||||||
echo "Uploading backup for app: $app"
|
echo "Uploading backup for app: $app"
|
||||||
restic --verbose --tag wild-cloud --tag "$app" --tag "$(date +%Y-%m-%d)" backup "$app_dir"
|
restic --verbose --tag wild-cloud --tag "$app" --tag "$(date +%Y-%m-%d)" backup "$app_dir"
|
||||||
echo "Backup for app '$app' completed."
|
echo "Backup for app '$app' completed."
|
||||||
done
|
done
|
||||||
|
else
|
||||||
|
echo "Skipping application backups."
|
||||||
|
fi
|
||||||
|
|
||||||
# Back up Kubernetes resources
|
# --- etcd Backup Function ----------------------------------------------------
|
||||||
# kubectl get all -A -o yaml > "$BACKUP_DIR/all-resources.yaml"
|
backup_etcd() {
|
||||||
# kubectl get secrets -A -o yaml > "$BACKUP_DIR/secrets.yaml"
|
local cluster_backup_dir="$1"
|
||||||
# kubectl get configmaps -A -o yaml > "$BACKUP_DIR/configmaps.yaml"
|
local etcd_backup_file="$cluster_backup_dir/etcd-snapshot.db"
|
||||||
|
|
||||||
# Back up persistent volumes
|
echo "Creating etcd snapshot..."
|
||||||
# TODO: Add logic to back up persistent volume data
|
|
||||||
|
# For Talos, we use talosctl to create etcd snapshots
|
||||||
|
if command -v talosctl >/dev/null 2>&1; then
|
||||||
|
# Try to get etcd snapshot via talosctl (works for Talos clusters)
|
||||||
|
local control_plane_nodes
|
||||||
|
control_plane_nodes=$(kubectl get nodes -l node-role.kubernetes.io/control-plane -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}' | tr ' ' '\n' | head -1)
|
||||||
|
|
||||||
|
if [[ -n "$control_plane_nodes" ]]; then
|
||||||
|
echo "Using talosctl to backup etcd from control plane node: $control_plane_nodes"
|
||||||
|
if talosctl --nodes "$control_plane_nodes" etcd snapshot "$etcd_backup_file"; then
|
||||||
|
echo " etcd backup created: $etcd_backup_file"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo " talosctl etcd snapshot failed, trying alternative method..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " No control plane nodes found for talosctl method"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Alternative: Try to backup via etcd pod if available
|
||||||
|
local etcd_pod
|
||||||
|
etcd_pod=$(kubectl get pods -n kube-system -l component=etcd -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
|
||||||
|
|
||||||
|
if [[ -n "$etcd_pod" ]]; then
|
||||||
|
echo "Using etcd pod: $etcd_pod"
|
||||||
|
# Create snapshot using etcdctl inside the etcd pod
|
||||||
|
if kubectl exec -n kube-system "$etcd_pod" -- etcdctl \
|
||||||
|
--endpoints=https://127.0.0.1:2379 \
|
||||||
|
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
|
||||||
|
--cert=/etc/kubernetes/pki/etcd/server.crt \
|
||||||
|
--key=/etc/kubernetes/pki/etcd/server.key \
|
||||||
|
snapshot save /tmp/etcd-snapshot.db; then
|
||||||
|
|
||||||
|
# Copy snapshot out of pod
|
||||||
|
kubectl cp -n kube-system "$etcd_pod:/tmp/etcd-snapshot.db" "$etcd_backup_file"
|
||||||
|
|
||||||
|
# Clean up temporary file in pod
|
||||||
|
kubectl exec -n kube-system "$etcd_pod" -- rm -f /tmp/etcd-snapshot.db
|
||||||
|
|
||||||
|
echo " etcd backup created: $etcd_backup_file"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo " etcd pod snapshot failed"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " No etcd pod found in kube-system namespace"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Final fallback: Try direct etcdctl if available on local system
|
||||||
|
if command -v etcdctl >/dev/null 2>&1; then
|
||||||
|
echo "Attempting local etcdctl backup..."
|
||||||
|
# This would need proper certificates and endpoints configured
|
||||||
|
echo " Local etcdctl backup not implemented (requires certificate configuration)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " Warning: Could not create etcd backup - no working method found"
|
||||||
|
echo " Consider installing talosctl or ensuring etcd pods are accessible"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Back up Kubernetes cluster resources
|
||||||
|
if [ "$BACKUP_CLUSTER" = true ]; then
|
||||||
|
echo "Backing up Kubernetes cluster resources..."
|
||||||
|
CLUSTER_BACKUP_DIR="$STAGING_DIR/cluster"
|
||||||
|
|
||||||
|
# Clean up any existing cluster backup files
|
||||||
|
if [[ -d "$CLUSTER_BACKUP_DIR" ]]; then
|
||||||
|
echo "Cleaning up existing cluster backup files..."
|
||||||
|
rm -rf "$CLUSTER_BACKUP_DIR"
|
||||||
|
fi
|
||||||
|
mkdir -p "$CLUSTER_BACKUP_DIR"
|
||||||
|
|
||||||
|
kubectl get all -A -o yaml > "$CLUSTER_BACKUP_DIR/all-resources.yaml"
|
||||||
|
kubectl get secrets -A -o yaml > "$CLUSTER_BACKUP_DIR/secrets.yaml"
|
||||||
|
kubectl get configmaps -A -o yaml > "$CLUSTER_BACKUP_DIR/configmaps.yaml"
|
||||||
|
kubectl get persistentvolumes -o yaml > "$CLUSTER_BACKUP_DIR/persistentvolumes.yaml"
|
||||||
|
kubectl get persistentvolumeclaims -A -o yaml > "$CLUSTER_BACKUP_DIR/persistentvolumeclaims.yaml"
|
||||||
|
kubectl get storageclasses -o yaml > "$CLUSTER_BACKUP_DIR/storageclasses.yaml"
|
||||||
|
|
||||||
|
echo "Backing up etcd..."
|
||||||
|
backup_etcd "$CLUSTER_BACKUP_DIR"
|
||||||
|
|
||||||
|
echo "Cluster resources backed up to $CLUSTER_BACKUP_DIR"
|
||||||
|
|
||||||
|
# Upload cluster backup to restic
|
||||||
|
echo "Uploading cluster backup to restic..."
|
||||||
|
restic --verbose --tag wild-cloud --tag cluster --tag "$(date +%Y-%m-%d)" backup "$CLUSTER_BACKUP_DIR"
|
||||||
|
echo "Cluster backup completed."
|
||||||
|
else
|
||||||
|
echo "Skipping cluster backup."
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Backup completed: $BACKUP_DIR"
|
echo "Backup completed: $BACKUP_DIR"
|
||||||
|
Reference in New Issue
Block a user