Configure Tailscale with Kubernetes cluster networking integration

Intermediate 25 min Apr 16, 2026 160 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up Tailscale mesh VPN with Kubernetes cluster integration for secure pod-to-pod communication, subnet routing, and service discovery across distributed nodes.

Prerequisites

  • Running Kubernetes cluster
  • Tailscale account with admin access
  • Root access on all nodes
  • kubectl configured

What this solves

Tailscale provides secure, encrypted networking between Kubernetes nodes without complex VPN infrastructure. This tutorial shows you how to integrate Tailscale with your Kubernetes cluster to enable secure pod-to-pod communication, implement subnet routing for cluster networks, and configure service discovery across distributed environments.

Step-by-step configuration

Update system packages

Start by updating your package manager on all Kubernetes nodes to ensure compatibility with Tailscale.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install Tailscale on Kubernetes nodes

Add the Tailscale repository and install the client on each Kubernetes node. This enables secure networking between cluster nodes.

curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt update
sudo apt install -y tailscale
sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/rhel/9/tailscale.repo
sudo dnf install -y tailscale

Start Tailscale daemon

Enable and start the Tailscale daemon on all nodes. This creates the encrypted mesh network foundation.

sudo systemctl enable --now tailscaled
sudo systemctl status tailscaled

Authenticate control plane node

Connect the Kubernetes control plane node to your Tailscale network with subnet routing enabled. This allows the node to advertise cluster subnets.

sudo tailscale up --advertise-routes=10.96.0.0/12,10.244.0.0/16 --accept-routes
tailscale ip -4
Note: Replace the CIDR ranges with your actual cluster service network (10.96.0.0/12) and pod network (10.244.0.0/16). Check your cluster configuration with kubectl cluster-info dump | grep -E 'service-cluster-ip-range|cluster-cidr'.

Authenticate worker nodes

Connect each worker node to the Tailscale network with route acceptance enabled. This allows nodes to access cluster services through the control plane.

sudo tailscale up --accept-routes
tailscale status

Configure Tailscale ACL policies

Create Access Control List policies in the Tailscale admin console to secure cluster communication. Navigate to the Tailscale admin panel and update your ACL policy.

{
  "groups": {
    "group:k8s-nodes": ["user1@example.com", "user2@example.com"]
  },
  "tagOwners": {
    "tag:k8s-control": ["group:k8s-nodes"],
    "tag:k8s-worker": ["group:k8s-nodes"]
  },
  "acls": [
    {
      "action": "accept",
      "src": ["tag:k8s-control", "tag:k8s-worker"],
      "dst": ["tag:k8s-control:", "tag:k8s-worker:"]
    },
    {
      "action": "accept",
      "src": ["group:k8s-nodes"],
      "dst": ["tag:k8s-control:6443", "tag:k8s-control:2379-2380"]
    }
  ]
}

Apply node tags

Tag your Kubernetes nodes in the Tailscale admin console to apply the ACL policies. This enables role-based access control for cluster components.

# On control plane node
sudo tailscale up --advertise-routes=10.96.0.0/12,10.244.0.0/16 --accept-routes --advertise-tags=tag:k8s-control

On worker nodes

sudo tailscale up --accept-routes --advertise-tags=tag:k8s-worker

Enable subnet routing approval

Approve the subnet routes in the Tailscale admin console to allow cluster traffic routing. This step must be completed in the web interface.

Note: Navigate to the Machines page in your Tailscale admin console, find your control plane node, click the three dots menu, and select "Edit route settings". Enable the advertised subnet routes.

Deploy Tailscale operator

Install the Tailscale Kubernetes operator to manage subnet routing and service exposure automatically. This provides native Kubernetes integration.

kubectl apply -f https://raw.githubusercontent.com/tailscale/tailscale/main/cmd/k8s-operator/deploy/manifests/operator.yaml

Create operator authentication secret

Generate an auth key in the Tailscale admin console and create a Kubernetes secret for the operator authentication.

