Продовжуємо розвивати наш стек моніторингу. Див. VictoriaMetrics: створення Kubernetes monitoring stack з власним Helm-чартом.
Що хочеться: зробити доступ девелоперам, щоб вони могли в Alertmanager самі виставляти Silence для алертів аби не спамити в Slack, див. Prometheus: Alertmanager Web UI и Silence алертов.
Для того, щоб забезпечити безпечний доступ до нього можна використати рішення від VictoriaMetrics – компонент VMAuth, який дозволяє створити єдиний ендпоінт, через який будуть ходити всі юзери і налаштувати відповідні бекенди для інших компонентів кластеру.
Кратко – що можна з VMAuth:
- створити єдину точку входу для сервісів з Basic або Bearer user аутентифікацією та авторизацією
- в залежності від юзера та роута/URI направляти його до відповідного сервіса (фактично, ви можете створити один Ingress і всі запити обслуговувати через нього замість того, щоб створювати Ingress та аутентифікацію для кожного сервіса окремо)
- мати простий round-robin load balancer
- налаштувати IP фільтри з Allow та Deny листами
- керувати додаванням власних хедерів до запитів
Деплоїти будемо у AWS EKS з Helm-чарту victoria-metrics-auth, але можна робити через yaml-маніфести, див. документацію та інші приклади на Authorization and exposing components та VMAuth.
Зміст
Встановлення чарту VMAuth
Так як ми маємо umbrella-chart, то додаємо в Chart.yaml
в блок dependecy
новий сабчарт:
... - name: victoria-metrics-auth version: ~0.3.3 repository: https://victoriametrics.github.io/helm-charts/ ...
Дефолтні вальюси – values.yaml.
У власних values.yaml
описуємо конфіг VMAuth – створення Ingress, ім’я користувача, пароль, та куди перенаправляти його запити – тут це буде Kubernetes Service для Alertmanager:
... victoria-metrics-auth: ingress: enabled: true annotations: kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:49***148:certificate/66e3050e-7f27-4f0c-8ad4-0733a6d8071a alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}, {"HTTP":80}]' alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=600 hosts: - name: vmauth.dev.example.co path: / port: http config: users: - username: "vmadmin" password: "p@ssw0rd" url_prefix: "http://vmalertmanager-vm-k8s-stack.dev-monitoring-ns.svc:9093" ...
Вновлюмо Helm dependency:
[simterm]
$ helm dependency update
[/simterm]
І деплоїмо чарт:
[simterm]
$ helm -n dev-monitoring-ns upgrade --install atlas-victoriametrics . -f values/dev/atlas-monitoring-dev-values.yaml
[/simterm]
Перевіряємо чи додався Ingress і AWS ALB до нього:
[simterm]
$ kk -n dev-monitoring-ns get ingress NAME CLASS HOSTS ADDRESS PORTS AGE atlas-victoriametrics-victoria-metrics-auth <none> vmauth.dev.example.co k8s-***elb.amazonaws.com 80 3m12s
[/simterm]
Чекаємо поки оновляться DNS, і відкриваємо https://vmauth.dev.example.co:
Логінимось, і попадаємо прямо в Алертменеджер:
Конфіг в Kubernetes Secret
Замість того, щоб тримати конфіг в values чарту можно створити Kubernetes Secret. Це додатково дасть можливість передавати пароль, якщо він у вас один, через helm install --set
:
apiVersion: v1 kind: Secret metadata: name: vmauth-config-secret stringData: auth.yml: |- users: - username: vmadmin password: {{ .Values.vmauth_password }} url_map: url_prefix: http://vmalertmanager-vm-k8s-stack.dev-monitoring-ns.svc:9093/
VMAuth, users та routes
Є можливість створити одного користувача, і з url_map
йому налаштувати кілька роутів – в залежності від URI запиту, він буде перенаправлений на відповідний бекенд, а з default_url
задати URL, куди будуть перенаравлені запроси, для яких не задано роута. При цьому в роутах можна використовувати регулярки.
Наприклад:
... users: - username: vmadmin password: {{ .Values.vmauth_password }} url_map: - src_paths: - /alertmanager.* url_prefix: http://vmalertmanager-vm-k8s-stack.dev-monitoring-ns.svc:9093/ - src_paths: - /vmui.* url_prefix: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429 default_url: - https://google.com
Якщо плануєте додавати доступ до інстансу VMSingle – додайте блок для Prometheus, бо інакше будуть помилки виду:
{“ts”:”2023-08-22T14:37:43.363Z”,”level”:”warn”,”caller”:”VictoriaMetrics/app/vmauth/main.go:159″,”msg”:”remoteAddr: \”10.0.0.74:25806, X-Forwarded-For: 217.***.***.253\”; requestURI: /prometheus/vmui/custom-dashboards; missing route for \”/prometheus/v
mui/custom-dashboards\””}
{“ts”:”2023-08-22T14:37:43.396Z”,”level”:”warn”,”caller”:”VictoriaMetrics/app/vmauth/main.go:159″,”msg”:”remoteAddr: \”10.0.0.74:25806, X-Forwarded-For: ***.***.165.253\”; requestURI: /prometheus/api/v1/label/__name__/values; missing route for \”/promet
heus/api/v1/label/__name__/values\””}
Для Prometheus блок виглядає аналогічно:
... - src_paths: - /prometheus.* url_prefix: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429
Для того, щоб сам Alertmanager працював через URI /alertmanager
– в його values налаштовуємо routePrefix
:
... alertmanager: enabled: true spec: configSecret: "alertmanager-config" routePrefix: "/alertmanager" ...
І не забудьте в такому випадку змінити дефолтний URL для VMAlert у його values:
... vmalert: annotations: {} enabled: true spec: notifier: url: "http://vmalertmanager-vm-k8s-stack.dev-monitoring-ns.svc:9093/alertmanager" ...
Деплоїмо зміни, а щоб застосувати зміни конфіг в самому інстансі VMAuth, виконуємо запит до ендпоінту /-/reload
, тобто – https://vmauth.dev.example.co/-/reload.
Тепер Alertmanager доступний за адресою https://vmauth.dev.example.co/alertmanager:
Насправді, настройка src_paths
може бути трохи геморною, бо, наприклад, в документації роути вказані просто як /uri/path
:
url_map: - src_paths: - /api/v1/query - /api/v1/query_range
Але коли я почав це робити, то виявилось, що при виконанні редіректу з VMAuth на внутрішній сервіс в кінці додається зайвий слеш, і доступ до Alertmanager не працював.
Саме тому в моїх прикладах вище роути задані з “.*
“.
Години дві спілкувався з саппортом в VictoriaMetrcis Slack, намагались знайти причину проблем з доступом к Alertmanager, наче знайшли, завів GitHub issue, подивимось, як воно буде далі.
Взагалі, підтримку VictoriaMetrics варто згадати окремо, бо працює вона чудово і досить швидко. Є Slack, є Telegram-канал.
Basic Auth vs Bearer token
Замість звичайного логіна:пароля можемо використати ServiceAccount токен.
Створюємо ServiceAccount та Secret для нього з типом kubernetes.io/service-account-token
:
apiVersion: v1 kind: ServiceAccount metadata: name: vmauth-sa namespace: dev-monitoring-ns secrets: - name: vmauth-token-secret --- apiVersion: v1 kind: Secret metadata: name: vmauth-token-secret namespace: dev-monitoring-ns annotations: kubernetes.io/service-account.name: vmauth-sa type: kubernetes.io/service-account-token
Деплоїмо, отримуємо токен для цього ServicAccount:
[simterm]
$ kk -n dev-monitoring-ns create token vmauth-sa eyJhbGciOi***gfeNGWVjJn5-LWd2aslxAwnUTpQ
[/simterm]
Додаємо bearer_token
в конфіг VMAuth:
... users: - username: vmadmin password: {{ .Values.vmauth_password }} url_map: - src_paths: - /alertmanager.* url_prefix: http://vmalertmanager-vm-k8s-stack.dev-monitoring-ns.svc:9093 - src_paths: - /vmui.* url_prefix: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429 - src_paths: - /prometheus.* url_prefix: http://vmsingle-vm-k8s-stack.dev-monitoring-ns.svc:8429 - bearer_token: "eyJhbGciOiJSUzI1NiIsImtpZ***gfeNGWVjJn5-LWd2aslxAwnUTpQ" url_prefix: http://vmalertmanager-vm-k8s-stack.dev-monitoring-ns.svc:9093
Деплоїмо, знов робимо /-/reload
, та перевіряємо доступ.
Заносимо токен в змінну:
[simterm]
$ token="eyJhbGciOiJSUzI1NiIsImt***-LWd2aslxAwnUTpQ"wnUTpQ
[/simterm]
І з curl
відкриваємо ендпоінт:
[simterm]
$ curl -H "Authorization: Bearer ${token}" https://vmauth.dev.example.co/ <a href="/alertmanager">Found</a>.
[/simterm]
VMAuth та “AnyService”
Ну і на останнє – VMAuth можна використовувати для аутентифікації не тільки VictoriaMetrics та її сервісів, а (майже) будь-яких.
Наприклад, маємо под з Nginx Demo:
apiVersion: v1 kind: Pod metadata: name: my-pod labels: app: my-pod spec: containers: - name: my-container image: nginxdemos/hello --- apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: my-pod ports: - protocol: TCP port: 80 targetPort: 80
У VMAuth додаємо роут:
... - src_paths: - /nginxdemo.* url_prefix: http://my-service.default.svc:80
І тепер за адресою https://vmauth.dev.example.co/nginxdemo попадаемо на Nginx:
А от для стандартної Kubernetes Dashboard так не вийде, бо вона використовує self-signed TLS сертифиікат, і VMAuth не підключається до відповідного сервісу, бо не може провалідувати сертификат. Можливо, є рішення, але не шукав, бо в принципі не потрібно.
VMAuth Self-Security
Див. документацію.
Закрийте аутентифікацією “службові” роути самого VMAuth.
У values.yaml
додаємо ключі:
... extraArgs: reloadAuthKey: password flagsAuthKey: password metricsAuthKey: password pprofAuthKey: password ...
Деплоїмо, і тепер якщо викликати /-/reload
без ключа – буде помилка:
[simterm]
$ curl https://vmauth.dev.example.co/-/reload The provided authKey doesn't match -reloadAuthKey
[/simterm]
Щоб передати ключ для аутентифікації – використовуємо форму /-/reload?authKey=password
:
[simterm]
$ curl -I https://vmauth.dev.example.co/-/reload?authKey=password HTTP/2 200
[/simterm]
Поки що наче немає можливості передачи ключі через Kubertes Secret, тільки хардкодити у values.yaml
, але вже є фіча-реквест.