1
0
Fork 0
mirror of https://github.com/prometheus-operator/prometheus-operator.git synced 2025-04-21 11:48:53 +00:00

alertmanager: Allows specifying additional secrets

This commit is contained in:
Frederic Branczyk 2018-03-23 15:17:01 +01:00
parent 0971f911e2
commit 2d53e51de0
No known key found for this signature in database
GPG key ID: 7741A52782A90069
7 changed files with 118 additions and 25 deletions
Documentation
example/prometheus-operator-crd
pkg

View file

@ -91,6 +91,7 @@ Specification of the desired behavior of the Alertmanager cluster. More info: ht
| version | Version the cluster should be on. | string | false |
| baseImage | Base image that is used to deploy pods, without tag. | string | false |
| imagePullSecrets | An optional list of references to secrets in the same namespace to use for pulling prometheus and alertmanager images from registries see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod | [][v1.LocalObjectReference](https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6/#localobjectreference-v1-core) | false |
| secrets | Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/<secret-name>. | []string | false |
| replicas | Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the running cluster equal to the expected size. | *int32 | false |
| storage | Storage is the definition of how storage will be used by the Alertmanager instances. | *[StorageSpec](#storagespec) | false |
| externalUrl | The external URL the Alertmanager instances will be available under. This is necessary to generate correct URLs. This is necessary if Alertmanager is not served from root of a DNS name. | string | false |

View file

@ -1590,6 +1590,13 @@ spec:
the server serves requests under a different route prefix. For example
for use with `kubectl proxy`.
type: string
secrets:
description: Secrets is a list of Secrets in the same namespace as the
Alertmanager object, which shall be mounted into the Alertmanager
Pods. The Secrets are mounted into /etc/alertmanager/secrets/<secret-name>.
items:
type: string
type: array
securityContext:
description: PodSecurityContext holds pod-level security attributes
and common container settings. Some fields are also present in container.securityContext. Field

View file

@ -34,6 +34,7 @@ import (
const (
governingServiceName = "alertmanager-operated"
defaultVersion = "v0.14.0"
secretsDir = "/etc/alertmanager/secrets/"
alertmanagerConfDir = "/etc/alertmanager/config"
alertmanagerConfFile = alertmanagerConfDir + "/alertmanager.yaml"
alertmanagerStorageDir = "/alertmanager"
@ -306,6 +307,43 @@ func makeStatefulSetSpec(a *monitoringv1.Alertmanager, config Config) (*appsv1.S
return nil, errors.Errorf("unsupported Alertmanager major version %s", version)
}
volumes := []v1.Volume{
{
Name: "config-volume",
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: configSecretName(a.Name),
},
},
},
}
amVolumeMounts := []v1.VolumeMount{
{
Name: "config-volume",
MountPath: alertmanagerConfDir,
},
{
Name: volumeName(a.Name),
MountPath: alertmanagerStorageDir,
SubPath: subPathForStorage(a.Spec.Storage),
},
}
for _, s := range a.Spec.Secrets {
volumes = append(volumes, v1.Volume{
Name: "secret-" + s,
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: s,
},
},
})
amVolumeMounts = append(amVolumeMounts, v1.VolumeMount{
Name: "secret-" + s,
ReadOnly: true,
MountPath: secretsDir + s,
})
}
terminationGracePeriod := int64(0)
finalLabels := config.Labels.Merge(podLabels)
return &appsv1.StatefulSetSpec{
@ -327,21 +365,11 @@ func makeStatefulSetSpec(a *monitoringv1.Alertmanager, config Config) (*appsv1.S
TerminationGracePeriodSeconds: &terminationGracePeriod,
Containers: append([]v1.Container{
{
Args: amArgs,
Name: "alertmanager",
Image: image,
Ports: ports,
VolumeMounts: []v1.VolumeMount{
{
Name: "config-volume",
MountPath: alertmanagerConfDir,
},
{
Name: volumeName(a.Name),
MountPath: alertmanagerStorageDir,
SubPath: subPathForStorage(a.Spec.Storage),
},
},
Args: amArgs,
Name: "alertmanager",
Image: image,
Ports: ports,
VolumeMounts: amVolumeMounts,
LivenessProbe: livenessProbe,
ReadinessProbe: readinessProbe,
Resources: a.Spec.Resources,
@ -367,16 +395,7 @@ func makeStatefulSetSpec(a *monitoringv1.Alertmanager, config Config) (*appsv1.S
},
},
}, a.Spec.Containers...),
Volumes: []v1.Volume{
{
Name: "config-volume",
VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: configSecretName(a.Name),
},
},
},
},
Volumes: volumes,
ServiceAccountName: a.Spec.ServiceAccountName,
SecurityContext: securityContext,
Tolerations: a.Spec.Tolerations,

View file

@ -351,6 +351,49 @@ func TestMakeStatefulSetSpecPeerFlagPort(t *testing.T) {
}
}
func TestAdditionalSecretsMounted(t *testing.T) {
secrets := []string{"secret1", "secret2"}
sset, err := makeStatefulSet(&monitoringv1.Alertmanager{
ObjectMeta: metav1.ObjectMeta{},
Spec: monitoringv1.AlertmanagerSpec{
Secrets: secrets,
},
}, nil, defaultTestConfig)
require.NoError(t, err)
secret1Found := false
secret2Found := false
for _, v := range sset.Spec.Template.Spec.Volumes {
if v.Secret != nil {
if v.Secret.SecretName == "secret1" {
secret1Found = true
}
if v.Secret.SecretName == "secret2" {
secret2Found = true
}
}
}
if !(secret1Found && secret2Found) {
t.Fatal("Additional secrets were not found.")
}
secret1Found = false
secret2Found = false
for _, v := range sset.Spec.Template.Spec.Containers[0].VolumeMounts {
if v.Name == "secret-secret1" && v.MountPath == "/etc/alertmanager/secrets/secret1" {
secret1Found = true
}
if v.Name == "secret-secret2" && v.MountPath == "/etc/alertmanager/secrets/secret2" {
secret2Found = true
}
}
if !(secret1Found && secret2Found) {
t.Fatal("Additional secrets were not found.")
}
}
func sliceContains(slice []string, match string) bool {
contains := false
for _, s := range slice {

View file

@ -231,6 +231,20 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
},
},
},
"secrets": {
SchemaProps: spec.SchemaProps{
Description: "Secrets is a list of Secrets in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods. The Secrets are mounted into /etc/alertmanager/secrets/<secret-name>.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
"replicas": {
SchemaProps: spec.SchemaProps{
Description: "Size is the expected size of the alertmanager cluster. The controller will eventually make the size of the running cluster equal to the expected size.",

View file

@ -402,6 +402,10 @@ type AlertmanagerSpec struct {
// to use for pulling prometheus and alertmanager images from registries
// see http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod
ImagePullSecrets []v1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
// Secrets is a list of Secrets in the same namespace as the Alertmanager
// object, which shall be mounted into the Alertmanager Pods.
// The Secrets are mounted into /etc/alertmanager/secrets/<secret-name>.
Secrets []string `json:"secrets,omitempty"`
// Size is the expected size of the alertmanager cluster. The controller will
// eventually make the size of the running cluster equal to the expected
// size.

View file

@ -142,6 +142,11 @@ func (in *AlertmanagerSpec) DeepCopyInto(out *AlertmanagerSpec) {
*out = make([]core_v1.LocalObjectReference, len(*in))
copy(*out, *in)
}
if in.Secrets != nil {
in, out := &in.Secrets, &out.Secrets
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
if *in == nil {