Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/operator/resources_pod_template.go
4095 views
1
package operator
2
3
import (
4
"fmt"
5
"path"
6
7
"github.com/grafana/agent/pkg/build"
8
gragent "github.com/grafana/agent/pkg/operator/apis/monitoring/v1alpha1"
9
"github.com/grafana/agent/pkg/operator/clientutil"
10
core_v1 "k8s.io/api/core/v1"
11
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
"k8s.io/apimachinery/pkg/util/intstr"
13
"k8s.io/utils/pointer"
14
)
15
16
type podTemplateOptions struct {
17
ExtraSelectorLabels map[string]string
18
ExtraVolumes []core_v1.Volume
19
ExtraVolumeMounts []core_v1.VolumeMount
20
ExtraEnvVars []core_v1.EnvVar
21
Privileged bool
22
}
23
24
func generatePodTemplate(
25
cfg *Config,
26
name string,
27
d gragent.Deployment,
28
opts podTemplateOptions,
29
) (core_v1.PodTemplateSpec, *meta_v1.LabelSelector, error) {
30
31
// generatePodTemplate assumes that the deployment has default values applied
32
// to it.
33
applyDeploymentDefaults(&d)
34
35
useVersion := d.Agent.Spec.Version
36
if useVersion == "" {
37
useVersion = DefaultAgentVersion
38
}
39
imagePath := fmt.Sprintf("%s:%s", DefaultAgentBaseImage, useVersion)
40
if d.Agent.Spec.Image != nil && *d.Agent.Spec.Image != "" {
41
imagePath = *d.Agent.Spec.Image
42
}
43
44
agentArgs := []string{
45
"-config.file=/var/lib/grafana-agent/config/agent.yml",
46
"-config.expand-env=true",
47
"-server.http.address=0.0.0.0:8080",
48
"-enable-features=integrations-next",
49
}
50
51
enableConfigReadAPI := d.Agent.Spec.EnableConfigReadAPI
52
if enableConfigReadAPI {
53
agentArgs = append(agentArgs, "-config.enable-read-api")
54
}
55
56
disableReporting := d.Agent.Spec.DisableReporting
57
if disableReporting {
58
agentArgs = append(agentArgs, "-disable-reporting")
59
}
60
61
if d.Agent.Spec.DisableSupportBundle {
62
agentArgs = append(agentArgs, "-disable-support-bundle")
63
}
64
65
// NOTE(rfratto): the Prometheus Operator supports a ListenLocal to prevent a
66
// service from being created. Given the intent is that Agents can connect to
67
// each other, ListenLocal isn't currently supported and we always create a
68
// port.
69
ports := []core_v1.ContainerPort{{
70
Name: d.Agent.Spec.PortName,
71
ContainerPort: 8080,
72
Protocol: core_v1.ProtocolTCP,
73
}}
74
75
volumes := []core_v1.Volume{
76
{
77
Name: "config",
78
VolumeSource: core_v1.VolumeSource{
79
Secret: &core_v1.SecretVolumeSource{
80
SecretName: fmt.Sprintf("%s-config", name),
81
},
82
},
83
},
84
{
85
// We need a separate volume for storing the rendered config with
86
// environment variables replaced. While the Agent supports environment
87
// variable substitution, the value for __replica__ can only be
88
// determined at runtime. We use a dedicated container for both config
89
// reloading and rendering.
90
Name: "config-out",
91
VolumeSource: core_v1.VolumeSource{
92
EmptyDir: &core_v1.EmptyDirVolumeSource{},
93
},
94
},
95
{
96
Name: "secrets",
97
VolumeSource: core_v1.VolumeSource{
98
Secret: &core_v1.SecretVolumeSource{
99
SecretName: fmt.Sprintf("%s-secrets", d.Agent.Name),
100
},
101
},
102
},
103
}
104
volumes = append(volumes, opts.ExtraVolumes...)
105
volumes = append(volumes, d.Agent.Spec.Volumes...)
106
107
volumeMounts := []core_v1.VolumeMount{
108
{
109
Name: "config",
110
ReadOnly: true,
111
MountPath: "/var/lib/grafana-agent/config-in",
112
},
113
{
114
Name: "config-out",
115
MountPath: "/var/lib/grafana-agent/config",
116
},
117
{
118
Name: "secrets",
119
ReadOnly: true,
120
MountPath: "/var/lib/grafana-agent/secrets",
121
},
122
}
123
volumeMounts = append(volumeMounts, opts.ExtraVolumeMounts...)
124
volumeMounts = append(volumeMounts, d.Agent.Spec.VolumeMounts...)
125
126
for _, s := range d.Agent.Spec.Secrets {
127
volumes = append(volumes, core_v1.Volume{
128
Name: clientutil.SanitizeVolumeName("secret-" + s),
129
VolumeSource: core_v1.VolumeSource{
130
Secret: &core_v1.SecretVolumeSource{SecretName: s},
131
},
132
})
133
volumeMounts = append(volumeMounts, core_v1.VolumeMount{
134
Name: clientutil.SanitizeVolumeName("secret-" + s),
135
ReadOnly: true,
136
MountPath: path.Join("/var/lib/grafana-agent/extra-secrets", s),
137
})
138
}
139
140
for _, c := range d.Agent.Spec.ConfigMaps {
141
volumes = append(volumes, core_v1.Volume{
142
Name: clientutil.SanitizeVolumeName("configmap-" + c),
143
VolumeSource: core_v1.VolumeSource{
144
ConfigMap: &core_v1.ConfigMapVolumeSource{
145
LocalObjectReference: core_v1.LocalObjectReference{Name: c},
146
},
147
},
148
})
149
volumeMounts = append(volumeMounts, core_v1.VolumeMount{
150
Name: clientutil.SanitizeVolumeName("configmap-" + c),
151
ReadOnly: true,
152
MountPath: path.Join("/var/lib/grafana-agent/extra-configmaps", c),
153
})
154
}
155
156
var (
157
podAnnotations = map[string]string{}
158
podLabels = map[string]string{}
159
podSelectorLabels = map[string]string{
160
"app.kubernetes.io/name": "grafana-agent",
161
"app.kubernetes.io/version": clientutil.SanitizeVolumeName(build.Version),
162
"app.kubernetes.io/instance": d.Agent.Name,
163
"grafana-agent": d.Agent.Name,
164
managedByOperatorLabel: managedByOperatorLabelValue,
165
agentNameLabelName: d.Agent.Name,
166
}
167
)
168
for k, v := range opts.ExtraSelectorLabels {
169
podSelectorLabels[k] = v
170
}
171
172
if d.Agent.Spec.PodMetadata != nil {
173
for k, v := range d.Agent.Spec.PodMetadata.Labels {
174
podLabels[k] = v
175
}
176
for k, v := range d.Agent.Spec.PodMetadata.Annotations {
177
podAnnotations[k] = v
178
}
179
}
180
for k, v := range podSelectorLabels {
181
podLabels[k] = v
182
}
183
184
podAnnotations["kubectl.kubernetes.io/default-container"] = "grafana-agent"
185
186
var (
187
finalSelectorLabels = cfg.Labels.Merge(podSelectorLabels)
188
finalLabels = cfg.Labels.Merge(podLabels)
189
)
190
191
envVars := []core_v1.EnvVar{{
192
Name: "POD_NAME",
193
ValueFrom: &core_v1.EnvVarSource{
194
FieldRef: &core_v1.ObjectFieldSelector{FieldPath: "metadata.name"},
195
},
196
}}
197
envVars = append(envVars, opts.ExtraEnvVars...)
198
199
operatorContainers := []core_v1.Container{
200
{
201
Name: "config-reloader",
202
Image: "quay.io/prometheus-operator/prometheus-config-reloader:v0.62.0",
203
VolumeMounts: volumeMounts,
204
Env: envVars,
205
SecurityContext: &core_v1.SecurityContext{
206
RunAsUser: pointer.Int64(0),
207
},
208
Args: []string{
209
"--config-file=/var/lib/grafana-agent/config-in/agent.yml",
210
"--config-envsubst-file=/var/lib/grafana-agent/config/agent.yml",
211
212
"--watch-interval=1m",
213
"--statefulset-ordinal-from-envvar=POD_NAME",
214
"--reload-url=http://127.0.0.1:8080/-/reload",
215
},
216
},
217
{
218
Name: "grafana-agent",
219
Image: imagePath,
220
Ports: ports,
221
Args: agentArgs,
222
VolumeMounts: volumeMounts,
223
Env: envVars,
224
ReadinessProbe: &core_v1.Probe{
225
ProbeHandler: core_v1.ProbeHandler{
226
HTTPGet: &core_v1.HTTPGetAction{
227
Path: "/-/ready",
228
Port: intstr.FromString(d.Agent.Spec.PortName),
229
},
230
},
231
TimeoutSeconds: probeTimeoutSeconds,
232
PeriodSeconds: 5,
233
FailureThreshold: 120, // Allow up to 10m on startup for data recovery
234
},
235
Resources: d.Agent.Spec.Resources,
236
SecurityContext: &core_v1.SecurityContext{
237
Privileged: pointer.Bool(opts.Privileged),
238
},
239
TerminationMessagePolicy: core_v1.TerminationMessageFallbackToLogsOnError,
240
},
241
}
242
243
containers, err := clientutil.MergePatchContainers(operatorContainers, d.Agent.Spec.Containers)
244
if err != nil {
245
return core_v1.PodTemplateSpec{}, nil, fmt.Errorf("failed to merge containers spec: %w", err)
246
}
247
248
var pullSecrets []core_v1.LocalObjectReference
249
if len(d.Agent.Spec.ImagePullSecrets) > 0 {
250
pullSecrets = d.Agent.Spec.ImagePullSecrets
251
}
252
253
template := core_v1.PodTemplateSpec{
254
ObjectMeta: meta_v1.ObjectMeta{
255
Labels: finalLabels,
256
Annotations: podAnnotations,
257
},
258
Spec: core_v1.PodSpec{
259
Containers: containers,
260
ImagePullSecrets: pullSecrets,
261
InitContainers: d.Agent.Spec.InitContainers,
262
SecurityContext: d.Agent.Spec.SecurityContext,
263
ServiceAccountName: d.Agent.Spec.ServiceAccountName,
264
NodeSelector: d.Agent.Spec.NodeSelector,
265
PriorityClassName: d.Agent.Spec.PriorityClassName,
266
RuntimeClassName: d.Agent.Spec.RuntimeClassName,
267
TerminationGracePeriodSeconds: pointer.Int64(4800),
268
Volumes: volumes,
269
Tolerations: d.Agent.Spec.Tolerations,
270
Affinity: d.Agent.Spec.Affinity,
271
TopologySpreadConstraints: d.Agent.Spec.TopologySpreadConstraints,
272
},
273
}
274
return template, &meta_v1.LabelSelector{MatchLabels: finalSelectorLabels}, nil
275
}
276
277
func applyDeploymentDefaults(d *gragent.Deployment) {
278
if d.Agent.Spec.Metrics.Replicas != nil && *d.Agent.Spec.Metrics.Replicas < 0 {
279
intZero := int32(0)
280
d.Agent.Spec.Metrics.Replicas = &intZero
281
}
282
283
if d.Agent.Spec.Resources.Requests == nil {
284
d.Agent.Spec.Resources.Requests = core_v1.ResourceList{}
285
}
286
287
if d.Agent.Spec.Metrics.Replicas == nil {
288
d.Agent.Spec.Metrics.Replicas = &minReplicas
289
}
290
291
if d.Agent.Spec.PortName == "" {
292
d.Agent.Spec.PortName = defaultPortName
293
}
294
}
295
296