Skip to content

Commit c0d7702

Browse files
author
Israel Blancas
committed
Inject K8S_NODE_NAME environment variable when using the kubeletstats receiver
Signed-off-by: Israel Blancas <[email protected]>
1 parent b64ed2c commit c0d7702

File tree

9 files changed

+105
-1
lines changed

9 files changed

+105
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
5+
component: collector
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Inject environment K8S_NODE_NAME environment variable for the Kubelet Stats Receiver.
9+
10+
# One or more tracking issues related to the change
11+
issues: [2779]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext:

apis/v1beta1/config.go

+40
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,42 @@ func (c *Config) getPortsForComponentKinds(logger logr.Logger, componentKinds ..
226226
return ports, nil
227227
}
228228

229+
// getEnvironmentVariablesForComponentKinds gets the environment variables for the given ComponentKind(s).
230+
func (c *Config) getEnvironmentVariablesForComponentKinds(logger logr.Logger, componentKinds ...ComponentKind) ([]corev1.EnvVar, error) {
231+
var envVars []corev1.EnvVar
232+
enabledComponents := c.GetEnabledComponents()
233+
for _, componentKind := range componentKinds {
234+
var retriever components.ParserRetriever
235+
var cfg AnyConfig
236+
237+
switch componentKind {
238+
case KindReceiver:
239+
retriever = receivers.ReceiverFor
240+
cfg = c.Receivers
241+
case KindExporter:
242+
continue
243+
case KindProcessor:
244+
continue
245+
case KindExtension:
246+
continue
247+
}
248+
for componentName := range enabledComponents[componentKind] {
249+
parser := retriever(componentName)
250+
if parsedEnvVars, err := parser.GetEnvironmentVariables(logger, cfg.Object[componentName]); err != nil {
251+
return nil, err
252+
} else {
253+
envVars = append(envVars, parsedEnvVars...)
254+
}
255+
}
256+
}
257+
258+
sort.Slice(envVars, func(i, j int) bool {
259+
return envVars[i].Name < envVars[j].Name
260+
})
261+
262+
return envVars, nil
263+
}
264+
229265
// applyDefaultForComponentKinds applies defaults to the endpoints for the given ComponentKind(s).
230266
func (c *Config) applyDefaultForComponentKinds(logger logr.Logger, componentKinds ...ComponentKind) error {
231267
if err := c.Service.ApplyDefaults(); err != nil {
@@ -286,6 +322,10 @@ func (c *Config) GetAllPorts(logger logr.Logger) ([]corev1.ServicePort, error) {
286322
return c.getPortsForComponentKinds(logger, KindReceiver, KindExporter)
287323
}
288324

325+
func (c *Config) GetEnvironmentVariables(logger logr.Logger) ([]corev1.EnvVar, error) {
326+
return c.getEnvironmentVariablesForComponentKinds(logger, KindReceiver)
327+
}
328+
289329
func (c *Config) GetAllRbacRules(logger logr.Logger) ([]rbacv1.PolicyRule, error) {
290330
return c.getRbacRulesForComponentKinds(logger, KindReceiver, KindExporter, KindProcessor)
291331
}

internal/components/builder.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type Settings[ComponentConfigType any] struct {
3838
livenessGen ProbeGenerator[ComponentConfigType]
3939
readinessGen ProbeGenerator[ComponentConfigType]
4040
defaultsApplier Defaulter[ComponentConfigType]
41+
envVarGen EnvVarGenerator[ComponentConfigType]
4142
}
4243

4344
func NewEmptySettings[ComponentConfigType any]() *Settings[ComponentConfigType] {
@@ -124,7 +125,11 @@ func (b Builder[ComponentConfigType]) WithReadinessGen(readinessGen ProbeGenerat
124125
o.readinessGen = readinessGen
125126
})
126127
}
127-
128+
func (b Builder[ComponentConfigType]) WithEnvVarGen(envVarGen EnvVarGenerator[ComponentConfigType]) Builder[ComponentConfigType] {
129+
return append(b, func(o *Settings[ComponentConfigType]) {
130+
o.envVarGen = envVarGen
131+
})
132+
}
128133
func (b Builder[ComponentConfigType]) WithDefaultsApplier(defaultsApplier Defaulter[ComponentConfigType]) Builder[ComponentConfigType] {
129134
return append(b, func(o *Settings[ComponentConfigType]) {
130135
o.defaultsApplier = defaultsApplier

internal/components/component.go

+7
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ type RBACRuleGenerator[ComponentConfigType any] func(logger logr.Logger, config
4949
// It's expected that type Config is the configuration used by a parser.
5050
type ProbeGenerator[ComponentConfigType any] func(logger logr.Logger, config ComponentConfigType) (*corev1.Probe, error)
5151

52+
// EnvVarGenerator is a function that generates a list of environment variables for a given config.
53+
// It's expected that type Config is the configuration used by a parser.
54+
type EnvVarGenerator[ComponentConfigType any] func(logger logr.Logger, config ComponentConfigType) ([]corev1.EnvVar, error)
55+
5256
// Defaulter is a function that applies given defaults to the passed Config.
5357
// It's expected that type Config is the configuration used by a parser.
5458
type Defaulter[ComponentConfigType any] func(logger logr.Logger, defaultAddr string, defaultPort int32, config ComponentConfigType) (map[string]interface{}, error)
@@ -105,6 +109,9 @@ type Parser interface {
105109
// GetLivenessProbe returns a liveness probe set for the collector
106110
GetLivenessProbe(logger logr.Logger, config interface{}) (*corev1.Probe, error)
107111

112+
// GetEnvironmentVariables returns a list of environment variables for the collector
113+
GetEnvironmentVariables(logger logr.Logger, config interface{}) ([]corev1.EnvVar, error)
114+
108115
// GetReadinessProbe returns a readiness probe set for the collector
109116
GetReadinessProbe(logger logr.Logger, config interface{}) (*corev1.Probe, error)
110117

internal/components/generic_parser.go

+12
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type GenericParser[T any] struct {
3434
settings *Settings[T]
3535
portParser PortParser[T]
3636
rbacGen RBACRuleGenerator[T]
37+
envVarGen EnvVarGenerator[T]
3738
livenessGen ProbeGenerator[T]
3839
readinessGen ProbeGenerator[T]
3940
defaultsApplier Defaulter[T]
@@ -88,6 +89,17 @@ func (g *GenericParser[T]) GetRBACRules(logger logr.Logger, config interface{})
8889
return g.rbacGen(logger, parsed)
8990
}
9091

92+
func (g *GenericParser[T]) GetEnvironmentVariables(logger logr.Logger, config interface{}) ([]corev1.EnvVar, error) {
93+
if g.envVarGen == nil {
94+
return nil, nil
95+
}
96+
var parsed T
97+
if err := mapstructure.Decode(config, &parsed); err != nil {
98+
return nil, err
99+
}
100+
return g.envVarGen(logger, parsed)
101+
}
102+
91103
func (g *GenericParser[T]) Ports(logger logr.Logger, name string, config interface{}) ([]corev1.ServicePort, error) {
92104
if g.portParser == nil {
93105
return nil, nil

internal/components/multi_endpoint.go

+4
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ func (m *MultiPortReceiver) GetRBACRules(logr.Logger, interface{}) ([]rbacv1.Pol
116116
return nil, nil
117117
}
118118

119+
func (m *MultiPortReceiver) GetEnvironmentVariables(logger logr.Logger, config interface{}) ([]corev1.EnvVar, error) {
120+
return nil, nil
121+
}
122+
119123
type MultiPortBuilder[ComponentConfigType any] []Builder[ComponentConfigType]
120124

121125
func NewMultiPortReceiverBuilder(name string) MultiPortBuilder[*MultiProtocolEndpointConfig] {

internal/components/receivers/helpers.go

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ var (
138138
MustBuild(),
139139
components.NewBuilder[kubeletStatsConfig]().WithName("kubeletstats").
140140
WithRbacGen(generateKubeletStatsRbacRules).
141+
WithEnvVarGen(generateKubeletStatsEnvVars).
141142
MustBuild(),
142143
NewScraperParser("prometheus"),
143144
NewScraperParser("sshcheck"),

internal/components/receivers/kubeletstats.go

+13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package receivers
1616

1717
import (
1818
"github.com/go-logr/logr"
19+
corev1 "k8s.io/api/core/v1"
1920
rbacv1 "k8s.io/api/rbac/v1"
2021
)
2122

@@ -42,6 +43,18 @@ type kubeletStatsConfig struct {
4243
AuthType string `mapstructure:"auth_type"`
4344
}
4445

46+
func generateKubeletStatsEnvVars(_ logr.Logger, config kubeletStatsConfig) ([]corev1.EnvVar, error) {
47+
// The documentation mentions that the K8S_NODE_NAME environment variable is required when using the serviceAccount auth type.
48+
// Also, it mentions that it is a good idea to use it for the Read Only Endpoint. Added always to make it easier for users.
49+
// https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/receiver/kubeletstatsreceiver/README.md
50+
if config.AuthType == "serviceAccount" {
51+
return []corev1.EnvVar{
52+
{Name: "K8S_NODE_NAME", ValueFrom: &corev1.EnvVarSource{FieldRef: &corev1.ObjectFieldSelector{FieldPath: "spec.nodeName"}}},
53+
}, nil
54+
}
55+
return nil, nil
56+
}
57+
4558
func generateKubeletStatsRbacRules(_ logr.Logger, config kubeletStatsConfig) ([]rbacv1.PolicyRule, error) {
4659
// The Kubelet Stats Receiver needs get permissions on the nodes/stats resources always.
4760
prs := []rbacv1.PolicyRule{

internal/manifests/collector/container.go

+6
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ func Container(cfg config.Config, logger logr.Logger, otelcol v1beta1.OpenTeleme
177177
)
178178
}
179179

180+
if envVars, err := otelcol.Spec.Config.GetEnvironmentVariables(logger); err != nil {
181+
logger.Error(err, "could not get the environment variables from the config")
182+
} else {
183+
envVars = append(envVars, envVars...)
184+
}
185+
180186
envVars = append(envVars, proxy.ReadProxyVarsFromEnv()...)
181187
return corev1.Container{
182188
Name: naming.Container(),

0 commit comments

Comments
 (0)