From ecd64f6ed98ed3790312b310459bb3b674aee8db Mon Sep 17 00:00:00 2001 From: Irbe Krumina Date: Sun, 8 Sep 2024 07:48:38 +0300 Subject: [PATCH] cmd/k8s-operator,kube: set app name for Kubernetes Operator proxies (#13410) Updates tailscale/corp#22920 Signed-off-by: Irbe Krumina --- cmd/derper/depaware.txt | 1 + cmd/k8s-operator/connector.go | 7 ++++--- cmd/k8s-operator/connector_test.go | 4 ++++ cmd/k8s-operator/ingress.go | 3 ++- cmd/k8s-operator/ingress_test.go | 3 +++ cmd/k8s-operator/nameserver.go | 5 ++--- cmd/k8s-operator/operator.go | 13 +++++++------ cmd/k8s-operator/operator_test.go | 14 ++++++++++++++ cmd/k8s-operator/sts.go | 29 +++++++++++++++++++++++++++++ cmd/k8s-operator/svc.go | 5 +++-- cmd/k8s-operator/testutils_test.go | 6 ++++++ cmd/stund/depaware.txt | 4 +++- cmd/tailscale/depaware.txt | 1 + cmd/tailscaled/depaware.txt | 2 +- cmd/tailscaled/tailscaled.go | 4 ++++ envknob/envknob.go | 14 ++++++++++++++ kube/metrics.go | 23 +++++++++++++++++++++++ 17 files changed, 121 insertions(+), 17 deletions(-) create mode 100644 kube/metrics.go diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt index 53b263d03..5be7e761a 100644 --- a/cmd/derper/depaware.txt +++ b/cmd/derper/depaware.txt @@ -99,6 +99,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa tailscale.com/hostinfo from tailscale.com/net/netmon+ tailscale.com/ipn from tailscale.com/client/tailscale tailscale.com/ipn/ipnstate from tailscale.com/client/tailscale+ + tailscale.com/kube from tailscale.com/envknob tailscale.com/metrics from tailscale.com/cmd/derper+ tailscale.com/net/dnscache from tailscale.com/derp/derphttp tailscale.com/net/ktimeout from tailscale.com/cmd/derper diff --git a/cmd/k8s-operator/connector.go b/cmd/k8s-operator/connector.go index 4586dfdbf..621836f94 100644 --- a/cmd/k8s-operator/connector.go +++ b/cmd/k8s-operator/connector.go @@ -26,6 +26,7 @@ "sigs.k8s.io/controller-runtime/pkg/reconcile" tsoperator "tailscale.com/k8s-operator" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/tstime" "tailscale.com/util/clientmetric" "tailscale.com/util/set" @@ -61,11 +62,11 @@ type ConnectorReconciler struct { var ( // gaugeConnectorResources tracks the overall number of Connectors currently managed by this operator instance. - gaugeConnectorResources = clientmetric.NewGauge("k8s_connector_resources") + gaugeConnectorResources = clientmetric.NewGauge(kube.MetricConnectorResourceCount) // gaugeConnectorSubnetRouterResources tracks the number of Connectors managed by this operator instance that are subnet routers. - gaugeConnectorSubnetRouterResources = clientmetric.NewGauge("k8s_connector_subnetrouter_resources") + gaugeConnectorSubnetRouterResources = clientmetric.NewGauge(kube.MetricConnectorWithSubnetRouterCount) // gaugeConnectorExitNodeResources tracks the number of Connectors currently managed by this operator instance that are exit nodes. - gaugeConnectorExitNodeResources = clientmetric.NewGauge("k8s_connector_exitnode_resources") + gaugeConnectorExitNodeResources = clientmetric.NewGauge(kube.MetricConnectorWithExitNodeCount) ) func (a *ConnectorReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) { diff --git a/cmd/k8s-operator/connector_test.go b/cmd/k8s-operator/connector_test.go index 8a7a5dd53..48f59e15b 100644 --- a/cmd/k8s-operator/connector_test.go +++ b/cmd/k8s-operator/connector_test.go @@ -16,6 +16,7 @@ "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client/fake" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/tstest" "tailscale.com/util/mak" ) @@ -74,6 +75,7 @@ func TestConnector(t *testing.T) { hostname: "test-connector", isExitNode: true, subnetRoutes: "10.40.0.0/14", + app: kube.AppConnector, } expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation) @@ -169,6 +171,7 @@ func TestConnector(t *testing.T) { parentType: "connector", subnetRoutes: "10.40.0.0/14", hostname: "test-connector", + app: kube.AppConnector, } expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation) @@ -254,6 +257,7 @@ func TestConnectorWithProxyClass(t *testing.T) { hostname: "test-connector", isExitNode: true, subnetRoutes: "10.40.0.0/14", + app: kube.AppConnector, } expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation) diff --git a/cmd/k8s-operator/ingress.go b/cmd/k8s-operator/ingress.go index badc1e7a4..99aabc441 100644 --- a/cmd/k8s-operator/ingress.go +++ b/cmd/k8s-operator/ingress.go @@ -23,6 +23,7 @@ "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" "tailscale.com/ipn" + "tailscale.com/kube" "tailscale.com/types/opt" "tailscale.com/util/clientmetric" "tailscale.com/util/set" @@ -53,7 +54,7 @@ type IngressReconciler struct { var ( // gaugeIngressResources tracks the number of ingress resources that we're // currently managing. - gaugeIngressResources = clientmetric.NewGauge("k8s_ingress_resources") + gaugeIngressResources = clientmetric.NewGauge(kube.MetricIngressResourceCount) ) func (a *IngressReconciler) Reconcile(ctx context.Context, req reconcile.Request) (_ reconcile.Result, err error) { diff --git a/cmd/k8s-operator/ingress_test.go b/cmd/k8s-operator/ingress_test.go index 10d109653..2588a804d 100644 --- a/cmd/k8s-operator/ingress_test.go +++ b/cmd/k8s-operator/ingress_test.go @@ -17,6 +17,7 @@ "sigs.k8s.io/controller-runtime/pkg/client/fake" "tailscale.com/ipn" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/types/ptr" "tailscale.com/util/mak" ) @@ -93,6 +94,7 @@ func TestTailscaleIngress(t *testing.T) { namespace: "default", parentType: "ingress", hostname: "default-test", + app: kube.AppIngressResource, } serveConfig := &ipn.ServeConfig{ TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}}, @@ -224,6 +226,7 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) { namespace: "default", parentType: "ingress", hostname: "default-test", + app: kube.AppIngressResource, } serveConfig := &ipn.ServeConfig{ TCP: map[uint16]*ipn.TCPPortHandler{443: {HTTPS: true}}, diff --git a/cmd/k8s-operator/nameserver.go b/cmd/k8s-operator/nameserver.go index 237fe6e82..4a864e12b 100644 --- a/cmd/k8s-operator/nameserver.go +++ b/cmd/k8s-operator/nameserver.go @@ -28,6 +28,7 @@ "sigs.k8s.io/yaml" tsoperator "tailscale.com/k8s-operator" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/tstime" "tailscale.com/util/clientmetric" "tailscale.com/util/set" @@ -62,9 +63,7 @@ type NameserverReconciler struct { managedNameservers set.Slice[types.UID] // one or none } -var ( - gaugeNameserverResources = clientmetric.NewGauge("k8s_nameserver_resources") -) +var gaugeNameserverResources = clientmetric.NewGauge(kube.MetricNameserverCount) func (a *NameserverReconciler) Reconcile(ctx context.Context, req reconcile.Request) (res reconcile.Result, err error) { logger := a.logger.With("dnsConfig", req.Name) diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index 18665bd8f..aa59d8de2 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -39,6 +39,7 @@ "tailscale.com/ipn" "tailscale.com/ipn/store/kubestore" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/tsnet" "tailscale.com/tstime" "tailscale.com/types/logger" @@ -87,9 +88,9 @@ func main() { // https://tailscale.com/kb/1236/kubernetes-operator/?q=kubernetes#accessing-the-kubernetes-control-plane-using-an-api-server-proxy. mode := parseAPIProxyMode() if mode == apiserverProxyModeDisabled { - hostinfo.SetApp("k8s-operator") + hostinfo.SetApp(kube.AppOperator) } else { - hostinfo.SetApp("k8s-operator-proxy") + hostinfo.SetApp(kube.AppAPIServerProxy) } s, tsClient := initTSNet(zlog) @@ -300,10 +301,10 @@ func runReconcilers(opts reconcilerOpts) { Watches(&corev1.Service{}, svcHandlerForIngress). Watches(&tsapi.ProxyClass{}, proxyClassFilterForIngress). Complete(&IngressReconciler{ - ssr: ssr, - recorder: eventRecorder, - Client: mgr.GetClient(), - logger: opts.log.Named("ingress-reconciler"), + ssr: ssr, + recorder: eventRecorder, + Client: mgr.GetClient(), + logger: opts.log.Named("ingress-reconciler"), proxyDefaultClass: opts.proxyDefaultClass, }) if err != nil { diff --git a/cmd/k8s-operator/operator_test.go b/cmd/k8s-operator/operator_test.go index 448db71e2..583d5a3d4 100644 --- a/cmd/k8s-operator/operator_test.go +++ b/cmd/k8s-operator/operator_test.go @@ -22,6 +22,7 @@ "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/reconcile" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/net/dns/resolvconffile" "tailscale.com/tstest" "tailscale.com/tstime" @@ -123,6 +124,7 @@ func TestLoadBalancerClass(t *testing.T) { parentType: "svc", hostname: "default-test", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSecret(t, fc, opts), nil) @@ -260,6 +262,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) { parentType: "svc", tailnetTargetFQDN: tailnetTargetFQDN, hostname: "default-test", + app: kube.AppEgressProxy, } expectEqual(t, fc, expectedSecret(t, fc, o), nil) @@ -371,6 +374,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) { parentType: "svc", tailnetTargetIP: tailnetTargetIP, hostname: "default-test", + app: kube.AppEgressProxy, } expectEqual(t, fc, expectedSecret(t, fc, o), nil) @@ -479,6 +483,7 @@ func TestAnnotations(t *testing.T) { parentType: "svc", hostname: "default-test", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSecret(t, fc, o), nil) @@ -584,6 +589,7 @@ func TestAnnotationIntoLB(t *testing.T) { parentType: "svc", hostname: "default-test", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSecret(t, fc, o), nil) @@ -713,6 +719,7 @@ func TestLBIntoAnnotation(t *testing.T) { parentType: "svc", hostname: "default-test", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSecret(t, fc, o), nil) @@ -852,6 +859,7 @@ func TestCustomHostname(t *testing.T) { parentType: "svc", hostname: "reindeer-flotilla", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSecret(t, fc, o), nil) @@ -964,6 +972,7 @@ func TestCustomPriorityClassName(t *testing.T) { hostname: "tailscale-critical", priorityClassName: "custom-priority-class-name", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation) @@ -1032,6 +1041,7 @@ func TestProxyClassForService(t *testing.T) { parentType: "svc", hostname: "default-test", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSecret(t, fc, opts), nil) expectEqual(t, fc, expectedHeadlessService(shortName, "svc"), nil) @@ -1125,6 +1135,7 @@ func TestDefaultLoadBalancer(t *testing.T) { parentType: "svc", hostname: "default-test", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation) @@ -1181,6 +1192,7 @@ func TestProxyFirewallMode(t *testing.T) { hostname: "default-test", firewallMode: "nftables", clusterTargetIP: "10.20.30.40", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSTS(t, fc, o), removeHashAnnotation) } @@ -1235,6 +1247,7 @@ func TestTailscaledConfigfileHash(t *testing.T) { hostname: "default-test", clusterTargetIP: "10.20.30.40", confFileHash: "e09bededa0379920141cbd0b0dbdf9b8b66545877f9e8397423f5ce3e1ba439e", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSTS(t, fc, o), nil) @@ -1529,6 +1542,7 @@ func Test_externalNameService(t *testing.T) { parentType: "svc", hostname: "default-test", clusterTargetDNS: "foo.com", + app: kube.AppIngressProxy, } expectEqual(t, fc, expectedSecret(t, fc, opts), nil) diff --git a/cmd/k8s-operator/sts.go b/cmd/k8s-operator/sts.go index 17cc047d0..a6b03ee83 100644 --- a/cmd/k8s-operator/sts.go +++ b/cmd/k8s-operator/sts.go @@ -31,6 +31,7 @@ "tailscale.com/ipn" tsoperator "tailscale.com/k8s-operator" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/net/netutil" "tailscale.com/tailcfg" "tailscale.com/types/opt" @@ -598,6 +599,18 @@ func (a *tailscaleSTSReconciler) reconcileSTS(ctx context.Context, logger *zap.S }, }) } + app, err := appInfoForProxy(sts) + if err != nil { + // No need to error out if now or in future we end up in a + // situation where app info cannot be determined for one of the + // many proxy configurations that the operator can produce. + logger.Error("[unexpected] unable to determine proxy type") + } else { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "TS_INTERNAL_APP", + Value: app, + }) + } logger.Debugf("reconciling statefulset %s/%s", ss.GetNamespace(), ss.GetName()) if sts.ProxyClassName != "" { logger.Debugf("configuring proxy resources with ProxyClass %s", sts.ProxyClassName) @@ -611,6 +624,22 @@ func (a *tailscaleSTSReconciler) reconcileSTS(ctx context.Context, logger *zap.S return createOrUpdate(ctx, a.Client, a.operatorNamespace, ss, updateSS) } +func appInfoForProxy(cfg *tailscaleSTSConfig) (string, error) { + if cfg.ClusterTargetDNSName != "" || cfg.ClusterTargetIP != "" { + return kube.AppIngressProxy, nil + } + if cfg.TailnetTargetFQDN != "" || cfg.TailnetTargetIP != "" { + return kube.AppEgressProxy, nil + } + if cfg.ServeConfig != nil { + return kube.AppIngressResource, nil + } + if cfg.Connector != nil { + return kube.AppConnector, nil + } + return "", errors.New("unable to determine proxy type") +} + // mergeStatefulSetLabelsOrAnnots returns a map that contains all keys/values // present in 'custom' map as well as those keys/values from the current map // whose keys are present in the 'managed' map. The reason why this merge is diff --git a/cmd/k8s-operator/svc.go b/cmd/k8s-operator/svc.go index 9e7c6f4f3..3062488bf 100644 --- a/cmd/k8s-operator/svc.go +++ b/cmd/k8s-operator/svc.go @@ -25,6 +25,7 @@ "sigs.k8s.io/controller-runtime/pkg/reconcile" tsoperator "tailscale.com/k8s-operator" tsapi "tailscale.com/k8s-operator/apis/v1alpha1" + "tailscale.com/kube" "tailscale.com/net/dns/resolvconffile" "tailscale.com/tstime" "tailscale.com/util/clientmetric" @@ -69,10 +70,10 @@ type ServiceReconciler struct { var ( // gaugeEgressProxies tracks the number of egress proxies that we're // currently managing. - gaugeEgressProxies = clientmetric.NewGauge("k8s_egress_proxies") + gaugeEgressProxies = clientmetric.NewGauge(kube.MetricEgressProxyCount) // gaugeIngressProxies tracks the number of ingress proxies that we're // currently managing. - gaugeIngressProxies = clientmetric.NewGauge("k8s_ingress_proxies") + gaugeIngressProxies = clientmetric.NewGauge(kube.MetricIngressProxyCount) ) func childResourceLabels(name, ns, typ string) map[string]string { diff --git a/cmd/k8s-operator/testutils_test.go b/cmd/k8s-operator/testutils_test.go index f5f9ece2b..0854e9039 100644 --- a/cmd/k8s-operator/testutils_test.go +++ b/cmd/k8s-operator/testutils_test.go @@ -51,6 +51,7 @@ type configOpts struct { serveConfig *ipn.ServeConfig shouldEnableForwardingClusterTrafficViaIngress bool proxyClass string // configuration from the named ProxyClass should be applied to proxy resources + app string } func expectedSTS(t *testing.T, cl client.Client, opts configOpts) *appsv1.StatefulSet { @@ -142,6 +143,10 @@ func expectedSTS(t *testing.T, cl client.Client, opts configOpts) *appsv1.Statef volumes = append(volumes, corev1.Volume{Name: "serve-config", VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: opts.secretName, Items: []corev1.KeyToPath{{Key: "serve-config", Path: "serve-config"}}}}}) tsContainer.VolumeMounts = append(tsContainer.VolumeMounts, corev1.VolumeMount{Name: "serve-config", ReadOnly: true, MountPath: "/etc/tailscaled"}) } + tsContainer.Env = append(tsContainer.Env, corev1.EnvVar{ + Name: "TS_INTERNAL_APP", + Value: opts.app, + }) ss := &appsv1.StatefulSet{ TypeMeta: metav1.TypeMeta{ Kind: "StatefulSet", @@ -224,6 +229,7 @@ func expectedSTSUserspace(t *testing.T, cl client.Client, opts configOpts) *apps {Name: "EXPERIMENTAL_TS_CONFIGFILE_PATH", Value: "/etc/tsconfig/tailscaled"}, {Name: "TS_EXPERIMENTAL_VERSIONED_CONFIG_DIR", Value: "/etc/tsconfig"}, {Name: "TS_SERVE_CONFIG", Value: "/etc/tailscaled/serve-config"}, + {Name: "TS_INTERNAL_APP", Value: opts.app}, }, ImagePullPolicy: "Always", VolumeMounts: []corev1.VolumeMount{ diff --git a/cmd/stund/depaware.txt b/cmd/stund/depaware.txt index 69a399559..31bacf2b4 100644 --- a/cmd/stund/depaware.txt +++ b/cmd/stund/depaware.txt @@ -50,6 +50,7 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar google.golang.org/protobuf/types/known/timestamppb from github.com/prometheus/client_golang/prometheus+ tailscale.com from tailscale.com/version tailscale.com/envknob from tailscale.com/tsweb+ + tailscale.com/kube from tailscale.com/envknob tailscale.com/metrics from tailscale.com/net/stunserver+ tailscale.com/net/netaddr from tailscale.com/net/tsaddr tailscale.com/net/stun from tailscale.com/net/stunserver @@ -74,6 +75,7 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar tailscale.com/util/dnsname from tailscale.com/tailcfg tailscale.com/util/fastuuid from tailscale.com/tsweb tailscale.com/util/lineread from tailscale.com/version/distro + tailscale.com/util/multierr from tailscale.com/kube tailscale.com/util/nocasemaps from tailscale.com/types/ipproto tailscale.com/util/slicesx from tailscale.com/tailcfg tailscale.com/util/vizerror from tailscale.com/tailcfg+ @@ -129,7 +131,7 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar crypto/sha512 from crypto/ecdsa+ crypto/subtle from crypto/aes+ crypto/tls from net/http+ - crypto/x509 from crypto/tls + crypto/x509 from crypto/tls+ crypto/x509/pkix from crypto/x509 database/sql/driver from github.com/google/uuid embed from crypto/internal/nistec+ diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index b5d5735b7..ec4ba4aa4 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -98,6 +98,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/internal/noiseconn from tailscale.com/cmd/tailscale/cli tailscale.com/ipn from tailscale.com/client/tailscale+ tailscale.com/ipn/ipnstate from tailscale.com/client/tailscale+ + tailscale.com/kube from tailscale.com/envknob tailscale.com/licenses from tailscale.com/client/web+ tailscale.com/metrics from tailscale.com/derp+ tailscale.com/net/captivedetection from tailscale.com/net/netcheck diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index eed37c7d4..2ae69623e 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -279,7 +279,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L tailscale.com/ipn/store/awsstore from tailscale.com/ipn/store L tailscale.com/ipn/store/kubestore from tailscale.com/ipn/store tailscale.com/ipn/store/mem from tailscale.com/ipn/ipnlocal+ - L tailscale.com/kube from tailscale.com/ipn/store/kubestore + tailscale.com/kube from tailscale.com/ipn/store/kubestore+ tailscale.com/licenses from tailscale.com/client/web tailscale.com/log/filelogger from tailscale.com/logpolicy tailscale.com/log/sockstatlog from tailscale.com/ipn/ipnlocal diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 160e56da4..eb53f4f15 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -417,6 +417,10 @@ func run() (err error) { sys.Set(driveimpl.NewFileSystemForRemote(logf)) + if app := envknob.App(); app != "" { + hostinfo.SetApp(app) + } + return startIPNServer(context.Background(), logf, pol.PublicID, sys) } diff --git a/envknob/envknob.go b/envknob/envknob.go index 6eb6cdf9f..0fc723746 100644 --- a/envknob/envknob.go +++ b/envknob/envknob.go @@ -31,6 +31,7 @@ "sync/atomic" "time" + "tailscale.com/kube" "tailscale.com/types/opt" "tailscale.com/version" "tailscale.com/version/distro" @@ -402,6 +403,19 @@ func SSHIgnoreTailnetPolicy() bool { return Bool("TS_DEBUG_SSH_IGNORE_TAILNET_PO // TKASkipSignatureCheck reports whether to skip node-key signature checking for development. func TKASkipSignatureCheck() bool { return Bool("TS_UNSAFE_SKIP_NKS_VERIFICATION") } +// App returns the tailscale app type of this instance, if set via +// TS_INTERNAL_APP env var. TS_INTERNAL_APP can be used to set app type for +// components that wrap tailscaled, such as containerboot. App type is intended +// to only be used to set known predefined app types, such as Tailscale +// Kubernetes Operator components. +func App() string { + a := os.Getenv("TS_INTERNAL_APP") + if a == kube.AppConnector || a == kube.AppEgressProxy || a == kube.AppIngressProxy || a == kube.AppIngressResource { + return a + } + return "" +} + // CrashOnUnexpected reports whether the Tailscale client should panic // on unexpected conditions. If TS_DEBUG_CRASH_ON_UNEXPECTED is set, that's // used. Otherwise the default value is true for unstable builds. diff --git a/kube/metrics.go b/kube/metrics.go new file mode 100644 index 000000000..a0e33f5f7 --- /dev/null +++ b/kube/metrics.go @@ -0,0 +1,23 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package kube + +const ( + // Hostinfo App values for the Tailscale Kubernetes Operator components. + AppOperator = "k8s-operator" + AppAPIServerProxy = "k8s-operator-proxy" + AppIngressProxy = "k8s-operator-ingress-proxy" + AppIngressResource = "k8s-operator-ingress-resource" + AppEgressProxy = "k8s-operator-egress-proxy" + AppConnector = "k8s-operator-connector-resource" + + // Clientmetrics for Tailscale Kubernetes Operator components + MetricIngressProxyCount = "k8s_ingress_proxies" // L3 + MetricIngressResourceCount = "k8s_ingress_resources" // L7 + MetricEgressProxyCount = "k8s_egress_proxies" + MetricConnectorResourceCount = "k8s_connector_resources" + MetricConnectorWithSubnetRouterCount = "k8s_connector_subnetrouter_resources" + MetricConnectorWithExitNodeCount = "k8s_connector_exitnode_resources" + MetricNameserverCount = "k8s_nameserver_resources" +)