Skip to content

Commit debee2e

Browse files
committed
fix(k8s): publish host aliases to coredns-custom instead of patching Corefile
Signed-off-by: Oleksander Piskun <oleksandr2088@icloud.com>
1 parent 21b30a1 commit debee2e

1 file changed

Lines changed: 66 additions & 50 deletions

File tree

haproxy_agent.py

Lines changed: 66 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,79 +2071,95 @@ def _k8s_parse_host_aliases() -> list[dict[str, Any]]:
20712071

20722072

20732073
async def _k8s_ensure_coredns_host_aliases() -> None:
2074-
"""Patch CoreDNS to resolve HP_K8S_HOST_ALIASES cluster-wide."""
2074+
"""Publish HP_K8S_HOST_ALIASES into the 'coredns-custom' ConfigMap so they resolve cluster-wide.
2075+
2076+
Uses k3s's /etc/coredns/custom/*.server import convention (also honoured by any CoreDNS
2077+
Deployment that mounts a 'coredns-custom' ConfigMap with optional=true). The main
2078+
'coredns' ConfigMap managed by the distribution operator is never touched; the 'reload'
2079+
plugin present in the stock Corefile picks up the new file within seconds, so no
2080+
Deployment restart is needed either. The ConfigMap key is prefixed 'harp-' so other
2081+
operators writing unrelated keys into 'coredns-custom' are not disturbed.
2082+
"""
20752083
if not K8S_ENABLED or not K8S_HOST_ALIASES_RAW.strip():
20762084
return
20772085

20782086
host_aliases = _k8s_parse_host_aliases()
20792087
if not host_aliases:
20802088
return
20812089

2082-
LOGGER.info("Ensuring CoreDNS resolves host aliases: %s", K8S_HOST_ALIASES_RAW)
2090+
# Build one standalone Corefile server block per zone. Entries share a single block
2091+
# to keep the file compact and to avoid plugin-instance conflicts between zones.
2092+
hosts_entries: list[str] = []
2093+
zone_names: list[str] = []
2094+
for alias in host_aliases:
2095+
for hostname in alias["hostnames"]:
2096+
hosts_entries.append(f" {alias['ip']} {hostname}")
2097+
zone_names.append(f"{hostname}:53")
2098+
2099+
server_file = (
2100+
f"{' '.join(zone_names)} {{\n"
2101+
" hosts {\n"
2102+
f"{chr(10).join(hosts_entries)}\n"
2103+
" fallthrough\n"
2104+
" }\n"
2105+
" forward . /etc/resolv.conf\n"
2106+
"}\n"
2107+
)
20832108

2084-
try:
2085-
status, data, _text = await _k8s_request(
2086-
"GET", "/api/v1/namespaces/kube-system/configmaps/coredns",
2087-
)
2088-
if status != 200 or not data:
2089-
LOGGER.warning("Could not read CoreDNS ConfigMap (HTTP %d), skipping.", status)
2090-
return
2109+
cm_path = "/api/v1/namespaces/kube-system/configmaps/coredns-custom"
2110+
key = "harp-host-aliases.server"
20912111

2092-
corefile = data.get("data", {}).get("Corefile", "")
2093-
if not corefile:
2094-
LOGGER.warning("CoreDNS ConfigMap has no Corefile entry, skipping.")
2095-
return
2112+
LOGGER.info("Publishing %d host alias zone(s) into coredns-custom: %s", len(zone_names), K8S_HOST_ALIASES_RAW)
20962113

