diff --git a/comp/core/workloadmeta/collectors/internal/kubelet/BUILD.bazel b/comp/core/workloadmeta/collectors/internal/kubelet/BUILD.bazel index a78ed089a6a8..fce04bf64e40 100644 --- a/comp/core/workloadmeta/collectors/internal/kubelet/BUILD.bazel +++ b/comp/core/workloadmeta/collectors/internal/kubelet/BUILD.bazel @@ -15,6 +15,7 @@ go_library( "//comp/core/workloadmeta/collectors/util", "//comp/core/workloadmeta/def", "//pkg/config/env", + "//pkg/config/helper", "//pkg/errors", "//pkg/util/containers", "//pkg/util/kubernetes/kubelet", @@ -37,10 +38,13 @@ dd_agent_go_test( include_default = False, deps = [ "//comp/core", + "//comp/core/config", "//comp/core/workloadmeta/collectors/util", "//comp/core/workloadmeta/def", "//comp/core/workloadmeta/fx-mock", "//comp/core/workloadmeta/mock", + "//pkg/config/env", + "//pkg/errors", "//pkg/util/fxutil", "//pkg/util/kubernetes", "//pkg/util/kubernetes/kubelet", diff --git a/comp/core/workloadmeta/collectors/internal/kubelet/kubelet.go b/comp/core/workloadmeta/collectors/internal/kubelet/kubelet.go index 3e53defd29e8..fc0959802859 100644 --- a/comp/core/workloadmeta/collectors/internal/kubelet/kubelet.go +++ b/comp/core/workloadmeta/collectors/internal/kubelet/kubelet.go @@ -18,6 +18,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/util" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/config/env" + "github.com/DataDog/datadog-agent/pkg/config/helper" "github.com/DataDog/datadog-agent/pkg/errors" "github.com/DataDog/datadog-agent/pkg/util/containers" "github.com/DataDog/datadog-agent/pkg/util/kubernetes/kubelet" @@ -39,6 +40,7 @@ type dependencies struct { type collector struct { id string + cfg config.Component catalog workloadmeta.AgentType store workloadmeta.Component collectEphemeralContainers bool @@ -57,6 +59,7 @@ func NewCollector(deps dependencies) (workloadmeta.CollectorProvider, error) { return workloadmeta.CollectorProvider{ Collector: &collector{ id: collectorID, + cfg: deps.Config, catalog: workloadmeta.NodeAgent, collectEphemeralContainers: deps.Config.GetBool("include_ephemeral_containers"), pullInterval: time.Duration(deps.Config.GetInt("kubelet_collector_pull_interval")) * time.Second, @@ -78,6 +81,10 @@ func (c *collector) Start(_ context.Context, store workloadmeta.Component) error return errors.NewDisabled(componentName, "Agent is not running on Kubernetes") } + if helper.IsCLCRunner(c.cfg) { + return errors.NewDisabled(componentName, "Agent is a Cluster Checks Runner and has no reachable local Kubelet") + } + c.store = store var err error diff --git a/comp/core/workloadmeta/collectors/internal/kubelet/kubelet_test.go b/comp/core/workloadmeta/collectors/internal/kubelet/kubelet_test.go index f3dd888e5389..fa63b184f8a1 100644 --- a/comp/core/workloadmeta/collectors/internal/kubelet/kubelet_test.go +++ b/comp/core/workloadmeta/collectors/internal/kubelet/kubelet_test.go @@ -8,6 +8,7 @@ package kubelet import ( + "context" "maps" "slices" "sort" @@ -21,16 +22,42 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "github.com/DataDog/datadog-agent/comp/core" + config "github.com/DataDog/datadog-agent/comp/core/config" "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/util" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" workloadmetafxmock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/fx-mock" workloadmetamock "github.com/DataDog/datadog-agent/comp/core/workloadmeta/mock" + pkgconfigenv "github.com/DataDog/datadog-agent/pkg/config/env" + pkgerrors "github.com/DataDog/datadog-agent/pkg/errors" "github.com/DataDog/datadog-agent/pkg/util/fxutil" "github.com/DataDog/datadog-agent/pkg/util/kubernetes" "github.com/DataDog/datadog-agent/pkg/util/kubernetes/kubelet" "github.com/DataDog/datadog-agent/pkg/util/pointer" ) +// TestDisabledCLCRunner verifies that the collector refuses to start (with a +// non-retriable "disabled" error) on Cluster Checks Runners, since they are +// never scheduled with a locally-reachable kubelet and would otherwise retry +// kubelet.GetKubeUtil() forever, generating noisy WARN logs. +func TestDisabledCLCRunner(t *testing.T) { + pkgconfigenv.SetFeatures(t, pkgconfigenv.Kubernetes) + + cfg := config.NewMockWithOverrides(t, map[string]interface{}{ + "clc_runner_enabled": true, + "config_providers": []map[string]interface{}{{"name": "clusterchecks"}}, + }) + + c := &collector{ + id: collectorID, + cfg: cfg, + catalog: workloadmeta.NodeAgent, + } + + err := c.Start(context.Background(), nil) + require.Error(t, err) + assert.True(t, pkgerrors.IsDisabled(err)) +} + func TestPodParser(t *testing.T) { creationTimestamp := time.Date(2025, time.January, 1, 12, 0, 0, 0, time.UTC) startTime := creationTimestamp.Add(time.Minute) diff --git a/comp/core/workloadmeta/collectors/internal/kubemetadata/BUILD.bazel b/comp/core/workloadmeta/collectors/internal/kubemetadata/BUILD.bazel index 2eed3e190681..780acdb216a7 100644 --- a/comp/core/workloadmeta/collectors/internal/kubemetadata/BUILD.bazel +++ b/comp/core/workloadmeta/collectors/internal/kubemetadata/BUILD.bazel @@ -21,6 +21,7 @@ go_library( "//pkg/api/util", "//pkg/clusteragent/api/v1:api", "//pkg/config/env", + "//pkg/config/helper", "//pkg/config/model", "//pkg/config/utils", "//pkg/errors", @@ -62,12 +63,15 @@ dd_agent_go_test( include_default = False, deps = [ "//comp/core", + "//comp/core/config", "//comp/core/workloadmeta/def", "//comp/core/workloadmeta/fx-mock", "//comp/core/workloadmeta/mock", "//pkg/clusteragent/api/v1:api", "//pkg/clusteragent/clusterchecks/types", + "//pkg/config/env", "//pkg/config/mock", + "//pkg/errors", "//pkg/proto/pbgo/core", "//pkg/proto/pbgo/process", "//pkg/util/cache", diff --git a/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata.go b/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata.go index 4300e339641b..662d2adafd6a 100644 --- a/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata.go +++ b/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata.go @@ -19,6 +19,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/util" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/config/env" + "github.com/DataDog/datadog-agent/pkg/config/helper" configutils "github.com/DataDog/datadog-agent/pkg/config/utils" "github.com/DataDog/datadog-agent/pkg/errors" "github.com/DataDog/datadog-agent/pkg/util/clusteragent" @@ -83,6 +84,10 @@ func (c *collector) Start(ctx context.Context, store workloadmeta.Component) err return errors.NewDisabled(componentName, "Agent is not running on Kubernetes") } + if helper.IsCLCRunner(c.cfg) { + return errors.NewDisabled(componentName, "Agent is a Cluster Checks Runner and has no reachable local Kubelet") + } + c.store = store var err error diff --git a/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata_test.go b/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata_test.go index 391fde1db237..33dfc5f2f443 100644 --- a/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata_test.go +++ b/comp/core/workloadmeta/collectors/internal/kubemetadata/kubemetadata_test.go @@ -13,13 +13,17 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" k8sschema "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" + compconfig "github.com/DataDog/datadog-agent/comp/core/config" workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" apiv1 "github.com/DataDog/datadog-agent/pkg/clusteragent/api/v1" "github.com/DataDog/datadog-agent/pkg/clusteragent/clusterchecks/types" + pkgconfigenv "github.com/DataDog/datadog-agent/pkg/config/env" configmock "github.com/DataDog/datadog-agent/pkg/config/mock" + pkgerrors "github.com/DataDog/datadog-agent/pkg/errors" pbgo "github.com/DataDog/datadog-agent/pkg/proto/pbgo/process" "github.com/DataDog/datadog-agent/pkg/util/cache" "github.com/DataDog/datadog-agent/pkg/util/clusteragent" @@ -143,6 +147,28 @@ func (f *FakeDCAClient) SupportsNamespaceMetadataCollection() bool { return f.LocalVersion.Major >= 7 && f.LocalVersion.Minor >= 55 } +// TestDisabledCLCRunner verifies that the collector refuses to start (with a +// non-retriable "disabled" error) on Cluster Checks Runners, since they are +// never scheduled with a locally-reachable kubelet and would otherwise retry +// kubelet.GetKubeUtil() forever, generating noisy WARN logs. +func TestDisabledCLCRunner(t *testing.T) { + pkgconfigenv.SetFeatures(t, pkgconfigenv.Kubernetes) + + cfg := compconfig.NewMockWithOverrides(t, map[string]interface{}{ + "clc_runner_enabled": true, + "config_providers": []map[string]interface{}{{"name": "clusterchecks"}}, + }) + + c := &collector{ + id: collectorID, + cfg: cfg, + } + + err := c.Start(context.Background(), nil) + require.Error(t, err) + assert.True(t, pkgerrors.IsDisabled(err)) +} + func TestCollector_selectPullBasedProvider(t *testing.T) { tests := []struct { name string diff --git a/comp/metadata/host/impl/hosttags/BUILD.bazel b/comp/metadata/host/impl/hosttags/BUILD.bazel index 6bf5c6637bd1..fb2bfd9acb1a 100644 --- a/comp/metadata/host/impl/hosttags/BUILD.bazel +++ b/comp/metadata/host/impl/hosttags/BUILD.bazel @@ -12,6 +12,7 @@ go_library( deps = [ "//comp/core/tagger/tags", "//pkg/config/env", + "//pkg/config/helper", "//pkg/config/model", "//pkg/config/utils", "//pkg/gohai/cpu", @@ -38,6 +39,7 @@ dd_agent_go_test( srcs = ["tags_test.go"], embed = [":hosttags"], deps = [ + "//pkg/config/env", "//pkg/config/mock", "//pkg/config/model", "@com_github_stretchr_testify//assert", diff --git a/comp/metadata/host/impl/hosttags/tags.go b/comp/metadata/host/impl/hosttags/tags.go index a23485697d3f..da246b8d92aa 100644 --- a/comp/metadata/host/impl/hosttags/tags.go +++ b/comp/metadata/host/impl/hosttags/tags.go @@ -14,6 +14,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/tagger/tags" "github.com/DataDog/datadog-agent/pkg/config/env" + "github.com/DataDog/datadog-agent/pkg/config/helper" "github.com/DataDog/datadog-agent/pkg/config/model" configUtils "github.com/DataDog/datadog-agent/pkg/config/utils" gpu "github.com/DataDog/datadog-agent/pkg/gpu/tags" @@ -66,7 +67,11 @@ func getProvidersDefinitions(conf model.Reader) map[string]*providerDef { } if env.IsFeaturePresent(env.Kubernetes) { - providers["kubernetes"] = &providerDef{10, k8s.NewKubeNodeTagsProvider(conf).GetTags} + // Cluster Checks Runners have no reachable local Kubelet, so node-label-based + // tags can never be retrieved and would otherwise retry (and log WARNs) forever. + if !helper.IsCLCRunner(conf) { + providers["kubernetes"] = &providerDef{10, k8s.NewKubeNodeTagsProvider(conf).GetTags} + } providers["kubernetes_cluster_agent_tags"] = &providerDef{10, clusterinfo.GetClusterAgentStaticTags} } diff --git a/comp/metadata/host/impl/hosttags/tags_test.go b/comp/metadata/host/impl/hosttags/tags_test.go index 4644f4229566..1f540639f21a 100644 --- a/comp/metadata/host/impl/hosttags/tags_test.go +++ b/comp/metadata/host/impl/hosttags/tags_test.go @@ -16,6 +16,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/DataDog/datadog-agent/pkg/config/env" configmock "github.com/DataDog/datadog-agent/pkg/config/mock" "github.com/DataDog/datadog-agent/pkg/config/model" ) @@ -169,6 +170,30 @@ func TestSanitizeEUDMTagValue(t *testing.T) { assert.Equal(t, "trim_me", sanitizeEUDMTagValue(" trim me ")) } +func TestGetProvidersDefinitionsSkipsKubernetesNodeTagsOnCLCRunner(t *testing.T) { + mockConfig, _ := setupTest(t) + env.SetFeatures(t, env.Kubernetes) + + mockConfig.SetInTest("clc_runner_enabled", true) + mockConfig.SetInTest("config_providers", []map[string]interface{}{{"name": "clusterchecks"}}) + + providers := getProvidersDefinitions(mockConfig) + _, hasKubernetesNodeTags := providers["kubernetes"] + assert.False(t, hasKubernetesNodeTags, "kubernetes node-tags provider should be skipped on Cluster Checks Runners, which have no reachable local Kubelet") + + _, hasClusterAgentTags := providers["kubernetes_cluster_agent_tags"] + assert.True(t, hasClusterAgentTags, "kubernetes_cluster_agent_tags provider should still be registered on Cluster Checks Runners") +} + +func TestGetProvidersDefinitionsIncludesKubernetesNodeTagsOnNodeAgent(t *testing.T) { + mockConfig, _ := setupTest(t) + env.SetFeatures(t, env.Kubernetes) + + providers := getProvidersDefinitions(mockConfig) + _, hasKubernetesNodeTags := providers["kubernetes"] + assert.True(t, hasKubernetesNodeTags, "kubernetes node-tags provider should be registered on a regular node Agent") +} + func TestHostTagsCache(t *testing.T) { mockConfig, ctx := setupTest(t) mockConfig.SetInTest("collect_gce_tags", false) diff --git a/pkg/util/cloudproviders/BUILD.bazel b/pkg/util/cloudproviders/BUILD.bazel index a48551fdad3a..e6f289a072cf 100644 --- a/pkg/util/cloudproviders/BUILD.bazel +++ b/pkg/util/cloudproviders/BUILD.bazel @@ -10,6 +10,7 @@ go_library( importpath = "github.com/DataDog/datadog-agent/pkg/util/cloudproviders", visibility = ["//visibility:public"], deps = [ + "//pkg/config/helper", "//pkg/config/setup", "//pkg/util/cloudproviders/alibaba", "//pkg/util/cloudproviders/azure", diff --git a/pkg/util/cloudproviders/cloudproviders.go b/pkg/util/cloudproviders/cloudproviders.go index d1371cd083a6..eebed264580e 100644 --- a/pkg/util/cloudproviders/cloudproviders.go +++ b/pkg/util/cloudproviders/cloudproviders.go @@ -12,6 +12,7 @@ import ( "sync" "time" + "github.com/DataDog/datadog-agent/pkg/config/helper" configsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/util/hostname/validate" "github.com/DataDog/datadog-agent/pkg/util/kubelet" @@ -134,16 +135,34 @@ var ( hostAliasLogOnce = true ) +// kubeletDependentHostAliasDetectors are the host-alias detectors that route through +// the shared kubelet client singleton. Cluster Checks Runners are Deployment +// replicas, not DaemonSets, so they are never colocated with a node's kubelet and can +// never reach it. +var kubeletDependentHostAliasDetectors = map[string]bool{ + "kubelet": true, + kubernetes.CloudProviderName: true, +} + // GetHostAliases returns the hostname aliases and the name of the possible cloud providers func GetHostAliases(ctx context.Context) ([]string, string) { aliases := []string{} cloudprovider := "" + isCLCRunner := helper.IsCLCRunner(configsetup.Datadog()) // cloud providers endpoints can take a few seconds to answer. We're using a WaitGroup to call all of them // concurrently since GetHostAliases is called during the agent startup and is blocking. var wg sync.WaitGroup for _, hostAliasesDetector := range hostAliasesDetectors { + if isCLCRunner && kubeletDependentHostAliasDetectors[hostAliasesDetector.name] { + // Skip probing the kubelet client singleton: it can never succeed on a + // CCR and would otherwise trigger its exponential-backoff retrier and + // its "Impossible to reach Kubelet" warning for no benefit. + log.Debugf("Skipping %s Host Alias: Agent is a Cluster Checks Runner and has no reachable local Kubelet", hostAliasesDetector.name) + continue + } + wg.Add(1) go func(hostAliasesDetector cloudProviderAliasesDetector) { defer wg.Done() diff --git a/pkg/util/cloudproviders/cloudproviders_test.go b/pkg/util/cloudproviders/cloudproviders_test.go index 3ff12f0813ac..c575ec466432 100644 --- a/pkg/util/cloudproviders/cloudproviders_test.go +++ b/pkg/util/cloudproviders/cloudproviders_test.go @@ -64,6 +64,55 @@ func TestCloudProviderAliases(t *testing.T) { assert.Contains(t, []string{"detector1", "detector3"}, cloudprovider) } +// TestCloudProviderAliasesSkipsKubeletDependentDetectorsOnCLCRunner ensures +// that GetHostAliases never invokes the "kubelet" or "kubernetes" detectors +// on a Cluster Checks Runner, since CCRs are Deployment replicas (not +// DaemonSets) and can never reach a local kubelet. +func TestCloudProviderAliasesSkipsKubeletDependentDetectorsOnCLCRunner(t *testing.T) { + origDetectors := hostAliasesDetectors + defer func() { hostAliasesDetectors = origDetectors }() + + config := configmock.New(t) + config.SetInTest("clc_runner_enabled", true) + config.SetInTest("config_providers", []map[string]interface{}{{"name": "clusterchecks"}}) + + kubeletCalled := false + kubernetesDetectorCalled := false + otherDetectorCalled := false + + hostAliasesDetectors = []cloudProviderAliasesDetector{ + { + name: "kubelet", + callback: func(_ context.Context) ([]string, error) { + kubeletCalled = true + return []string{"kubelet-alias"}, nil + }, + }, + { + name: "kubernetes", + callback: func(_ context.Context) ([]string, error) { + kubernetesDetectorCalled = true + return []string{"kubernetes-alias"}, nil + }, + }, + { + name: "other", + isCloudEnv: true, + callback: func(_ context.Context) ([]string, error) { + otherDetectorCalled = true + return []string{"other-alias"}, nil + }, + }, + } + + aliases, cloudprovider := GetHostAliases(context.TODO()) + assert.False(t, kubeletCalled, "kubelet host alias detector should be skipped on a Cluster Checks Runner") + assert.False(t, kubernetesDetectorCalled, "kubernetes host alias detector should be skipped on a Cluster Checks Runner") + assert.True(t, otherDetectorCalled, "non-kubelet-dependent host alias detectors should still run on a Cluster Checks Runner") + assert.Equal(t, []string{"other-alias"}, aliases) + assert.Equal(t, "other", cloudprovider) +} + func TestCloudProviderHostCCRID(t *testing.T) { origDetectors := hostCCRIDDetectors defer func() { hostCCRIDDetectors = origDetectors }() diff --git a/pkg/util/containers/metrics/kubelet/BUILD.bazel b/pkg/util/containers/metrics/kubelet/BUILD.bazel index 179fc0ae9486..654ab3a56218 100644 --- a/pkg/util/containers/metrics/kubelet/BUILD.bazel +++ b/pkg/util/containers/metrics/kubelet/BUILD.bazel @@ -12,6 +12,8 @@ go_library( deps = [ "//comp/core/workloadmeta/def", "//pkg/config/env", + "//pkg/config/helper", + "//pkg/config/setup", "//pkg/errors", "//pkg/util/containers/metrics/provider", "//pkg/util/kubernetes/kubelet", diff --git a/pkg/util/containers/metrics/kubelet/collector.go b/pkg/util/containers/metrics/kubelet/collector.go index bf069a5436b2..db0f4a0400ee 100644 --- a/pkg/util/containers/metrics/kubelet/collector.go +++ b/pkg/util/containers/metrics/kubelet/collector.go @@ -16,6 +16,8 @@ import ( workloadmeta "github.com/DataDog/datadog-agent/comp/core/workloadmeta/def" "github.com/DataDog/datadog-agent/pkg/config/env" + "github.com/DataDog/datadog-agent/pkg/config/helper" + pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" pkgerrors "github.com/DataDog/datadog-agent/pkg/errors" "github.com/DataDog/datadog-agent/pkg/util/containers/metrics/provider" kutil "github.com/DataDog/datadog-agent/pkg/util/kubernetes/kubelet" @@ -65,6 +67,13 @@ func newKubeletCollector(_ *provider.Cache, wmeta workloadmeta.Component) (provi return collectorMetadata, provider.ErrPermaFail } + // Cluster Checks Runners have no reachable local Kubelet: never let this + // collector be retried, otherwise the background collector discovery + // ticker will hammer the kubelet client forever and spam WARN logs. + if helper.IsCLCRunner(pkgconfigsetup.Datadog()) { + return collectorMetadata, provider.ErrPermaFail + } + client, err := kutil.GetKubeUtil() if err != nil { return collectorMetadata, provider.ConvertRetrierErr(err) diff --git a/pkg/util/kubernetes/cloudprovider/BUILD.bazel b/pkg/util/kubernetes/cloudprovider/BUILD.bazel index 07a4550f6f22..6dbe4001d2bb 100644 --- a/pkg/util/kubernetes/cloudprovider/BUILD.bazel +++ b/pkg/util/kubernetes/cloudprovider/BUILD.bazel @@ -13,6 +13,8 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/config/env", + "//pkg/config/helper", + "//pkg/config/setup", "//pkg/config/setup/constants", "//pkg/util/cache", "//pkg/util/clusteragent", @@ -37,6 +39,7 @@ dd_agent_go_test( ]], deps = [ "//pkg/config/env", + "//pkg/config/mock", "@com_github_stretchr_testify//assert", ], ) diff --git a/pkg/util/kubernetes/cloudprovider/cloudprovider.go b/pkg/util/kubernetes/cloudprovider/cloudprovider.go index 585ddad66cad..18dadf7cffe5 100644 --- a/pkg/util/kubernetes/cloudprovider/cloudprovider.go +++ b/pkg/util/kubernetes/cloudprovider/cloudprovider.go @@ -10,6 +10,8 @@ import ( "regexp" "github.com/DataDog/datadog-agent/pkg/config/env" + "github.com/DataDog/datadog-agent/pkg/config/helper" + pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/config/setup/constants" "github.com/DataDog/datadog-agent/pkg/util/cache" "github.com/DataDog/datadog-agent/pkg/util/clusteragent" @@ -29,6 +31,10 @@ func GetName(ctx context.Context) (string, error) { return "", nil } + if helper.IsCLCRunner(pkgconfigsetup.Datadog()) { + return "", nil + } + cacheKey := cache.BuildAgentKey(constants.NodeKubeDistributionKey) if cloudProvider, found := cache.Cache.Get(cacheKey); found { return cloudProvider.(string), nil diff --git a/pkg/util/kubernetes/cloudprovider/cloudprovider_test.go b/pkg/util/kubernetes/cloudprovider/cloudprovider_test.go index a183dddd92ed..6185b092f6a8 100644 --- a/pkg/util/kubernetes/cloudprovider/cloudprovider_test.go +++ b/pkg/util/kubernetes/cloudprovider/cloudprovider_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/DataDog/datadog-agent/pkg/config/env" + "github.com/DataDog/datadog-agent/pkg/config/mock" ) func TestKubeDistributionName(t *testing.T) { @@ -53,3 +54,18 @@ func TestGetNameNotKubernetes(t *testing.T) { assert.NoError(t, err) assert.Empty(t, name) } + +// TestGetNameCLCRunner ensures GetName returns early without probing the +// kubelet when running on a Cluster Checks Runner and they never have a +// locally-reachable kubelet. +func TestGetNameCLCRunner(t *testing.T) { + env.SetFeatures(t, env.Kubernetes) + + cfg := mock.New(t) + cfg.SetInTest("clc_runner_enabled", true) + cfg.SetInTest("config_providers", []map[string]interface{}{{"name": "clusterchecks"}}) + + name, err := GetName(context.Background()) + assert.NoError(t, err) + assert.Empty(t, name) +} diff --git a/pkg/util/kubernetes/clustername/BUILD.bazel b/pkg/util/kubernetes/clustername/BUILD.bazel index 741196cabe20..4118785a6009 100644 --- a/pkg/util/kubernetes/clustername/BUILD.bazel +++ b/pkg/util/kubernetes/clustername/BUILD.bazel @@ -8,6 +8,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/config/env", + "//pkg/config/helper", "//pkg/config/setup", "//pkg/config/setup/constants", "//pkg/util/cache", diff --git a/pkg/util/kubernetes/clustername/clustername.go b/pkg/util/kubernetes/clustername/clustername.go index 02d528e2330a..aa6e80cdc24f 100644 --- a/pkg/util/kubernetes/clustername/clustername.go +++ b/pkg/util/kubernetes/clustername/clustername.go @@ -15,6 +15,7 @@ import ( "sync" "github.com/DataDog/datadog-agent/pkg/config/env" + "github.com/DataDog/datadog-agent/pkg/config/helper" pkgconfigsetup "github.com/DataDog/datadog-agent/pkg/config/setup" "github.com/DataDog/datadog-agent/pkg/config/setup/constants" "github.com/DataDog/datadog-agent/pkg/util/cache" @@ -117,14 +118,19 @@ func getClusterName(ctx context.Context, data *clusterNameData, hostname string) } } + // Cluster check runners aren't scheduled on a specific node and don't have a + // reachable local kubelet, so skip the node-label based auto discovery to avoid + // noisy "Impossible to reach Kubelet" warnings. var clusterName string - nodeInfo, err := hostinfo.NewNodeInfo() - if err != nil { - log.Debugf("Unable to auto discover the cluster name from node label : %s", err) - } else { - clusterName, err = nodeInfo.GetNodeClusterNameLabel(ctx, data.clusterName) + if !helper.IsCLCRunner(pkgconfigsetup.Datadog()) { + nodeInfo, err := hostinfo.NewNodeInfo() if err != nil { log.Debugf("Unable to auto discover the cluster name from node label : %s", err) + } else { + clusterName, err = nodeInfo.GetNodeClusterNameLabel(ctx, data.clusterName) + if err != nil { + log.Debugf("Unable to auto discover the cluster name from node label : %s", err) + } } } if len(clusterName) > 0 { diff --git a/pkg/util/kubernetes/clustername/clustername_test.go b/pkg/util/kubernetes/clustername/clustername_test.go index fc4c05540c05..26d7aeaad541 100644 --- a/pkg/util/kubernetes/clustername/clustername_test.go +++ b/pkg/util/kubernetes/clustername/clustername_test.go @@ -82,6 +82,23 @@ func TestGetClusterName(t *testing.T) { assert.Equal(t, wantedClustername, getClusterName(ctx, newClusterNameData(), "hostname")) } +// TestGetClusterNameCLCRunner ensures that a Cluster Checks Runner (which +// never has a locally-reachable kubelet) still honors a cluster name provided +// via config, without needing the node-label based auto discovery. +func TestGetClusterNameCLCRunner(t *testing.T) { + ctx := context.Background() + mockConfig := configmock.New(t) + env.SetFeatures(t, env.Kubernetes) + + mockConfig.SetInTest("clc_runner_enabled", true) + mockConfig.SetInTest("config_providers", []map[string]interface{}{{"name": "clusterchecks"}}) + + testClusterName := "laika" + mockConfig.SetInTest("cluster_name", testClusterName) + + assert.Equal(t, testClusterName, getClusterName(ctx, newClusterNameData(), "hostname")) +} + func TestGetClusterID(t *testing.T) { // missing env cid, err := GetClusterID() diff --git a/releasenotes/notes/suppress-kubelet-warn-ccr-4ada973824224c29.yaml b/releasenotes/notes/suppress-kubelet-warn-ccr-4ada973824224c29.yaml new file mode 100644 index 000000000000..ae4f0d7eb6ed --- /dev/null +++ b/releasenotes/notes/suppress-kubelet-warn-ccr-4ada973824224c29.yaml @@ -0,0 +1,10 @@ +--- +fixes: + - | + Stop the Agent from attempting to reach a Kubelet when running as a + Cluster Checks Runner. Cluster Checks Runners are Deployment replicas, + not DaemonSets, so they never have a locally-reachable Kubelet, since a CCR + doesn't correspond to any one node. This removes the recurring + ``Impossible to reach Kubelet through HTTPS`` warning + logged by Cluster Checks Runner pods. There is no change in behavior on + the node Agent or Cluster Agent.