Path: blob/main/pkg/operator/resources_pod_template.go
4095 views
package operator12import (3"fmt"4"path"56"github.com/grafana/agent/pkg/build"7gragent "github.com/grafana/agent/pkg/operator/apis/monitoring/v1alpha1"8"github.com/grafana/agent/pkg/operator/clientutil"9core_v1 "k8s.io/api/core/v1"10meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"11"k8s.io/apimachinery/pkg/util/intstr"12"k8s.io/utils/pointer"13)1415type podTemplateOptions struct {16ExtraSelectorLabels map[string]string17ExtraVolumes []core_v1.Volume18ExtraVolumeMounts []core_v1.VolumeMount19ExtraEnvVars []core_v1.EnvVar20Privileged bool21}2223func generatePodTemplate(24cfg *Config,25name string,26d gragent.Deployment,27opts podTemplateOptions,28) (core_v1.PodTemplateSpec, *meta_v1.LabelSelector, error) {2930// generatePodTemplate assumes that the deployment has default values applied31// to it.32applyDeploymentDefaults(&d)3334useVersion := d.Agent.Spec.Version35if useVersion == "" {36useVersion = DefaultAgentVersion37}38imagePath := fmt.Sprintf("%s:%s", DefaultAgentBaseImage, useVersion)39if d.Agent.Spec.Image != nil && *d.Agent.Spec.Image != "" {40imagePath = *d.Agent.Spec.Image41}4243agentArgs := []string{44"-config.file=/var/lib/grafana-agent/config/agent.yml",45"-config.expand-env=true",46"-server.http.address=0.0.0.0:8080",47"-enable-features=integrations-next",48}4950enableConfigReadAPI := d.Agent.Spec.EnableConfigReadAPI51if enableConfigReadAPI {52agentArgs = append(agentArgs, "-config.enable-read-api")53}5455disableReporting := d.Agent.Spec.DisableReporting56if disableReporting {57agentArgs = append(agentArgs, "-disable-reporting")58}5960if d.Agent.Spec.DisableSupportBundle {61agentArgs = append(agentArgs, "-disable-support-bundle")62}6364// NOTE(rfratto): the Prometheus Operator supports a ListenLocal to prevent a65// service from being created. Given the intent is that Agents can connect to66// each other, ListenLocal isn't currently supported and we always create a67// port.68ports := []core_v1.ContainerPort{{69Name: d.Agent.Spec.PortName,70ContainerPort: 8080,71Protocol: core_v1.ProtocolTCP,72}}7374volumes := []core_v1.Volume{75{76Name: "config",77VolumeSource: core_v1.VolumeSource{78Secret: &core_v1.SecretVolumeSource{79SecretName: fmt.Sprintf("%s-config", name),80},81},82},83{84// We need a separate volume for storing the rendered config with85// environment variables replaced. While the Agent supports environment86// variable substitution, the value for __replica__ can only be87// determined at runtime. We use a dedicated container for both config88// reloading and rendering.89Name: "config-out",90VolumeSource: core_v1.VolumeSource{91EmptyDir: &core_v1.EmptyDirVolumeSource{},92},93},94{95Name: "secrets",96VolumeSource: core_v1.VolumeSource{97Secret: &core_v1.SecretVolumeSource{98SecretName: fmt.Sprintf("%s-secrets", d.Agent.Name),99},100},101},102}103volumes = append(volumes, opts.ExtraVolumes...)104volumes = append(volumes, d.Agent.Spec.Volumes...)105106volumeMounts := []core_v1.VolumeMount{107{108Name: "config",109ReadOnly: true,110MountPath: "/var/lib/grafana-agent/config-in",111},112{113Name: "config-out",114MountPath: "/var/lib/grafana-agent/config",115},116{117Name: "secrets",118ReadOnly: true,119MountPath: "/var/lib/grafana-agent/secrets",120},121}122volumeMounts = append(volumeMounts, opts.ExtraVolumeMounts...)123volumeMounts = append(volumeMounts, d.Agent.Spec.VolumeMounts...)124125for _, s := range d.Agent.Spec.Secrets {126volumes = append(volumes, core_v1.Volume{127Name: clientutil.SanitizeVolumeName("secret-" + s),128VolumeSource: core_v1.VolumeSource{129Secret: &core_v1.SecretVolumeSource{SecretName: s},130},131})132volumeMounts = append(volumeMounts, core_v1.VolumeMount{133Name: clientutil.SanitizeVolumeName("secret-" + s),134ReadOnly: true,135MountPath: path.Join("/var/lib/grafana-agent/extra-secrets", s),136})137}138139for _, c := range d.Agent.Spec.ConfigMaps {140volumes = append(volumes, core_v1.Volume{141Name: clientutil.SanitizeVolumeName("configmap-" + c),142VolumeSource: core_v1.VolumeSource{143ConfigMap: &core_v1.ConfigMapVolumeSource{144LocalObjectReference: core_v1.LocalObjectReference{Name: c},145},146},147})148volumeMounts = append(volumeMounts, core_v1.VolumeMount{149Name: clientutil.SanitizeVolumeName("configmap-" + c),150ReadOnly: true,151MountPath: path.Join("/var/lib/grafana-agent/extra-configmaps", c),152})153}154155var (156podAnnotations = map[string]string{}157podLabels = map[string]string{}158podSelectorLabels = map[string]string{159"app.kubernetes.io/name": "grafana-agent",160"app.kubernetes.io/version": clientutil.SanitizeVolumeName(build.Version),161"app.kubernetes.io/instance": d.Agent.Name,162"grafana-agent": d.Agent.Name,163managedByOperatorLabel: managedByOperatorLabelValue,164agentNameLabelName: d.Agent.Name,165}166)167for k, v := range opts.ExtraSelectorLabels {168podSelectorLabels[k] = v169}170171if d.Agent.Spec.PodMetadata != nil {172for k, v := range d.Agent.Spec.PodMetadata.Labels {173podLabels[k] = v174}175for k, v := range d.Agent.Spec.PodMetadata.Annotations {176podAnnotations[k] = v177}178}179for k, v := range podSelectorLabels {180podLabels[k] = v181}182183podAnnotations["kubectl.kubernetes.io/default-container"] = "grafana-agent"184185var (186finalSelectorLabels = cfg.Labels.Merge(podSelectorLabels)187finalLabels = cfg.Labels.Merge(podLabels)188)189190envVars := []core_v1.EnvVar{{191Name: "POD_NAME",192ValueFrom: &core_v1.EnvVarSource{193FieldRef: &core_v1.ObjectFieldSelector{FieldPath: "metadata.name"},194},195}}196envVars = append(envVars, opts.ExtraEnvVars...)197198operatorContainers := []core_v1.Container{199{200Name: "config-reloader",201Image: "quay.io/prometheus-operator/prometheus-config-reloader:v0.62.0",202VolumeMounts: volumeMounts,203Env: envVars,204SecurityContext: &core_v1.SecurityContext{205RunAsUser: pointer.Int64(0),206},207Args: []string{208"--config-file=/var/lib/grafana-agent/config-in/agent.yml",209"--config-envsubst-file=/var/lib/grafana-agent/config/agent.yml",210211"--watch-interval=1m",212"--statefulset-ordinal-from-envvar=POD_NAME",213"--reload-url=http://127.0.0.1:8080/-/reload",214},215},216{217Name: "grafana-agent",218Image: imagePath,219Ports: ports,220Args: agentArgs,221VolumeMounts: volumeMounts,222Env: envVars,223ReadinessProbe: &core_v1.Probe{224ProbeHandler: core_v1.ProbeHandler{225HTTPGet: &core_v1.HTTPGetAction{226Path: "/-/ready",227Port: intstr.FromString(d.Agent.Spec.PortName),228},229},230TimeoutSeconds: probeTimeoutSeconds,231PeriodSeconds: 5,232FailureThreshold: 120, // Allow up to 10m on startup for data recovery233},234Resources: d.Agent.Spec.Resources,235SecurityContext: &core_v1.SecurityContext{236Privileged: pointer.Bool(opts.Privileged),237},238TerminationMessagePolicy: core_v1.TerminationMessageFallbackToLogsOnError,239},240}241242containers, err := clientutil.MergePatchContainers(operatorContainers, d.Agent.Spec.Containers)243if err != nil {244return core_v1.PodTemplateSpec{}, nil, fmt.Errorf("failed to merge containers spec: %w", err)245}246247var pullSecrets []core_v1.LocalObjectReference248if len(d.Agent.Spec.ImagePullSecrets) > 0 {249pullSecrets = d.Agent.Spec.ImagePullSecrets250}251252template := core_v1.PodTemplateSpec{253ObjectMeta: meta_v1.ObjectMeta{254Labels: finalLabels,255Annotations: podAnnotations,256},257Spec: core_v1.PodSpec{258Containers: containers,259ImagePullSecrets: pullSecrets,260InitContainers: d.Agent.Spec.InitContainers,261SecurityContext: d.Agent.Spec.SecurityContext,262ServiceAccountName: d.Agent.Spec.ServiceAccountName,263NodeSelector: d.Agent.Spec.NodeSelector,264PriorityClassName: d.Agent.Spec.PriorityClassName,265RuntimeClassName: d.Agent.Spec.RuntimeClassName,266TerminationGracePeriodSeconds: pointer.Int64(4800),267Volumes: volumes,268Tolerations: d.Agent.Spec.Tolerations,269Affinity: d.Agent.Spec.Affinity,270TopologySpreadConstraints: d.Agent.Spec.TopologySpreadConstraints,271},272}273return template, &meta_v1.LabelSelector{MatchLabels: finalSelectorLabels}, nil274}275276func applyDeploymentDefaults(d *gragent.Deployment) {277if d.Agent.Spec.Metrics.Replicas != nil && *d.Agent.Spec.Metrics.Replicas < 0 {278intZero := int32(0)279d.Agent.Spec.Metrics.Replicas = &intZero280}281282if d.Agent.Spec.Resources.Requests == nil {283d.Agent.Spec.Resources.Requests = core_v1.ResourceList{}284}285286if d.Agent.Spec.Metrics.Replicas == nil {287d.Agent.Spec.Metrics.Replicas = &minReplicas288}289290if d.Agent.Spec.PortName == "" {291d.Agent.Spec.PortName = defaultPortName292}293}294295296