From 9c5511ac5dee8ba463239b28458f5969fd89f55b Mon Sep 17 00:00:00 2001 From: "A. F. Dudley" Date: Tue, 3 Mar 2026 03:55:54 +0000 Subject: [PATCH] feat(k8s): map compose service ports to Kind extraPortMappings and support hostNetwork _generate_kind_port_mappings now reads ports from compose services and adds them to Kind's extraPortMappings with correct protocol handling (TCP/UDP). Previously only ports 80/443 for Caddy were mapped, so application ports like Solana gossip/RPC were unreachable from the host. Also adds hostNetwork support: when any compose service declares network_mode: host, the K8s pod spec gets hostNetwork: true and dnsPolicy: ClusterFirstWithHostNet. This is required for workloads like Solana validators that need direct host networking for UDP gossip and TPU protocols. Co-Authored-By: Claude Opus 4.6 --- stack_orchestrator/deploy/k8s/cluster_info.py | 13 +++++++++++ stack_orchestrator/deploy/k8s/helpers.py | 23 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/stack_orchestrator/deploy/k8s/cluster_info.py b/stack_orchestrator/deploy/k8s/cluster_info.py index da24bdc2..0011db7a 100644 --- a/stack_orchestrator/deploy/k8s/cluster_info.py +++ b/stack_orchestrator/deploy/k8s/cluster_info.py @@ -568,6 +568,15 @@ class ClusterInfo: ) ) + # Check if any compose service declares network_mode: host + use_host_network = False + for pod_name in self.parsed_pod_yaml_map: + pod = self.parsed_pod_yaml_map[pod_name] + for svc in pod.get("services", {}).values(): + if svc.get("network_mode") == "host": + use_host_network = True + break + template = client.V1PodTemplateSpec( metadata=client.V1ObjectMeta(annotations=annotations, labels=labels), spec=client.V1PodSpec( @@ -577,6 +586,10 @@ class ClusterInfo: affinity=affinity, tolerations=tolerations, runtime_class_name=self.spec.get_runtime_class(), + host_network=use_host_network or None, + dns_policy=( + "ClusterFirstWithHostNet" if use_host_network else None + ), ), ) spec = client.V1DeploymentSpec( diff --git a/stack_orchestrator/deploy/k8s/helpers.py b/stack_orchestrator/deploy/k8s/helpers.py index 8b367f86..c3f869f1 100644 --- a/stack_orchestrator/deploy/k8s/helpers.py +++ b/stack_orchestrator/deploy/k8s/helpers.py @@ -683,11 +683,34 @@ def _generate_kind_port_mappings_from_services(parsed_pod_files): def _generate_kind_port_mappings(parsed_pod_files): port_definitions = [] + seen = set() # Map port 80 and 443 for the Caddy ingress controller (HTTPS support) for port_string in ["80", "443"]: port_definitions.append( f" - containerPort: {port_string}\n hostPort: {port_string}\n" ) + seen.add((port_string, "TCP")) + # Map ports declared in compose services + for pod in parsed_pod_files: + parsed_pod_file = parsed_pod_files[pod] + if "services" in parsed_pod_file: + for service_name in parsed_pod_file["services"]: + service_obj = parsed_pod_file["services"][service_name] + for port_entry in service_obj.get("ports", []): + port_str = str(port_entry) + if "/" in port_str: + port_num, proto = port_str.split("/", 1) + proto = proto.upper() + else: + port_num = port_str.strip("'\"") + proto = "TCP" + if (port_num, proto) not in seen: + seen.add((port_num, proto)) + port_definitions.append( + f" - containerPort: {port_num}\n" + f" hostPort: {port_num}\n" + f" protocol: {proto}\n" + ) return ( "" if len(port_definitions) == 0