feat(k8s): add kind-mount-root for unified kind extraMount

When kind-mount-root is set in spec.yml, emit a single extraMount
mapping the root to /mnt instead of per-volume mounts. This allows
adding new volumes without recreating the kind cluster.

Volumes whose host path is under the root are skipped for individual
extraMounts and their PV paths resolve to /mnt/{relative_path}.
Volumes outside the root keep individual extraMounts as before.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix/k8s-port-mappings-v5
A. F. Dudley 2026-03-04 16:41:16 +00:00
parent f305214ce1
commit 7cd5043a83
4 changed files with 29 additions and 2 deletions

View File

@ -45,3 +45,4 @@ runtime_class_key = "runtime-class"
high_memlock_runtime = "high-memlock" high_memlock_runtime = "high-memlock"
high_memlock_spec_filename = "high-memlock-spec.json" high_memlock_spec_filename = "high-memlock-spec.json"
acme_email_key = "acme-email" acme_email_key = "acme-email"
kind_mount_root_key = "kind-mount-root"

View File

@ -371,7 +371,11 @@ class ClusterInfo:
if self.spec.is_kind_deployment(): if self.spec.is_kind_deployment():
host_path = client.V1HostPathVolumeSource( host_path = client.V1HostPathVolumeSource(
path=get_kind_pv_bind_mount_path(volume_name) path=get_kind_pv_bind_mount_path(
volume_name,
kind_mount_root=self.spec.get_kind_mount_root(),
host_path=volume_path,
)
) )
else: else:
host_path = client.V1HostPathVolumeSource(path=volume_path) host_path = client.V1HostPathVolumeSource(path=volume_path)

View File

@ -440,7 +440,11 @@ def named_volumes_from_pod_files(parsed_pod_files):
return named_volumes return named_volumes
def get_kind_pv_bind_mount_path(volume_name: str): def get_kind_pv_bind_mount_path(volume_name: str, kind_mount_root: Optional[str] = None,
host_path: Optional[str] = None):
if kind_mount_root and host_path and host_path.startswith(kind_mount_root):
rel = os.path.relpath(host_path, kind_mount_root)
return f"/mnt/{rel}"
return f"/mnt/{volume_name}" return f"/mnt/{volume_name}"
@ -563,6 +567,7 @@ def _generate_kind_mounts(parsed_pod_files, deployment_dir, deployment_context):
volume_definitions = [] volume_definitions = []
volume_host_path_map = _get_host_paths_for_volumes(deployment_context) volume_host_path_map = _get_host_paths_for_volumes(deployment_context)
seen_host_path_mounts = set() # Track to avoid duplicate mounts seen_host_path_mounts = set() # Track to avoid duplicate mounts
kind_mount_root = deployment_context.spec.get_kind_mount_root()
# Cluster state backup for offline data recovery (unique per deployment) # Cluster state backup for offline data recovery (unique per deployment)
# etcd contains all k8s state; PKI certs needed to decrypt etcd offline # etcd contains all k8s state; PKI certs needed to decrypt etcd offline
@ -583,6 +588,17 @@ def _generate_kind_mounts(parsed_pod_files, deployment_dir, deployment_context):
f" - hostPath: {pki_host_path}\n" f" containerPath: /etc/kubernetes/pki\n" f" - hostPath: {pki_host_path}\n" f" containerPath: /etc/kubernetes/pki\n"
) )
# When kind-mount-root is set, emit a single extraMount for the root.
# Individual volumes whose host path starts with the root are covered
# by this single mount and don't need their own extraMount entries.
mount_root_emitted = False
if kind_mount_root:
volume_definitions.append(
f" - hostPath: {kind_mount_root}\n"
f" containerPath: /mnt\n"
)
mount_root_emitted = True
# Note these paths are relative to the location of the pod files (at present) # 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 # So we need to fix up to make them correct and absolute because kind assumes
# relative to the cwd. # relative to the cwd.
@ -642,6 +658,9 @@ def _generate_kind_mounts(parsed_pod_files, deployment_dir, deployment_context):
volume_host_path_map[volume_name], volume_host_path_map[volume_name],
deployment_dir, deployment_dir,
) )
# Skip individual extraMount if covered by mount root
if mount_root_emitted and str(host_path).startswith(kind_mount_root):
continue
container_path = get_kind_pv_bind_mount_path( container_path = get_kind_pv_bind_mount_path(
volume_name volume_name
) )

View File

@ -202,5 +202,8 @@ class Spec:
def is_kind_deployment(self): def is_kind_deployment(self):
return self.get_deployment_type() in [constants.k8s_kind_deploy_type] return self.get_deployment_type() in [constants.k8s_kind_deploy_type]
def get_kind_mount_root(self):
return self.obj.get(constants.kind_mount_root_key)
def is_docker_deployment(self): def is_docker_deployment(self):
return self.get_deployment_type() in [constants.compose_deploy_type] return self.get_deployment_type() in [constants.compose_deploy_type]