Introduce a per-tailnet shared ACME account key so that all ingress ProxyGroup replicas on a tailnet present the same account identity to Let's Encrypt. This lets renewals claim the ARI "replaces" exemption from the 50-certs-per-week rate limit, surviving Pod restarts, ProxyGroup recreation, and cluster migrations. The operator provisions a "tailscale-acme-accounts" Secret in its namespace, guarded by a finalizer and a deletion warning event, and watched so it is recreated promptly if removed. Proxies migrate any pre-existing per-pod key into the shared Secret on first boot, adopt the shared key on subsequent boots, and restore it on cert writes if the Secret was recreated empty. Certs are stamped with the fingerprint of the issuing account so renewals skip the "replaces" claim when the account doesn't match. Opt-in per-ProxyGroup via the tailscale.com/share-acme-account annotation, or operator-wide via OPERATOR_SHARED_ACME_ACCOUNT_KEY. Updates #18251 Updates #20288 Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
156 lines
6.4 KiB
YAML
156 lines
6.4 KiB
YAML
# Copyright (c) Tailscale Inc & contributors
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
# Operator oauth credentials. If unset a Secret named operator-oauth must be
|
|
# precreated or oauthSecretVolume needs to be adjusted. This block will be
|
|
# overridden by oauthSecretVolume, if set.
|
|
oauth:
|
|
# The Client ID the operator will authenticate with.
|
|
clientId: ""
|
|
# If set a Kubernetes Secret with the provided value will be created in
|
|
# the operator namespace, and mounted into the operator Pod. Takes precedence
|
|
# over oauth.audience.
|
|
clientSecret: ""
|
|
# The audience for oauth.clientId if using a workload identity federation
|
|
# OAuth client. Mutually exclusive with oauth.clientSecret.
|
|
# See https://tailscale.com/kb/1581/workload-identity-federation.
|
|
audience: ""
|
|
|
|
# URL of the control plane to be used by all resources managed by the operator.
|
|
loginServer: ""
|
|
|
|
# Secret volume.
|
|
# If set it defines the volume the oauth secrets will be mounted from.
|
|
# The volume needs to contain two files named `client_id` and `client_secret`.
|
|
# If unset the volume will reference the Secret named operator-oauth.
|
|
# This block will override the oauth block.
|
|
oauthSecretVolume: {}
|
|
# csi:
|
|
# driver: secrets-store.csi.k8s.io
|
|
# readOnly: true
|
|
# volumeAttributes:
|
|
# secretProviderClass: tailscale-oauth
|
|
#
|
|
## NAME is pre-defined!
|
|
|
|
# installCRDs determines whether tailscale.com CRDs should be installed as part
|
|
# of chart installation. We do not use Helm's CRD installation mechanism as that
|
|
# does not allow for upgrading CRDs.
|
|
# https://helm.sh/docs/chart_best_practices/custom_resource_definitions/
|
|
installCRDs: true
|
|
|
|
operatorConfig:
|
|
# ACL tag that operator will be tagged with. Operator must be made owner of
|
|
# these tags
|
|
# https://tailscale.com/kb/1236/kubernetes-operator/?q=operator#setting-up-the-kubernetes-operator
|
|
# Multiple tags are defined as array items and passed to the operator as a comma-separated string
|
|
defaultTags:
|
|
- "tag:k8s-operator"
|
|
|
|
image:
|
|
# Repository defaults to DockerHub, but images are also synced to ghcr.io/tailscale/k8s-operator.
|
|
repository: tailscale/k8s-operator
|
|
# Digest will be prioritized over tag. If neither are set appVersion will be
|
|
# used.
|
|
tag: ""
|
|
digest: ""
|
|
pullPolicy: Always
|
|
logging: "info" # info, debug, dev
|
|
hostname: "tailscale-operator"
|
|
nodeSelector:
|
|
kubernetes.io/os: linux
|
|
|
|
resources: {}
|
|
|
|
# Specifies annotations for deployment
|
|
annotations: {}
|
|
|
|
podAnnotations: {}
|
|
podLabels: {}
|
|
|
|
serviceAccountAnnotations: {}
|
|
# eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/tailscale-operator-role
|
|
|
|
tolerations: []
|
|
|
|
affinity: {}
|
|
|
|
priorityClassName: ""
|
|
|
|
podSecurityContext: {}
|
|
|
|
securityContext: {}
|
|
|
|
extraEnv: []
|
|
# - name: EXTRA_VAR1
|
|
# value: "value1"
|
|
# - name: EXTRA_VAR2
|
|
# value: "value2"
|
|
|
|
# Default for the tailscale.com/share-acme-account annotation on new
|
|
# ProxyGroups. When true, the operator provisions a shared per-tailnet
|
|
# ACME account key Secret and configures proxies to use it, preserving
|
|
# Let's Encrypt's ARI "replaces" renewal exemption across pod restarts
|
|
# and ProxyGroup recreation. See #18251.
|
|
sharedACMEAccountKey: false
|
|
|
|
# In the case that you already have a tailscale ingressclass in your cluster (or vcluster), you can disable the creation here
|
|
ingressClass:
|
|
# Allows for customization of the ingress class name used by the operator to identify ingresses to reconcile. This does
|
|
# not allow multiple operator instances to manage different ingresses, but provides an onboarding route for users that
|
|
# may have previously set up ingress classes named "tailscale" prior to using the operator.
|
|
name: "tailscale"
|
|
enabled: true
|
|
|
|
# proxyConfig contains configuraton that will be applied to any ingress/egress
|
|
# proxies created by the operator.
|
|
# https://tailscale.com/kb/1439/kubernetes-operator-cluster-ingress
|
|
# https://tailscale.com/kb/1438/kubernetes-operator-cluster-egress
|
|
# Note that this section contains only a few global configuration options and
|
|
# will not be updated with more configuration options in the future.
|
|
# If you need more configuration options, take a look at ProxyClass:
|
|
# https://tailscale.com/kb/1445/kubernetes-operator-customization#cluster-resource-customization-using-proxyclass-custom-resource
|
|
proxyConfig:
|
|
# Configure the proxy image to use instead of the default tailscale/tailscale:latest.
|
|
# Applying a ProxyClass with `spec.statefulSet.pod.tailscaleContainer.image`
|
|
# set will override any defaults here.
|
|
#
|
|
# Note that ProxyGroups of type "kube-apiserver" use a different default image,
|
|
# tailscale/k8s-proxy:latest, and it is currently only possible to override
|
|
# that image via the same ProxyClass field.
|
|
image:
|
|
# Repository defaults to DockerHub, but images are also synced to ghcr.io/tailscale/tailscale.
|
|
repository: tailscale/tailscale
|
|
# Digest will be prioritized over tag. If neither are set appVersion will be
|
|
# used.
|
|
tag: ""
|
|
digest: ""
|
|
# ACL tag that operator will tag proxies with. Operator must be made owner of
|
|
# these tags
|
|
# https://tailscale.com/kb/1236/kubernetes-operator/?q=operator#setting-up-the-kubernetes-operator
|
|
# Multiple tags can be passed as a comma-separated string i.e 'tag:k8s-proxies,tag:prod'.
|
|
# Note that if you pass multiple tags to this field via `--set` flag to helm upgrade/install commands you must escape the comma (for example, "tag:k8s-proxies\,tag:prod"). See https://github.com/helm/helm/issues/1556
|
|
defaultTags: "tag:k8s"
|
|
firewallMode: auto
|
|
# If defined, this proxy class will be used as the default proxy class for
|
|
# service and ingress resources that do not have a proxy class defined. It
|
|
# does not apply to Connector resources.
|
|
defaultProxyClass: ""
|
|
|
|
# apiServerProxyConfig allows to configure whether the operator should expose
|
|
# Kubernetes API server.
|
|
# https://tailscale.com/kb/1437/kubernetes-operator-api-server-proxy
|
|
apiServerProxyConfig:
|
|
# Set to "true" to create the ClusterRole permissions required for the API
|
|
# server proxy's auth mode. In auth mode, the API server proxy impersonates
|
|
# groups and users based on tailnet ACL grants. Required for ProxyGroups of
|
|
# type "kube-apiserver" running in auth mode.
|
|
allowImpersonation: "false" # "true", "false"
|
|
|
|
# If true or noauth, the operator will run an in-process API server proxy.
|
|
# You can deploy a ProxyGroup of type "kube-apiserver" to run a high
|
|
# availability set of API server proxies instead.
|
|
mode: "false" # "true", "false", "noauth"
|
|
|
|
imagePullSecrets: []
|