feat: Split DNS with correct IPs per service type

Fix dnsmasq reconciliation to use the correct DNS target IP:
- tcp-passthrough (k8s instances): DNS → k8s LB IP (LAN direct)
- http/static (Central apps): DNS → Central IP (HAProxy terminates)

Also handle ExtraDomains properly:
- Internal domains (internal.cloud.payne.io) get local=/ entries
  to prevent upstream DNS forwarding
- Extra domains get their own dnsmasq address= entries
- HAProxy already propagated ExtraDomains for SNI ACLs

Verified: cloud.payne.io → 192.168.8.240 (direct to k8s),
cloud2.payne.io → 192.168.8.80, central.payne.io → 192.168.8.151.
SNI routing through HAProxy works for both instances.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 15:46:35 +00:00
parent 7e8f660d11
commit ed0691d56f

View File

@@ -101,8 +101,9 @@ func (api *API) reconcileNetworking() {
}
// Generate dnsmasq DNS entries from registered services.
// All service domains resolve to Central's IP (where HAProxy listens).
// HAProxy then routes to the actual backend based on SNI or Host header.
// DNS target IP depends on service type:
// tcp-passthrough (k8s): DNS → k8s LB IP (LAN traffic goes direct to k8s)
// http/static: DNS → Central IP (HAProxy terminates TLS)
centralIP, _ := network.GetWildCentralIP()
if centralIP == "" {
centralIP = "127.0.0.1"
@@ -113,9 +114,27 @@ func (api *API) reconcileNetworking() {
if svc.Reach == services.ReachOff || svc.Domain == "" {
continue
}
// Choose the DNS target IP based on service type
dnsIP := centralIP
if svc.Backend.Type == services.BackendTCPPassthrough {
// k8s instances: LAN clients connect directly to the k8s LB
dnsIP = extractHost(svc.Backend.Address)
}
// Primary domain
ic := config.InstanceConfig{}
ic.Cloud.Domain = svc.Domain
ic.Cluster.LoadBalancerIp = centralIP // DNS points to Central, not the backend
ic.Cluster.LoadBalancerIp = dnsIP
// Extra domains (e.g., internal.cloud.payne.io)
for _, extra := range svc.ExtraDomains {
if strings.HasPrefix(extra, "internal.") {
// Internal-only domain: local=/ prevents upstream DNS forwarding
ic.Cloud.InternalDomain = extra
}
}
instanceConfigs = append(instanceConfigs, ic)
}