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
- name: OPERATOR_LOGGING
value: {{ .Values.operatorConfig.logging }}
- name: OPERATOR_EPHEMERAL
value: "{{ .Values.operatorConfig.ephemeral }}"
- name: OPERATOR_NAMESPACE
valueFrom:
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
defaultTags:
- "tag:k8s-operator"
# When true, the operator will use an ephemeral auth key
# https://tailscale.com/kb/1111/ephemeral-nodes/
ephemeral: false
image:
# 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
Defaults to false.
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:
description: |-
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
Defaults to false.
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
useLetsEncryptStagingEnvironment:
description: |-
@ -5009,6 +5017,8 @@ spec:
value: operator
- name: OPERATOR_LOGGING
value: info
- name: OPERATOR_EPHEMERAL
value: "false"
- name: OPERATOR_NAMESPACE
valueFrom:
fieldRef:

View File

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

View File

@ -477,7 +477,11 @@ func (r *ProxyGroupReconciler) ensureConfigSecretsCreated(ctx context.Context, p
if len(tags) == 0 {
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 {
return "", err
}

View File

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

View File

@ -289,7 +289,7 @@ func (r *RecorderReconciler) ensureAuthSecretCreated(ctx context.Context, tsr *t
if len(tags) == 0 {
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 {
return err
}

View File

@ -1013,5 +1013,6 @@ _Appears in:_
| 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. | | |
| `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
// Defaults to false.
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 {