From d31f76eb5a130e0c632029dec82da06800f0e58c Mon Sep 17 00:00:00 2001 From: "A. F. Dudley" Date: Sun, 25 Jan 2026 19:12:44 -0500 Subject: [PATCH] Add etcd + PKI extraMounts for offline data recovery Mount /var/lib/etcd and /etc/kubernetes/pki to host filesystem so cluster state is preserved for offline recovery. Each deployment gets its own backup directory keyed by deployment ID. Directory structure: data/cluster-backups/{deployment_id}/etcd/ data/cluster-backups/{deployment_id}/pki/ This enables extracting secrets from etcd backups using etcdctl with the preserved PKI certificates. Co-Authored-By: Claude Opus 4.5 --- stack_orchestrator/deploy/k8s/helpers.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/stack_orchestrator/deploy/k8s/helpers.py b/stack_orchestrator/deploy/k8s/helpers.py index 695a56b2..32d8c116 100644 --- a/stack_orchestrator/deploy/k8s/helpers.py +++ b/stack_orchestrator/deploy/k8s/helpers.py @@ -339,6 +339,25 @@ def _generate_kind_mounts(parsed_pod_files, deployment_dir, deployment_context): volume_host_path_map = _get_host_paths_for_volumes(deployment_context) seen_host_path_mounts = set() # Track to avoid duplicate mounts + # Cluster state backup for offline data recovery (unique per deployment) + # etcd contains all k8s state; PKI certs needed to decrypt etcd offline + deployment_id = deployment_context.id + backup_subdir = f"cluster-backups/{deployment_id}" + + etcd_host_path = _make_absolute_host_path( + Path(f"./data/{backup_subdir}/etcd"), deployment_dir + ) + volume_definitions.append( + f" - hostPath: {etcd_host_path}\n" f" containerPath: /var/lib/etcd\n" + ) + + pki_host_path = _make_absolute_host_path( + Path(f"./data/{backup_subdir}/pki"), deployment_dir + ) + volume_definitions.append( + f" - hostPath: {pki_host_path}\n" f" containerPath: /etc/kubernetes/pki\n" + ) + # Note these paths are relative to the location of the pod files (at present) # So we need to fix up to make them correct and absolute because kind assumes # relative to the cwd.