Commit Graph
30 Commits
Author SHA1 Message Date
David BondandGitHub eea39eaf52 cmd/k8s-operator: add affinity rules to DNSConfig (#19360)
This commit modifies the `DNSConfig` custom resource to allow the
user to specify affinity rules on the nameserver pods.

Updates: https://github.com/tailscale/tailscale/issues/18556

Signed-off-by: David Bond <davidsbond93@gmail.com>
2026-04-15 22:39:04 +01:00
David BondandGitHub 85d6ba9473 cmd/k8s-operator: migrate to tailscale-client-go-v2 (#19010)
This commit modifies the kubernetes operator to use the `tailscale-client-go-v2`
package instead of the internal tailscale client it was previously using. This
now gives us the ability to expand out custom resources and features as they
become available via the API module.

The tailnet reconciler has also been modified to manage clients as tailnets
are created and removed, providing each subsequent reconciler with a single
`ClientProvider` that obtains a tailscale client for the respective tailnet
by name, or the operator's default when presented with a blank string.

Fixes: https://github.com/tailscale/corp/issues/38418

Signed-off-by: David Bond <davidsbond93@gmail.com>
2026-04-09 14:39:46 +01:00
9522619031 cmd/k8s-operator: use correct tailnet client for L7 & L3 ingresses (#18749)
* cmd/k8s-operator: use correct tailnet client for L7 & L3 ingresses

This commit fixes a bug when using multi-tailnet within the operator
to spin up L7 & L3 ingresses where the client used to create the
tailscale services was not switching depending on the tailnet used
by the proxygroup backing the service/ingress.

Updates: https://github.com/tailscale/corp/issues/34561

Signed-off-by: David Bond <davidsbond93@gmail.com>

* cmd/k8s-operator: adding server url to proxygroups when a custom tailnet has been specified

Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
(cherry picked from commit 3b21ac5504e713e32dfcd43d9ee21e7e712ac200)

---------

Signed-off-by: David Bond <davidsbond93@gmail.com>
Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
Co-authored-by: chaosinthecrd <tom@tmlabs.co.uk>
2026-03-10 10:33:55 +00:00
David BondandGitHub eb3d35c8b5 cmd/k8s-operator,k8s-operator: define ProxyGroupPolicy reconciler (#18654)
This commit implements a reconciler for the new `ProxyGroupPolicy`
custom resource. When created, all `ProxyGroupPolicy` resources
within the same namespace are merged into two `ValidatingAdmissionPolicy`
resources, one for egress and one for ingress.

These policies use CEL expressions to limit the usage of the
"tailscale.com/proxy-group" annotation on `Service` and `Ingress`
resources on create & update.

Included here is also a new e2e test that ensures that resources that
violate the policy return an error on creation, and that once the
policy is changed to allow them they can be created.

Closes: https://github.com/tailscale/corp/issues/36830

Signed-off-by: David Bond <davidsbond93@gmail.com>
2026-02-18 09:34:55 +00:00
David BondandGitHub a341eea00b k8s-operator,cmd/k8s-operator: define ProxyGroupPolicy CRD (#18614)
This commit adds a new custom resource definition to the kubernetes
operator named `ProxyGroupPolicy`. This resource is namespace scoped
and is used as an allow list for which `ProxyGroup` resources can be
used within its namespace.

The `spec` contains two fields, `ingress` and `egress`. These should
contain the names of `ProxyGroup` resources to denote which can be
used as values in the `tailscale.com/proxy-group` annotation within
`Service` and `Ingress` resources.

The intention is for these policies to be merged within a namespace and
produce a `ValidatingAdmissionPolicy` and `ValidatingAdmissionPolicyBinding`
for both ingress and egress that prevents users from using names of
`ProxyGroup` resources in those annotations.

Closes: https://github.com/tailscale/corp/issues/36829

Signed-off-by: David Bond <davidsbond93@gmail.com>
2026-02-13 16:04:34 +00:00
David BondandGitHub f2b4d7065d cmd/containerboot: handle v6 pod ips that are missing square brackets (#18519)
This commit fixes an issue within containerboot that arose from the
kubernetes operator. When users enable metrics on custom resources that
are running on dual stack or ipv6 only clusters, they end up with an error
as we pass the hostport combintation using $(POD_IP):PORT.

In go, `netip.ParseAddrPort` expects square brackets `[]` to wrap the host
portion of an ipv6 address and would naturally, crash.

When loading the containerboot configuration from the environment we now
check if the `TS_LOCAL_ADDR_PORT` value contains the pod's v6 ip address.
If it does & does not already contain brackets, we add the brackets in.

Closes: #15762
Closes: #15467

Signed-off-by: David Bond <davidsbond93@gmail.com>
2026-02-03 11:16:59 +00:00
David BondandGitHub 2cb86cf65e cmd/k8s-operator,k8s-operator: Allow the use of multiple tailnets (#18344)
This commit contains  the implementation of multi-tailnet support within the Kubernetes Operator

Each of our custom resources now expose the `spec.tailnet` field. This field is a string that must match the name of an existing `Tailnet` resource. A `Tailnet` resource looks like this:

```yaml
apiVersion: tailscale.com/v1alpha1
kind: Tailnet
metadata:
  name: example  # This is the name that must be referenced by other resources
spec:
  credentials:
    secretName: example-oauth
```

Each `Tailnet` references a `Secret` resource that contains a set of oauth credentials. This secret must be created in the same namespace as the operator:

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: example-oauth # This is the name that's referenced by the Tailnet resource.
  namespace: tailscale
stringData:
  client_id: "client-id"
  client_secret: "client-secret"
```

When created, the operator performs a basic check that the oauth client has access to all required scopes. This is done using read actions on devices, keys & services. While this doesn't capture a missing "write" permission, it catches completely missing permissions. Once this check passes, the `Tailnet` moves into a ready state and can be referenced. Attempting to use a `Tailnet` in a non-ready state will stall the deployment of `Connector`s, `ProxyGroup`s and `Recorder`s until the `Tailnet` becomes ready.

The `spec.tailnet` field informs the operator that a `Connector`, `ProxyGroup`, or `Recorder` must be given an auth key generated using the specified oauth client. For backwards compatibility, the set of credentials the operator is configured with are considered the default. That is, where `spec.tailnet` is not set, the resource will be deployed in the same tailnet as the operator. 

Updates https://github.com/tailscale/corp/issues/34561
2026-01-21 12:35:44 +00:00
David BondandGitHub d4821cdc2f cmd/k8s-operator: allow HA ingresses to be deleted when VIP service does not exist (#18050)
This commit fixes a bug in our HA ingress reconciler where ingress resources would
be stuck in a deleting state should their associated VIP service be deleted within
control.

The reconciliation loop would check for the existence of the VIP service and if not
found perform no additional cleanup steps. The code has been modified to continue
onwards even if the VIP service is not found.

Fixes: https://github.com/tailscale/tailscale/issues/18049

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-11-25 12:41:39 +00:00
David BondandGitHub 42a5262016 cmd/k8s-operator: add multi replica support for recorders (#17864)
This commit adds the `spec.replicas` field to the `Recorder` custom
resource that allows for a highly available deployment of `tsrecorder`
within a kubernetes cluster.

Many changes were required here as the code hard-coded the assumption
of a single replica. This has required a few loops, similar to what we
do for the `Connector` resource to create auth and state secrets. It
was also required to add a check to remove dangling state and auth
secrets should the recorder be scaled down.

Updates: https://github.com/tailscale/tailscale/issues/17965

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-11-20 11:46:34 +00:00
David BondandGitHub 86a849860e cmd/k8s-operator: use stable image for k8s-nameserver (#17985)
This commit modifies the kubernetes operator to use the "stable" version
of `k8s-nameserver` by default.

Updates: https://github.com/tailscale/corp/issues/19028

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-11-20 00:00:27 +00:00
David BondandGitHub 38ccdbe35c cmd/k8s-operator: default to stable image (#17848)
This commit modifies the helm/static manifest configuration for the
k8s-operator to prefer the stable image tag. This avoids making those
using static manifests seeing unstable behaviour by default if they
do not manually make the change.

This is managed for us when using helm but not when generating the
static manifests.

Updates https://github.com/tailscale/tailscale/issues/10655

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-11-19 11:57:27 +00:00
David BondandGitHub 9083ef1ac4 cmd/k8s-operator: allow pod tolerations on nameservers (#17260)
This commit modifies the `DNSConfig` custom resource to allow specifying
[tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)
on the nameserver pods.

This will allow users to dictate where their nameserver pods are located
within their clusters.

Fixes: https://github.com/tailscale/tailscale/issues/17092

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-10-17 18:32:30 +01:00
David BondandGitHub 419fba40e0 k8s-operator/api-proxy: put kube api server events behind environment variable (#17550)
This commit modifies the k8s-operator's api proxy implementation to only
enable forwarding of api requests to tsrecorder when an environment
variable is set.

This new environment variable is named `TS_EXPERIMENTAL_KUBE_API_EVENTS`.

Updates https://github.com/tailscale/corp/issues/32448

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-10-16 10:11:34 +01:00
David BondandGitHub e466488a2a cmd/k8s-operator: add replica support to nameserver (#17246)
This commit modifies the `DNSConfig` custom resource to allow specifying
a replica count when deploying a nameserver. This allows deploying
nameservers in a HA configuration.

Updates https://github.com/tailscale/corp/issues/32589

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-09-29 12:38:15 +01:00
David BondandGitHub cc1761e8d2 cmd/k8s-operator: send operator logs to tailscale (#17110)
This commit modifies the k8s operator to wrap its logger using the logtail
logger provided via the tsnet server. This causes any logs written by
the operator to make their way to Tailscale in the same fashion as
wireguard logs to be used by support.

This functionality can also be opted-out of entirely using the
"TS_NO_LOGS_NO_SUPPORT" environment variable.

Updates https://github.com/tailscale/corp/issues/32037

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-09-22 13:55:16 +01:00
David BondandGitHub 782c16c513 k8s-operator: reset service status before append (#17120)
This commit fixes an issue within the service reconciler where we end
up in a constant reconciliation loop. When reconciling, the loadbalancer
status is appended to but not reset between each reconciliation, leading
to an ever growing slice of duplicate statuses.

Fixes https://github.com/tailscale/tailscale/issues/17105
Fixes https://github.com/tailscale/tailscale/issues/17107

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-09-15 12:37:28 +01:00
David BondandGitHub cfb2ca724b tsnet: expose logtail's Logf method (#17057)
This commit adds a new method to the tsnet.Server type named `Logger`
that returns the underlying logtail instance's Logf method.

This is intended to be used within the Kubernetes operator to wrap its
existing logger in a way such that operator specific logs can also be
sent to control for support & debugging purposes.

Updates https://github.com/tailscale/corp/issues/32037

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-09-12 12:04:39 +01:00
David BondandGitHub 624cdd2961 cmd/containerboot: do not reset state on non-existant secret (#17021)
This commit modifies containerboot's state reset process to handle the
state secret not existing. During other parts of the boot process we
gracefully handle the state secret not being created yet, but missed
that check within `resetContainerbootState`

Fixes https://github.com/tailscale/tailscale/issues/16804

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-09-04 12:40:55 +01:00
David BondandGitHub 04f00339b6 cmd/k8s-operator: update connector example (#17020)
This commit modifies the connector example to use the new hostname prefix
and replicas fields

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-09-03 22:08:45 +01:00
David BondandGitHub 12ad630128 cmd/k8s-operator: allow specifying replicas for connectors (#16721)
This commit adds a `replicas` field to the `Connector` custom resource that
allows users to specify the number of desired replicas deployed for their
connectors.

This allows users to deploy exit nodes, subnet routers and app connectors
in a highly available fashion.

Fixes #14020

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-09-02 13:10:03 +01:00
David BondandGitHub 4494705496 cmd/{k8s-proxy,containerboot,k8s-operator},kube: add health check and metrics endpoints for k8s-proxy (#16540)
* Modifies the k8s-proxy to expose health check and metrics
endpoints on the Pod's IP.

* Moves cmd/containerboot/healthz.go and cmd/containerboot/metrics.go to
  /kube to be shared with /k8s-proxy.

Updates #13358

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-22 17:07:51 +01:00
David BondandGitHub c989824aac cmd/k8s-operator: Allow specifying cluster ips for nameservers (#16477)
This commit modifies the kubernetes operator's `DNSConfig` resource
with the addition of a new field at `nameserver.service.clusterIP`.

This field allows users to specify a static in-cluster IP address of
the nameserver when deployed.

Fixes #14305

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-21 19:06:36 +01:00
David BondandGitHub d0cafc0a67 cmd/{k8s-operator,k8s-proxy}: apply accept-routes configuration to k8s-proxy (#16522)
This commit modifies the k8s-operator and k8s-proxy to support passing down
the accept-routes configuration from the proxy class as a configuration value
read and used by the k8s-proxy when ran as a distinct container managed by
the operator.

Updates #13358

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-10 15:53:01 +01:00
David BondandGitHub 2b665c370c cmd/{k8s-operator,k8s-proxy}: allow setting login server url (#16504)
This commit modifies the k8s proxy application configuration to include a
new field named `ServerURL` which, when set, modifies
the tailscale coordination server used by the proxy. This works in the same
way as the operator and the proxies it deploys.

If unset, the default coordination server is used.

Updates https://github.com/tailscale/tailscale/issues/13358

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-10 14:33:30 +01:00
David BondandGitHub cf0460b9da cmd/k8s-operator: allow letsencrypt staging on k8s proxies (#16521)
This commit modifies the operator to detect the usage of k8s-apiserver
type proxy groups that wish to use the letsencrypt staging directory and
apply the appropriate environment variable to the statefulset it
produces.

Updates #13358

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-10 14:33:13 +01:00
David BondandGitHub 84eac7b8de cmd/k8s-operator: Allow custom ingress class names (#16472)
This commit modifies the k8s operator to allow for customisation of the ingress class name
via a new `OPERATOR_INGRESS_CLASS_NAME` environment variable. For backwards compatibility,
this defaults to `tailscale`.

When using helm, a new `ingress.name` value is provided that will set this environment variable
and modify the name of the deployed `IngressClass` resource.

Fixes https://github.com/tailscale/tailscale/issues/16248

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-07 12:12:59 +01:00
David BondandGitHub c46145b99e cmd/k8s-operator: Move login server value to top-level (#16470)
This commit modifies the operator helm chart values to bring the newly
added `loginServer` field to the top level. We felt as though it was a bit
confusing to be at the `operatorConfig` level as this value modifies the
behaviour or the operator, api server & all resources that the operator
manages.

Updates https://github.com/tailscale/corp/issues/29847

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-04 12:19:23 +01:00
David BondandGitHub 5dc11d50f7 cmd/k8s-operator: Set login server on tsrecorder nodes (#16443)
This commit modifies the recorder node reconciler to include the environment
variable added in https://github.com/tailscale/corp/pull/30058 which allows
for configuration of the coordination server.

Updates https://github.com/tailscale/corp/issues/29847

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-03 15:53:35 +01:00
David BondandGitHub eb03d42fe6 cmd/k8s-operator: Allow configuration of login server (#16432)
This commit modifies the kubernetes operator to allow for customisation of the tailscale
login url. This provides some data locality for people that want to configure it.

This value is set in the `loginServer` helm value and is propagated down to all resources
managed by the operator. The only exception to this is recorder nodes, where additional
changes are required to support modifying the url.

Updates https://github.com/tailscale/corp/issues/29847

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-07-02 21:42:31 +01:00
David BondandGitHub b75fe9eeca cmd/k8s-operator: Add NOTES.txt to Helm chart (#16364)
This commit adds a NOTES.txt to the operator helm chart that will be written to the
terminal upon successful installation of the operator.

It includes a small list of knowledgebase articles with possible next steps for
the actor that installed the operator to the cluster. It also provides possible
commands to use for explaining the custom resources.

Fixes #13427

Signed-off-by: David Bond <davidsbond93@gmail.com>
2025-06-25 14:14:17 +01:00