Add static endpoints to a cluster
Last validated:
This feature is available in Tailscale v1.86 and later, and is only available to proxies within ProxyGroups.
Tailscale uses various NAT traversal techniques to securely connect to other Tailscale nodes without manual intervention. Most of the time, you do not need to open any firewall ports for Tailscale. However, in some scenarios where NAT traversal is unsuccessful, Tailscale proxies deployed by the operator rely on a relayed connection, resulting in lower throughput and performance compared to direct connections. For example, when using AWS NAT Gateways, which are hard NATs.
In these scenarios, ProxyClass provides configuration to use Kubernetes NodePort services as extra endpoints to enable direct connections to ProxyGroups. After configuring, these endpoints work only for tailnet devices on the same network as that Kubernetes Node. If the Kubernetes Node has a public IP address, the configured static endpoint is reachable by all Tailscale devices.
Configure firewall rules
A maximum of two static endpoints are allowed per ProxyGroup. To specify which nodes the operator uses for NodePort Services, configure the spec.staticEndpoints.selector field in the ProxyClass resource.
To use static endpoints, configure inbound firewall rules for each relevant Node's IP address. Tailscale recommends configuring a sufficient number of ports on the firewall to avoid running out of ports as ProxyGroup replicas scale.
Configure static endpoints
To configure static endpoints, complete the following steps.
-
Create a
ProxyClass.The configuration for static endpoints is exposed as part of the
ProxyClasscustom resource, underspec.staticEndpoints:apiVersion: tailscale.com/v1alpha1 kind: ProxyClass metadata: name: prod spec: staticEndpoints: nodePort: ports: - "31667-31680" selector: kubernetes.io/os: linuxThe example above configures
ProxyClassto use Kubernetes NodePort services for the static endpoints. In thenodePortconfiguration, configure a list ofports. Ensure the specified ranges have the necessary firewall rules so the endpoints are reachable from other tailnet devices. Use theselectorfield to specify which Kubernetes node'sExternalIPs to use for the static endpoints.
After creating this ProxyClass, reference it on a ProxyGroup to configure static endpoints for all its replicas:
-
Create a
ProxyGroup.apiVersion: tailscale.com/v1alpha1 kind: ProxyGroup metadata: name: ingress spec: type: ingress proxyClass: prod replicas: 3After applying this configuration, the example creates three proxy replicas and three Kubernetes NodePort services to enable connections to the
ProxyGroupfrom other tailnet devices:NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE prod-0-nodeport NodePort 172.20.123.3 <none> 22918:31669/UDP 84m prod-1-nodeport NodePort 172.20.163.230 <none> 22918:31668/UDP 84m prod-2-nodeport NodePort 172.20.84.83 <none> 22918:31667/UDP 84m -
Test the connection.
After creating the
ProxyGroup, create a testPodand expose it using an HA cluster ingress to test the static endpoint:apiVersion: v1 kind: Pod metadata: name: test namespace: default labels: app: test spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: test namespace: default annotations: tailscale.com/proxy-group: ingress spec: type: LoadBalancer loadBalancerClass: tailscale selector: app: test ports: - port: 80 targetPort: 80 protocol: TCPRun
kubectl get service -n defaultto find the TailscaleServiceIP address used to expose thePodto the tailnet.NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE test LoadBalancer 172.20.50.164 100.64.1.2 80:31109/TCP 2m17sTest for a direct connection to the
Podin your tailnet by using the TailscaleServiceIP address:tailscale ping <external-ip>If a direct connection is successful, observe a log output similar to:
pong from prod-0 (100.64.1.1) via 203.0.113.1:31670 in 91msIf unsuccessful, observe a log output similar to:
pong from prod-0 (100.64.1.1) via DERP(nyc) in 90msIf this log output is observed, ensure that:
-
Inbound firewall rules are configured appropriately for traffic to flow to the correct Kubernetes nodes and port ranges, as configured in the
ProxyClass. -
Selected nodes using
spec.staticEndpoints.nodePort.selectorhaveExternalIPs instatus.addresses. -
The
staticEndpointsfield on theProxyGroup'sstatus.devicesis populated with the correct address using a validExternalIPand the correctNodePortfor that replica'sService.
-