kubectl create secret generic operator-oauth --from-literal=client_id=your-client-id --from-literal=client_secret=your-client-secret -n tailscale

Configure service discovery integration

Create a ConfigMap to configure automatic service discovery and DNS integration for Tailscale-connected services.

apiVersion: v1
kind: ConfigMap
metadata:
  name: tailscale-config
  namespace: tailscale
data:
  TS_KUBE_SECRET: "operator-oauth"
  TS_USERSPACE: "false"
  TS_AUTH_ONCE: "true"
  TS_ACCEPT_DNS: "true"
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: tailscale-subnet-router
  namespace: tailscale
spec:
  selector:
    matchLabels:
      app: tailscale-subnet-router
  template:
    metadata:
      labels:
        app: tailscale-subnet-router
    spec:
      serviceAccountName: tailscale-operator
      hostNetwork: true
      containers:
      - name: tailscale
        image: tailscale/tailscale:latest
        env:
        - name: TS_KUBE_SECRET
          value: "operator-oauth"
        - name: TS_ROUTES
          value: "10.96.0.0/12,10.244.0.0/16"
        - name: TS_ACCEPT_DNS
          value: "true"
        securityContext:
          capabilities:
            add:
            - NET_ADMIN
            - NET_RAW
        volumeMounts:
        - name: dev-net-tun
          mountPath: /dev/net/tun
      volumes:
      - name: dev-net-tun
        hostPath:
          path: /dev/net/tun
kubectl apply -f tailscale-config.yaml

Configure pod-to-pod communication

Create a NetworkPolicy to allow secure communication between pods across Tailscale-connected nodes. This enables encrypted inter-pod communication.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: tailscale-pod-communication
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: tailscale
    - podSelector:
        matchLabels:
          networking/tailscale: "enabled"
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: tailscale
    - podSelector:
        matchLabels:
          networking/tailscale: "enabled"
  - to: []
    ports:
    - protocol: UDP
      port: 53
kubectl apply -f tailscale-network-policy.yaml

Expose services via Tailscale

Configure a LoadBalancer service to expose cluster services through Tailscale networking. This allows external access to cluster services via the mesh network.

apiVersion: v1
kind: Service
metadata:
  name: example-app-tailscale
  annotations:
    tailscale.com/expose: "true"
    tailscale.com/hostname: "k8s-example-app"
spec:
  type: LoadBalancer
  loadBalancerClass: tailscale
  selector:
    app: example-app
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
kubectl apply -f tailscale-service.yaml

Verify your setup

Test the Tailscale and Kubernetes integration to ensure secure networking is functioning correctly.

# Check Tailscale status on all nodes
tailscale status
tailscale ip -4

Verify subnet routes are advertised

tailscale status --json | grep -A5 "AdvertiseRoutes"

Check Kubernetes connectivity

kubectl get nodes -o wide kubectl get services -A

Test pod-to-pod communication

kubectl run test-pod --image=busybox --restart=Never -- sleep 3600 kubectl exec test-pod -- nslookup kubernetes.default.svc.cluster.local

Verify Tailscale operator

kubectl get pods -n tailscale kubectl logs -n tailscale deployment/tailscale-operator

Common issues

Symptom Cause Fix
Subnet routes not working Routes not approved in admin console Enable subnet routes in Tailscale admin panel under machine settings
Pods can't reach services Incorrect CIDR ranges in advertise-routes Check actual cluster CIDRs with kubectl cluster-info dump | grep -E 'service-cluster-ip-range|cluster-cidr'
Tailscale operator failing Missing authentication credentials Recreate the operator-oauth secret with valid client ID and secret
Network policy blocking traffic Restrictive NetworkPolicy rules Add appropriate pod labels and update NetworkPolicy selectors
DNS resolution failing DNS not configured in Tailscale Enable MagicDNS in Tailscale admin console and use --accept-dns flag

Next steps

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle private cloud infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.