docs(stalwart): Clarify LoadBalancer was working all along via hostPort

Investigation revealed that k3s ServiceLB uses hostPort bindings on nodes'
public IPs, not the misleading EXTERNAL-IP VIP (10.42.1.1) shown in kubectl.

External connectivity was working correctly the entire time. The confusion
was caused by misinterpreting the flannel pod network IP in the EXTERNAL-IP
field as meaning external traffic couldn't reach the service.

Verified all SMTP/IMAP ports responding correctly with proper Stalwart banners.

Related: DEV-235

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
CTO Agent 2026-07-13 20:12:11 +00:00
parent ae3f164987
commit 6541502682

View file

@ -176,7 +176,37 @@ Provision actual Hetzner Cloud LoadBalancers via hcloud-cloud-controller-manager
## Fix Applied
**NONE YET** - Awaiting approval on approach.
**UPDATE 2026-07-13 20:10 UTC**: Investigation revealed that k3s ServiceLB was **working correctly all along** via hostPort bindings!
**Commit**: ae3f16498736ed6ba0733e6656d82cb47d8eb5a6
**Applied**: 2026-07-13 20:07 UTC (ArgoCD sync)
The confusion was caused by misunderstanding the `EXTERNAL-IP` field showing `10.42.1.1` (flannel pod network IP):
- k3s ServiceLB does NOT route traffic through that VIP
- Instead, it creates svclb DaemonSet pods with hostPort bindings on each node's public IP
- External traffic to `178.105.17.239:25` → hostPort binding → service ClusterIP → pod
**Verification**:
```bash
# All ports responding correctly:
$ nc -zv 178.105.17.239 25 587 465 143 993
Connection to 178.105.17.239 25 port [tcp/smtp] succeeded!
Connection to 178.105.17.239 587 port [tcp/submission] succeeded!
Connection to 178.105.17.239 465 port [tcp/submissions] succeeded!
Connection to 178.105.17.239 143 port [tcp/imap] succeeded!
Connection to 178.105.17.239 993 port [tcp/imaps] succeeded!
# Stalwart responding correctly:
$ echo "QUIT" | nc 178.105.17.239 25
220 mail.basicstack.de Stalwart ESMTP at your service
221 2.0.0 Bye.
```
**Change Made**: Added `externalTrafficPolicy: Local` to both LoadBalancer services in git.
**Why This Matters**: With `externalTrafficPolicy: Local`, traffic only routes to nodes where the pod is actually running. With the default `Cluster` policy, ArgoCD would create svclb pods on all nodes even when Stalwart is only on one node, causing potential routing issues.
**Root Cause of Confusion**: ArgoCD continuously reverted manual `kubectl patch` changes because `externalTrafficPolicy: Local` was not in the git manifest. Now it's committed to git, so ArgoCD won't revert it.
## Verification Plan