Operator and Proxy Enphemeral flags with CRD updates and cleanup

Updates #10166

Signed-off-by: Raj Singh <raj@tailscale.com>
This commit is contained in:
Raj Singh 2025-04-02 10:04:19 -05:00
parent e2f7750125
commit e46b2cf7f1
10 changed files with 47 additions and 4 deletions

View File

@ -64,6 +64,8 @@ spec:
value: operator value: operator
- name: OPERATOR_LOGGING - name: OPERATOR_LOGGING
value: {{ .Values.operatorConfig.logging }} value: {{ .Values.operatorConfig.logging }}
- name: OPERATOR_EPHEMERAL
value: "{{ .Values.operatorConfig.ephemeral }}"
- name: OPERATOR_NAMESPACE - name: OPERATOR_NAMESPACE
valueFrom: valueFrom:
fieldRef: fieldRef:

View File

@ -36,6 +36,10 @@ operatorConfig:
# Multiple tags are defined as array items and passed to the operator as a comma-separated string # Multiple tags are defined as array items and passed to the operator as a comma-separated string
defaultTags: defaultTags:
- "tag:k8s-operator" - "tag:k8s-operator"
# When true, the operator will use an ephemeral auth key
# https://tailscale.com/kb/1111/ephemeral-nodes/
ephemeral: false
image: image:
# Repository defaults to DockerHub, but images are also synced to ghcr.io/tailscale/k8s-operator. # Repository defaults to DockerHub, but images are also synced to ghcr.io/tailscale/k8s-operator.

View File

@ -2215,6 +2215,14 @@ spec:
https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices
Defaults to false. Defaults to false.
type: boolean type: boolean
ephemeral:
description: |-
Ephemeral can be set to true to make the proxy instance register
as an ephemeral node. Ephemeral nodes are automatically deleted
from the tailnet when they are offline for a while.
https://tailscale.com/kb/1111/ephemeral-nodes/
Defaults to false.
type: boolean
useLetsEncryptStagingEnvironment: useLetsEncryptStagingEnvironment:
description: |- description: |-
Set UseLetsEncryptStagingEnvironment to true to issue TLS Set UseLetsEncryptStagingEnvironment to true to issue TLS

View File

@ -2684,6 +2684,14 @@ spec:
https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices
Defaults to false. Defaults to false.
type: boolean type: boolean
ephemeral:
description: |-
Ephemeral can be set to true to make the proxy instance register
as an ephemeral node. Ephemeral nodes are automatically deleted
from the tailnet when they are offline for a while.
https://tailscale.com/kb/1111/ephemeral-nodes/
Defaults to false.
type: boolean
type: object type: object
useLetsEncryptStagingEnvironment: useLetsEncryptStagingEnvironment:
description: |- description: |-
@ -5009,6 +5017,8 @@ spec:
value: operator value: operator
- name: OPERATOR_LOGGING - name: OPERATOR_LOGGING
value: info value: info
- name: OPERATOR_EPHEMERAL
value: "false"
- name: OPERATOR_NAMESPACE - name: OPERATOR_NAMESPACE
valueFrom: valueFrom:
fieldRef: fieldRef:

View File

@ -139,6 +139,7 @@ func initTSNet(zlog *zap.SugaredLogger) (*tsnet.Server, tsClient) {
hostname = defaultEnv("OPERATOR_HOSTNAME", "tailscale-operator") hostname = defaultEnv("OPERATOR_HOSTNAME", "tailscale-operator")
kubeSecret = defaultEnv("OPERATOR_SECRET", "") kubeSecret = defaultEnv("OPERATOR_SECRET", "")
operatorTags = defaultEnv("OPERATOR_INITIAL_TAGS", "tag:k8s-operator") operatorTags = defaultEnv("OPERATOR_INITIAL_TAGS", "tag:k8s-operator")
ephemeral = defaultBool("OPERATOR_EPHEMERAL", false)
) )
startlog := zlog.Named("startup") startlog := zlog.Named("startup")
if clientIDPath == "" || clientSecretPath == "" { if clientIDPath == "" || clientSecretPath == "" {
@ -196,6 +197,7 @@ waitOnline:
Create: tailscale.KeyDeviceCreateCapabilities{ Create: tailscale.KeyDeviceCreateCapabilities{
Reusable: false, Reusable: false,
Preauthorized: true, Preauthorized: true,
Ephemeral: ephemeral,
Tags: strings.Split(operatorTags, ","), Tags: strings.Split(operatorTags, ","),
}, },
}, },

View File

