TailscaleServices
TailscaleServices provides the service mesh layer for the Tailscale Gateway Operator, implementing Kubernetes-style selector patterns to create VIP services that aggregate multiple TailscaleEndpoints with advanced load balancing, health checking, and auto-provisioning capabilities.
Overview
TailscaleServices represents the highest-level abstraction in the Tailscale Gateway architecture, sitting above the infrastructure layer (TailscaleEndpoints) to provide sophisticated service management. It uses familiar Kubernetes selector patterns to dynamically compose services from multiple endpoint resources.
Architecture Pattern
TailscaleServices ──selects via labels──> TailscaleEndpoints
│ │
│ creates VIP service │ creates StatefulSets
▼ ▼
Tailscale VIP Service Tailscale Proxy Pods
(web-service.tailnet.ts.net) (machines in tailnet)
│ │
└────────── routes traffic to ────────────┘
Specification
Core Fields
apiVersion: gateway.tailscale.com/v1alpha1
kind: TailscaleServices
metadata:
name: web-service
spec:
# Kubernetes-style label selector (REQUIRED)
selector:
matchLabels:
service-type: web
environment: production
matchExpressions:
- key: region
operator: In
values: ["east", "west"]
# VIP service configuration
vipService:
name: "svc:web-service"
ports: ["tcp:80", "tcp:443"]
tags: ["tag:web-service", "tag:production"]
comment: "Production web service"
autoApprove: true
annotations:
environment: "production"
team: "backend"
# Load balancing strategies
loadBalancing:
strategy: round-robin # round-robin, least-connections, weighted, failover
healthCheck:
enabled: true
path: "/health"
interval: "30s"
timeout: "5s"
healthyThreshold: 2
unhealthyThreshold: 3
weights:
web-east: 70
web-west: 30
failoverConfig:
primaryEndpoints: ["web-east"]
secondaryEndpoints: ["web-west"]
failbackDelay: "60s"
# Service discovery configuration
serviceDiscovery:
discoverVIPServices: true
vipServiceSelector:
tags: ["tag:shared-service"]
serviceNames: ["svc:external-api"]
externalServices:
- name: external-api
address: api.example.com
port: 443
protocol: HTTPS
weight: 10
# Auto-provisioning template
endpointTemplate:
tailnet: production-tailnet
tags: ["tag:auto-web", "tag:k8s"]
proxy:
replicas: 3
connectionType: bidirectional
ports:
- port: 80
protocol: TCP
labels:
service-type: web # Must match selector
environment: production
auto-provisioned: "true"
Selector Pattern
TailscaleServices uses the same label selector pattern as Kubernetes Services, providing familiar and powerful selection capabilities.
Basic Label Matching
selector:
matchLabels:
service-type: web
environment: production
Advanced Expression Matching
selector:
matchExpressions:
- key: region
operator: In
values: ["east", "west", "central"]
- key: tier
operator: NotIn
values: ["deprecated"]
- key: auto-provisioned
operator: Exists
Dynamic Selection
The controller continuously monitors TailscaleEndpoints and automatically updates service membership when:
- New TailscaleEndpoints are created that match the selector
- Existing TailscaleEndpoints labels change
- TailscaleEndpoints are deleted
Load Balancing Strategies
Round Robin (Default)
Distributes requests evenly across all healthy backends.
loadBalancing:
strategy: round-robin
Least Connections
Routes to the backend with the fewest active connections.
loadBalancing:
strategy: least-connections
Weighted Distribution
Distributes traffic based on configured weights.
loadBalancing:
strategy: weighted
weights:
web-east: 70 # 70% of traffic
web-west: 20 # 20% of traffic
web-backup: 10 # 10% of traffic
Failover with Primary/Secondary Tiers
Uses primary endpoints preferentially, failing over to secondary when primary endpoints are unhealthy.
loadBalancing:
strategy: failover
failoverConfig:
primaryEndpoints: ["web-primary-east", "web-primary-west"]
secondaryEndpoints: ["web-backup-central"]
failbackDelay: "120s" # Wait 2 minutes before failing back
Auto-Provisioning
When no TailscaleEndpoints match the selector, TailscaleServices can automatically create them using the endpointTemplate.
Auto-Provisioning Template
endpointTemplate:
tailnet: production-tailnet
tags: ["tag:auto-web", "tag:k8s-proxy"]
proxy:
replicas: 2
connectionType: bidirectional
ports:
- port: 80
protocol: TCP
- port: 443
protocol: TCP
labels:
service-type: web # Must match selector
environment: production # Must match selector
region: auto # Additional labels
Auto-Created Resources
Auto-provisioned TailscaleEndpoints have:
- Annotation:
tailscale-gateway.com/auto-provisioned: "true"
- Owner References: Point to the creating TailscaleServices
- Labels: Must match the selector requirements
- Automatic Cleanup: Deleted when no longer selected
Service Discovery
VIP Service Discovery
Discover and attach to existing Tailscale VIP services instead of creating new ones.
serviceDiscovery:
discoverVIPServices: true
vipServiceSelector:
tags: ["tag:shared-infrastructure"]
serviceNames: ["svc:database", "svc:cache"]
External Service Integration
Include non-Kubernetes backends in the service.
serviceDiscovery:
externalServices:
- name: legacy-api
address: legacy.internal.com
port: 8080
protocol: HTTP
weight: 5
- name: cloud-service
address: api.cloud-provider.com
port: 443
protocol: HTTPS
weight: 15
Health Checking
Service-level health checking monitors all backends and adjusts traffic routing based on health status.
loadBalancing:
healthCheck:
enabled: true
path: "/health" # HTTP health check path
interval: "30s" # Check every 30 seconds
timeout: "5s" # 5 second timeout
healthyThreshold: 2 # 2 consecutive successes = healthy
unhealthyThreshold: 3 # 3 consecutive failures = unhealthy
Health Check Protocols
- HTTP/HTTPS: Uses GET requests to specified path
- TCP: Tests port connectivity
- UDP: Tests port availability (limited)
Multi-Operator Coordination
TailscaleServices integrates with the ServiceCoordinator for multi-operator service sharing.
Service Registry Integration
# Multiple operators can share the same VIP service
vipService:
name: "svc:shared-database"
# First operator creates the service
# Subsequent operators attach as consumers
Coordination Status
status:
serviceInfo:
multiOperatorService: true
ownerOperator: "operator-cluster-1"
consumerOperators: ["operator-cluster-2", "operator-cluster-3"]
serviceRegistryKey: "shared-database-registry"
lastCoordination: "2025-06-25T10:30:00Z"
Status Fields
TailscaleServices provides comprehensive status information about service health, backend distribution, and coordination state.
Selected Endpoints Status
status:
selectedEndpoints:
- name: web-east
namespace: production
status: Ready
machines: ["web-east-0", "web-east-1"]
lastSelected: "2025-06-25T10:25:00Z"
labels:
service-type: web
environment: production
region: east
healthStatus:
healthyMachines: 2
unhealthyMachines: 0
lastHealthCheck: "2025-06-25T10:30:00Z"
VIP Service Status
status:
vipServiceStatus:
created: true
serviceName: "svc:web-service"
dnsName: "web-service.production-tailnet.ts.net"
addresses: ["100.100.100.50"]
backendCount: 4
healthyBackendCount: 4
serviceTags: ["tag:web-service", "tag:production"]
lastRegistration: "2025-06-25T10:30:00Z"
Load Balancing Status
status:
loadBalancingStatus:
strategy: weighted
endpointWeights:
web-east: 70
web-west: 30
requestCounts:
web-east: 1450
web-west: 620
failoverStatus:
activeTier: primary
lastFailover: "2025-06-24T15:20:00Z"
failoverReason: "primary-endpoints-unhealthy"
Complete Example
apiVersion: gateway.tailscale.com/v1alpha1
kind: TailscaleServices
metadata:
name: production-web-service
namespace: production
spec:
selector:
matchLabels:
service-type: web
environment: production
matchExpressions:
- key: region
operator: In
values: ["east", "west"]
vipService:
name: "svc:production-web"
ports: ["tcp:80", "tcp:443"]
tags: ["tag:web-service", "tag:production", "tag:multi-region"]
comment: "Production web service with multi-region failover"
autoApprove: true
annotations:
team: "platform"
environment: "production"
monitoring: "enabled"
loadBalancing:
strategy: failover
healthCheck:
enabled: true
path: "/health"
interval: "15s"
timeout: "3s"
healthyThreshold: 2
unhealthyThreshold: 3
failoverConfig:
primaryEndpoints: ["web-east"]
secondaryEndpoints: ["web-west"]
failbackDelay: "300s"
serviceDiscovery:
discoverVIPServices: true
vipServiceSelector:
tags: ["tag:shared-infrastructure"]
externalServices:
- name: cdn-service
address: cdn.example.com
port: 443
protocol: HTTPS
weight: 5
endpointTemplate:
tailnet: production-tailnet
tags: ["tag:auto-web", "tag:k8s-proxy", "tag:production"]
proxy:
replicas: 2
connectionType: bidirectional
ports:
- port: 80
protocol: TCP
- port: 443
protocol: TCP
labels:
service-type: web
environment: production
region: auto
auto-provisioned: "true"
---
# This will be auto-created if no matching TailscaleEndpoints exist
apiVersion: gateway.tailscale.com/v1alpha1
kind: TailscaleEndpoints
metadata:
name: production-web-service-auto
namespace: production
annotations:
tailscale-gateway.com/auto-provisioned: "true"
ownerReferences:
- apiVersion: gateway.tailscale.com/v1alpha1
kind: TailscaleServices
name: production-web-service
uid: "..."
spec:
tailnet: production-tailnet
tags: ["tag:auto-web", "tag:k8s-proxy", "tag:production"]
proxy:
replicas: 2
connectionType: bidirectional
ports:
- port: 80
protocol: TCP
- port: 443
protocol: TCP
Integration with Gateway API
TailscaleServices can be used as backends in Gateway API resources:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
spec:
parentRefs:
- name: envoy-gateway
rules:
- matches:
- path:
type: PathPrefix
value: "/api/"
backendRefs:
- group: gateway.tailscale.com
kind: TailscaleServices # Use TailscaleServices as backend
name: production-web-service
port: 80
Best Practices
Selector Design
- Use Stable Labels: Ensure selector labels are stable and meaningful
- Avoid Over-Selection: Be specific to prevent unintended endpoint inclusion
- Use Expressions for Flexibility: Leverage
matchExpressions
for complex selection logic
Load Balancing Strategy
- Start with Round Robin: Use default strategy unless specific requirements exist
- Use Failover for HA: Implement primary/secondary for high availability
- Monitor Health Checks: Enable health checking for production services
- Configure Appropriate Timeouts: Balance responsiveness with stability
Auto-Provisioning
- Use for Dynamic Workloads: Ideal for auto-scaling environments
- Set Appropriate Labels: Ensure auto-provisioned endpoints have correct labels
- Monitor Resource Usage: Track auto-provisioning to prevent resource sprawl
- Use Owner References: Ensure proper cleanup via owner references
Multi-Operator Coordination
- Use Discovery-First: Let TailscaleServices discover existing VIP services
- Coordinate Tags: Use consistent tagging across operators
- Monitor Service Registry: Track multi-operator service sharing
- Plan for Conflicts: Design VIP service naming to avoid conflicts