Access tailnet resources from your cluster with Egress
Last validated:
Cluster egress lets workloads running in your Kubernetes cluster access devices and services on your tailnet, without those workloads needing to run Tailscale themselves.
This topic explains egress architecture and available proxy modes.
Overview
Egress works by creating a Kubernetes ExternalName Service that acts as an in-cluster proxy to a tailnet target. Your workloads connect to this Service like any other Kubernetes Service, and the egress proxy forwards the traffic over the tailnet to the target device.
You can target a tailnet device by either:
- MagicDNS name: Use the
tailscale.com/tailnet-fqdnannotation (for example,db.example.ts.net). The proxy resolves the FQDN using the tailnet netmap and updates automatically if the target's IP address changes. - Tailnet IP address: Use the
tailscale.com/tailnet-target-ipannotation. The proxy forwards directly to the specified IP address.
Both standalone and high-availability configurations are supported. Standalone mode runs a single egress proxy pod, while high-availability mode uses a ProxyGroup with multiple replicas. High-availability mode is recommended for production use cases.
Standalone egress
In standalone mode, you annotate an ExternalName Service with the tailnet target. On creation of the Service, the operator:
- Creates a headless
Servicepointing at the egress proxy pod. - Creates a combined config and state
Secret. - Creates an egress proxy
Pod(single replicaStatefulSet) that forwards traffic to the tailnet target. - Updates the
ExternalNameServiceto point at the headlessService.
Your workloads' DNS queries for the ExternalName Service resolve to the headless Service, which routes to the egress proxy pod. The proxy pod uses iptables or nftables DNAT rules to forward traffic over the tailnet to the target device.
To get started with egress, refer to the guides in Further exploration.
High-availability (HA) egress
A high-availability egress is similar to the standalone variant, but uses a ProxyGroup with spec.type: egress to deploy multiple replicas. This lets you:
- Forward traffic to tailnet targets through multiple active egress proxies, preventing downtime during proxy pod restarts.
- Serve multiple
ExternalNameservices from a shared set of proxy pods.
You configure HA egress by adding a tailscale.com/proxy-group annotation to the ExternalName Service.
On creation of a correctly annotated ExternalName Service, the operator:
- Creates a
ClusterIPServiceandEndpointSliceper egress target in the operator's namespace. Each port defined on theExternalNameServiceis mapped to a randomly allocated port on theClusterIPService. - Updates the egress
ConfigMap(created with theProxyGroup) with the port mappings for this target. ThisConfigMapis mounted to allProxyGrouppods and tells each proxy which incoming ports map to which tailnet targets. - Updates the
ExternalNameServiceto point at theClusterIPService.
Traffic flows from your workload to the ExternalName Service, which resolves to the ClusterIP Service. kube-proxy routes traffic to the ProxyGroup pod IPs through the EndpointSlice. The proxy pod uses iptables or nftables DNAT rules to forward traffic over the tailnet.
HA egress supports graceful failover: when a proxy pod is terminated, in-flight connections are drained to other replicas automatically.
To get started with HA egress, refer to High availability with ProxyGroup.
Further exploration
- Access a tailnet device from your cluster by its MagicDNS name or tailnet IP address.
- Access an IP address behind a subnet router from your cluster workloads.
- Expose Amazon RDS to your tailnet through an egress proxy.
- Enable MagicDNS resolution so workloads can resolve tailnet names in your cluster.
- Configure high availability to run multiple egress proxy replicas for production.