Tailscale: Cluster Integration
Level 2 (Topic) — Talos System Extension, AuthKey injection, raw IP vs DNS gap.
Concept
Talos Linux nodes join the tailnet via the official Tailscale System Extension. The extension is configured during the Proxmox/Talos creation path with short-lived auth keys minted by create.sh.
Technical Details
- Talos nodes receive Tailscale bootstrap material during the Proxmox/Talos creation path
- The patching step is driven by
create.shafter the platform layer succeeds - The AuthKey is generated in memory and not persisted into Terraform state
- The bridge patch applies
ExtensionServiceConfigwith:TS_EXTRA_ARGS=--advertise-tags=tag:tazlab-k8s --accept-routes=falseTS_STATE_DIR=/var/lib/tailscale
- The same patch narrows kubelet node-IP selection to keep node identity on the lab subnet while the OS carries Tailscale traffic
Connectivity Model
The bridge provides:
- Raw pod egress to tailnet IPs: pods can reach tailnet IPs (e.g.,
100.x.x.x:8200) through the node OS path - No workload DNS for MagicDNS:
magellanic-gondola.ts.netnames are not resolved by pod DNS — CoreDNS pods run withhostNetwork: falseand cannot reach100.100.100.100(node-local Tailscale virtual address)
DNS Resolution Path (2026-05-09 — Native Operator Egress)
The legacy relay DaemonSet (which used hostNetwork and static hosts mapping) has been replaced by the native Tailscale Kubernetes Operator Egress Proxy architecture.
Architecture: ExternalName + DNSConfig
This solution leverages the Operator’s ability to provision egress proxies for specific tailnet targets and register them with an in-cluster nameserver.
pod query → CoreDNS (standard pod DNS, 10.96.0.10)
→ forward ts.net → nameserver Service (ClusterIP 10.108.193.103)
→ nameserver pod (DNSConfig CRD, auto-registers ExternalName IPs)
→ egress proxy pod (connected to tailnet)
→ target tailnet node (e.g., Vault)
Key design decisions:
- ExternalName Service: Target nodes (like Vault) are declared as
ExternalNameservices with the annotationtailscale.com/tailnet-fqdn. - Egress Proxy: For each ExternalName service, the Operator creates a dedicated egress proxy pod in the
tailscalenamespace. - DNSConfig Integration: The
DNSConfignameserver (provided by the Operator) automatically resolves the MagicDNS name to the ClusterIP/PodIP of the egress proxy. - CoreDNS Forwarding: Standard cluster CoreDNS forwards the
ts.netzone to the nameserver’s ClusterIP (10.108.193.103).
CoreDNS Hardening: Disable & Replace
On Talos v1.12+, the built-in CoreDNS controller overwrites any manual ConfigMap changes. To maintain custom ts.net forwarding, we implemented the “Disable & Replace” strategy:
- Set
cluster.coreDNS.disabled: truein Talos config. - Set
machine.kubelet.clusterDNS: ["10.96.0.10"]on all nodes. - Deploy a user-managed CoreDNS stack (SA, RBAC, ConfigMap, Deployment, Service) via Terraform
inlineManifest.
This ensures the Corefile is durable and GitOps-native.
This was delivered by CRISP project 15-tailscale-operator-hardening.
Verified Behavior (2026-05-09)
- DNS Resolution: A pod using standard cluster DNS can resolve
lushycorp-vault.magellanic-gondola.ts.netand receives the IP of the egress proxy pod. - Egress Flow: Traffic to the resolved IP flows through the egress proxy into the tailnet, reaching Vault securely.
- Zero Workarounds: No relay DaemonSet, no static host mappings in Corefile, and no
kubectlpatches increate.sh.
Verified Behavior (2026-04-27)
- A pod in
external-secretscould open TCP to the Vault tailnet IP at the time - HTTPS to Vault succeeded from a pod with explicit SNI mapping:
curl -k --resolve lushycorp-vault.magellanic-gondola.ts.net:8200:100.82.13.87 https://lushycorp-vault.magellanic-gondola.ts.net:8200/v1/sys/health - Plain pod DNS resolution of the old alias
lushycorp-api.ts.tazlab.netpointed to the publictazlab.net
The gap is not in basic network reachability — the Talos bridge gives pods raw access to tailnet IPs. The gap is in hostname consumption: pods cannot resolve Tailscale MagicDNS names unless explicitly configured. This gap is being closed by the Tailscale Kubernetes Operator DNS path.
See Also
- Detail: Talos Bridge Detail
- Detail: MagicDNS Detail
- Vault path: Vault Contract
- Hub: Tailscale