2097-
hosts_lines: list[str] = []
2098-
for alias in host_aliases:
2099-
for hostname in alias["hostnames"]:
2100-
hosts_lines.append(f" {alias['ip']} {hostname}")
2101-
hosts_block = "hosts {\n" + "\n".join(hosts_lines) + "\n fallthrough\n }"
2102-
2103-
hosts_re = re.compile(r"hosts\s*\{[^}]*\}")
2104-
if hosts_re.search(corefile):
2105-
new_corefile = hosts_re.sub(hosts_block, corefile, count=1)
2106-
elif "forward ." in corefile:
2107-
new_corefile = corefile.replace("forward .", f"{hosts_block}\n forward .", 1)
2108-
else:
2109-
LOGGER.warning(
2110-
"CoreDNS Corefile has no 'hosts' block and no 'forward' directive, cannot patch."
2114+
try:
2115+
status, existing, _text = await _k8s_request("GET", cm_path)
2116+
2117+
if status == 404:
2118+
configmap = {
2119+
"apiVersion": "v1",
2120+
"kind": "ConfigMap",
2121+
"metadata": {
2122+
"name": "coredns-custom",
2123+
"namespace": "kube-system",
2124+
"labels": {"app.kubernetes.io/managed-by": "harp"},
2125+
},
2126+
"data": {key: server_file},
2127+
}
2128+
status, _, _text = await _k8s_request(
2129+
"POST",
2130+
"/api/v1/namespaces/kube-system/configmaps",
2131+
json_body=configmap,
21112132
)
2133+
if status in (200, 201):
2134+
LOGGER.info("Created coredns-custom ConfigMap with HaRP host aliases.")
2135+
else:
2136+
LOGGER.warning("Failed to create coredns-custom (HTTP %d): %s", status, _text[:200])
21122137
return
21132138

2114-
if new_corefile == corefile:
2115-
LOGGER.info("CoreDNS already has correct host aliases, no patch needed.")
2139+
if status != 200 or not isinstance(existing, dict):
2140+
LOGGER.warning("Could not read coredns-custom (HTTP %d), skipping.", status)
21162141
return
21172142

2118-
status, _, _text = await _k8s_request(
2119-
"PATCH",
2120-
"/api/v1/namespaces/kube-system/configmaps/coredns",
2121-
json_body={"data": {"Corefile": new_corefile}},
2122-
content_type="application/strategic-merge-patch+json",
2123-
)
2124-
if status != 200:
2125-
LOGGER.warning("Failed to patch CoreDNS ConfigMap (HTTP %d): %s", status, _text[:200])
2143+
current = (existing.get("data") or {}).get(key)
2144+
if current == server_file:
2145+
LOGGER.info("coredns-custom already carries the expected HaRP host aliases, no patch needed.")
21262146
return
21272147

2128-
restart_annotation = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
2148+
# Strategic merge patch on ConfigMap.data merges keys individually — unrelated keys
2149+
# written by other operators stay intact.
21292150
status, _, _text = await _k8s_request(
21302151
"PATCH",
2131-
"/apis/apps/v1/namespaces/kube-system/deployments/coredns",
2132-
json_body={
2133-
"spec": {"template": {"metadata": {"annotations": {
2134-
"harp.nextcloud.com/restartedAt": restart_annotation,
2135-
}}}}
2136-
},
2152+
cm_path,
2153+
json_body={"data": {key: server_file}},
21372154
content_type="application/strategic-merge-patch+json",
21382155
)
2139-
if status != 200:
2140-
LOGGER.warning("Failed to restart CoreDNS Deployment (HTTP %d): %s", status, _text[:200])
2141-
return
2142-
2143-
LOGGER.info("CoreDNS patched and restarted with host aliases: %s", K8S_HOST_ALIASES_RAW)
2156+
if status == 200:
2157+
LOGGER.info("Updated coredns-custom with HaRP host aliases.")
2158+
else:
2159+
LOGGER.warning("Failed to patch coredns-custom (HTTP %d): %s", status, _text[:200])
21442160

21452161
except Exception as exc:
2146-
LOGGER.warning("Failed to configure CoreDNS host aliases (non-fatal): %s", exc)
2162+
LOGGER.warning("Failed to configure coredns-custom host aliases (non-fatal): %s", exc)
21472163

21482164

21492165
def _k8s_build_deployment_manifest(payload: CreateExAppPayload, replicas: int) -> dict[str, Any]:

0 commit comments

Comments
 (0)