tailscale namespace. Two platform behaviors shape the configuration:
- Exposing an in-cluster Service through the Tailscale operator lets tailnet devices connect to it. Outbound connections from a Pod to a tailnet device require Tailscale’s cluster egress feature.
- Sandbox egress rules are allow-only over a default-deny baseline, and
EgressRule(any=True)excludes cluster-internal addresses. An in-cluster destination such as a Tailscale proxy is reachable only through aselectorortenantrule.
Prerequisites
- A CKS cluster with a managed sandbox runner whose
installStatusisREADY. See Use your own compute. - The Tailscale Kubernetes Operator installed on that cluster, with your tailnet policy file configured for CKS. See Deploy the Tailscale Kubernetes Operator.
- The MagicDNS name of the tailnet device you want to reach, such as
db-host.[TAILNET-NAME].ts.net, and the port your service listens on. - A runner policy that permits this selector egress rule. An
anyentitlement never covers selectors, so a policy with a nonemptyallowed_egressmust carry aselectorentitlement that matches in form: it must also setnamespace_labels, and its labels must be a subset of the ones the sandbox declares, and its port filter must cover TCP port 8080. SeeSelectorBlock. - The
cwsandboxPython SDK configured with credentials for CKS placement, and a sandbox image withcurlandgetentinstalled. kubectlaccess to create or update Services in thedefaultnamespace and list Pods in the operator’s namespace.- A tailnet policy that allows the egress proxy to connect to the target device and application port.
Create a Tailscale egress Service
Create anExternalName Service annotated with the tailnet device’s MagicDNS name. The operator creates a proxy Pod and a headless Service in its own namespace, then points the ExternalName Service at that headless Service. The examples use tailscale, as in the linked installation guide; if you installed the operator in another namespace, update the commands and namespace_labels below.
Replace [TAILNET-FQDN] with the device’s MagicDNS name. This example creates the Service in default and uses its fully qualified DNS name so sandboxes can connect from other namespaces. It assumes an HTTP service on port 8080 with a /health endpoint; adjust the port and path for your service.
tailnet-egress.yaml
internal-api.default.svc.cluster.local:8080. The short name internal-api:8080 works only from the Service’s namespace. If your cluster uses a DNS suffix other than cluster.local, replace that suffix in the examples.
Confirm that the operator created the proxy Pod:
Grant the sandbox egress to the proxy
Select the proxy Pod by label in anEgressRule. The rule requires both label sets:
pod_labelsidentifies the proxy by the Service it fronts, through the operator’stailscale.com/parent-resourceandtailscale.com/parent-resource-nslabels. Include the namespace label so the rule doesn’t also match a proxy for a same-named Service in another namespace.namespace_labelsselects thetailscalenamespace. Without it, the rule applies only to the sandbox’s own namespace and doesn’t reach a proxy in another namespace.
ports to the same port the service listens on. Replace [RUNNER-ID] with the ID of the runner on the cluster where you created the Service. Without runner_ids, CKS placement can use any eligible runner in your organization, including one on a cluster without the proxy.
ProxyGroup uses shared proxy Pods and remaps ports, so this rule isn’t a complete configuration for that mode. See Tailscale’s high-availability egress guide.
Cluster DNS stays reachable unless the runner policy denies DNS egress on the dns_egress constraint, so the sandbox resolves the Service name without an additional rule.
Verify the connection
The example prints the HTTP response headers and body, plus any curl errors. For a health endpoint that returns status 200, expect a status line such asHTTP/1.1 200 OK followed by the service’s health response. An HTTP error such as 401 or 404 shows that an HTTP server responded; check application authentication or the requested path.
A timeout or connection error can occur between the sandbox and proxy, between the proxy and tailnet device, or at the application. To check DNS and the HTTP exchange separately, run this diagnostic example with your runner ID:
Troubleshoot
Related pages
- Deploy the Tailscale Kubernetes Operator: deploy and configure the operator on CKS.
- Network rules: the full
EgressRuleandSelectorBlockreference. - Policy reference: the policy entitlements a declared egress rule must fit inside.
- Public endpoints: give a service inside a sandbox a public address.