mirror of
https://github.com/tailscale/tailscale.git
synced 2026-05-06 04:36:15 +02:00
* cmd/k8s-operator: truncate long label values in metrics resources Kubernetes label values have a 63-character limit, but resource names can be up to 253 characters. When a Service or Ingress with a long name is exposed via Tailscale, the operator fails to reconcile because it uses the parent resource name directly as label values on metrics Services. Truncate label values that may exceed the limit by keeping the first 54 characters and appending a SHA256-based hash suffix to preserve uniqueness. Fixes #18894 Signed-off-by: Daniel Pañeda <daniel.paneda@clickhouse.com> Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk> * cmd/k8s-operator: move TruncateLabelValue to shared k8s-operator package Move the label truncation helper to k8s-operator/utils.go so it can be reused by other components that need to produce valid Kubernetes labels. Signed-off-by: Daniel Pañeda <daniel.paneda@clickhouse.com> Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk> * cmd/k8s-operator: truncate long domain label values in cert resources Applies TruncateLabelValue to certResourceLabels in order to prevent API server validation failures. This covers both the HA Ingress and kube-apiserver proxy reconcilers, as both flow through certResourceLabels. Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk> * cmd/k8s-operator: remove empty metrics_resources_test.go, use hyphens in test names to satisfy go vet Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk> --------- Signed-off-by: Daniel Pañeda <daniel.paneda@clickhouse.com> Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk> Co-authored-by: chaosinthecrd <tom@tmlabs.co.uk>
69 lines
2.1 KiB
Go
69 lines
2.1 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
//go:build !plan9
|
|
|
|
// Package kube contains types and utilities for the Tailscale Kubernetes Operator.
|
|
package kube
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
|
|
"tailscale.com/tailcfg"
|
|
)
|
|
|
|
const (
|
|
Alpha1Version = "v1alpha1"
|
|
|
|
DNSRecordsCMName = "dnsrecords"
|
|
DNSRecordsCMKey = "records.json"
|
|
)
|
|
|
|
type Records struct {
|
|
// Version is the version of this Records configuration. Version is
|
|
// written by the operator, i.e when it first populates the Records.
|
|
// k8s-nameserver must verify that it knows how to parse a given
|
|
// version.
|
|
Version string `json:"version"`
|
|
// IP4 contains a mapping of DNS names to IPv4 address(es).
|
|
IP4 map[string][]string `json:"ip4"`
|
|
// IP6 contains a mapping of DNS names to IPv6 address(es).
|
|
// This field is optional and will be omitted from JSON if empty.
|
|
// It enables dual-stack DNS support in Kubernetes clusters.
|
|
// +optional
|
|
IP6 map[string][]string `json:"ip6,omitempty"`
|
|
}
|
|
|
|
// TailscaledConfigFileName returns a tailscaled config file name in
|
|
// format expected by containerboot for the given CapVer.
|
|
func TailscaledConfigFileName(cap tailcfg.CapabilityVersion) string {
|
|
return fmt.Sprintf("cap-%v.hujson", cap)
|
|
}
|
|
|
|
// CapVerFromFileName parses the capability version from a tailscaled
|
|
// config file name previously generated by TailscaledConfigFileNameForCap.
|
|
func CapVerFromFileName(name string) (tailcfg.CapabilityVersion, error) {
|
|
if name == "tailscaled" {
|
|
return 0, nil
|
|
}
|
|
var cap tailcfg.CapabilityVersion
|
|
_, err := fmt.Sscanf(name, "cap-%d.hujson", &cap)
|
|
return cap, err
|
|
}
|
|
|
|
// TruncateLabelValue truncates a Kubernetes label value to fit within the
|
|
// 63-character limit. If the value exceeds the limit, it is truncated and a
|
|
// short hash suffix is appended to preserve uniqueness.
|
|
func TruncateLabelValue(val string) string {
|
|
const maxLen = 63
|
|
if len(val) <= maxLen {
|
|
return val
|
|
}
|
|
hash := sha256.Sum256([]byte(val))
|
|
suffix := hex.EncodeToString(hash[:4]) // 8 hex chars
|
|
truncated := val[:maxLen-len(suffix)-1]
|
|
return truncated + "-" + suffix
|
|
}
|