From df59cb0f01bb88651744a8229935d3b729639de0 Mon Sep 17 00:00:00 2001 From: heylongdacoder Date: Tue, 31 May 2022 22:03:50 +0800 Subject: [PATCH] Allow user to configure hostAliases for Alertmanager, Prometheus and Thanos Pods. Signed-off-by: heylongdacoder --- Documentation/api.md | 18 ++++ bundle.yaml | 66 ++++++++++++++ .../monitoring.coreos.com_alertmanagers.yaml | 22 +++++ .../monitoring.coreos.com_prometheuses.yaml | 22 +++++ .../monitoring.coreos.com_thanosrulers.yaml | 22 +++++ .../alertmanagers-crd.json | 29 ++++++ .../prometheus-operator/prometheuses-crd.json | 29 ++++++ .../prometheus-operator/thanosrulers-crd.json | 29 ++++++ pkg/alertmanager/statefulset.go | 1 + pkg/alertmanager/statefulset_test.go | 86 ++++++++++++++++++ pkg/apis/monitoring/v1/thanos_types.go | 4 + pkg/apis/monitoring/v1/types.go | 19 ++++ .../monitoring/v1/zz_generated.deepcopy.go | 41 +++++++++ pkg/k8sutil/k8sutil.go | 14 +++ pkg/prometheus/statefulset.go | 1 + pkg/prometheus/statefulset_test.go | 88 +++++++++++++++++++ pkg/thanos/statefulset.go | 1 + pkg/thanos/statefulset_test.go | 21 ++++- 18 files changed, 512 insertions(+), 1 deletion(-) diff --git a/Documentation/api.md b/Documentation/api.md index 082b1835ff0..ae4624d03ae 100644 --- a/Documentation/api.md +++ b/Documentation/api.md @@ -31,6 +31,7 @@ This Document documents the types introduced by the Prometheus Operator to be co * [EmbeddedObjectMetadata](#embeddedobjectmetadata) * [EmbeddedPersistentVolumeClaim](#embeddedpersistentvolumeclaim) * [Endpoint](#endpoint) +* [HostAlias](#hostalias) * [MetadataConfig](#metadataconfig) * [NamespaceSelector](#namespaceselector) * [OAuth2](#oauth2) @@ -253,6 +254,7 @@ AlertmanagerSpec is a specification of the desired behavior of the Alertmanager | alertmanagerConfigSelector | AlertmanagerConfigs to be selected for to merge and configure Alertmanager with. | *[metav1.LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#labelselector-v1-meta) | false | | alertmanagerConfigNamespaceSelector | Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own namespace. | *[metav1.LabelSelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#labelselector-v1-meta) | false | | minReadySeconds | Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) This is an alpha field and requires enabling StatefulSetMinReadySeconds feature gate. | *uint32 | false | +| hostAliases | Pods' hostAliases configuration | [][HostAlias](#hostalias) | false | | alertmanagerConfiguration | EXPERIMENTAL: alertmanagerConfiguration specifies the global Alertmanager configuration. If defined, it takes precedence over the `configSecret` field. This field may change in future releases. | *[AlertmanagerConfiguration](#alertmanagerconfiguration) | false | [Back to TOC](#table-of-contents) @@ -377,6 +379,20 @@ Endpoint defines a scrapeable endpoint serving Prometheus metrics. [Back to TOC](#table-of-contents) +## HostAlias + +HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file. + + +appears in: [AlertmanagerSpec](#alertmanagerspec), [PrometheusSpec](#prometheusspec), [ThanosRulerSpec](#thanosrulerspec) + +| Field | Description | Scheme | Required | +| ----- | ----------- | ------ | -------- | +| ip | IP address of the host file entry. | string | true | +| hostnames | Hostnames for the above IP address. | []string | true | + +[Back to TOC](#table-of-contents) + ## MetadataConfig MetadataConfig configures the sending of series metadata to the remote storage. @@ -829,6 +845,7 @@ PrometheusSpec is a specification of the desired behavior of the Prometheus clus | enforcedLabelValueLengthLimit | Per-scrape limit on length of labels value that will be accepted for a sample. If a label value is longer than this number post metric-relabeling, the entire scrape will be treated as failed. 0 means no limit. Only valid in Prometheus versions 2.27.0 and newer. | *uint64 | false | | enforcedBodySizeLimit | EnforcedBodySizeLimit defines the maximum size of uncompressed response body that will be accepted by Prometheus. Targets responding with a body larger than this many bytes will cause the scrape to fail. Example: 100MB. If defined, the limit will apply to all service/pod monitors and probes. This is an experimental feature, this behaviour could change or be removed in the future. Only valid in Prometheus versions 2.28.0 and newer. | ByteSize | false | | minReadySeconds | Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) This is an alpha field and requires enabling StatefulSetMinReadySeconds feature gate. | *uint32 | false | +| hostAliases | Pods' hostAliases configuration | [][HostAlias](#hostalias) | false | | retention | Time duration Prometheus shall retain data for. Default is '24h' if retentionSize is not set, and must match the regular expression `[0-9]+(ms\|s\|m\|h\|d\|w\|y)` (milliseconds seconds minutes hours days weeks years). | Duration | false | | retentionSize | Maximum amount of disk space used by blocks. | ByteSize | false | | disableCompaction | Disable prometheus compaction. | bool | false | @@ -1328,6 +1345,7 @@ ThanosRulerSpec is a specification of the desired behavior of the ThanosRuler. M | minReadySeconds | Minimum number of seconds for which a newly created pod should be ready without any of its container crashing for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) This is an alpha field and requires enabling StatefulSetMinReadySeconds feature gate. | *uint32 | false | | alertRelabelConfigs | AlertRelabelConfigs configures alert relabeling in ThanosRuler. Alert relabel configurations must have the form as specified in the official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs Alternative to AlertRelabelConfigFile, and lower order priority. | *[v1.SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#secretkeyselector-v1-core) | false | | alertRelabelConfigFile | AlertRelabelConfigFile specifies the path of the alert relabeling configuration file. When used alongside with AlertRelabelConfigs, alertRelabelConfigFile takes precedence. | *string | false | +| hostAliases | Pods' hostAliases configuration | [][HostAlias](#hostalias) | false | [Back to TOC](#table-of-contents) diff --git a/bundle.yaml b/bundle.yaml index 1083f8937eb..1bc4ebf9d7b 100644 --- a/bundle.yaml +++ b/bundle.yaml @@ -6240,6 +6240,28 @@ spec: Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. type: boolean + hostAliases: + description: Pods' hostAliases configuration + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map image: description: Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary @@ -14121,6 +14143,28 @@ spec: under. This is necessary to generate correct URLs. This is necessary if Prometheus is not served from root of a DNS name. type: string + hostAliases: + description: Pods' hostAliases configuration + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map ignoreNamespaceSelectors: description: IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from all PodMonitor, ServiceMonitor and Probe objects. @@ -22888,6 +22932,28 @@ spec: description: Used to verify the hostname for the targets. type: string type: object + hostAliases: + description: Pods' hostAliases configuration + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map image: description: Thanos container image URL. type: string diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml index cf0a8156b3e..804be513248 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_alertmanagers.yaml @@ -2258,6 +2258,28 @@ spec: Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each. type: boolean + hostAliases: + description: Pods' hostAliases configuration + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map image: description: Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml index 84cd14a30ab..a589bd0a1c6 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_prometheuses.yaml @@ -2785,6 +2785,28 @@ spec: under. This is necessary to generate correct URLs. This is necessary if Prometheus is not served from root of a DNS name. type: string + hostAliases: + description: Pods' hostAliases configuration + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map ignoreNamespaceSelectors: description: IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from all PodMonitor, ServiceMonitor and Probe objects. diff --git a/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml b/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml index 3ddcf84d69c..96f30ab522b 100644 --- a/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml +++ b/example/prometheus-operator-crd/monitoring.coreos.com_thanosrulers.yaml @@ -2333,6 +2333,28 @@ spec: description: Used to verify the hostname for the targets. type: string type: object + hostAliases: + description: Pods' hostAliases configuration + items: + description: HostAlias holds the mapping between IP and hostnames + that will be injected as an entry in the pod's hosts file. + properties: + hostnames: + description: Hostnames for the above IP address. + items: + type: string + type: array + ip: + description: IP address of the host file entry. + type: string + required: + - hostnames + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map image: description: Thanos container image URL. type: string diff --git a/jsonnet/prometheus-operator/alertmanagers-crd.json b/jsonnet/prometheus-operator/alertmanagers-crd.json index df18df7aad6..66f6678c44d 100644 --- a/jsonnet/prometheus-operator/alertmanagers-crd.json +++ b/jsonnet/prometheus-operator/alertmanagers-crd.json @@ -1974,6 +1974,35 @@ "description": "ForceEnableClusterMode ensures Alertmanager does not deactivate the cluster mode when running with a single replica. Use case is e.g. spanning an Alertmanager cluster across Kubernetes clusters with a single replica in each.", "type": "boolean" }, + "hostAliases": { + "description": "Pods' hostAliases configuration", + "items": { + "description": "HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file.", + "properties": { + "hostnames": { + "description": "Hostnames for the above IP address.", + "items": { + "type": "string" + }, + "type": "array" + }, + "ip": { + "description": "IP address of the host file entry.", + "type": "string" + } + }, + "required": [ + "hostnames", + "ip" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "ip" + ], + "x-kubernetes-list-type": "map" + }, "image": { "description": "Image if specified has precedence over baseImage, tag and sha combinations. Specifying the version is still necessary to ensure the Prometheus Operator knows what version of Alertmanager is being configured.", "type": "string" diff --git a/jsonnet/prometheus-operator/prometheuses-crd.json b/jsonnet/prometheus-operator/prometheuses-crd.json index b40d4ab6b03..1bfa60c83ae 100644 --- a/jsonnet/prometheus-operator/prometheuses-crd.json +++ b/jsonnet/prometheus-operator/prometheuses-crd.json @@ -2516,6 +2516,35 @@ "description": "The external URL the Prometheus instances will be available under. This is necessary to generate correct URLs. This is necessary if Prometheus is not served from root of a DNS name.", "type": "string" }, + "hostAliases": { + "description": "Pods' hostAliases configuration", + "items": { + "description": "HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file.", + "properties": { + "hostnames": { + "description": "Hostnames for the above IP address.", + "items": { + "type": "string" + }, + "type": "array" + }, + "ip": { + "description": "IP address of the host file entry.", + "type": "string" + } + }, + "required": [ + "hostnames", + "ip" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "ip" + ], + "x-kubernetes-list-type": "map" + }, "ignoreNamespaceSelectors": { "description": "IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from all PodMonitor, ServiceMonitor and Probe objects. They will only discover endpoints within their current namespace. Defaults to false.", "type": "boolean" diff --git a/jsonnet/prometheus-operator/thanosrulers-crd.json b/jsonnet/prometheus-operator/thanosrulers-crd.json index 05f2ab1480b..8ce7b3c4b84 100644 --- a/jsonnet/prometheus-operator/thanosrulers-crd.json +++ b/jsonnet/prometheus-operator/thanosrulers-crd.json @@ -2087,6 +2087,35 @@ }, "type": "object" }, + "hostAliases": { + "description": "Pods' hostAliases configuration", + "items": { + "description": "HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the pod's hosts file.", + "properties": { + "hostnames": { + "description": "Hostnames for the above IP address.", + "items": { + "type": "string" + }, + "type": "array" + }, + "ip": { + "description": "IP address of the host file entry.", + "type": "string" + } + }, + "required": [ + "hostnames", + "ip" + ], + "type": "object" + }, + "type": "array", + "x-kubernetes-list-map-keys": [ + "ip" + ], + "x-kubernetes-list-type": "map" + }, "image": { "description": "Thanos container image URL.", "type": "string" diff --git a/pkg/alertmanager/statefulset.go b/pkg/alertmanager/statefulset.go index 51061dba52f..9d22d0daed0 100644 --- a/pkg/alertmanager/statefulset.go +++ b/pkg/alertmanager/statefulset.go @@ -628,6 +628,7 @@ func makeStatefulSetSpec(a *monitoringv1.Alertmanager, config Config, tlsAssetSe Tolerations: a.Spec.Tolerations, Affinity: a.Spec.Affinity, TopologySpreadConstraints: a.Spec.TopologySpreadConstraints, + HostAliases: k8sutil.HostAliasesMonitoringV1ToCoreV1(a.Spec.HostAliases), }, }, }, nil diff --git a/pkg/alertmanager/statefulset_test.go b/pkg/alertmanager/statefulset_test.go index 4d1f3aa7e54..dedb1ba211c 100644 --- a/pkg/alertmanager/statefulset_test.go +++ b/pkg/alertmanager/statefulset_test.go @@ -22,6 +22,7 @@ import ( "github.com/kylelemons/godebug/pretty" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + "github.com/prometheus-operator/prometheus-operator/pkg/k8sutil" "github.com/prometheus-operator/prometheus-operator/pkg/operator" "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" @@ -1081,3 +1082,88 @@ func TestExpectStatefulSetMinReadySeconds(t *testing.T) { t.Fatalf("expected MinReadySeconds to be %d but got %d", expect, statefulSet.MinReadySeconds) } } + +func TestPodTemplateConfig(t *testing.T) { + nodeSelector := map[string]string{ + "foo": "bar", + } + affinity := v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{}, + PodAffinity: &v1.PodAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{ + { + PodAffinityTerm: v1.PodAffinityTerm{ + Namespaces: []string{"foo"}, + }, + Weight: 100, + }, + }, + }, + PodAntiAffinity: &v1.PodAntiAffinity{}, + } + + tolerations := []v1.Toleration{ + { + Key: "key", + }, + } + userid := int64(1234) + securityContext := v1.PodSecurityContext{ + RunAsUser: &userid, + } + priorityClassName := "foo" + serviceAccountName := "alertmanager-sa" + hostAliases := []monitoringv1.HostAlias{ + { + Hostnames: []string{"foo.com"}, + IP: "1.1.1.1", + }, + } + imagePullSecrets := []v1.LocalObjectReference{ + { + Name: "registry-secret", + }, + } + + sset, err := makeStatefulSet(&monitoringv1.Alertmanager{ + ObjectMeta: metav1.ObjectMeta{}, + Spec: monitoringv1.AlertmanagerSpec{ + NodeSelector: nodeSelector, + Affinity: &affinity, + Tolerations: tolerations, + SecurityContext: &securityContext, + PriorityClassName: priorityClassName, + ServiceAccountName: serviceAccountName, + HostAliases: hostAliases, + ImagePullSecrets: imagePullSecrets, + }, + }, defaultTestConfig, "", nil) + if err != nil { + t.Fatalf("Unexpected error while making StatefulSet: %v", err) + } + + if !reflect.DeepEqual(sset.Spec.Template.Spec.NodeSelector, nodeSelector) { + t.Fatalf("expected node selector to match, want %v, got %v", nodeSelector, sset.Spec.Template.Spec.NodeSelector) + } + if !reflect.DeepEqual(*sset.Spec.Template.Spec.Affinity, affinity) { + t.Fatalf("expected affinity to match, want %v, got %v", affinity, *sset.Spec.Template.Spec.Affinity) + } + if !reflect.DeepEqual(sset.Spec.Template.Spec.Tolerations, tolerations) { + t.Fatalf("expected tolerations to match, want %v, got %v", tolerations, sset.Spec.Template.Spec.Tolerations) + } + if !reflect.DeepEqual(*sset.Spec.Template.Spec.SecurityContext, securityContext) { + t.Fatalf("expected security context to match, want %v, got %v", securityContext, *sset.Spec.Template.Spec.SecurityContext) + } + if sset.Spec.Template.Spec.PriorityClassName != priorityClassName { + t.Fatalf("expected priority class name to match, want %s, got %s", priorityClassName, sset.Spec.Template.Spec.PriorityClassName) + } + if sset.Spec.Template.Spec.ServiceAccountName != serviceAccountName { + t.Fatalf("expected service account name to match, want %s, got %s", serviceAccountName, sset.Spec.Template.Spec.ServiceAccountName) + } + if !reflect.DeepEqual(sset.Spec.Template.Spec.HostAliases, k8sutil.HostAliasesMonitoringV1ToCoreV1(hostAliases)) { + t.Fatalf("expected host aliases to match, want %s, got %s", hostAliases, sset.Spec.Template.Spec.HostAliases) + } + if !reflect.DeepEqual(sset.Spec.Template.Spec.ImagePullSecrets, imagePullSecrets) { + t.Fatalf("expected image pull secrets to match, want %s, got %s", imagePullSecrets, sset.Spec.Template.Spec.ImagePullSecrets) + } +} diff --git a/pkg/apis/monitoring/v1/thanos_types.go b/pkg/apis/monitoring/v1/thanos_types.go index 23f60ed0c78..3490bdbf859 100644 --- a/pkg/apis/monitoring/v1/thanos_types.go +++ b/pkg/apis/monitoring/v1/thanos_types.go @@ -208,6 +208,10 @@ type ThanosRulerSpec struct { // AlertRelabelConfigFile specifies the path of the alert relabeling configuration file. // When used alongside with AlertRelabelConfigs, alertRelabelConfigFile takes precedence. AlertRelabelConfigFile *string `json:"alertRelabelConfigFile,omitempty"` + // Pods' hostAliases configuration + // +listType=map + // +listMapKey=ip + HostAliases []HostAlias `json:"hostAliases,omitempty"` } // ThanosRulerStatus is the most recent observed status of the ThanosRuler. Read-only. Not diff --git a/pkg/apis/monitoring/v1/types.go b/pkg/apis/monitoring/v1/types.go index 6522ffcd184..ca23042dbe7 100644 --- a/pkg/apis/monitoring/v1/types.go +++ b/pkg/apis/monitoring/v1/types.go @@ -337,6 +337,10 @@ type CommonPrometheusFields struct { // This is an alpha field and requires enabling StatefulSetMinReadySeconds feature gate. // +optional MinReadySeconds *uint32 `json:"minReadySeconds,omitempty"` + // Pods' hostAliases configuration + // +listType=map + // +listMapKey=ip + HostAliases []HostAlias `json:"hostAliases,omitempty"` } // Prometheus defines a Prometheus deployment. @@ -380,6 +384,17 @@ type ByteSize string // +kubebuilder:validation:Pattern:="^(0|(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?)$" type Duration string +// HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the +// pod's hosts file. +type HostAlias struct { + // IP address of the host file entry. + // +kubebuilder:validation:Required + IP string `json:"ip"` + // Hostnames for the above IP address. + // +kubebuilder:validation:Required + Hostnames []string `json:"hostnames"` +} + // PrometheusSpec is a specification of the desired behavior of the Prometheus cluster. More info: // https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status // +k8s:openapi-gen=true @@ -1836,6 +1851,10 @@ type AlertmanagerSpec struct { // This is an alpha field and requires enabling StatefulSetMinReadySeconds feature gate. // +optional MinReadySeconds *uint32 `json:"minReadySeconds,omitempty"` + // Pods' hostAliases configuration + // +listType=map + // +listMapKey=ip + HostAliases []HostAlias `json:"hostAliases,omitempty"` // EXPERIMENTAL: alertmanagerConfiguration specifies the global Alertmanager configuration. // If defined, it takes precedence over the `configSecret` field. // This field may change in future releases. diff --git a/pkg/apis/monitoring/v1/zz_generated.deepcopy.go b/pkg/apis/monitoring/v1/zz_generated.deepcopy.go index b4f77c39397..f95d26fb658 100644 --- a/pkg/apis/monitoring/v1/zz_generated.deepcopy.go +++ b/pkg/apis/monitoring/v1/zz_generated.deepcopy.go @@ -288,6 +288,13 @@ func (in *AlertmanagerSpec) DeepCopyInto(out *AlertmanagerSpec) { *out = new(uint32) **out = **in } + if in.HostAliases != nil { + in, out := &in.HostAliases, &out.HostAliases + *out = make([]HostAlias, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.AlertmanagerConfiguration != nil { in, out := &in.AlertmanagerConfiguration, &out.AlertmanagerConfiguration *out = new(AlertmanagerConfiguration) @@ -591,6 +598,13 @@ func (in *CommonPrometheusFields) DeepCopyInto(out *CommonPrometheusFields) { *out = new(uint32) **out = **in } + if in.HostAliases != nil { + in, out := &in.HostAliases, &out.HostAliases + *out = make([]HostAlias, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonPrometheusFields. @@ -744,6 +758,26 @@ func (in *Endpoint) DeepCopy() *Endpoint { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostAlias) DeepCopyInto(out *HostAlias) { + *out = *in + if in.Hostnames != nil { + in, out := &in.Hostnames, &out.Hostnames + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostAlias. +func (in *HostAlias) DeepCopy() *HostAlias { + if in == nil { + return nil + } + out := new(HostAlias) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MetadataConfig) DeepCopyInto(out *MetadataConfig) { *out = *in @@ -2245,6 +2279,13 @@ func (in *ThanosRulerSpec) DeepCopyInto(out *ThanosRulerSpec) { *out = new(string) **out = **in } + if in.HostAliases != nil { + in, out := &in.HostAliases, &out.HostAliases + *out = make([]HostAlias, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ThanosRulerSpec. diff --git a/pkg/k8sutil/k8sutil.go b/pkg/k8sutil/k8sutil.go index b5471760e38..1204196f342 100644 --- a/pkg/k8sutil/k8sutil.go +++ b/pkg/k8sutil/k8sutil.go @@ -37,6 +37,8 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/retry" + + monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" ) // KubeConfigEnv (optionally) specify the location of kubeconfig file @@ -247,6 +249,18 @@ func SanitizeVolumeName(name string) string { return strings.Trim(name, "-") } +// HostAliasesMonitoringV1ToCoreV1 converts array of monitoringv1 HostAlias to array of corev1 HostAlias +func HostAliasesMonitoringV1ToCoreV1(input []monitoringv1.HostAlias) []v1.HostAlias { + output := make([]v1.HostAlias, len(input)) + + for i, in := range input { + output[i].Hostnames = in.Hostnames + output[i].IP = in.IP + } + + return output +} + func mergeOwnerReferences(old []metav1.OwnerReference, new []metav1.OwnerReference) []metav1.OwnerReference { existing := make(map[metav1.OwnerReference]bool) for _, ownerRef := range old { diff --git a/pkg/prometheus/statefulset.go b/pkg/prometheus/statefulset.go index 40701651dfe..21549489a83 100644 --- a/pkg/prometheus/statefulset.go +++ b/pkg/prometheus/statefulset.go @@ -999,6 +999,7 @@ func makeStatefulSetSpec(p monitoringv1.Prometheus, c *operator.Config, shard in Tolerations: p.Spec.Tolerations, Affinity: p.Spec.Affinity, TopologySpreadConstraints: p.Spec.TopologySpreadConstraints, + HostAliases: k8sutil.HostAliasesMonitoringV1ToCoreV1(p.Spec.HostAliases), }, }, }, nil diff --git a/pkg/prometheus/statefulset_test.go b/pkg/prometheus/statefulset_test.go index a822ea099bc..4f6fda0d614 100644 --- a/pkg/prometheus/statefulset_test.go +++ b/pkg/prometheus/statefulset_test.go @@ -23,6 +23,7 @@ import ( "github.com/kylelemons/godebug/pretty" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + "github.com/prometheus-operator/prometheus-operator/pkg/k8sutil" "github.com/prometheus-operator/prometheus-operator/pkg/operator" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" @@ -2237,3 +2238,90 @@ func TestEnableRemoteWriteReceiver(t *testing.T) { }) } } + +func TestPodTemplateConfig(t *testing.T) { + nodeSelector := map[string]string{ + "foo": "bar", + } + affinity := v1.Affinity{ + NodeAffinity: &v1.NodeAffinity{}, + PodAffinity: &v1.PodAffinity{ + PreferredDuringSchedulingIgnoredDuringExecution: []v1.WeightedPodAffinityTerm{ + { + PodAffinityTerm: v1.PodAffinityTerm{ + Namespaces: []string{"foo"}, + }, + Weight: 100, + }, + }, + }, + PodAntiAffinity: &v1.PodAntiAffinity{}, + } + + tolerations := []v1.Toleration{ + { + Key: "key", + }, + } + userid := int64(1234) + securityContext := v1.PodSecurityContext{ + RunAsUser: &userid, + } + priorityClassName := "foo" + serviceAccountName := "prometheus-sa" + hostAliases := []monitoringv1.HostAlias{ + { + Hostnames: []string{"foo.com"}, + IP: "1.1.1.1", + }, + } + imagePullSecrets := []v1.LocalObjectReference{ + { + Name: "registry-secret", + }, + } + + sset, err := makeStatefulSet("test", monitoringv1.Prometheus{ + ObjectMeta: metav1.ObjectMeta{}, + Spec: monitoringv1.PrometheusSpec{ + CommonPrometheusFields: monitoringv1.CommonPrometheusFields{ + NodeSelector: nodeSelector, + Affinity: &affinity, + Tolerations: tolerations, + SecurityContext: &securityContext, + PriorityClassName: priorityClassName, + ServiceAccountName: serviceAccountName, + HostAliases: hostAliases, + ImagePullSecrets: imagePullSecrets, + }, + }, + }, defaultTestConfig, nil, "", 0, nil) + if err != nil { + t.Fatalf("Unexpected error while making StatefulSet: %v", err) + } + + if !reflect.DeepEqual(sset.Spec.Template.Spec.NodeSelector, nodeSelector) { + t.Fatalf("expected node selector to match, want %v, got %v", nodeSelector, sset.Spec.Template.Spec.NodeSelector) + } + if !reflect.DeepEqual(*sset.Spec.Template.Spec.Affinity, affinity) { + t.Fatalf("expected affinity to match, want %v, got %v", affinity, *sset.Spec.Template.Spec.Affinity) + } + if !reflect.DeepEqual(sset.Spec.Template.Spec.Tolerations, tolerations) { + t.Fatalf("expected tolerations to match, want %v, got %v", tolerations, sset.Spec.Template.Spec.Tolerations) + } + if !reflect.DeepEqual(*sset.Spec.Template.Spec.SecurityContext, securityContext) { + t.Fatalf("expected security context to match, want %v, got %v", securityContext, *sset.Spec.Template.Spec.SecurityContext) + } + if sset.Spec.Template.Spec.PriorityClassName != priorityClassName { + t.Fatalf("expected priority class name to match, want %s, got %s", priorityClassName, sset.Spec.Template.Spec.PriorityClassName) + } + if sset.Spec.Template.Spec.ServiceAccountName != serviceAccountName { + t.Fatalf("expected service account name to match, want %s, got %s", serviceAccountName, sset.Spec.Template.Spec.ServiceAccountName) + } + if !reflect.DeepEqual(sset.Spec.Template.Spec.HostAliases, k8sutil.HostAliasesMonitoringV1ToCoreV1(hostAliases)) { + t.Fatalf("expected host aliases to match, want %s, got %s", hostAliases, sset.Spec.Template.Spec.HostAliases) + } + if !reflect.DeepEqual(sset.Spec.Template.Spec.ImagePullSecrets, imagePullSecrets) { + t.Fatalf("expected image pull secrets to match, want %s, got %s", imagePullSecrets, sset.Spec.Template.Spec.ImagePullSecrets) + } +} diff --git a/pkg/thanos/statefulset.go b/pkg/thanos/statefulset.go index f3955aef008..f0d2d8c58c4 100644 --- a/pkg/thanos/statefulset.go +++ b/pkg/thanos/statefulset.go @@ -486,6 +486,7 @@ func makeStatefulSetSpec(tr *monitoringv1.ThanosRuler, config Config, ruleConfig Tolerations: tr.Spec.Tolerations, Affinity: tr.Spec.Affinity, TopologySpreadConstraints: tr.Spec.TopologySpreadConstraints, + HostAliases: k8sutil.HostAliasesMonitoringV1ToCoreV1(tr.Spec.HostAliases), }, }, }, nil diff --git a/pkg/thanos/statefulset_test.go b/pkg/thanos/statefulset_test.go index 0069d127845..aef2f7cc6d2 100644 --- a/pkg/thanos/statefulset_test.go +++ b/pkg/thanos/statefulset_test.go @@ -26,6 +26,7 @@ import ( "github.com/kylelemons/godebug/pretty" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + "github.com/prometheus-operator/prometheus-operator/pkg/k8sutil" "github.com/prometheus-operator/prometheus-operator/pkg/operator" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/api/resource" @@ -617,7 +618,6 @@ func TestRetention(t *testing.T) { } func TestPodTemplateConfig(t *testing.T) { - nodeSelector := map[string]string{ "foo": "bar", } @@ -647,6 +647,17 @@ func TestPodTemplateConfig(t *testing.T) { } priorityClassName := "foo" serviceAccountName := "thanos-ruler-sa" + hostAliases := []monitoringv1.HostAlias{ + { + Hostnames: []string{"foo.com"}, + IP: "1.1.1.1", + }, + } + imagePullSecrets := []v1.LocalObjectReference{ + { + Name: "registry-secret", + }, + } sset, err := makeStatefulSet(&monitoringv1.ThanosRuler{ ObjectMeta: metav1.ObjectMeta{}, @@ -658,6 +669,8 @@ func TestPodTemplateConfig(t *testing.T) { SecurityContext: &securityContext, PriorityClassName: priorityClassName, ServiceAccountName: serviceAccountName, + HostAliases: hostAliases, + ImagePullSecrets: imagePullSecrets, }, }, defaultTestConfig, nil, "") if err != nil { @@ -682,6 +695,12 @@ func TestPodTemplateConfig(t *testing.T) { if sset.Spec.Template.Spec.ServiceAccountName != serviceAccountName { t.Fatalf("expected service account name to match, want %s, got %s", serviceAccountName, sset.Spec.Template.Spec.ServiceAccountName) } + if !reflect.DeepEqual(sset.Spec.Template.Spec.HostAliases, k8sutil.HostAliasesMonitoringV1ToCoreV1(hostAliases)) { + t.Fatalf("expected host aliases to match, want %s, got %s", hostAliases, sset.Spec.Template.Spec.HostAliases) + } + if !reflect.DeepEqual(sset.Spec.Template.Spec.ImagePullSecrets, imagePullSecrets) { + t.Fatalf("expected image pull secrets to match, want %s, got %s", imagePullSecrets, sset.Spec.Template.Spec.ImagePullSecrets) + } } func TestExternalQueryURL(t *testing.T) {