{"id":13928747,"url":"https://github.com/clrxbl/tailscale-svc-lb","last_synced_at":"2025-07-19T10:31:56.456Z","repository":{"id":38615731,"uuid":"500975272","full_name":"clrxbl/tailscale-svc-lb","owner":"clrxbl","description":"klipper-lb but Tailscale. A Kubernetes load balancer controller to provide LoadBalancers a Tailscale endpoint.","archived":true,"fork":false,"pushed_at":"2023-02-03T00:07:51.000Z","size":71,"stargazers_count":65,"open_issues_count":3,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-08-08T18:20:02.529Z","etag":null,"topics":["kubernetes","tailscale"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clrxbl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-07T19:21:44.000Z","updated_at":"2023-09-03T00:57:42.000Z","dependencies_parsed_at":"2023-02-18T01:45:58.595Z","dependency_job_id":null,"html_url":"https://github.com/clrxbl/tailscale-svc-lb","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clrxbl%2Ftailscale-svc-lb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clrxbl%2Ftailscale-svc-lb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clrxbl%2Ftailscale-svc-lb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clrxbl%2Ftailscale-svc-lb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clrxbl","download_url":"https://codeload.github.com/clrxbl/tailscale-svc-lb/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226588815,"owners_count":17655793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubernetes","tailscale"],"created_at":"2024-08-07T18:01:36.839Z","updated_at":"2024-11-26T17:30:55.665Z","avatar_url":"https://github.com/clrxbl.png","language":"Python","funding_links":[],"categories":["kubernetes"],"sub_categories":[],"readme":"# tailscale-svc-lb\n\n[klipper-lb](https://github.com/k3s-io/klipper-lb) but Tailscale.\nBasically does what [Tailscale's k8s examples](https://github.com/tailscale/tailscale/tree/main/docs/k8s) do but as a Kubernetes load balancer controller to automatically provision Tailscale IPs for internal Kubernetes LoadBalancer services.\n\n[![asciicast](https://asciinema.org/a/smlS1PDekgvJBDuClsz9huMJy.svg)](https://asciinema.org/a/smlS1PDekgvJBDuClsz9huMJy)\n\n## End of Life\n\nAs of February 2023, Tailscale has released an alpha version of their own Kubernetes operator.\nThis operator still functions perfectly fine (and I personally still use it until Tailscale's version is considered GA) but I will be archiving this repository in favour of the official solution.\n\n## Installation\n\nAdd the Helm chart as shown below\n\n```bash\nhelm repo add tailscale-svc-lb https://clrxbl.github.io/tailscale-svc-lb/\nhelm repo update\n```\n\nInstall the controller with\n```bash\nhelm install tailscale-svc-lb tailscale-svc-lb/tailscale-svc-lb -n kube-system\n```\n\nOnce the controller is deployed, create a LoadBalancer service with the loadBalancerClass set to \"svc-lb.tailscale.iptables.sh/lb\".\n\nThere should be a Deployment (or DaemonSet) created in the controller's namespace for the newly-created LoadBalancer service. View the logs of the leader-elected pod and click the login.tailscale.com link to authenticate. You only have to do this once per service.\n\nThis can be automated by creating a secret in the controller's namespace called `tailscale-svc-lb` with the key `ts-auth-key` and the value being your Tailscale's registration token.\n\n## Configuration Variables\n\nAll configuration options are supplied using Environment Variables\n\n| Variable                             | Description                                                                                                                        | Default                                        |\n|--------------------------------------|------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|\n| `RESOURCE_PREFIX`                    | Prefix to prepend to the service name when creating proxy resources                                                                | `ts-`                                          |\n| `SECRET_NAME`                        | Name of the secret that the `ts-auth-key` value should be used from                                                                | `tailscale-svc-lb`                             |\n| `LOAD_BALANCER_CLASS`                | LoadBalancerClass that this controller will implement                                                                              | `svc-lb.tailscale.iptables.sh/lb`              |\n| `NODE_SELECTOR_LABEL`                | Label to use when selecting nodes to run Tailscale on. The value of this label should be `true`                                    | None                                           |\n| `IMAGE_PULL_SECRETS`                 | A semi-colon seperated list of secret names to use as the `imagePullSecrets` for the Tailscale Proxy                               | None                                           |\n| `DEPLOYMENT_TYPE`                    | The type of deployment to use for the Tailscale Proxy. Can be one of: `Deployment`, `DaemonSet`                                    | `Deployment`                                   |\n| `TS_PROXY_NAMESPACE`                 | Namespace all of the Tailscale Proxies will be created in                                                                          | `default`                                      |\n| `TS_PROXY_REPLICA_COUNT`             | The number of replicas to deploy for each Tailscale Proxy instance. Only used if `DEPLOYMENT_TYPE` is `Deployment`                 | `1`                                            |\n| `TS_PROXY_RUNTIME_IMAGE`             | Image to use as the Tailscale Proxy Runtime container                                                                              | `clrxbl/tailscale-svc-lb-runtime:latest`       |\n| `TS_PROXY_RUNTIME_IMAGE_PULL_POLICY` | ImagePullPolicy to use for the Tailscale Proxy Runtime container                                                                   | `IfNotPresent`                                 |\n| `TS_PROXY_RUNTIME_REQUEST_CPU`       | CPU Request for the Tailscale Proxy Runtime container                                                                              | None                                           |\n| `TS_PROXY_RUNTIME_REQUEST_MEM`       | Memory Request for the Tailscale Proxy Runtime container                                                                           | None                                           |\n| `TS_PROXY_RUNTIME_LIMIT_CPU`         | CPU Limit for the Tailscale Proxy Runtime container                                                                                | None                                           |\n| `TS_PROXY_RUNTIME_LIMIT_MEM`         | Memory Limit for the Tailscale Proxy Runtime container                                                                             | None                                           |\n| `LEADER_ELECTOR_IMAGE`               | Image to use as the Leader Elector container                                                                                       | `gcr.io/google_containers/leader-elector: 0.5` |\n| `LEADER_ELECTOR_IMAGE_PULL_POLICY`   | ImagePullPolicy to use for the Leader Elector container                                                                            | `IfNotPresent`                                 |\n| `LEADER_ELECTOR_REQUEST_CPU`         | CPU Request for the Leader Elector container                                                                                       | None                                           |\n| `LEADER_ELECTOR_REQUEST_MEM`         | Memory Request for the Leader Elector container                                                                                    | None                                           |\n| `LEADER_ELECTOR_LIMIT_CPU`           | CPU Limit for the Leader Elector container                                                                                         | None                                           |\n| `LEADER_ELECTOR_LIMIT_MEM`           | Memory Limit for the Leader Elector container                                                                                      | None                                           |\n| `TS_HOSTNAME_FROM_SERVICE`           | If set to `true`, the Hostname of the Tailscale Proxy will be generated from the namespace and service name of the proxied service | `false`                                        |\n| `TS_HOSTNAME_FROM_SERVICE_SUFFIX`    | An optional hostname suffix to add to automatically generated Hostnames. Only applies if `TS_HOSTNAME_FROM_SERVICE` is `true`      | None                                           |\n\n## How it works\n\n**On new LoadBalancer service:**\n1. Look for LoadBalancer services with our loadBalancerClass (Default: `svc-lb.tailscale.iptables.sh/lb`)\n2. Look for nodes with our nodeSelectorLabel (Default: `svc-lb.tailscale.iptables.sh/deploy`) with the value `true`\n3. Deploy a Deployment or DaemonSet with the name: `${RESOURCE_PREFIX}${SVC_NAME}` and our custom Docker image containing tailscaled.\n4. Let the Deployment or DaemonSet run tailscaled, once IP is acquired, update tailscaled's secret with the Tailscale IP.\n5. Retrieve IP from secret/configmap, update LoadBalancer service with ingress IP (Tailscale IP)\n\nEach `tailscale-svc-lb-runtime` DaemonSet/Deployment runs the `leader-elector` sidecar to automatically elect a leader using the Kubernetes leader election system.  `tailscaled` only works properly when ran on 1 pod at a time, hence this leader election system.\n\niptables DNAT is used to redirect incoming traffic to the service ClusterIP address, so `NET_ADMIN` capability is required \u0026 ipv4 forwarding.\n\n**On LoadBalancer service deletion:**\n1. Delete the DaemonSet\n2. Delete the Secret/ConfigMap\n3. Let Kubernetes delete the service\n\n**Every 15 Seconds, after an initial 30 second idle time:**\n1. Iterate all LoadBalancer services with our loadBalancerClass (Default: `svc-lb.tailscale.iptables.sh/lb`)\n2. Reconcile the state of the relevant `${RESOURCE_PREFIX}${SVC_NAME` resources\n3. If any resources are missing, create the Deployment/DaemonSet/Role/RoleBindings/ServiceAccount as necessary","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclrxbl%2Ftailscale-svc-lb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclrxbl%2Ftailscale-svc-lb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclrxbl%2Ftailscale-svc-lb/lists"}