Add VictoriaMetrics observability stack + sync catalog for monitoring test

- VM stack 10 charts: victoria-metrics-cluster/auth, victoria-logs-cluster,
  victoria-metrics-agent/alert, opentelemetry-collector, kube-state-metrics,
  prometheus-node-exporter, alertmanager, perses (JWT/OIDC, Infisical-ready)
- ArgoCD ApplicationSet (syncWave) + per-chart dip-values overlays
- doc/victoria-metrics-architecture.md, define-chart-resources updates
- includes pending working-tree changes (mlflow, kubeflow, apisix, CLAUDE.md)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
wbsong111
2026-06-25 11:10:51 +09:00
parent a55427730e
commit 6290322f1b
514 changed files with 68103 additions and 40 deletions
@@ -0,0 +1,26 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
unittests/
ci/
@@ -0,0 +1,70 @@
# alertmanager 버전 갱신 가이드
> **카탈로그 업데이트 방식**: 기존 버전 디렉토리는 유지하고, 신규 버전 디렉토리를 새로 생성한다.
> `manifests/helm/alertmanager/<new-version>/` 디렉토리를 직접 추가하는 방식으로 관리한다.
## 1. git 작업 환경 구성
- dip-catalog git 다운로드
```sh
git clone https://github.com/paasup/dip-catalog.git
```
- 작업 브랜치로 체크아웃
```sh
git checkout -b update-alertmanager/<new-version>
```
## 2. helm chart 업데이트
### 1) 기존 버전 디렉토리 복사
신규 버전 디렉토리를 기존 버전에서 복사하여 시작한다.
`BUILD-README.md`, `CUSTOM-README.md`, `custom-values.yaml`가 함께 복사된다.
```sh
cd ~/dip-catalog/manifests/helm/alertmanager
# 기존 버전에서 신규 버전 디렉토리 복사
cp -r 1.37.0 <new-version>
```
### 2) 업스트림 차트 파일 업데이트
신규 버전 디렉토리에서 업스트림 차트 파일만 교체한다.
`BUILD-README.md`, `CUSTOM-README.md`, `custom-values.yaml`는 유지한다.
```sh
cd ~/dip-catalog/manifests/helm/alertmanager
# helm repo 추가
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# 신규 버전 차트 다운로드 후 압축 해제
helm pull prometheus-community/alertmanager --version="<new-version>"
tar xzvf alertmanager-<new-version>.tgz -C <new-version> --strip-components=1
# 불필요한 파일 삭제
rm alertmanager-<new-version>.tgz
```
## 3. git push 및 tag 추가
```sh
git add .
git commit -m "update alertmanager/<new-version>"
git checkout main
git merge update-alertmanager/<new-version>
git push -u origin main
git branch -d update-alertmanager/<new-version>
git tag alertmanager/<new-version>
git push origin alertmanager/<new-version>
```
## 4. 차트 버전 정보
- alertmanager/1.37.0
- Chart version: 1.37.0
- App version: v0.32.1
- 업스트림: https://prometheus-community.github.io/helm-charts
@@ -0,0 +1,84 @@
# Alertmanager 배포 (알림 라우팅·중복제거·Discord 발송)
vmalert가 보낸 알림을 그룹핑·중복제거·억제(inhibit)한 뒤 Discord로 발송한다.
## 1. 배포 방법
### 사전 준비 — Discord Webhook Secret
Webhook URL을 값 파일에 평문으로 적지 않는다. Secret으로 주입한다.
```sh
kubectl create secret generic alertmanager-discord -n monitoring \
--from-literal=webhook-url="https://discord.com/api/webhooks/..."
```
```sh
helm upgrade alertmanager ./ -f custom-values.yaml --install -n monitoring
```
## 2. custom-values.yaml 설정 설명
- `extraSecretMounts``alertmanager-discord` Secret을 `/etc/alertmanager/secrets`에 마운트.
- `config.receivers[].discord_configs[].webhook_url_file` — 마운트된 파일 참조(평문 금지).
- `route``[alertname, severity]` 그룹핑, repeat 4h.
- `inhibit_rules` — 동일 노드에서 critical 발생 시 warning 억제.
- `persistence.enabled: false` — 단일 인스턴스(HA 미사용).
## 3. 의존 관계
- **수신**: vmalert notifier → alertmanager:9093
## 4. 검증
```sh
kubectl port-forward -n monitoring svc/alertmanager 9093:9093
curl -s http://localhost:9093/api/v2/status | jq '.cluster.status'
# 테스트 알림 발송 후 Discord 채널 수신 확인
```
## 5. 알림 채널 교체·추가 (Discord / Slack / Email)
알림 채널은 고정이 아니다. **receiver는 채널 무관하게 작성**하고, 자격증명은 평문 대신 **Infisical 동기화 Secret을 파일로 마운트**(`*_file`)한다. ArgoCD 배포에서는 `dip-values` 오버레이로 receiver를 덮어쓴다(`config.receivers`는 배열이라 전체 재정의).
### 채널별 receiver 형태
| 채널 | receiver 키 | 자격증명 파일 |
|------|------------|--------------|
| Discord | `discord_configs[].webhook_url_file` | webhook URL |
| Slack | `slack_configs[].api_url_file` | webhook URL |
| Email | `email_configs[]` (smarthost/from/to) | `auth_password_file` |
```yaml
# Slack 예시
config:
route:
receiver: slack
receivers:
- name: slack
slack_configs:
- api_url_file: /etc/alertmanager/secrets/slack-webhook
channel: "#alerts"
title: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
# Email 예시
config:
route:
receiver: email
receivers:
- name: email
email_configs:
- to: "ops@example.org"
from: "alert@example.org"
smarthost: "smtp.example.org:587"
auth_username: "alert@example.org"
auth_password_file: /etc/alertmanager/secrets/smtp-password
```
### 새 채널 추가 3단계
1. **Infisical 등록** — 채널 자격증명(webhook URL / SMTP password)을 dip-console로 Infisical에 추가 → external-secrets가 `monitoring` ns Secret(`$INFISICAL_ALERTMANAGER_SECRET`)에 동기화. 키를 `extraSecretMounts` 경로(`/etc/alertmanager/secrets/<key>`)에 노출.
2. **dip-values 수정**`victoria-metrics/alertmanager-values.yaml` 오버레이의 `config.receivers`/`route.receiver`를 위 예시처럼 교체·추가. 필요 시 `extraSecretMounts`에 키 추가.
3. **재동기화** — ArgoCD가 변경을 감지해 동기화(또는 `argocd app sync alertmanager`). config 변경은 alertmanager가 자동 reload.
> 여러 채널 동시 발송은 `route.routes`로 severity/label별 분기하거나, 단일 receiver에 여러 `*_configs`를 나열한다.
@@ -0,0 +1,26 @@
annotations:
artifacthub.io/license: Apache-2.0
artifacthub.io/links: |
- name: Chart Source
url: https://github.com/prometheus-community/helm-charts
apiVersion: v2
appVersion: v0.32.1
description: The Alertmanager handles alerts sent by client applications such as the
Prometheus server.
home: https://prometheus.io/
icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png
keywords:
- monitoring
kubeVersion: '>=1.25.0-0'
maintainers:
- email: monotek23@gmail.com
name: monotek
url: https://github.com/monotek
- email: naseem@transit.app
name: naseemkullah
url: https://github.com/naseemkullah
name: alertmanager
sources:
- https://github.com/prometheus/alertmanager
type: application
version: 1.37.0
@@ -0,0 +1,62 @@
# Alertmanager
As per [prometheus.io documentation](https://prometheus.io/docs/alerting/latest/alertmanager/):
> The Alertmanager handles alerts sent by client applications such as the
> Prometheus server. It takes care of deduplicating, grouping, and routing them
> to the correct receiver integration such as email, PagerDuty, or OpsGenie. It
> also takes care of silencing and inhibition of alerts.
## Prerequisites
Kubernetes 1.14+
## Usage
The chart is distributed as an [OCI Artifact](https://helm.sh/docs/topics/registries/) as well as via a traditional [Helm Repository](https://helm.sh/docs/topics/chart_repository/).
- OCI Artifact: `oci://ghcr.io/prometheus-community/charts/alertmanager`
- Helm Repository: `https://prometheus-community.github.io/helm-charts` with chart `alertmanager`
The installation instructions use the OCI registry. Refer to the [`helm repo`]([`helm repo`](https://helm.sh/docs/helm/helm_repo/)) command documentation for information on installing charts via the traditional repository.
### Install Chart
```console
helm install [RELEASE_NAME] oci://ghcr.io/prometheus-community/charts/alertmanager
```
_See [configuration](#configuration) below._
_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._
### Uninstall Chart
```console
helm uninstall [RELEASE_NAME]
```
This removes all the Kubernetes components associated with the chart and deletes the release.
_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._
### Upgrading Chart
```console
helm upgrade [RELEASE_NAME] [CHART] --install
```
_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._
### To 1.0
The [configmap-reload](https://github.com/jimmidyson/configmap-reload) container was replaced by the [prometheus-config-reloader](https://github.com/prometheus-operator/prometheus-operator/tree/main/cmd/prometheus-config-reloader).
Extra command-line arguments specified via configmapReload.prometheus.extraArgs are not compatible and will break with the new prometheus-config-reloader, refer to the [sources](https://github.com/prometheus-operator/prometheus-operator/blob/main/cmd/prometheus-config-reloader/main.go) in order to make the appropriate adjustment to the extea command-line arguments.
The `networking.k8s.io/v1beta1` is no longer supported. use [`networking.k8s.io/v1`](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#ingressclass-v122).
## Configuration
See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing). To see all configurable options with detailed comments, visit the chart's [values.yaml](./values.yaml), or run these configuration commands:
```console
helm show values oci://ghcr.io/prometheus-community/charts/alertmanager
```
@@ -0,0 +1,51 @@
# =============================================================================
# Alertmanager — PaaSup 커스텀 오버라이드 (알림 라우팅·중복제거·Discord 발송)
# 차트: prometheus-community/alertmanager
# 수신: vmalert가 notifier로 알림 전송 (alertmanager:9093)
#
# Discord Webhook URL 주입 (값 파일에 평문 기입 금지):
# kubectl create secret generic alertmanager-discord -n monitoring \
# --from-literal=webhook-url="https://discord.com/api/webhooks/..."
# → extraSecretMounts로 마운트 후 discord_configs.webhook_url_file 로 참조
# =============================================================================
extraSecretMounts:
- name: alertmanager-discord
mountPath: /etc/alertmanager/secrets
subPath: ""
secretName: alertmanager-discord
readOnly: true
config:
global:
resolve_timeout: 5m
route:
group_by: [alertname, severity]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: discord
receivers:
- name: discord
discord_configs:
- webhook_url_file: /etc/alertmanager/secrets/webhook-url
title: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}'
message: |
{{ range .Alerts -}}
**{{ .Labels.severity | toUpper }}** {{ .Annotations.summary }}
{{- if .Annotations.description }}
{{ .Annotations.description }}
{{- end }}
{{ end }}
inhibit_rules:
- source_match:
severity: critical
target_match:
severity: warning
equal: [alertname, node]
persistence:
enabled: false
@@ -0,0 +1,21 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ include "alertmanager.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "alertmanager.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ include "alertmanager.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ include "alertmanager.namespace" . }} svc -w {{ include "alertmanager.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ include "alertmanager.namespace" . }} {{ include "alertmanager.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ include "alertmanager.namespace" . }} -l "app.kubernetes.io/name={{ include "alertmanager.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:{{ .Values.service.port }} to use your application"
kubectl --namespace {{ include "alertmanager.namespace" . }} port-forward $POD_NAME {{ .Values.service.port }}:80
{{- end }}
@@ -0,0 +1,81 @@
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "alertmanager.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "alertmanager.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "alertmanager.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "alertmanager.labels" -}}
helm.sh/chart: {{ include "alertmanager.chart" . }}
{{ include "alertmanager.selectorLabels" . }}
{{- with .Chart.AppVersion }}
app.kubernetes.io/version: {{ . | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "alertmanager.selectorLabels" -}}
app.kubernetes.io/name: {{ include "alertmanager.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "alertmanager.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "alertmanager.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Define Ingress apiVersion
*/}}
{{- define "alertmanager.ingress.apiVersion" -}}
{{- printf "networking.k8s.io/v1" }}
{{- end }}
{{/*
Allow overriding alertmanager namespace
*/}}
{{- define "alertmanager.namespace" -}}
{{- if .Values.namespaceOverride -}}
{{- .Values.namespaceOverride -}}
{{- else -}}
{{- .Release.Namespace -}}
{{- end -}}
{{- end -}}
@@ -0,0 +1,21 @@
{{- if .Values.config.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "alertmanager.fullname" . }}
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- with .Values.configAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ include "alertmanager.namespace" . }}
data:
alertmanager.yml: |
{{- $config := omit .Values.config "enabled" }}
{{- toYaml $config | default "{}" | nindent 4 }}
{{- range $key, $value := .Values.templates }}
{{ $key }}: |-
{{- $value | nindent 4 }}
{{- end }}
{{- end }}
@@ -0,0 +1,47 @@
{{- if .Values.ingress.enabled }}
{{- $fullName := include "alertmanager.fullname" . }}
{{- $svcPort := .Values.service.port }}
apiVersion: {{ include "alertmanager.ingress.apiVersion" . }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- if .Values.ingress.labels }}
{{- toYaml .Values.ingress.labels | nindent 4 }}
{{- end }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ include "alertmanager.namespace" . }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
@@ -0,0 +1,56 @@
{{- if and .Values.servicePerReplica.enabled .Values.ingressPerReplica.enabled }}
{{- $pathType := .Values.ingressPerReplica.pathType }}
{{- $count := .Values.replicaCount | int -}}
{{- $servicePort := .Values.service.port -}}
{{- $ingressValues := .Values.ingressPerReplica -}}
{{- $fullName := include "alertmanager.fullname" . }}
apiVersion: v1
kind: List
metadata:
name: {{ $fullName }}-ingressperreplica
namespace: {{ include "alertmanager.namespace" . }}
items:
{{- range $i, $e := until $count }}
- kind: Ingress
apiVersion: {{ include "alertmanager.ingress.apiVersion" $ }}
metadata:
name: {{ $fullName }}-{{ $i }}
namespace: {{ include "alertmanager.namespace" $ }}
labels:
{{- include "alertmanager.labels" $ | nindent 8 }}
{{- if $ingressValues.labels }}
{{ toYaml $ingressValues.labels | indent 8 }}
{{- end }}
{{- if $ingressValues.annotations }}
annotations:
{{ toYaml $ingressValues.annotations | indent 8 }}
{{- end }}
spec:
{{- if $ingressValues.className }}
ingressClassName: {{ $ingressValues.className }}
{{- end }}
rules:
- host: {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }}
http:
paths:
{{- range $p := $ingressValues.paths }}
- path: {{ tpl $p $ }}
pathType: {{ $pathType }}
backend:
service:
name: {{ $fullName }}-{{ $i }}
port:
name: http
{{- end -}}
{{- if or $ingressValues.tlsSecretName $ingressValues.tlsSecretPerReplica.enabled }}
tls:
- hosts:
- {{ $ingressValues.hostPrefix }}-{{ $i }}.{{ $ingressValues.hostDomain }}
{{- if $ingressValues.tlsSecretPerReplica.enabled }}
secretName: {{ $ingressValues.tlsSecretPerReplica.prefix }}-{{ $i }}
{{- else }}
secretName: {{ $ingressValues.tlsSecretName }}
{{- end }}
{{- end }}
{{- end -}}
{{- end -}}
@@ -0,0 +1,14 @@
{{- if .Values.podDisruptionBudget }}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ include "alertmanager.fullname" . }}
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
namespace: {{ include "alertmanager.namespace" . }}
spec:
selector:
matchLabels:
{{- include "alertmanager.selectorLabels" . | nindent 6 }}
{{- toYaml .Values.podDisruptionBudget | nindent 2 }}
{{- end }}
@@ -0,0 +1,14 @@
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "alertmanager.serviceAccountName" . }}
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ include "alertmanager.namespace" . }}
automountServiceAccountToken: {{ .Values.automountServiceAccountToken }}
{{- end }}
@@ -0,0 +1,51 @@
{{- if .Values.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "alertmanager.fullname" . }}
namespace: {{ default (include "alertmanager.namespace" .) .Values.serviceMonitor.namespace }}
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- with .Values.serviceMonitor.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
- port: http
path: {{ .Values.serviceMonitor.path }}
honorLabels: {{ .Values.serviceMonitor.honorLabels }}
{{- with .Values.serviceMonitor.interval }}
interval: {{ . }}
{{- end }}
{{- with .Values.serviceMonitor.scrapeTimeout }}
scrapeTimeout: {{ . }}
{{- end }}
{{- with .Values.serviceMonitor.scheme }}
scheme: {{ . }}
{{- end }}
{{- with .Values.serviceMonitor.tlsConfig }}
tlsConfig:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.serviceMonitor.bearerTokenFile }}
bearerTokenFile: {{ . }}
{{- end }}
{{- with .Values.serviceMonitor.basicAuth }}
basicAuth:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.serviceMonitor.metricRelabelings }}
metricRelabelings:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.serviceMonitor.relabelings }}
relabelings:
{{- toYaml . | nindent 8 }}
{{- end }}
namespaceSelector:
matchNames:
- {{ include "alertmanager.namespace" . }}
selector:
matchLabels:
{{- include "alertmanager.selectorLabels" . | nindent 6 }}
{{- end }}
@@ -0,0 +1,44 @@
{{- if and .Values.servicePerReplica.enabled }}
{{- $count := .Values.replicaCount | int -}}
{{- $serviceValues := .Values.servicePerReplica -}}
apiVersion: v1
kind: List
metadata:
name: {{ include "alertmanager.fullname" . }}-serviceperreplica
namespace: {{ include "alertmanager.namespace" . }}
items:
{{- range $i, $e := until $count }}
- apiVersion: v1
kind: Service
metadata:
name: {{ include "alertmanager.fullname" $ }}-{{ $i }}
namespace: {{ include "alertmanager.namespace" $ }}
labels:
{{- include "alertmanager.labels" $ | nindent 8 }}
{{- if $serviceValues.annotations }}
annotations:
{{ toYaml $serviceValues.annotations | indent 8 }}
{{- end }}
spec:
{{- if $serviceValues.clusterIP }}
clusterIP: {{ $serviceValues.clusterIP }}
{{- end }}
{{- if $serviceValues.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{- range $cidr := $serviceValues.loadBalancerSourceRanges }}
- {{ $cidr }}
{{- end }}
{{- end }}
{{- if ne $serviceValues.type "ClusterIP" }}
externalTrafficPolicy: {{ $serviceValues.externalTrafficPolicy }}
{{- end }}
ports:
- name: http
port: {{ $.Values.service.port }}
targetPort: {{ $.Values.containerPortName }}
selector:
{{- include "alertmanager.selectorLabels" $ | nindent 8 }}
statefulset.kubernetes.io/pod-name: {{ include "alertmanager.fullname" $ }}-{{ $i }}
type: "{{ $serviceValues.type }}"
{{- end }}
{{- end }}
@@ -0,0 +1,75 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "alertmanager.fullname" . }}
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- with .Values.service.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ include "alertmanager.namespace" . }}
spec:
{{- if .Values.service.ipDualStack.enabled }}
ipFamilies: {{ toYaml .Values.service.ipDualStack.ipFamilies | nindent 4 }}
ipFamilyPolicy: {{ .Values.service.ipDualStack.ipFamilyPolicy }}
{{- end }}
type: {{ .Values.service.type }}
{{- with .Values.service.loadBalancerIP }}
loadBalancerIP: {{ . }}
{{- end }}
{{- with .Values.service.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{- range $cidr := . }}
- {{ $cidr }}
{{- end }}
{{- end }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.containerPortName }}
protocol: TCP
name: http
{{- if (and (eq .Values.service.type "NodePort") .Values.service.nodePort) }}
nodePort: {{ .Values.service.nodePort }}
{{- end }}
{{- with .Values.service.extraPorts }}
{{- toYaml . | nindent 4 }}
{{- end }}
selector:
{{- include "alertmanager.selectorLabels" . | nindent 4 }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ include "alertmanager.fullname" . }}-headless
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- with .Values.service.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ include "alertmanager.namespace" . }}
spec:
clusterIP: None
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.containerPortName }}
protocol: TCP
name: http
{{- if or (gt (int .Values.replicaCount) 1) (.Values.additionalPeers) }}
- port: {{ .Values.service.clusterPort }}
targetPort: clusterpeer-tcp
protocol: TCP
name: cluster-tcp
- port: {{ .Values.service.clusterPort }}
targetPort: clusterpeer-udp
protocol: UDP
name: cluster-udp
{{- end }}
{{- with .Values.service.extraPorts }}
{{- toYaml . | nindent 4 }}
{{- end }}
selector:
{{- include "alertmanager.selectorLabels" . | nindent 4 }}
@@ -0,0 +1,280 @@
{{- $svcClusterPort := .Values.service.clusterPort }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "alertmanager.fullname" . }}
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- with .Values.statefulSet.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ include "alertmanager.namespace" . }}
spec:
replicas: {{ .Values.replicaCount }}
minReadySeconds: {{ .Values.minReadySeconds }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
selector:
matchLabels:
{{- include "alertmanager.selectorLabels" . | nindent 6 }}
serviceName: {{ include "alertmanager.fullname" . }}-headless
template:
metadata:
labels:
{{- include "alertmanager.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
annotations:
{{- if not .Values.configmapReload.enabled }}
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- end }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- if .Values.hostUsers }}
hostUsers: true
{{- end }}
automountServiceAccountToken: {{ .Values.automountServiceAccountToken }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "alertmanager.serviceAccountName" . }}
{{- with .Values.dnsConfig }}
dnsConfig:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.hostAliases }}
hostAliases:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.schedulerName }}
schedulerName: {{ . }}
{{- end }}
{{- if or .Values.podAntiAffinity .Values.affinity }}
affinity:
{{- end }}
{{- with .Values.affinity }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if eq .Values.podAntiAffinity "hard" }}
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: {{ .Values.podAntiAffinityTopologyKey }}
labelSelector:
matchExpressions:
- {key: app.kubernetes.io/name, operator: In, values: [{{ include "alertmanager.name" . }}]}
{{- else if eq .Values.podAntiAffinity "soft" }}
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
topologyKey: {{ .Values.podAntiAffinityTopologyKey }}
labelSelector:
matchExpressions:
- {key: app.kubernetes.io/name, operator: In, values: [{{ include "alertmanager.name" . }}]}
{{- end }}
{{- with .Values.priorityClassName }}
priorityClassName: {{ . }}
{{- end }}
{{- with .Values.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
{{- with .Values.extraInitContainers }}
initContainers:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
{{- if .Values.configmapReload.enabled }}
- name: {{ .Chart.Name }}-{{ .Values.configmapReload.name }}
image: "{{ .Values.configmapReload.image.repository }}:{{ .Values.configmapReload.image.tag }}"
imagePullPolicy: "{{ .Values.configmapReload.image.pullPolicy }}"
{{- with .Values.configmapReload.extraEnv }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
args:
{{- if and (hasKey .Values.configmapReload.extraArgs "config-file" | not) (hasKey .Values.configmapReload.extraArgs "watched-dir" | not) }}
- --watched-dir=/etc/alertmanager
{{- end }}
{{- if not (hasKey .Values.configmapReload.extraArgs "reload-url") }}
- --reload-url=http://127.0.0.1:9093/-/reload
{{- end }}
{{- range $key, $value := .Values.configmapReload.extraArgs }}
- --{{ $key }}={{ $value }}
{{- end }}
resources:
{{- toYaml .Values.configmapReload.resources | nindent 12 }}
{{- with .Values.configmapReload.containerPort }}
ports:
- containerPort: {{ . }}
{{- end }}
{{- with .Values.configmapReload.livenessProbe }}
livenessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.configmapReload.readinessProbe }}
readinessProbe:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.configmapReload.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
{{- if .Values.config.enabled }}
- name: config
mountPath: /etc/alertmanager
{{- end }}
{{- if .Values.configmapReload.extraVolumeMounts }}
{{- toYaml .Values.configmapReload.extraVolumeMounts | nindent 12 }}
{{- end }}
{{- end }}
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
{{- if .Values.extraEnv }}
{{- toYaml .Values.extraEnv | nindent 12 }}
{{- end }}
{{- with .Values.command }}
command:
{{- toYaml . | nindent 12 }}
{{- end }}
args:
- --storage.path=/alertmanager
{{- if not (hasKey .Values.extraArgs "config.file") }}
- --config.file=/etc/alertmanager/alertmanager.yml
{{- end }}
{{- if or (gt (int .Values.replicaCount) 1) (.Values.additionalPeers) }}
- --cluster.advertise-address=[$(POD_IP)]:{{ $svcClusterPort }}
- --cluster.listen-address=0.0.0.0:{{ $svcClusterPort }}
{{- end }}
{{- if gt (int .Values.replicaCount) 1}}
{{- $fullName := include "alertmanager.fullname" . }}
{{- range $i := until (int .Values.replicaCount) }}
- --cluster.peer={{ $fullName }}-{{ $i }}.{{ $fullName }}-headless:{{ $svcClusterPort }}
{{- end }}
{{- end }}
{{- if .Values.additionalPeers }}
{{- range $item := .Values.additionalPeers }}
- --cluster.peer={{ $item }}
{{- end }}
{{- end }}
{{- range $key, $value := .Values.extraArgs }}
- --{{ $key }}={{ $value }}
{{- end }}
{{- if .Values.baseURL }}
- --web.external-url={{ .Values.baseURL }}
{{- end }}
ports:
- name: {{ .Values.containerPortName }}
containerPort: 9093
protocol: TCP
{{- if or (gt (int .Values.replicaCount) 1) (.Values.additionalPeers) }}
- name: clusterpeer-tcp
containerPort: {{ $svcClusterPort }}
protocol: TCP
- name: clusterpeer-udp
containerPort: {{ $svcClusterPort }}
protocol: UDP
{{- end }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
{{- if .Values.config.enabled }}
- name: config
mountPath: /etc/alertmanager
{{- end }}
{{- range .Values.extraSecretMounts }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
subPath: {{ .subPath }}
readOnly: {{ .readOnly }}
{{- end }}
- name: storage
mountPath: /alertmanager
{{- if .Values.extraVolumeMounts }}
{{- toYaml .Values.extraVolumeMounts | nindent 12 }}
{{- end }}
{{- with .Values.extraContainers }}
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
{{- if .Values.config.enabled }}
- name: config
configMap:
name: {{ include "alertmanager.fullname" . }}
{{- end }}
{{- range .Values.extraSecretMounts }}
- name: {{ .name }}
secret:
secretName: {{ .secretName }}
{{- with .optional }}
optional: {{ . }}
{{- end }}
{{- end }}
{{- if .Values.extraVolumes }}
{{- toYaml .Values.extraVolumes | nindent 8 }}
{{- end }}
{{- if .Values.extraPodConfigs }}
{{- toYaml .Values.extraPodConfigs | nindent 6 }}
{{- end }}
{{- if .Values.persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: storage
{{- with .Values.persistence.annotations }}
annotations:
{{ toYaml . | nindent 14 }}
{{- end }}
{{- with .Values.persistence.labels }}
labels:
{{ toYaml . | nindent 14 }}
{{- end }}
spec:
accessModes:
{{- toYaml .Values.persistence.accessModes | nindent 10 }}
resources:
requests:
storage: {{ .Values.persistence.size }}
{{- if .Values.persistence.storageClass }}
{{- if (eq "-" .Values.persistence.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: {{ .Values.persistence.storageClass }}
{{- end }}
{{- end }}
{{- else }}
- name: storage
{{- with .Values.persistence.emptyDir }}
emptyDir:
{{- toYaml . | nindent 12 }}
{{- else }}
emptyDir: {}
{{- end -}}
{{- end }}
@@ -0,0 +1,20 @@
{{- if .Values.testFramework.enabled }}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "alertmanager.fullname" . }}-test-connection"
labels:
{{- include "alertmanager.labels" . | nindent 4 }}
{{- with .Values.testFramework.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
namespace: {{ include "alertmanager.namespace" . }}
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "alertmanager.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
{{- end }}
@@ -0,0 +1,26 @@
{{- if .Values.verticalPodAutoscaler.enabled }}
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: {{ include "alertmanager.fullname" . }}
namespace: {{ .Release.Namespace }}
spec:
{{- if .Values.verticalPodAutoscaler.recommenders }}
recommenders:
{{- range .Values.verticalPodAutoscaler.recommenders }}
- name: {{ .name }}
{{- end }}
{{- end }}
targetRef:
apiVersion: apps/v1
kind: StatefulSet
name: {{ include "alertmanager.fullname" . }}
{{- if .Values.verticalPodAutoscaler.updatePolicy }}
updatePolicy:
{{- toYaml .Values.verticalPodAutoscaler.updatePolicy | nindent 4 }}
{{- end }}
{{- if .Values.verticalPodAutoscaler.resourcePolicy }}
resourcePolicy:
{{- toYaml .Values.verticalPodAutoscaler.resourcePolicy | nindent 4 }}
{{- end }}
{{- end }}
@@ -0,0 +1,972 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "alertmanager",
"description": "The Alertmanager handles alerts sent by client applications such as the Prometheus server.",
"type": "object",
"required": [
"replicaCount",
"image",
"serviceAccount",
"service",
"persistence",
"config"
],
"definitions": {
"image": {
"description": "Container image parameters.",
"type": "object",
"required": ["repository"],
"additionalProperties": false,
"properties": {
"repository": {
"description": "Image repository. Path to the image with registry(quay.io) or without(prometheus/alertmanager) for docker.io.",
"type": "string"
},
"pullPolicy": {
"description": "Image pull policy. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.",
"type": "string",
"enum": [
"Never",
"IfNotPresent",
"Always"
],
"default": "IfNotPresent"
},
"tag": {
"description": "Use chart appVersion by default.",
"type": "string",
"default": ""
}
}
},
"resources": {
"description": "Resource limits and requests for the Container.",
"type": "object",
"properties": {
"limits": {
"description": "Resource limits for the Container.",
"type": "object",
"properties": {
"cpu": {
"description": "CPU request for the Container.",
"type": "string"
},
"memory": {
"description": "Memory request for the Container.",
"type": "string"
}
}
},
"requests": {
"description": "Resource requests for the Container.",
"type": "object",
"properties": {
"cpu": {
"description": "CPU request for the Container.",
"type": "string"
},
"memory": {
"description": "Memory request for the Container.",
"type": "string"
}
}
}
}
},
"securityContext": {
"description": "Security context for the container.",
"type": "object",
"properties": {
"capabilities": {
"description": "Specifies the capabilities to be dropped by the container.",
"type": "object",
"properties": {
"drop": {
"description": "List of capabilities to be dropped.",
"type": "array",
"items": {
"type": "string"
}
}
}
},
"readOnlyRootFilesystem": {
"description": "Specifies whether the root file system should be mounted as read-only.",
"type": "boolean"
},
"runAsUser": {
"description": "Specifies the UID (User ID) to run the container as.",
"type": "integer"
},
"runAsNonRoot": {
"description": "Specifies whether to run the container as a non-root user.",
"type": "boolean"
},
"runAsGroup": {
"description": "Specifies the GID (Group ID) to run the container as.",
"type": "integer"
}
}
},
"volumeMounts": {
"description": "List of volume mounts for the Container.",
"type": "array",
"items": {
"description": "Volume mounts for the Container.",
"type": "object",
"required": ["name", "mountPath"],
"properties": {
"name": {
"description": "The name of the volume to mount.",
"type": "string"
},
"mountPath": {
"description": "The mount path for the volume.",
"type": "string"
},
"readOnly": {
"description": "Specifies if the volume should be mounted in read-only mode.",
"type": "boolean"
}
}
}
},
"env": {
"description": "List of environment variables for the Container.",
"type": "array",
"items": {
"description": "Environment variables for the Container.",
"type": "object",
"required": ["name"],
"properties": {
"name": {
"description": "The name of the environment variable.",
"type": "string"
},
"value": {
"description": "The value of the environment variable.",
"type": "string"
}
}
}
},
"config": {
"description": "https://prometheus.io/docs/alerting/latest/configuration/",
"duration": {
"type": "string",
"pattern": "^((([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?|0)$"
},
"labelname": {
"type": "string",
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$|^...$"
},
"route": {
"description": "Alert routing configuration.",
"type": "object",
"properties": {
"receiver": {
"description": "The default receiver to send alerts to.",
"type": "string"
},
"group_by": {
"description": "The labels by which incoming alerts are grouped together.",
"type": "array",
"items": {
"type": "string",
"$ref": "#/definitions/config/labelname"
}
},
"continue": {
"description": "Whether an alert should continue matching subsequent sibling nodes.",
"type": "boolean",
"default": false
},
"matchers": {
"description": "A list of matchers that an alert has to fulfill to match the node.",
"type": "array",
"items": {
"type": "string"
}
},
"group_wait": {
"description": "How long to initially wait to send a notification for a group of alerts.",
"$ref": "#/definitions/config/duration"
},
"group_interval": {
"description": "How long to wait before sending a notification about new alerts that are added to a group of alerts for which an initial notification has already been sent.",
"$ref": "#/definitions/config/duration"
},
"repeat_interval": {
"description": "How long to wait before sending a notification again if it has already been sent successfully for an alert.",
"$ref": "#/definitions/config/duration"
},
"mute_time_intervals": {
"description": "Times when the route should be muted.",
"type": "array",
"items": {
"type": "string"
}
},
"active_time_intervals": {
"description": "Times when the route should be active.",
"type": "array",
"items": {
"type": "string"
}
},
"routes": {
"description": "Zero or more child routes.",
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/config/route"
}
}
}
}
}
},
"properties": {
"replicaCount": {
"description": "Number of desired pods.",
"type": "integer",
"default": 1,
"minimum": 0
},
"image": {
"description": "Container image parameters.",
"$ref": "#/definitions/image"
},
"baseURL": {
"description": "External URL where alertmanager is reachable.",
"type": "string",
"default": "",
"examples": [
"https://alertmanager.example.com"
]
},
"extraArgs": {
"description": "Additional alertmanager container arguments. Use args without '--', only 'key: value' syntax.",
"type": "object",
"default": {}
},
"extraSecretMounts": {
"description": "Additional Alertmanager Secret mounts.",
"type": "array",
"default": [],
"items": {
"type": "object",
"required": ["name", "mountPath", "secretName"],
"properties": {
"name": {
"type": "string"
},
"mountPath": {
"type": "string"
},
"subPath": {
"type": "string",
"default": ""
},
"secretName": {
"type": "string"
},
"readOnly": {
"type": "boolean",
"default": false
}
}
}
},
"imagePullSecrets": {
"description": "The property allows you to configure multiple image pull secrets.",
"type": "array",
"default": [],
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"description": "Specifies the Secret name of the image pull secret.",
"type": "string"
}
}
}
},
"nameOverride": {
"description": "Override value for the name of the Helm chart.",
"type": "string",
"default": ""
},
"fullnameOverride": {
"description": "Override value for the fully qualified app name.",
"type": "string",
"default": ""
},
"namespaceOverride": {
"description": "Override deployment namespace.",
"type": "string",
"default": ""
},
"automountServiceAccountToken": {
"description": "Specifies whether to automatically mount the ServiceAccount token into the Pod's filesystem.",
"type": "boolean",
"default": true
},
"hostUsers": {
"description": "Running within a user namespace, where the user IDs inside the container are mapped to different, usually unprivileged, user IDs on the host system.",
"type": "boolean",
"default": false
},
"serviceAccount": {
"description": "Contains properties related to the service account configuration.",
"type": "object",
"required": ["create"],
"properties": {
"create": {
"description": "Specifies whether a service account should be created.",
"type": "boolean",
"default": true
},
"annotations": {
"description": "Annotations to add to the service account.",
"type": "object",
"default": {}
},
"name": {
"description": "The name of the service account to use. If not set and create is true, a name is generated using the fullname template.",
"type": "string",
"default": ""
}
}
},
"schedulerName": {
"description": "Sets the schedulerName in the alertmanager pod.",
"type": "string",
"default": ""
},
"priorityClassName": {
"description": "Sets the priorityClassName in the alertmanager pod.",
"type": "string",
"default": ""
},
"podSecurityContext": {
"description": "Pod security context configuration.",
"type": "object",
"properties": {
"fsGroup": {
"description": "The fsGroup value for the pod's security context.",
"type": "integer",
"default": 65534
},
"runAsUser": {
"description": "The UID to run the pod's containers as.",
"type": "integer"
},
"runAsGroup": {
"description": "The GID to run the pod's containers as.",
"type": "integer"
}
}
},
"dnsConfig": {
"description": "DNS configuration for the pod.",
"type": "object",
"properties": {
"nameservers": {
"description": "List of DNS server IP addresses.",
"type": "array",
"items": {
"type": "string"
}
},
"searches": {
"description": "List of DNS search domains.",
"type": "array",
"items": {
"type": "string"
}
},
"options": {
"description": "List of DNS options.",
"type": "array",
"items": {
"description": "DNS options.",
"type": "object",
"required": ["name"],
"properties": {
"name": {
"description": "The name of the DNS option.",
"type": "string"
},
"value": {
"description": "The value of the DNS option.",
"type": "string"
}
}
}
}
}
},
"hostAliases": {
"description": "List of host aliases.",
"type": "array",
"items": {
"description": "Host aliases configuration.",
"type": "object",
"required": ["ip", "hostnames"],
"properties": {
"ip": {
"description": "IP address associated with the host alias.",
"type": "string"
},
"hostnames": {
"description": "List of hostnames associated with the IP address.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"securityContext": {
"description": "Security context for the container.",
"$ref": "#/definitions/securityContext"
},
"additionalPeers": {
"description": "Additional peers for a alertmanager.",
"type": "array",
"items": {
"type": "string"
}
},
"extraInitContainers": {
"description": "Additional InitContainers to initialize the pod.",
"type": "array",
"default": [],
"items": {
"required": ["name", "image"],
"properties": {
"name": {
"description": "The name of the InitContainer.",
"type": "string"
},
"image": {
"description": "The container image to use for the InitContainer.",
"type": "string"
},
"pullPolicy": {
"description": "Image pull policy. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.",
"type": "string",
"enum": [
"Never",
"IfNotPresent",
"Always"
],
"default": "IfNotPresent"
},
"command": {
"description": "The command to run in the InitContainer.",
"type": "array",
"items": {
"type": "string"
}
},
"args": {
"description": "Additional command arguments for the InitContainer.",
"type": "array",
"items": {
"type": "string"
}
},
"ports": {
"description": "List of ports to expose from the container.",
"type": "array",
"items": {
"type": "object"
}
},
"env": {
"description": "List of environment variables for the InitContainer.",
"$ref": "#/definitions/env"
},
"envFrom": {
"description": "List of sources to populate environment variables in the container.",
"type": "array",
"items": {
"type": "object"
}
},
"volumeMounts": {
"description": "List of volume mounts for the InitContainer.",
"$ref": "#/definitions/volumeMounts"
},
"resources": {
"description": "Resource requirements for the InitContainer.",
"$ref": "#/definitions/resources"
},
"securityContext": {
"$ref": "#/definitions/securityContext",
"description": "The security context for the InitContainer."
}
}
}
},
"extraContainers": {
"description": "Additional containers to add to the stateful set.",
"type": "array",
"default": [],
"items": {
"required": ["name", "image"],
"properties": {
"name": {
"description": "The name of the InitContainer.",
"type": "string"
},
"image": {
"description": "The container image to use for the InitContainer.",
"type": "string"
},
"pullPolicy": {
"description": "Image pull policy. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.",
"type": "string",
"enum": [
"Never",
"IfNotPresent",
"Always"
],
"default": "IfNotPresent"
},
"command": {
"description": "The command to run in the InitContainer.",
"type": "array",
"items": {
"type": "string"
}
},
"args": {
"description": "Additional command arguments for the InitContainer.",
"type": "array",
"items": {
"type": "string"
}
},
"ports": {
"description": "List of ports to expose from the container.",
"type": "array",
"items": {
"type": "object"
}
},
"env": {
"description": "List of environment variables for the InitContainer.",
"$ref": "#/definitions/env"
},
"envFrom": {
"description": "List of sources to populate environment variables in the container.",
"type": "array",
"items": {
"type": "object"
}
},
"volumeMounts": {
"description": "List of volume mounts for the InitContainer.",
"$ref": "#/definitions/volumeMounts"
},
"resources": {
"description": "Resource requirements for the InitContainer.",
"$ref": "#/definitions/resources"
},
"securityContext": {
"$ref": "#/definitions/securityContext",
"description": "The security context for the InitContainer."
}
}
}
},
"resources": {
"description": "Resource limits and requests for the pod.",
"$ref": "#/definitions/resources"
},
"containerPortName": {
"description": "Name of the port for the main container.",
"type": "string",
"default": "http"
},
"livenessProbe": {
"description": "Liveness probe configuration.",
"type": "object"
},
"readinessProbe": {
"description": "Readiness probe configuration.",
"type": "object"
},
"service": {
"description": "Service configuration.",
"type": "object",
"required": ["type", "port"],
"properties": {
"annotations": {
"description": "Annotations to add to the service.",
"type": "object"
},
"type": {
"description": "Service type.",
"type": "string"
},
"port": {
"description": "Port number for the service.",
"type": "integer"
},
"clusterPort": {
"description": "Port number for the cluster.",
"type": "integer"
},
"loadBalancerIP": {
"description": "External IP to assign when the service type is LoadBalancer.",
"type": "string"
},
"loadBalancerSourceRanges": {
"description": "IP ranges to allow access to the loadBalancerIP.",
"type": "array",
"items": {
"type": "string"
}
},
"nodePort": {
"description": "Specific nodePort to force when service type is NodePort.",
"type": "integer"
}
}
},
"ingress": {
"description": "Ingress configuration.",
"type": "object",
"properties": {
"enabled": {
"description": "Indicates if Ingress is enabled.",
"type": "boolean"
},
"className": {
"description": "Ingress class name.",
"type": "string"
},
"annotations": {
"description": "Annotations to add to the Ingress.",
"type": "object"
},
"hosts": {
"description": "Host and path configuration for the Ingress.",
"type": "array",
"items": {
"type": "object",
"properties": {
"host": {
"description": "Host name for the Ingress.",
"type": "string"
},
"paths": {
"description": "Path configuration for the Ingress.",
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"description": "Path for the Ingress.",
"type": "string"
},
"pathType": {
"description": "Path type for the Ingress.",
"type": "string"
}
}
}
}
}
}
},
"tls": {
"description": "TLS configuration for the Ingress.",
"type": "array",
"items": {
"type": "object",
"properties": {
"secretName": {
"description": "Name of the secret for TLS.",
"type": "string"
},
"hosts": {
"description": "Host names for the TLS configuration.",
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"nodeSelector": {
"description": "Node selector for pod assignment.",
"type": "object"
},
"tolerations": {
"description": "Tolerations for pod assignment.",
"type": "array"
},
"affinity": {
"description": "Affinity rules for pod assignment.",
"type": "object"
},
"podAntiAffinity": {
"description": "Pod anti-affinity configuration.",
"type": "string",
"enum": ["", "soft", "hard"],
"default": ""
},
"podAntiAffinityTopologyKey": {
"description": "Topology key to use for pod anti-affinity.",
"type": "string"
},
"topologySpreadConstraints": {
"description": "Topology spread constraints for pod assignment.",
"type": "array",
"items": {
"type": "object",
"required": ["maxSkew", "topologyKey", "whenUnsatisfiable", "labelSelector"],
"properties": {
"maxSkew": {
"type": "integer"
},
"topologyKey": {
"type": "string"
},
"whenUnsatisfiable": {
"type": "string",
"enum": ["DoNotSchedule", "ScheduleAnyway"]
},
"labelSelector": {
"type": "object",
"required": ["matchLabels"],
"properties": {
"matchLabels": {
"type": "object"
}
}
}
}
}
},
"statefulSet": {
"description": "StatefulSet configuration for managing pods.",
"type": "object",
"properties": {
"annotations": {
"type": "object"
}
}
},
"podAnnotations": {
"description": "Annotations to add to the pods.",
"type": "object"
},
"podLabels": {
"description": "Labels to add to the pods.",
"type": "object"
},
"podDisruptionBudget": {
"description": "Pod disruption budget configuration.",
"type": "object",
"properties": {
"maxUnavailable": {
"type": "integer"
},
"minAvailable": {
"type": "integer"
}
}
},
"command": {
"description": "The command to be executed in the container.",
"type": "array",
"items": {
"type": "string"
}
},
"persistence": {
"description": "Persistence configuration for storing data.",
"type": "object",
"required": ["enabled", "size"],
"properties": {
"enabled": {
"type": "boolean"
},
"storageClass": {
"type": "string"
},
"accessModes": {
"type": "array",
"items": {
"type": "string"
}
},
"size": {
"type": "string"
},
"annotations": {
"type": "object",
"description": "Custom annotations to apply to the PersistentVolumeClaim created by the Alertmanager StatefulSet.",
"additionalProperties": {
"type": "string"
},
"default": {}
},
"labels": {
"type": "object",
"description": "Custom labels to apply to the PersistentVolumeClaim created by the Alertmanager StatefulSet.",
"additionalProperties": {
"type": "string"
},
"default": {}
}
}
},
"configAnnotations": {
"description": "Annotations to be added to the Alertmanager configuration.",
"type": "object"
},
"config": {
"description": "Alertmanager configuration.",
"type": "object",
"properties": {
"enabled": {
"description": "Whether to create alermanager configmap or not.",
"type": "boolean"
},
"global": {
"description": "Global configuration options.",
"type": "object"
},
"templates": {
"description": "Alertmanager template files.",
"type": "array",
"items": {
"type": "string"
}
},
"receivers": {
"description": "Alert receivers configuration.",
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"description": "The unique name of the receiver.",
"type": "string"
}
}
}
},
"route": {
"description": "Alert routing configuration.",
"type": "object",
"$ref": "#/definitions/config/route"
}
}
},
"configmapReload": {
"description": "Monitors ConfigMap changes and POSTs to a URL.",
"type": "object",
"properties": {
"enabled": {
"description": "Specifies whether the configmap-reload container should be deployed.",
"type": "boolean",
"default": false
},
"name": {
"description": "The name of the configmap-reload container.",
"type": "string"
},
"image": {
"description": "The container image for the configmap-reload container.",
"$ref": "#/definitions/image"
},
"containerPort": {
"description": "Port number for the configmap-reload container.",
"type": "integer"
},
"resources": {
"description": "Resource requests and limits for the configmap-reload container.",
"$ref": "#/definitions/resources"
}
}
},
"templates": {
"description": "Custom templates used by Alertmanager.",
"type": "object"
},
"extraVolumeMounts": {
"description": "List of volume mounts for the Container.",
"$ref": "#/definitions/volumeMounts"
},
"extraVolumes": {
"description": "Additional volumes to be mounted in the Alertmanager pod.",
"type": "array",
"default": [],
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
}
}
}
},
"extraEnv": {
"description": "List of environment variables for the Container.",
"$ref": "#/definitions/env"
},
"testFramework": {
"description": "Configuration for the test Pod.",
"type": "object",
"properties": {
"enabled": {
"description": "Specifies whether the test Pod is enabled.",
"type": "boolean",
"default": false
},
"annotations": {
"description": "Annotations to be added to the test Pod.",
"type": "object"
}
}
},
"verticalPodAutoscaler": {
"description": "Vertical Pod Autoscaling configuration.",
"type": "object",
"properties": {
"enabled": {
"type": "boolean",
"default": false
},
"recommenders": {
"type": "array"
},
"updatePolicy": {
"type": "object"
},
"resourcePolicy": {
"type": "object"
}
}
},
"extraPodConfigs": {
"description": "Object to allow users to add additional Pod configuration like dnsPolicy or hostNetwork",
"type": "object"
}
}
}
@@ -0,0 +1,455 @@
# yaml-language-server: $schema=values.schema.json
# Default values for alertmanager.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
# Number of old history to retain to allow rollback
# Default Kubernetes value is set to 10
revisionHistoryLimit: 10
image:
repository: quay.io/prometheus/alertmanager
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
# Full external URL where alertmanager is reachable, used for backlinks.
baseURL: ""
extraArgs: {}
## Additional Alertmanager Secret mounts
# Defines additional mounts with secrets. Secrets must be manually created in the namespace.
extraSecretMounts: []
# - name: secret-files
# mountPath: /etc/secrets
# subPath: ""
# secretName: alertmanager-secret-files
# readOnly: true
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
## namespaceOverride overrides the namespace which the resources will be deployed in
namespaceOverride: ""
automountServiceAccountToken: true
## Running within a user namespace.
# Kubernetes server must be at or later than version v1.25.
# Kubernetes v1.25 through to v1.27 recognise UserNamespacesStatelessPodsSupport.
# Kubernetes v1.28 through to v1.32 need to enable the UserNamespacesSupport feature gate.
hostUsers: false
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
# Sets priorityClassName in alertmanager pod
priorityClassName: ""
# Sets schedulerName in alertmanager pod
schedulerName: ""
podSecurityContext:
fsGroup: 65534
dnsConfig: {}
# nameservers:
# - 1.2.3.4
# searches:
# - ns1.svc.cluster-domain.example
# - my.dns.search.suffix
# options:
# - name: ndots
# value: "2"
# - name: edns0
hostAliases: []
# - ip: "127.0.0.1"
# hostnames:
# - "foo.local"
# - "bar.local"
# - ip: "10.1.2.3"
# hostnames:
# - "foo.remote"
# - "bar.remote"
securityContext:
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
runAsUser: 65534
runAsNonRoot: true
runAsGroup: 65534
additionalPeers: []
## Additional InitContainers to initialize the pod
##
extraInitContainers: []
## Additional containers to add to the stateful set. This will allow to setup sidecarContainers like a proxy to integrate
## alertmanager with an external tool like teams that has not direct integration.
##
extraContainers: []
containerPortName: &containerPortName http
livenessProbe:
httpGet:
path: /
port: *containerPortName
readinessProbe:
httpGet:
path: /
port: *containerPortName
service:
annotations: {}
labels: {}
type: ClusterIP
port: 9093
clusterPort: 9094
loadBalancerIP: "" # Assign ext IP when Service type is LoadBalancer
loadBalancerSourceRanges: [] # Only allow access to loadBalancerIP from these IPs
# if you want to force a specific nodePort. Must be use with service.type=NodePort
# nodePort:
# Optionally specify extra list of additional ports exposed on both services
extraPorts: []
# ip dual stack
ipDualStack:
enabled: false
ipFamilies: ["IPv6", "IPv4"]
ipFamilyPolicy: "PreferDualStack"
# Configuration for creating a separate Service for each statefulset Alertmanager replica
#
servicePerReplica:
enabled: false
annotations: {}
# Loadbalancer source IP ranges
# Only used if servicePerReplica.type is "LoadBalancer"
loadBalancerSourceRanges: []
# Denotes if this Service desires to route external traffic to node-local or cluster-wide endpoints
#
externalTrafficPolicy: Cluster
# Service type
#
type: ClusterIP
serviceMonitor:
enabled: false
namespace: ""
additionalLabels: {}
interval: ""
scrapeTimeout: ""
path: /metrics
scheme: ""
tlsConfig: {}
bearerTokenFile: ""
basicAuth: {}
honorLabels: false
metricRelabelings: []
relabelings: []
ingress:
enabled: false
className: ""
labels: {}
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: alertmanager.domain.com
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - alertmanager.domain.com
# Configuration for creating an Ingress that will map to each Alertmanager replica service
# alertmanager.servicePerReplica must be enabled
#
ingressPerReplica:
enabled: false
# className for the ingresses
#
className: ""
annotations: {}
labels: {}
# Final form of the hostname for each per replica ingress is
# {{ ingressPerReplica.hostPrefix }}-{{ $replicaNumber }}.{{ ingressPerReplica.hostDomain }}
#
# Prefix for the per replica ingress that will have `-$replicaNumber`
# appended to the end
hostPrefix: "alertmanager"
# Domain that will be used for the per replica ingress
hostDomain: "domain.com"
# Paths to use for ingress rules
#
paths:
- /
# PathType for ingress rules
#
pathType: ImplementationSpecific
# Secret name containing the TLS certificate for alertmanager per replica ingress
# Secret must be manually created in the namespace
tlsSecretName: ""
# Separated secret for each per replica Ingress. Can be used together with cert-manager
#
tlsSecretPerReplica:
enabled: false
# Final form of the secret for each per replica ingress is
# {{ tlsSecretPerReplica.prefix }}-{{ $replicaNumber }}
#
prefix: "alertmanager"
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 10m
# memory: 32Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Pod anti-affinity can prevent the scheduler from placing Alertmanager replicas on the same node.
## The default value "soft" means that the scheduler should *prefer* to not schedule two replica pods onto the same node but no guarantee is provided.
## The value "hard" means that the scheduler is *required* to not schedule two replica pods onto the same node.
## The value "" will disable pod anti-affinity so that no anti-affinity rules will be configured.
##
podAntiAffinity: ""
## If anti-affinity is enabled sets the topologyKey to use for anti-affinity.
## This can be changed to, for example, failure-domain.beta.kubernetes.io/zone
##
podAntiAffinityTopologyKey: kubernetes.io/hostname
## Topology spread constraints rely on node labels to identify the topology domain(s) that each Node is in.
## Ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
topologySpreadConstraints: []
# - maxSkew: 1
# topologyKey: failure-domain.beta.kubernetes.io/zone
# whenUnsatisfiable: DoNotSchedule
# labelSelector:
# matchLabels:
# app.kubernetes.io/instance: alertmanager
statefulSet:
annotations: {}
## 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 from kubernetes 1.22 until 1.24 which requires enabling the StatefulSetMinReadySeconds
## feature gate.
## Ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#minimum-ready-seconds
minReadySeconds: 0
podAnnotations: {}
podLabels: {}
# Ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/
podDisruptionBudget: {}
# maxUnavailable: 1
# minAvailable: 1
command: []
persistence:
## If true, storage will create or use Persistence Volume
## If false, storage will use emptyDir
##
enabled: true
## Custom annotations for the PVC created by the alertmanager StatefulSet.
## Useful for configuring storage provider options such as disk type, KMS encryption keys, or custom volume name prefixes.
annotations: {}
## Custom labels for the PVC created by the alertmanager StatefulSet.
## Useful for selecting, grouping, and organizing so that they can be queried or targeted in deployments, policies, etc.
labels: {}
## Persistent Volume Storage Class
## If defined, storageClassName: <storageClass>
## If set to "-", storageClassName: "", which disables dynamic provisioning
## If undefined (the default) or set to null, no storageClassName spec is
## set, choosing the default provisioner.
##
# storageClass: "-"
accessModes:
- ReadWriteOnce
size: 50Mi
## Configure emptyDir volume
##
emptyDir: {}
configAnnotations: {}
## For example if you want to provide private data from a secret vault
## https://github.com/banzaicloud/bank-vaults/tree/main/charts/vault-secrets-webhook
## P.s.: Add option `configMapMutation: true` for vault-secrets-webhook
# vault.security.banzaicloud.io/vault-role: "admin"
# vault.security.banzaicloud.io/vault-addr: "https://vault.vault.svc.cluster.local:8200"
# vault.security.banzaicloud.io/vault-skip-verify: "true"
# vault.security.banzaicloud.io/vault-path: "kubernetes"
## Example for inject secret
# slack_api_url: '${vault:secret/data/slack-hook-alerts#URL}'
config:
enabled: true
global: {}
# slack_api_url: ''
templates:
- '/etc/alertmanager/*.tmpl'
receivers:
- name: default-receiver
# slack_configs:
# - channel: '@you'
# send_resolved: true
route:
group_wait: 10s
group_interval: 5m
receiver: default-receiver
repeat_interval: 3h
## Monitors ConfigMap changes and POSTs to a URL
## Ref: https://github.com/prometheus-operator/prometheus-operator/tree/main/cmd/prometheus-config-reloader
##
configmapReload:
## If false, the configmap-reload container will not be deployed
##
enabled: false
## configmap-reload container name
##
name: configmap-reload
## configmap-reload container image
##
image:
repository: quay.io/prometheus-operator/prometheus-config-reloader
tag: v0.91.0
pullPolicy: IfNotPresent
# containerPort: 9533
## configmap-reload resource requests and limits
## Ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources: {}
livenessProbe: {}
# httpGet:
# path: /healthz
# port: 8080
# scheme: HTTP
readinessProbe: {}
# httpGet:
# path: /healthz
# port: 8080
# scheme: HTTP
extraArgs: {}
## Optionally specify extra list of additional volumeMounts
extraVolumeMounts: []
# - name: extras
# mountPath: /usr/share/extras
# readOnly: true
## Optionally specify extra environment variables to add to alertmanager container
extraEnv: []
# - name: FOO
# value: BAR
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsUser: 65534
# runAsNonRoot: true
# runAsGroup: 65534
templates: {}
# alertmanager.tmpl: |-
## Optionally specify extra list of additional volumeMounts
extraVolumeMounts: []
# - name: extras
# mountPath: /usr/share/extras
# readOnly: true
## Optionally specify extra list of additional volumes
extraVolumes: []
# - name: extras
# emptyDir: {}
## Optionally specify extra environment variables to add to alertmanager container
extraEnv: []
# - name: FOO
# value: BAR
testFramework:
enabled: false
annotations:
"helm.sh/hook": test-success
# "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
# --- Vertical Pod Autoscaler
verticalPodAutoscaler:
# -- Use VPA for alertmanager
enabled: false
# recommenders:
# - name: 'alternative'
# updatePolicy:
# updateMode: "Auto"
# minReplicas: 1
# resourcePolicy:
# containerPolicies:
# - containerName: '*'
# minAllowed:
# cpu: 100m
# memory: 128Mi
# maxAllowed:
# cpu: 1
# memory: 500Mi
# controlledResources: ["cpu", "memory"]
# --- Extra Pod Configs
extraPodConfigs: {}
# dnsPolicy: ClusterFirstWithHostNet
# hostNetwork: true