Skip to content

Commit 93dc2de

Browse files
cmd/k8s-operator: support default proxy class in k8s-operator (tailscale#12711)
Signed-off-by: ChandonPierre <cpierre@coreweave.com> Closes tailscale#12421
1 parent 8f6a235 commit 93dc2de

File tree

5 files changed

+29
-4
lines changed

5 files changed

+29
-4
lines changed

cmd/k8s-operator/deploy/chart/templates/deployment.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ spec:
7777
value: "{{ .Values.apiServerProxyConfig.mode }}"
7878
- name: PROXY_FIREWALL_MODE
7979
value: {{ .Values.proxyConfig.firewallMode }}
80+
{{- if .Values.proxyConfig.defaultProxyClass }}
81+
- name: PROXY_DEFAULT_CLASS
82+
value: {{ .Values.proxyConfig.defaultProxyClass }}
83+
{{- end }}
8084
{{- with .Values.operatorConfig.extraEnv }}
8185
{{- toYaml . | nindent 12 }}
8286
{{- end }}

cmd/k8s-operator/deploy/chart/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ proxyConfig:
7878
# 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
7979
defaultTags: "tag:k8s"
8080
firewallMode: auto
81+
# If defined, this proxy class will be used as the default proxy class for
82+
# service and ingress resources that do not have a proxy class defined.
83+
defaultProxyClass: ""
8184

8285
# apiServerProxyConfig allows to configure whether the operator should expose
8386
# Kubernetes API server.

cmd/k8s-operator/ingress.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ type IngressReconciler struct {
4646
// managedIngresses is a set of all ingress resources that we're currently
4747
// managing. This is only used for metrics.
4848
managedIngresses set.Slice[types.UID]
49+
50+
proxyDefaultClass string
4951
}
5052

5153
var (
@@ -133,7 +135,7 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
133135
}
134136
}
135137

136-
proxyClass := proxyClassForObject(ing)
138+
proxyClass := proxyClassForObject(ing, a.proxyDefaultClass)
137139
if proxyClass != "" {
138140
if ready, err := proxyClassIsReady(ctx, proxyClass, a.Client); err != nil {
139141
return fmt.Errorf("error verifying ProxyClass for Ingress: %w", err)

cmd/k8s-operator/operator.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func main() {
6666
priorityClassName = defaultEnv("PROXY_PRIORITY_CLASS_NAME", "")
6767
tags = defaultEnv("PROXY_TAGS", "tag:k8s")
6868
tsFirewallMode = defaultEnv("PROXY_FIREWALL_MODE", "")
69+
defaultProxyClass = defaultEnv("PROXY_DEFAULT_CLASS", "")
6970
isDefaultLoadBalancer = defaultBool("OPERATOR_DEFAULT_LOAD_BALANCER", false)
7071
)
7172

@@ -106,6 +107,7 @@ func main() {
106107
proxyActAsDefaultLoadBalancer: isDefaultLoadBalancer,
107108
proxyTags: tags,
108109
proxyFirewallMode: tsFirewallMode,
110+
proxyDefaultClass: defaultProxyClass,
109111
}
110112
runReconcilers(rOpts)
111113
}
@@ -279,6 +281,7 @@ func runReconcilers(opts reconcilerOpts) {
279281
recorder: eventRecorder,
280282
tsNamespace: opts.tailscaleNamespace,
281283
clock: tstime.DefaultClock{},
284+
proxyDefaultClass: opts.proxyDefaultClass,
282285
})
283286
if err != nil {
284287
startlog.Fatalf("could not create service reconciler: %v", err)
@@ -301,6 +304,7 @@ func runReconcilers(opts reconcilerOpts) {
301304
recorder: eventRecorder,
302305
Client: mgr.GetClient(),
303306
logger: opts.log.Named("ingress-reconciler"),
307+
proxyDefaultClass: opts.proxyDefaultClass,
304308
})
305309
if err != nil {
306310
startlog.Fatalf("could not create ingress reconciler: %v", err)
@@ -424,6 +428,10 @@ type reconcilerOpts struct {
424428
// Auto is usually the best choice, unless you want to explicitly set
425429
// specific mode for debugging purposes.
426430
proxyFirewallMode string
431+
// proxyDefaultClass is the name of the ProxyClass to use as the default
432+
// class for proxies that do not have a ProxyClass set.
433+
// this is defined by an operator env variable.
434+
proxyDefaultClass string
427435
}
428436

429437
// enqueueAllIngressEgressProxySvcsinNS returns a reconcile request for each

cmd/k8s-operator/svc.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ type ServiceReconciler struct {
6262
tsNamespace string
6363

6464
clock tstime.Clock
65+
66+
proxyDefaultClass string
6567
}
6668

6769
var (
@@ -208,7 +210,7 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
208210
return nil
209211
}
210212

211-
proxyClass := proxyClassForObject(svc)
213+
proxyClass := proxyClassForObject(svc, a.proxyDefaultClass)
212214
if proxyClass != "" {
213215
if ready, err := proxyClassIsReady(ctx, proxyClass, a.Client); err != nil {
214216
errMsg := fmt.Errorf("error verifying ProxyClass for Service: %w", err)
@@ -404,8 +406,14 @@ func tailnetTargetAnnotation(svc *corev1.Service) string {
404406
return svc.Annotations[annotationTailnetTargetIPOld]
405407
}
406408

407-
func proxyClassForObject(o client.Object) string {
408-
return o.GetLabels()[LabelProxyClass]
409+
// proxyClassForObject returns the proxy class for the given object. If the
410+
// object does not have a proxy class label, it returns the default proxy class
411+
func proxyClassForObject(o client.Object, proxyDefaultClass string) string {
412+
proxyClass, exists := o.GetLabels()[LabelProxyClass]
413+
if !exists {
414+
proxyClass = proxyDefaultClass
415+
}
416+
return proxyClass
409417
}
410418

411419
func proxyClassIsReady(ctx context.Context, name string, cl client.Client) (bool, error) {

0 commit comments

Comments
 (0)