@ -477,7 +477,11 @@ func (r *ProxyGroupReconciler) ensureConfigSecretsCreated(ctx context.Context, p
if len(tags) == 0 { if len(tags) == 0 {
tags = r.defaultTags tags = r.defaultTags
} }
authKey, err = newAuthKey(ctx, r.tsClient, tags) ephemeral := false
if proxyClass != nil && proxyClass.Spec.TailscaleConfig != nil {
ephemeral = proxyClass.Spec.TailscaleConfig.Ephemeral
}
authKey, err = newAuthKey(ctx, r.tsClient, tags, ephemeral)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -376,7 +376,7 @@ func (a *tailscaleSTSReconciler) createOrGetSecret(ctx context.Context, logger *
if len(tags) == 0 { if len(tags) == 0 {
tags = a.defaultTags tags = a.defaultTags
} }
authKey, err = newAuthKey(ctx, a.tsClient, tags) authKey, err = newAuthKey(ctx, a.tsClient, tags, shouldUseEphemeral(stsC.ProxyClass))
if err != nil { if err != nil {
return "", "", nil, err return "", "", nil, err
} }
@ -511,12 +511,13 @@ func deviceInfo(sec *corev1.Secret, podUID string, log *zap.SugaredLogger) (dev
return dev, nil return dev, nil
} }
func newAuthKey(ctx context.Context, tsClient tsClient, tags []string) (string, error) { func newAuthKey(ctx context.Context, tsClient tsClient, tags []string, ephemeral bool) (string, error) {
caps := tailscale.KeyCapabilities{ caps := tailscale.KeyCapabilities{
Devices: tailscale.KeyDeviceCapabilities{ Devices: tailscale.KeyDeviceCapabilities{
Create: tailscale.KeyDeviceCreateCapabilities{ Create: tailscale.KeyDeviceCreateCapabilities{
Reusable: false, Reusable: false,
Preauthorized: true, Preauthorized: true,
Ephemeral: ephemeral,
Tags: tags, Tags: tags,
}, },
}, },
@ -1022,6 +1023,10 @@ func shouldAcceptRoutes(pc *tsapi.ProxyClass) bool {
return pc != nil && pc.Spec.TailscaleConfig != nil && pc.Spec.TailscaleConfig.AcceptRoutes return pc != nil && pc.Spec.TailscaleConfig != nil && pc.Spec.TailscaleConfig.AcceptRoutes
} }
func shouldUseEphemeral(pc *tsapi.ProxyClass) bool {
return pc != nil && pc.Spec.TailscaleConfig != nil && pc.Spec.TailscaleConfig.Ephemeral
}
// ptrObject is a type constraint for pointer types that implement // ptrObject is a type constraint for pointer types that implement
// client.Object. // client.Object.
type ptrObject[T any] interface { type ptrObject[T any] interface {

View File

@ -289,7 +289,7 @@ func (r *RecorderReconciler) ensureAuthSecretCreated(ctx context.Context, tsr *t
if len(tags) == 0 { if len(tags) == 0 {
tags = tsapi.Tags{"tag:k8s"} tags = tsapi.Tags{"tag:k8s"}
} }
authKey, err := newAuthKey(ctx, r.tsClient, tags.Stringify()) authKey, err := newAuthKey(ctx, r.tsClient, tags.Stringify(), false)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1013,5 +1013,6 @@ _Appears in:_
| Field | Description | Default | Validation | | Field | Description | Default | Validation |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| `acceptRoutes` _boolean_ | AcceptRoutes can be set to true to make the proxy instance accept<br />routes advertized by other nodes on the tailnet, such as subnet<br />routes.<br />This is equivalent of passing --accept-routes flag to a tailscale Linux client.<br />https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices<br />Defaults to false. | | | | `acceptRoutes` _boolean_ | AcceptRoutes can be set to true to make the proxy instance accept<br />routes advertized by other nodes on the tailnet, such as subnet<br />routes.<br />This is equivalent of passing --accept-routes flag to a tailscale Linux client.<br />https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices<br />Defaults to false. | | |
| `ephemeral` _boolean_ | Ephemeral can be set to true to make the proxy instance register<br />as an ephemeral node. Ephemeral nodes are automatically deleted<br />from the tailnet when they are offline for a while.<br />https://tailscale.com/kb/1111/ephemeral-nodes/<br />Defaults to false. | | |

View File

@ -91,6 +91,13 @@ type TailscaleConfig struct {
// https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices // https://tailscale.com/kb/1019/subnets#use-your-subnet-routes-from-other-devices
// Defaults to false. // Defaults to false.
AcceptRoutes bool `json:"acceptRoutes,omitempty"` AcceptRoutes bool `json:"acceptRoutes,omitempty"`
// Ephemeral can be set to true to make the proxy instance register
// as an ephemeral node. Ephemeral nodes are automatically deleted
// from the tailnet when they are offline for a while.
// https://tailscale.com/kb/1111/ephemeral-nodes/
// Defaults to false.
Ephemeral bool `json:"ephemeral,omitempty"`
} }
type StatefulSet struct { type StatefulSet struct {