1. Теория — разбор Traefik

Traefik – это обратный прокси с поддержкой Docker, который предоставляет встроенную панель мониторинга.




Проект Traefik предоставляет официальный образ Docker, который поможет быстро запустить Traefik в контейнере Docker.




Но прежде чем запустить контейнер Traefik, нужно создать конфигурационный файл и настроить зашифрованный пароль, чтобы получить доступ к панели мониторинга.
данные действия мы выполнили в предыдущей статье.
Панель инструментов представляет собой отдельное веб-приложение, которое будет работать в контейнере Traefik по порту 8080.




1: Настройка и запуск Traefik




Используйте утилиту htpasswd, чтобы создать зашифрованный пароль. Установите утилиту, которая входит в пакет httpd-tools.




yum install -y httpd-tools




Затем сгенерируйте пароль с помощью htpasswd. Замените secure_password паролем, который вы хотите использовать для пользователя администратора Traefik:




htpasswd -nb admin secure_password
admin:$apr1$kEG/8JKj$yEXj8vKO7HDvkUMI/SbOO.




Этот вывод используется в конфигурационном файле Traefic для настройки базовой аутентификации HTTP в панели мониторинга Traefik. Скопируйте всю строку, чтобы затем вставить ее в файл.




Чтобы настроить сервер Traefik, создайте файл traefik.toml в формате TOML. TOML – это стандартизированный язык конфигурации (аналогичный INI-файлам). Этот файл позволяет настроить сервер Traefik и дополнительные провайдеры. В этом мануале используются три доступных провайдера Traefik: api, docker и acme, который нужен для поддержки TLS сертификатов Let’s Encrypt.




Откройте файл:




vi traefik.toml




Перейдите в режим вставки, нажав i, а затем добавьте две именованные точки входа, http и https, доступ к которым будет у всех бэкендов по умолчанию.




defaultEntryPoints = ["http", "https"]




Точки http и https будут настроены немного позже.




Настройте провайдер api, который дает доступ к интерфейсу панели мониторинга. Здесь нужно использовать строку, сгенерированную командой htpasswd:




...
[entryPoints]
[entryPoints.dashboard]
address = ":8080"
[entryPoints.dashboard.auth]
[entryPoints.dashboard.auth.basic]
users = ["admin:your_encrypted_password"]
[api]
entrypoint="dashboard"




Панель инструментов представляет собой отдельное веб-приложение, которое будет работать в контейнере Traefik по порту 8080.




Раздел entrypoints.dashboard настраивает подключение с провайдером api.




Раздел entrypoints.dashboard.auth.basic настраивает базовую аутентификацию HTTP для дашборда.




Вставьте вместо your_encrypted_password строку, сгенерированную утилитой htpasswd. Вы можете указать несколько пар учетных данных, разделив их запятыми.




Итак, мы определили первую точку входа, entryPoint, но для стандартного взаимодействия HTTP и HTTPS нужны другие точки.




Раздел entryPoints настраивает адрес, который будут слушать Traefik и контейнеры. Добавьте в файл строки:




...
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
...




Точка входа http обрабатывает порт 80, а точка входа https использует порт 443 для поддержки TLS/SSL. Весь трафик, поступающий по порту 80, будет автоматически перенаправлен в точку входа https, чтобы все запросы обслуживались только по защищенным соединениям.




Затем добавьте следующий раздел, чтобы настроить сертификат Let’s Encrypt для Traefik.




...
[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"




Этот раздел называется acme, потому что ACME – это протокол, с помощью которого сервер взаимодействует с Let’s Encrypt для управления сертификатами. Чтобы Traefik создавал сертификаты для хостов, укажите в строке email свой адрес электронной почты. Затем нужно указать, что хранить информацию Let’s Encrypt нужно в файле JSON, acme.json. В строке entryPoint должен быть порт обработки точки входа 443 (в данном случае это точка входа https).




Ключ onHostRule определяет, как Traefik будет генерировать сертификаты. Сертификаты должны появиться сразу, как только будут созданы контейнеры с указанными именами хостов; за это отвечает параметр onHostRule.




В разделе acme.httpChallenge нужно указать, как Let’s Encrypt будет определять, что сертификат должен быть сгенерирован. Мы настроим его для обслуживания файла в рамках задачи через точку входа http.




Теперь добавьте настройки провайдера docker:




...
[docker]
domain = "your_domain"
watch = true
network = "web"




Провайдер Docker включает Traefik в качестве прокси-сервера для контейнеров Docker. Провайдер будет следить (строка watch) за новыми контейнерами в сети, которые мы скоро создадим, и выставлять их как субдомены your_domain.




На этом этапе файл traefik.toml должен выглядеть так:




defaultEntryPoints = ["http", "https"]
[entryPoints]
[entryPoints.dashboard]
address = ":8080"
[entryPoints.dashboard.auth]
[entryPoints.dashboard.auth.basic]
users = ["admin:your_encrypted_password"]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[api]
entrypoint="dashboard"
[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
[docker]
domain = "your_domain"
watch = true
network = "web"




Сохраните и закройте файл.




2: Запуск контейнера Traefik




Создайте сеть Docker для поддержки взаимодействия прокси-сервера и контейнеров. Сеть Docker необходима, так как ее можно использовать для работы с приложениями, запущенными в Docker Compose. Для примера можно назвать такую сеть web.




docker network create web




Когда контейнер Traefik будет запущен, нужно будет добавить его в эту сеть. Позже можно добавить в эту сеть дополнительные контейнеры, чтобы использовать Traefik в качестве прокси-сервера для этих контейнеров.




Затем создайте пустой файл, в котором будет храниться информация о шифровании Let’s Encrypt. Добавьте его в контейнер, чтобы Traefik мог его использовать.




touch acme.json




Затем заблокируйте доступ к файлу, чтобы только пользователь root мог читать и изменять его. Если вы этого не сделаете, Traefik не получится запустить.




chmod 600 acme.json




Когда файл будет передан Docker, права собственности автоматически перейдут пользователю root внутри контейнера.




Создайте контейнер Traefik с помощью команды:




docker run -d
-v /var/run/docker.sock:/var/run/docker.sock
-v $PWD/traefik.toml:/traefik.toml
-v $PWD/acme.json:/acme.json
-p 80:80
-p 443:443
-l traefik.frontend.rule=Host:monitor.your_domain
-l traefik.port=8080
--network web
--name traefik
traefik:1.7.6-alpine




Рассмотрим команду по частям:




  • Флаг –d запускает контейнер в фоновом режиме как демон. Затем команда добавляет в контейнер файл docker.sock, благодаря чему процесс Traefik может прослушивать изменения в контейнерах. Также в контейнер можно поместить конфигурационный файл traefik.toml и acme.json.



  • После этого порты 80 и 443 хоста Docker подключаются к одному и тому же порту в контейнере Traefik. Теперь Traefik получает все запросы HTTP и HTTPS.



  • Затем нужно установить две метки Docker, которые будут направлять трафик на хост monitor.your_domain по порту :8080 внутри контейнера Traefik, открывая дашборд.



  • В качестве сети контейнера нужно указать web. Контейнер называется traefik.



  • Затем для создания контейнера используется образ traefik:1.7.6-alpine.




ENTRYPOINT образа Docker – это команда, которая запускается всегда, когда контейнер создается из образа. В этом случае команда представляет собой бинарный файл traefik внутри контейнера. Вы можете передать дополнительные аргументы этой команде при запуске контейнера, но все необходимые данные мы уже указали в файле traefik.toml.




После запуска контейнера у вас будет дашборд, с помощью которого можно просмотреть состояние контейнеров. Вы также можете использовать эту панель для визуализации интерфейсов и бэкэндов, которые зарегистрировал Traefik. Откройте панель мониторинга в браузере:





https://monitor.your_domain




Будет предложено ввести имя пользователя и пароль администратора, и пароль (имя – admin, пароль – строка, которую вы сгенерировали в разделе 1).




После аутентификации на экране появится дашборд.




Пока что в панели еще не так много информации. Оставьте это окно открытым, и вы увидите, что содержимое дашборда изменится, когда вы добавите контейнеры для Traefik.




Теперь у вас есть прокси-сервер Traefik, настроенный для взаимодействия с Docker и готовый управлять другими контейнерами Docker.




3: Добавление контейнеров для Traefik




Контейнер Traefik запущен и готов обслуживать другие контейнеры приложений. Добавьте следующие контейнеры:




  1. Блог, запущенный с помощью официального образа WordPress.



  2. Сервер управления базами данных на основе официального образа Adminer.




Управлять этими приложениями можно с помощью Docker Compose, используя файл docker-compose.yml:




vi docker-compose.yml




Укажите в файле версии и сеть:




version: "3"
networks:
web:
external: true
internal:
external: false




Версия 3 Docker Compose – это новейшая версия формата файла Compose.




Чтобы сервер Traefik мог опознать приложения, они должны входить в одну сеть. Поскольку используемая сеть создана вручную, нужно указать ее имя (web ) и установить в external значение true. Затем нужно определить другую сеть, чтобы связать контейнеры с контейнером базы данных, который не будет обслуживаться контейнером Traefik. Эта внутренняя сеть будет называться internal.




Затем нужно определить все сервисы по очереди. Начать можно с контейнера blog, который основан на официальном образе WordPress. Добавьте в файл эту конфигурацию:




version: "3"
...
services:
blog:
image: wordpress:4.9.8-apache
environment:
WORDPRESS_DB_PASSWORD:
labels:
- traefik.backend=blog
- traefik.frontend.rule=Host:blog.your_domain
- traefik.docker.network=web
- traefik.port=80
networks:
- internal
- web
depends_on:
- mysql




Параметр environment позволяет указать переменные среды, которые будут установлены внутри контейнера. Если значение WORDPRESS_DB_PASSWORD не установлено, Docker Compose будет извлекать его из оболочки и передавать при создании контейнера. Определить эту переменную среды можно в оболочке перед запуском контейнеров. Таким образом пароли не попадут в конфигурационный файл.




В разделе labels указываются параметры Traefik. Метки Docker сами по себе ничего не делают, но Traefik читает их и понимает, как обращаться с контейнерами. Каждая метка выполняет такие действия:




  • traefik.backend определяет имя сервиса бэкенда (который указывает на контейнер blog).



  • traefik.frontend.rule=Host:blog.your_domain исследует запрашиваемый хост и, если он совпадает с шаблоном blog.your_domain, перенаправляет трафик в контейнер blog.



  • traefik.docker.network=web определяет сеть, в которой Traefik может найти внутренний IP-адрес контейнера. Поскольку Traefik имеет доступ ко всей информации Docker, он может случайно выбрать IP сети internal, если сеть не указана явно.



  • traefik.port указывает порт, который Traefik должен использовать для маршрутизации трафика в контейнеры.




При такой конфигурации весь трафик, отправленный на порт 80 хоста Docker, будет перенаправлен в контейнер blog.




Этот контейнер принадлежит двум различным сетям, чтобы Traefik мог найти его через сеть web и связываться с контейнером базы данных через сеть internal.




Параметр depends_on помогает Docker Compose понять, что этот контейнер нужно запускать после запуска его зависимостей. Поскольку для работы WordPress необходима запущенная БД, контейнер mysql запускается раньше, чем контейнер blog.




Теперь настройте сервис MySQL:




services:
...
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:
networks:
- internal
labels:
- traefik.enable=false




Для создания этого контейнера используется официальный образ MySQL 5.7. Обратите внимание: параметр environment снова не имеет значения. Для переменных MYSQL_ROOT_PASSWORD и WORDPRESS_DB_PASSWORD необходимо установить одинаковое значение, чтобы контейнер WordPress мог связываться с MySQL. Контейнер mysql не должен взаимодействовать с Traefik или с внешним миром, потому он принадлежит только сети internal. Поскольку Traefik имеет доступ к сокету Docker, процесс по-прежнему будет открывать фронтенд контейнера mysql по умолчанию. Поэтому нужно добавить метку traefik.enable = false, чтобы Traefik не смог сделать этот контейнер доступным.




Теперь нужно добавить параметры контейнера Adminer:




services:
...
adminer:
image: adminer:4.6.3-standalone
labels:
- traefik.backend=adminer
- traefik.frontend.rule=Host:db-admin.your_domain
- traefik.docker.network=web
- traefik.port=8080
networks:
- internal
- web
depends_on:
- mysql




Этот контейнер основан на официальном образе Adminer. Параметры network и depends_on совпадают с этими же параметрами контейнера blog.




Однако поскольку весь трафик порта 80 хоста Docker направляется непосредственно в контейнер blog, нужно настроить контейнер adminer немного иначе, чтобы он получал свой трафик.




Благодаря строке traefik.frontend.rule=Host:db-admin.your_domain сервер Traefik будет проверять запрашиваемый хост. Если он соответствует шаблону db-admin.your_domain, Traefik направит трафик в контейнер adminer.




В результате файл будет выглядеть так:




version: "3"
networks:
web:
external: true
internal:
external: false
services:
blog:
image: wordpress:4.9.8-apache
environment:
WORDPRESS_DB_PASSWORD:
labels:
- traefik.backend=blog
- traefik.frontend.rule=Host:blog.your_domain
- traefik.docker.network=web
- traefik.port=80
networks:
- internal
- web
depends_on:
- mysql
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:
networks:
- internal
labels:
- traefik.enable=false
adminer:
image: adminer:4.6.3-standalone
labels:
- traefik.backend=adminer
- traefik.frontend.rule=Host:db-admin.your_domain
- traefik.docker.network=web
- traefik.port=8080
networks:
- internal
- web
depends_on:
- mysql




Сохраните и закройте файл.




Теперь нужно задать значения переменных WORDPRESS_DB_PASSWORD и MYSQL_ROOT_PASSWORD, прежде чем запустить контейнеры.




export WORDPRESS_DB_PASSWORD=secure_database_password
export MYSQL_ROOT_PASSWORD=secure_database_password




Вместо secure_database_password укажите надежный пароль БД. В WORDPRESS_DB_PASSWORD и MYSQL_ROOT_PASSWORD нужно использовать один и тот же пароль.




Теперь запустите контейнеры:




docker-compose up -d




Снова откройте панель Traefik. Вы увидите, что в ней появились новые контейнеры, а также backend и frontend.




Откройте в браузере blog.your_domain (где your_domain – ваш домен). Соединение будет перенаправлено на зашифрованный порт 443. Теперь можно закончить установку WordPress.




После этого откройте в браузере db-admin.your_domain. Контейнер mysql не доступен в интернете, но контейнер adminer имеет доступ к нему через внутреннюю сеть Docker (internal).




На экране появится форма входа Adminer. Используйте имя пользователя root, укажите mysql в поле server, в поле пароля введите значение переменной MYSQL_ROOT_PASSWORD. После этого вы получите доступ к интерфейсу Adminer.




Оба сайта теперь работают. Чтобы получить доступ к дашборду, введите monitor.your_domain.




Заключение




Теперь сервер Traefik проксирует запросы в контейнеры приложений Docker.




Traefik позволяет легко настраивать большое количество сервисов и устраняет необходимость перезапускать контейнер traefik при добавлении новых приложений в контейнер traefik. Traefik незамедлительно получает все сведения об изменениях через файл сокета Docker.



2023-01-02T05:21:09
DevOps

Harbor – реджестри образов в Kubernetes (сканирование образов)

Harbor – это облачный реестр с открытым исходным кодом, который хранит, подписывает и сканирует образы контейнеров на наличие уязвимостей.




Это руководство покажет вам как установить Harbor Image Registry в Kubernetes / OpenShift с помощью чарта Helm.




Вот некоторые из интересных особенностей реестра образов Harbour:




Особенности Harbour




  • Поддержка Multi-tenant



  • Поддержка анализа безопасности и уязвимостей



  • Расширяемый API и веб-интерфейс



  • Подписание и проверка контента



  • Репликация образов в нескольких экземплярах Harbour



  • Интеграция и контроль доступа на основе ролей




Helm – это инструмент интерфейса командной строки (CLI), созданный для упрощения развертывания приложений и сервисов в кластерах Kubernetes / OpenShift 




Helm использует формат упаковки, называемый чартами.




Чарт Helm – это набор файлов, описывающих ресурсы Kubernetes.




Шаг 1: Установка Helm 3 на Linux / macOS




Helm имеет бинарник, что означает, что для его установки на вашем компьютере Linux / macOS не требуется никаких зависимостей:




--- Linux ---

sudo curl -L https://mirror.openshift.com/pub/openshift-v4/clients/helm/latest/helm-linux-amd64 -o /usr/local/bin/helm

sudo chmod +x /usr/local/bin/helm



--- macOS ---

sudo curl -L https://mirror.openshift.com/pub/openshift-v4/clients/helm/latest/helm-darwin-amd64 -o /usr/local/bin/helm

sudo chmod +x /usr/local/bin/helm




Проверьте установленную версию:




$ <strong>helm version</strong>

version.BuildInfo{Version:"<strong>v3.1</strong>+unreleased", GitCommit:"7ebdbb86fca32c77f2fce166f7f9e58ebf7e9946", GitTreeState:"clean", GoVersion:"go1.13.4"}




Шаг 2: Установите чарт Harbor в Kubernetes / OpenShift кластере




Чарт – это пакет Helm.




Он содержит все определения ресурсов, необходимые для запуска приложения, инструмента или службы внутри кластера Kubernetes.




Добавьте репозиторий Harbour Helm:




$ helm repo add harbor https://helm.goharbor.io

"harbor" has been added to your repositories




Обновите репозиторий:




$ helm repo update




Настройка чарта




Элементы конфигурации могут быть установлены с помощью флага –set во время установки или настроены путем непосредственного редактирования values.yaml.




Вы можете скачать файл values.yaml по умолчанию.




wget https://raw.githubusercontent.com/goharbor/harbor-helm/master/values.yaml

vim values.yaml




Установите чарт Harbor с пользовательскими настройками после внесения изменений.




$ helm install harbor harbor/harbor -f values.yaml -n harbor

NAME: harbor

LAST DEPLOYED: Wed Apr  1 19:20:07 2020

NAMESPACE: harbor

STATUS: deployed

REVISION: 1

TEST SUITE: None

NOTES:

Please wait for several minutes for Harbor deployment to complete.

Then you should be able to visit the Harbor portal at https://hbr.apps.hqocp.safaricom.net.

For more details, please visit https://github.com/goharbor/harbor.




Проверьте статус, чтобы подтвердить его развертывание:




$ helm status harbor




Исправление инициализации:CrashLoopBackOff в поде harbor-harbor-database на OpenShift




Некоторые образы контейнеров, такие как postgres и redis, требуют рутового доступа и имеют определенные ожидания относительно владения томами.




Нам нужно ослабить безопасность в кластере, чтобы образы не запускались как предварительно выделенный UID, не предоставляя всем доступ к привилегированному SCC:




Предоставьте всем аутентифицированным пользователям доступ к anyuid SCC:




$ oc adm policy add-scc-to-group anyuid system:authenticated




1$ oc adm policy add-scc-to-group anyuid system:authenticated




Проверьте статус ваших развертываний:




$ kubectl get deployments

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE

harbor-harbor-chartmuseum     1/1     1            1           24m

harbor-harbor-clair           1/1     1            1           24m

harbor-harbor-core            1/1     1            1           24m

harbor-harbor-jobservice      1/1     1            1           24m

harbor-harbor-notary-server   1/1     1            1           24m

harbor-harbor-notary-signer   1/1     1            1           24m

harbor-harbor-portal          1/1     1            1           24m

harbor-harbor-registry        1/1     1            1           24m




Проверьте статус  подов:




$ kubectl get pods

NAME                                           READY   STATUS    RESTARTS   AGE

harbor-harbor-chartmuseum-58f8647f95-mtmmf     1/1     Running   0          5m16s

harbor-harbor-clair-654dcfd8bf-77qs6           2/2     Running   0          5m16s

harbor-harbor-core-5cb85989d6-r7s84            1/1     Running   0          5m16s

harbor-harbor-database-0                       1/1     Running   0          5m33s

harbor-harbor-jobservice-fc54cf784-lv864       1/1     Running   0          5m16s

harbor-harbor-notary-server-65d8fb7c77-xgxvg   1/1     Running   0          5m16s

harbor-harbor-notary-signer-66c9db4cf4-5bwvh   1/1     Running   0          5m16s

harbor-harbor-portal-5cbc6d5897-r5wzh          1/1     Running   0          25m

harbor-harbor-redis-0                          1/1     Running   0          5m16s

harbor-harbor-registry-7ff65976f4-sgnnd        2/2     Running   0          5m16s




Посмотрите последние созданные сервисы и ингрессы:




$ kubectl get svc

NAME                          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE

harbor-harbor-chartmuseum     ClusterIP   172.30.161.108   &lt;none&gt;        80/TCP              26m

harbor-harbor-clair           ClusterIP   172.30.133.154   &lt;none&gt;        8080/TCP            26m

harbor-harbor-core            ClusterIP   172.30.29.180    &lt;none&gt;        80/TCP              26m

harbor-harbor-database        ClusterIP   172.30.199.219   &lt;none&gt;        5432/TCP            26m

harbor-harbor-jobservice      ClusterIP   172.30.86.18     &lt;none&gt;        80/TCP              26m

harbor-harbor-notary-server   ClusterIP   172.30.188.135   &lt;none&gt;        4443/TCP            26m

harbor-harbor-notary-signer   ClusterIP   172.30.165.7     &lt;none&gt;        7899/TCP            26m

harbor-harbor-portal          ClusterIP   172.30.41.233    &lt;none&gt;        80/TCP              26m

harbor-harbor-redis           ClusterIP   172.30.101.107   &lt;none&gt;        6379/TCP            26m

harbor-harbor-registry        ClusterIP   172.30.112.213   &lt;none&gt;        5000/TCP,8080/TCP   26m



$ kubectl get ing

NAME                    HOSTS                                     ADDRESS   PORTS     AGE

harbor-harbor-ingress   core.harbor.domain,notary.harbor.domain




Поскольку я на самом деле делаю это развертывание в OpenShift, у меня будут созданы определенные маршруты.




$ kubectl get route

NAME                          HOST/PORT              PATH          SERVICES                      PORT   TERMINATION     WILDCARD

harbor-harbor-ingress-7f9vg   notary.harbor.domain   /             harbor-harbor-notary-server   4443   edge/Redirect   None

harbor-harbor-ingress-9pvvz   core.harbor.domain     /             harbor-harbor-portal          8080   edge/Redirect   None

harbor-harbor-ingress-d7mcn   core.harbor.domain     /c/           harbor-harbor-core            8080   edge/Redirect   None

harbor-harbor-ingress-gn5w6   core.harbor.domain     /chartrepo/   harbor-harbor-core            8080   edge/Redirect   None

harbor-harbor-ingress-jf48l   core.harbor.domain     /service/     harbor-harbor-core            8080   edge/Redirect   None

harbor-harbor-ingress-lhbx4   core.harbor.domain     /api/         harbor-harbor-core            8080   edge/Redirect   None

harbor-harbor-ingress-vtt8v   core.harbor.domain     /v2/          harbor-harbor-core            8080   edge/Redirect   None




Также создан ряд pvc!




Подбирая значения указанного вами размера.




$ kubectl  get pvc

NAME                                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS                AGE

data-harbor-harbor-redis-0               Bound    pvc-1de4a5b2-d55a-48cc-b8b6-1b258214260c   1Gi        RWO            ocs-storagecluster-cephfs   29m

database-data-harbor-harbor-database-0   Bound    pvc-9754adde-e2bd-40ee-b18b-d72eacfdfc12   1Gi        RWO            ocs-storagecluster-cephfs   29m

harbor-harbor-chartmuseum                Bound    pvc-3944fce8-ecee-4bec-b0f6-cc5da3b30572   5Gi        RWO            ocs-storagecluster-cephfs   29m

harbor-harbor-jobservice                 Bound    pvc-5ecf0be4-002c-4628-8dcc-283e996175bc   1Gi        RWO            ocs-storagecluster-cephfs   29m

harbor-harbor-registry                   Bound    pvc-072358e9-06f2-4384-b7d6-88e97eb29499   5Gi        RWO            ocs-storagecluster-cephfs   29m




Шаг 3: Доступ к панели управления Harbour




Используйте внешний домен, настроенный во время установки, для доступа к панели мониторинга реестра контейнера Harbour.





Креды по умолчанию:




Username: admin
Password: Harbor12345




использовать Harbor для сканирования образов Docker на наличие уязвимостей




Harbor – это локальный реестр Docker, который, будучи собранным с поддержкой Clair, позволяет сканировать спушенные образы на наличие известных уязвимостей.




Это должно считаться обязательным в компаниях, которые полагаются на контейнеры.




Но как использовать Harbour для сканирования этих образов?




Давайте посмотрим.




Что вам нужно




Самое главное, вам понадобится это Harbor (с поддержкой Clair).




Вам также понадобятся образа для отправки на сервер Harbor и учетную запись пользователя на сервере Harbour. 




Сертификаты




Если вы планируете передавать образы с компьютеров в вашей сети (которые не являются вашим сервером Harbour), вам необходимо скопировать сертификаты с сервера Harbour на клиенты.




Если вы следовали инструкциям по установке Harbor, возможно, вы используете самозаверенные сертификаты.




Я собираюсь предположить, что это так.




И так … вот как скопировать эти сертификаты с сервера на клиент:




  1. подключитесь по ssh (или войдите в консоль) к серверу Harbor.



  2. Получите root-доступ с помощью команды sudo -s.



  3. Перейдите в каталог сертификатов с помощью команды cd /etc/docker/certs.d/SERVER_IP (где SERVER_IP – это IP-адрес вашего сервера).



  4. Скопируйте ключ ca.cert на клиент с помощью команды scp ca.cert USER @ CLIENT_IP: / home / USER (где USER – имя пользователя на клиентском компьютере, а CLIENT_IP – IP-адрес клиентского компьютера).



  5. Скопируйте ключ ca.crt на клиент с помощью команды scp ca.crt USER @ CLIENT_IP: / home / USER (где USER – это имя пользователя на клиентском компьютере, а CLIENT_IP – это IP-адрес клиентского компьютера).



  6. Скопируйте клиентский ключ ca.key с помощью команды scp ca.key USER @ CLIENT_IP: / home / USER (где USER – это имя пользователя на клиентском компьютере, а CLIENT_IP – это IP-адрес клиентского компьютера).



  7. SSH к клиентскому компьютеру с помощью команды ssh USER @ CLIENT_IP (где USER – имя пользователя на клиентском компьютере, а CLIENT_IP – IP-адрес клиентского компьютера).



  8. Создайте новый каталог сертификатов с помощью команды sudo mkdir -p /etc/docker/certs.d/SERVER_IP (где SERVER_IP – это IP-адрес сервера Harbour).



  9. Скопируйте файлы с помощью команды sudo cp ca. * /etc/docker/certs.d/SERVER_IP (где SERVER_IP – IP-адрес сервера Harbor).




Теперь ваш клиент должен иметь возможность войти в репозиторий Harbor и отправлять образы.




Пометка образов ( теги )




Прежде чем отправить образ с клиента на сервер, сначала необходимо пометить его.




Допустим, у вас есть официальный образ Ubuntu, и вы хотите пометить его конкретным именем разработчика.




Чтобы пометить его так, чтобы его можно было перенести в реестр Harbor, команда tag будет выглядеть так:




docker tag ubuntu SERVER_IP/PROJECT_NAME/ubuntu:DEVNAME




Где:




  •  SERVER_IP – это IP-адрес сервера Harbour.



  • PROJECT_NAME – это имя проекта на сервере Harbour.



  • DEVNAME: имя разработчика, которого вы хотите пометить.




Таким образом, команда может выглядеть так:




docker tag ubuntu 192.168.1.75/test/ubuntu:jack




Пушинг образа




Сначала вы должны войти в реестр на сервере Harbor.




Для этого выполните команду:




docker login SERVER_IP




Где SERVER_IP – это IP-адрес сервера Harbor.




Вам будет предложено ввести имя пользователя и пароль пользователя на сервере Harbour.




После входа в систему вы можете спушить образ с помощью команды:




docker push 192.168.1.75/test/ubuntu:jack




После завершения вы готовы отсканировать образ на наличие уязвимостей.




Сканирование образа




Войдите в свой реестр Harbor и перейдите к проекту, в котором размещен недавно подтянутый образ




Вы должны увидеть образ в списке:




Created with GIMP




Щелкните на новый образ и в появившемся окне установите флажок, связанный с тегом образа.




После выбора нажмите кнопку SCAN, чтобы начать сканирование.




Created with GIMP




Когда сканирование завершится, вы увидите полосу, представляющую результаты сканирования.




Наведите курсор на эту полосу, чтобы просмотреть отчет:




Created with GIMP




Если вы нажмете на имя тега, вы увидите полный отчет, в котором представлены полные результаты, включая CVE для каждой уязвимости:




Created with GIMP




Прокрутите весь отчет, чтобы просмотреть все уязвимости.




Если вы обнаружите, что образ содержит слишком много общих уязвимостей или достаточно средних или высоких уязвимостей, я предлагаю не использовать его.




Но важно просканировать эти уязвимости!




Источник: https://sidmid.ru/harbor-реджестри-образов-в-kubernetes-сканировани/



2023-01-02T04:57:39
DevOps

Grafana Loki

Установка пакетов




Для загрузки исходников нам понадобиться загрузить некоторые файлы. Для этого в системе должны быть установлены соответствующие пакеты. В зависимости от типа системы процесс установки будет незначительно отличаться.




а) на системах Red Hat:




yum install git wget




б) для систем на основе Debian:




apt-get install git wget




Установка Go




Для компиляции исходника, нам необходимо установить Golang. Для этого переходим на страницу загрузки и копируем ссылку на архив с его последней версией:




* по умолчанию, страница предлагает загрузить Go для нашей операционной системы, поэтому, если мы открыли сайт на компьютере Windows, ниже под кнопкой загрузки выбираем Linux.




Воспользовавшись ссылкой, скачиваем архив на наш сервер:




wget https://golang.org/dl/go1.15.6.linux-amd64.tar.gz




* на момент написания инструкции, последняя версия была 1.15.6.




Распаковываем архив в каталог /usr/local:




tar -v -C /usr/local -xzf go*.tar.gz




Открываем файл:




vi /etc/profile




Добавляем в самый низ строку:




export PATH=$PATH:/usr/local/go/bin




Один раз выполняем данную команду:




export PATH=$PATH:/usr/local/go/bin




Проверяем, что go установлен и готов выполнять команды:




go version




Мы должны увидеть версию скачанного пакета.




Настройка безопасности




1. Брандмауэр




В зависимости от используемого брандмауэра, необходимо выполнить следующие настройки.




а) если используем iptables (по умолчанию, в системах на базе Debian):




iptables -I INPUT 1 -p tcp —dport 3100 -j ACCEPT




* данная команда добавит правило на разрешение порта 3100 (на котором, по умолчанию, запускается Grafana Loki).




Для сохранения правил устанавливаем пакет:




apt-get install iptables-persistent




Сохранение правил теперь можно выполнить командой:




netfilter-persistent save




б) если используем firewalld (по умолчанию, в системах на базе Red Hat):




firewall-cmd —permanent —add-port=3100/tcp




firewall-cmd —reload




* данная команда добавит правило на разрешение порта 3100 (на котором, по умолчанию, запускается Grafana Loki).




2. SELinux




Как правило, в системах на базе Red Hat активирована дополнительная система безопасности. В нашей инструкции мы ее отключаем командами:




setenforce 0




sed -i ‘s/^SELINUX=.*/SELINUX=disabled/g’ /etc/selinux/config




* первая команда вводится до разового отключения SELinux. Вторая не дает ему запуститься после перезагрузки.




Установка




Установка Grafana Loki сводится к загрузке готового бинарника или исходника с последующей компиляцией. Также мы настроим юнит в systemd для работы приложения в качестве сервиса.




Копирование бинарника и конфигурационного файла




Переходим в каталог:




cd /usr/src/




Загружаем исходные файлы проекта:




git clone https://github.com/grafana/loki




Переходим в каталог loki:




cd loki/




Запускаем компиляцию бинарника:




go build ./cmd/loki




В текущем каталоге появится файл loki — перенесем его в каталог /usr/local/bin:




mv loki /usr/local/bin/




Создадим каталог:




mkdir /etc/loki




… и перенесем в него конфигурационный файл:




mv cmd/loki/loki-local-config.yaml /etc/loki/




В конфиге, который идет в исходнике в качестве рабочего каталога для Grafana Loki используется /tmp — мы это исправим двумя командами:




sed -i ‘s//tmp/wal//opt/loki/wal/g’ /etc/loki/loki-local-config.yaml




* первой командой мы меняем настройку dir для wal (журнала предзаписи). 




sed -i ‘s//tmp/loki//opt/loki/g’ /etc/loki/loki-local-config.yaml




* в данном примере мы заменили путь для storage_configworking_directory и ruler storage на /opt/loki.




Создаем каталог:




mkdir /opt/loki




Выполним первый тестовый запуск сервиса:




/usr/local/bin/loki -config.file=/etc/loki/loki-local-config.yaml




Открываем браузер и переходим по адресу http://192.168.0.15:3100/metrics, где 192.168.0.15 — IP-адрес нашего сервера Grafana Loki. Мы должны увидеть страницу с метриками:





Значит наш сервис запустился и нормально работает. Можно прервать его работу на сервере комбинацией клавиш Ctrl + С и продолжать настройку.




Автозапуск




Чтобы сервис мог автоматически запускаться при старте системы, добавим его в systemd.




Для начала, создадим пользователя, под которым будет работать сервис:




useradd —no-create-home —shell /bin/false loki




* данной командой мы создадим пользователя loki. Ему нельзя будет входить в систему в качестве интерактивного пользователя, также для него не будет создана домашняя директория.




Делаем владельцем loki бинарник для запуска сервиса:




chown loki:loki /usr/local/bin/loki




Задаем владельца для рабочих каталогов Loki:




chown -R loki:loki /etc/loki




chown -R loki:loki /opt/loki




Создаем юнит в systemd:




vi /etc/systemd/system/loki.service




[Unit]

Description=Grafana Loki Service

After=network.target



[Service]

User=loki

Group=loki

Type=simple

ExecStart=/usr/local/bin/loki -config.file=/etc/loki/loki-local-config.yaml

ExecReload=/bin/kill -HUP $MAINPID

Restart=on-failure



[Install]

WantedBy=multi-user.target




Перечитываем конфигурацию systemd:




systemctl daemon-reload




Теперь можно разрешить и стартовать наш сервис:




systemctl enable loki —now




Проверить, что он запустился и работает можно командой:




systemctl status loki




Установка серверной части завершена.




Отправка логов на сервер




В нашем примере мы передадим логи веб-сервера NGINX в нашу Grafana Loki. Для этого переходим на сервер с NGINX и выполним следующие действия.




Установка Promtail




Promtail — агент, который читает и отправляет логи на сервер. Его установка во многом напоминает установку сервера — получаем бинарник и добавляем его в автозагрузку. В нашем примере мы загрузим уже скомпилированный файл для запуска.




Для начала, установим следующие пакеты:




yum install unzip wget




unzip нужен для распаковки архива с бинарником; wget — для скачивания архива.




Загружаем последнюю версию promtail для Linux:




wget https://github.com/grafana/loki/releases/latest/download/promtail-linux-amd64.zip




* в нашем примере загружается бинарник на систему 64-бит. На странице https://github.com/grafana/loki/releases можно скачать файлы для установки под Linux и Windows.




Распаковываем скачанный архив:




unzip promtail-linux-amd64.zip




Переносим бинарник в каталог /usr/local/bin:




mv promtail-linux-amd64 /usr/local/bin/promtail




* обратите внимание, что мы его сразу переименовали в promtail.




Создаем каталог для конфигурационных файлов promtail:




mkdir /etc/promtail




Создаем конфигурационный файл:




vi /etc/promtail/promtail.yaml




server:

  http_listen_port: 9080

  grpc_listen_port: 0



positions:

  filename: /tmp/positions.yaml



clients:

  - url: http://192.168.0.15:3100/loki/api/v1/push




* где 9080 — номер порта, на котором будет слушать promtail; 192.168.0.15 — IP-адрес нашего сервера Loki, куда нужно отправлять данные.




Создаем юнит в systemd для promtail:




vi /etc/systemd/system/promtail.service




[Unit]

Description=Promtail Service

After=network.target



[Service]

Type=simple

ExecStart=/usr/local/bin/promtail -config.file=/etc/promtail/promtail.yaml

ExecReload=/bin/kill -HUP $MAINPID

Restart=on-failure



[Install]

WantedBy=multi-user.target




Перечитываем конфигурацию systemd:




systemctl daemon-reload




Разрешаем запуск сервиса promtail и стартуем его:




systemctl enable promtail —now




Проверяем статус:




systemctl status promtail




На клиенте в настройки брандмауэра добавляем правило на разрешение порта 9080.




а) если используем iptables (Debian, Ubuntu):




iptables -I INPUT 1 -p tcp —dport 9080 -j ACCEPT




apt-get install iptables-persistent




netfilter-persistent save




б) если используем firewalld (CentOS, Red Hat):




firewall-cmd —permanent —add-port=9080/tcp




firewall-cmd —reload




После установки promtail открываем браузер и переходим на страницу http://192.168.0.25:9080/targets, где 192.168.0.25 — IP-адрес клиентского компьютера с NGINX. Мы должны увидеть страницу:





Promtail работает. Можно приступать к сбору логов.




Настройка сбора логов




Открываем конфигурационный файл promtail:




vi /etc/promtail/promtail.yaml




...



scrape_configs:

- job_name: nginx

  static_configs:

  - targets:

      - localhost

    labels:

      job: nginxlogs

      __path__: /var/log/nginx/*log




* где:







Перезапускаем сервис promtail:




systemctl restart promtail




Снова заходим по адресу http://192.168.0.25:9080/targets — мы должны увидеть настроенное нами задание:





Сбор логов настроен.




Настройка Grafana




Переходим к серверу с Grafana. Он может быть установлен на отдельном сервере или на том же сервере с Loki.




Заходим в веб-интерфейс и переходим в Configuration — Data Sources:





Добавляем новый источник, кликая по Add data source:





Среди списка возможных источников выбираем Loki:





В настройках задаем имя и указываем IP-адрес сервера Loki:





* в нашем примере задается имя Loki и подключение к серверу 192.168.0.15.




Нажимаем на Save & Test:




Если мы увидели сообщение «Data source connected and labels found.»:значит подключение выполнено и можно двигаться дальше.




Переходим в раздел Create — Dashboard:





Кликаем по кнопке Add new panel:





В открывшемся окне выбираем в качестве источника данных Loki, затем кликаем по Log labels — выбираем job и nginxlogs:





Мы увидим Unable to graph data (так как логи представляют из себя данные, на основе которых нельзя постоить график) — кликаем по Switch to table view:





Мы должны увидеть строки из логов:





Логи NGINX отображаются в Grafana.




Парсинг лога




Мы увидели логи в графане, но они представленны в неудобном для отбора и фильрации виде. Попробуем это исправить с помощью парсинга логов на стороне promtail.




Открываем файл для редактирования:




vi /etc/promtail/promtail.yaml




Дополним нашу задачу для сбора логов NGINX:




...



scrape_configs:

- job_name: nginx

  static_configs:

  - targets:

      - localhost

    labels:

      job: nginxlogs

      __path__: /var/log/nginx/*log

  pipeline_stages:

    - match:

        selector: '{job="nginxlogs"}'

        stages:

        - regex:

            expression: '^(?P<remote_addr>[w.]+) - (?P<remote_user>[^ ]*) [(?P<time_local>.*)] "(?P<method>[^ ]*) (?P<request>[^ ]*) (?P<protocol>[^ ]*)" (?P<status>[d]+) (?P<body_bytes_sent>[d]+) "(?P<http_referer>[^"]*)" "(?P<http_user_agent>[^"]*)"?'

        - labels:

            remote_addr:

            remote_user:

            time_local:

            method:

            request:

            protocol:

            status:

            body_bytes_sent:

            http_referer:

            http_user_agent:




* обратите внимание, что к имеющейся настройки мы добавили pipeline_stages:







Перезапускаем сервис для promtail:




systemctl restart promtail




Идем в Grafana — в Log labels мы должны увидеть новые критерии для фильтра по тегам:





Пробуем добавить, например, фильтр по статусу ответа веб-сервера:





Источник: https://sidmid.ru/grafana-loki-2/



Работать с Terraform в yandex облаке

Регистрация на хостинге




Для работы с хостинг-провайдером нам заранее понадобятся авторизационные данные и идентификаторы ресурсов. Их мы будем прописывать в сценариях terraform.




Нам нужно зарегистрироваться на сервисе Yandex.Cloud (в нашем примере, мы будем работать, именно, с ним). После этого, нам нужно получить:




1. OAuth-токен. Используется в процедуре аутентификации для получения IAM-токена и нужен нам для прохождения авторизации при подключении terraform. Выдается на 1 год. Получить можно, отправив запрос со страницы документации Яндекс.




2. Идентификатор облака. После регистрации на хостинге мы заходим в контроль-панель. Мы должны увидеть наши ресурсы, в частности, облако:





А справа от него будет идентификатор.




3. Идентификатор каталога. На той же странице контроль панели, ниже облака мы увидим каталог:





Также, справа мы можем скопировать его идентификатор.




После получения нужных данных просто сохраняем их в отдельный файл. После установки terraform они нам понадобятся.




Установка Terraform




Terraform является клиентом и необходимо выполнить установку на компьютер, с которого планируется управление инфраструктурой. Актуальная инструкция по развертыванию представлена на официальном сайте. На текущий момент клиент может быть установлен из репозитория, с использованием бинарника, собран из исходников, а также с помощью choco на Windows или brew на Mac OS. В нашем примере будут рассмотрены установка на Ubuntu и Rocky Linux из репозитория, а также загрузка бинарника.




Ubuntu (Debian)




Обновляем список пакетов:




apt update




Установим дополнительные пакеты:




apt install gnupg software-properties-common curl




* где:




  • gnupg — программа для шифровки и дешифровки цифровых подписей. Нужна для работы с репозиториями.



  • software-properties-common — утилита для работы с репозиториями.



  • curl — отправка GET, POST и других запросов.




Установим в систему ключ для репозитория:




curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add —




Добавляем репозиторий:




apt-add-repository «deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main»




Обновляем список пакетов, чтобы загрузить списки с нового репозитория:




apt update




Можно устанавливать terraform:




apt install terraform




Rocky Linux




Устанавливаем утилиту для работы с репозиториями:




yum install yum-utils




Добавляем репозиторий:




yum-config-manager —add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo




Устанавливаем terraform:




yum install terraform




Скачиваем бинарник




Суть данного метода — скачать бинарный файл и перенести его в каталог /usr/local/bin.




Таким же образом устанавливаем terraform на Windows.




Для начала нам понадобятся утилиты unzip и wget. Устанавливаются они по-разному, в зависимости от дистрибутива Linux.




а) Ubuntu / Debian:




apt install unzip wget




б) Rocky Linux:




yum install unzip wget




Переходим к загрузке бинарного файла. Посмотреть ссылку на него можно на странице официального сайта:





Воспользуемся ссылкой, чтобы скачать архив:




wget https://releases.hashicorp.com/terraform/1.1.7/terraform_1.1.7_linux_amd64.zip




* в нашем примере будет загружена версия 1.1.7.




Распакуем архив командой:




unzip terraform_*_linux_amd64.zip




Перенесем распакованный бинарник в каталог:




mv terraform /usr/local/bin/




После установки




Убедимся, что terraform работает. Для этого вводим команду:




terraform -version




Мы должны получить что-то на подобие:




Terraform v1.1.7
on linux_amd64




Также рекомендуется установить автоподстановки:




terraform -install-autocomplete




Это позволит нам завершать команды terraform с помощью клавиши Tab.




Теперь создадим каталог, в котором будем работать со сценариями для тераформа:




mkdir -p /opt/terraform/yandex




* в моем примере я решил работать в каталоге /opt/terraform/yandex.




Перейдем в созданный каталог:




cd /opt/terraform/yandex




Мы готовы приступить непосредственно к работе с terraform.




Установка провайдера




Чтобы terraform мог корректно взаимодействовать с инфраструктурой провайдера, необходимо использовать набор инструкций, которые будет использовать наша утилита. В терминологии terraform это называется провайдер.




На сайте Hashicorp можно найти все поддерживаемые провайдеры. Как говорилось выше, мы будем работать с Yandex.Cloud. Рассмотрим подробнее установку провайдера для работы с ним.




В нашем рабочем каталоге создаем первый файл:




vi main.tf




terraform {

  required_version = "= 1.1.7"



  required_providers {

    yandex = {

      source  = "yandex-cloud/yandex"

      version = "= 0.73"

    }

  }

}



provider "yandex" {

  token     = "<OAuth>"

  cloud_id  = "<идентификатор облака>"

  folder_id = "<идентификатор каталога>"

  zone      = "<зона доступности по умолчанию>"

}




* где:




  • terraform required_version — версия клиента terraform, для которого должен запускаться сценарий. Параметр не обязательный, но является правилом хорошего тона и может помочь избежать некоторых ошибок, которые возникнут из-за несовместимости при работе в команде.



  • required_providers version — версия провайдера. Мы можем указать, как в данном примере, необходимость использовать конкретную версию, а можно с помощью знака >= или <= указать не выше или не ниже определенной.



  • token — OAuth-токен для прохождения авторизации. Был нами получен после регистрации на хостинге



  • cloud_id — идентификатор для облака, в котором будут создаваться ресурсы. Также получен был нами заранее.



  • folder_id — идентификатор каталога, который также был получен в начале инструкции.



  • zone — ресурсы, которые хранятся на мощностях Яндекс разделены по зонам. Каждая зона — это определенная географическая локация центра обработки данных. Список доступных зон можно посмотреть на странице Зоны доступности.




Теперь выполним команду:




terraform init




Система загрузит нужные файлы и установит провайдер:




Initializing the backend...



Initializing provider plugins...

- Finding latest version of yandex-cloud/yandex...

- Installing yandex-cloud/yandex v0.73.0...

- Installed yandex-cloud/yandex v0.73.0 (self-signed, key ID E40F590B50BB8E40)

...

Terraform has been successfully initialized!

...




Мы готовы двигаться дальше.




Работа с ресурсами




Мы рассмотрим небольшие примеры по созданию, редактированию и удалению ресурсов. В большей степени мы будем работать с виртуальными машинами. Большую часть информации по написанию сценариев можно найти на официальном сайте хостинга или самого terraform.




Создание ресурсов




В нашем рабочем каталоге создадим новый файл:




vi infrastructure1.tf




Напишем минимально необходимый сценарий для создания виртуальной машины:




data "yandex_compute_image" "ubuntu_image" {

  family = "ubuntu-2004-lts"

}



resource "yandex_compute_instance" "vm-test1" {

  name = "test1"



  resources {

    cores  = 2

    memory = 2

  }



  boot_disk {

    initialize_params {

      image_id = data.yandex_compute_image.ubuntu_image.id

    }

  }



  network_interface {

    subnet_id = yandex_vpc_subnet.subnet_terraform.id

    nat       = true

  }



  metadata = {

    user-data = "${file("./meta.yml")}"

  }



}



resource "yandex_vpc_network" "network_terraform" {

  name = "net_terraform"

}



resource "yandex_vpc_subnet" "subnet_terraform" {

  name           = "sub_terraform"

  zone           = "ru-central1-a"

  network_id     = yandex_vpc_network.network_terraform.id

  v4_cidr_blocks = ["192.168.15.0/24"]

}




* где:




  • data — позволяет запрашивать данные. В данном примере мы обращаемся к ресурсу yandex_compute_image с целью поиска идентификатора образа, с которого должна загрузиться наша машина.

    • yandex_compute_image — ресурс образа. Его название определено провайдером.



    • ubuntu_image — произвольное название ресурса. Его мы определили сами и будем использовать в нашем сценарии.



    • ubuntu-2004-lts — в нашем примере мы запрашиваем данные ресурса, который ищем по family с названием ubuntu-2004-lts. Данное название можно посмотреть в контроль панели хостинга — нужно выбрать образ и кликнуть по нему. Откроется страница с дополнительной информацией. В данном случае ubuntu-2004-lts соответствуем Ubuntu 20.04 LTS.




  • resource — позволяет создавать различные ресурсы.

    • yandex_compute_instance — ресурс виртуальной машины. Его название определено провайдером.



    • vm-test1 — наше название ресурса для виртуальной машины.



    • yandex_vpc_network — ресурс сети, определенный провайдером.



    • network_terraform — наше название для ресурса сети.



    • yandex_vpc_subnet — ресурс подсети, определенный провайдером.



    • subnet_terraform — наше название для ресурса подсети.



    • metadata — обратите особое внимание на передачу метеданных. В данном примере мы передаем содержимое файла, а сам файл рассмотрим ниже.




** в нашем примере будет создана виртуальная машина с названием test1, 2 CPU, 2 Gb RAM в сети 192.168.15.0/24 на базе Ubuntu 20.04 LTS.
*** обратите внимание, что мы указали идентификатор той подсети для виртуальной машины, которую создали также с помощью нашего сценария terraform.




Создаем файл с метеданными:




meta.yml




#cloud-config

users:

  - name: test

    groups: sudo

    shell: /bin/bash

    sudo: ['ALL=(ALL) NOPASSWD:ALL']

    ssh-authorized-keys:

      - ssh-rsa AAAAB3Nza..................UXFDCb/ujrK4KbpCyvk=




* в данном файле мы опишем пользователя, под которым мы сможем подключиться к нашему серверу по SSH:




  • #cloud-config — как выяснилось, этот комментарий обязательный.



  • name — имя пользователя, который будет создан на виртуальной машине.



  • groups — в какую группу добавить пользователя.



  • shell — оболочка shell по умолчанию.



  • sudo — правило повышения привилений.



  • ssh-authorized-keys — список ключей, которые будут добавлены в authorized_keys.




Попробуем испытать наш сценарий. Сначала вводим:




terraform plan




Если мы не ошиблись, утилита покажет, что terraform сделает в нашей облачной инфраструктуре. Очень важно внимательно просматривать изменения.




После того, как мы убедимся в корректности действий, применяем настройку:




terraform apply




Мы еще раз увидим, что будет выполнено, а также получим запрос на подтверждение действий — вводим yes:




Enter a value: yes




Terraform выполнит необходимые действия. Мы можем перейти в контроль-панель хостинга и убедиться, что наша виртуальная машина создалась.




Редактирование данных




Если необходимо внести изменения в нашу инфраструктуру, то достаточно просто открыть наш файл со сценарием:




vi infrastructure1.tf




Внести нужные изменения, например:




  ...

  resources {

    cores  = 4

    memory = 4

  }

  ...




* в нашем конкретном случае, мы увеличили количество процессоров и объем памяти для созданной виртуальной машины.




Однако, некоторые изменения требуют остановки виртуальной машины. В этом случае мы получим ошибку при попытке применить новые настройки с текстом:




Error: Changing the `secondary_disk`, `resources`, `platform_id`, `network_acceleration_type` or `network_interfaces` on an instance requires stopping it. To acknowledge this action, please set allow_stopping_for_update = true in your config file.




Мы должны явно разрешить для конкретных ресурсов выполнение остановки их работы для внесения изменений. В нашем файле для конкретного ресурса добавим:




...

resource "yandex_compute_instance" "vm-test1" {

  name = "test1"

  allow_stopping_for_update = true



...




* для нашей машины test1 мы указали опцию allow_stopping_for_update, которая говорит о том, что работу ресурса можно останавливать для внесения изменений.




Строим план:




terraform plan




Мы должны увидеть, что будет изменено в нашей инфраструктуре. В моем случае:




      ~ resources {

          ~ cores         = 2 -> 4

          ~ memory        = 2 -> 4

            # (2 unchanged attributes hidden)

        }




Применяем настройки:




terraform apply




Проверяем через контроль-панель, что изменения вступили в силу.




Удаление ресурсов




Для удаления ресурса можно использовать разные приемы.




1. Например, можно указать count = 0:




resource "yandex_compute_instance" "vm-test1" {

  count = 0

  ...




2. Можно закомментировать или удалить строки ресурса из файла tf.




3. Если мы хотим оставить содержимое файлов нетронутым, но при этом удалить все ресурсы, вводим:




terraform destroy




Утилита пройдет по всем файлам tf в директории, найдет ресурсы и выполнит их удаление.




Файл state




Очень важно уметь работать с файлом состояния terraform, а также понять, что это. Данный файл появляется после первого применения сценария в том же рабочем каталоге:




ls




terraform.tfstate




В нем содержатся все изменения, которые происходили с применением terraform. Без него последний не будет знать, что уже было сделано — на практике это приведет к дублированию инфраструктуры, то есть, если мы создали сервер, потеряли файл состояния и снова запустили terraform, он создаст еще один сервер. Для больших инфраструктур с большой историей все намного критичнее.




И так, файл состояния важен с точки зрения понимания инфраструктуры самим terraform. Также у него есть еще одна функция — блокировка параллельных выполнений. Это важно для работы в командах, где одновременные действия могут привести к неожиданным последствиям. Чтобы этого не произошло, terraform создает блокировку, которая запрещает выполнения, если уже идет процесс применения плана.




Из вышесказанного делаем выводы:







Рассмотрим возможность хранения данного файла состояния на облачном хранилище Яндекс.




Сначала мы должны создать хранилище. Это можно сделать через веб-интерфейс, но мы это сделаем в terraform.




Но сначала мы сделаем файл:




vi variables.tf




variable "yandex_folder_id" {

  type        = string

  default     = "<идентификатор каталога>"

}




* где yandex_folder_id — название для нашей переменной; <идентификатор каталога> — тот идентификатор, который мы указали в файле main под аргументом folder_id.




Теперь откроем файл main:




vi main.tf




И отредактируем значение folder_id на:




  ...

  folder_id = var.yandex_folder_id

  ...




* в данном примере мы теперь задаем folder_id не явно, а через созданную переменную.




Теперь создадим файл:




vi yandex_storage_bucket.tf




resource "yandex_iam_service_account" "sa" {

  folder_id = var.yandex_folder_id

  name      = "sa-test"

}



resource "yandex_resourcemanager_folder_iam_member" "sa-editor" {

  folder_id = var.yandex_folder_id

  role      = "storage.editor"

  member    = "serviceAccount:${yandex_iam_service_account.sa.id}"

}



resource "yandex_iam_service_account_static_access_key" "sa-static-key" {

  service_account_id = yandex_iam_service_account.sa.id

  description        = "Static access key for object storage"

}



resource "yandex_storage_bucket" "state" {

  bucket     = "tf-state-bucket-test"

  access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key

  secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_key

}




* рассмотрим файл немного подробнее:







Создаем еще один файл:




vi outputs.tf




output "access_key" {

  value = yandex_iam_service_account_static_access_key.sa-static-key.access_key

  sensitive = true

}

output "secret_key" {

  value = yandex_iam_service_account_static_access_key.sa-static-key.secret_key

  sensitive = true

}




* это делается для получения значений аргументов access_key и secret_key и сохранения данных значений в файле состояния. Если access_key можно посмотреть в панели Яндекса, то secret_key мы увидеть не можем.




Строим план и применяем настройки:




terraform plan




terraform apply




Заходим в контроль-панель Яндекса и видим, что у нас создалось хранилище. Его мы будем использовать для хранения файлов состояний terraform.




Открываем наш файл main:




vi main.tf




Добавляем:




terraform {

  ...



  backend "s3" {

    endpoint   = "storage.yandexcloud.net"

    bucket     = "tf-state-bucket-test"

    region     = "ru-central1-a"

    key        = "terraform/infrastructure1/terraform.tfstate"

    access_key = "<access_key>"

    secret_key = "<secret_key >"



    skip_region_validation      = true

    skip_credentials_validation = true

  }

}




* в раздел terraform мы добавили инструкцию для хранения файла state. В нашем примере он будет размещен на бакете tf-state-bucket-test по пути terraform/infrastructure1/terraform.tfstate.
** особое внимание обратите на access_key и secret_key. В разделе terraform мы не можем указать переменные, как это делали при создании хранилища. Сами значения можно найти в нашем локальном файле state.




Используем команду:,




terraform init




Система снова инициализирует состояние текущего каталога и создаст файл state на удаленном хранилище. Чтобы убедиться, можно зайти в контроль панель, найти наше хранилище, а в нем — файл terraform/infrastructure1/terraform.tfstate.




Реальный пример




Мы развернем 2 веб-сервера и поместим их за Network load balancer.




Для этого мы создадим новый рабочий каталог:




mkdir -p /opt/terraform/yandex-network-load balancer




И перейдем в него:




cd /opt/terraform/yandex-network-load balancer




Подразумевается, что все инфраструктура создается с нуля, поэтому нужно либо удалить предыдущие наработки, либо создать новый сервисный аккаунт для storage.




Мы создадим 5 файлов:




  1. main.tf — в нем мы опишем инструкции для init, а именно требования к версии клиента terraform, провайдера.



  2. web-servers.tf — сценарий для создания 2-х веб-серверов.



  3. network-load-balancer.tf — создание Network Load Balancer.



  4. variables.tf — описание переменных.



  5. outputs.tf — вывод значений после отработки terraform на экран и в файл состояния.




1. Создаем файл main.tf:




vi main.tf




terraform {

  required_version = "= 1.1.7"



  required_providers {

    yandex = {

      source  = "yandex-cloud/yandex"

      version = "= 0.73"

    }

  }

}

provider "yandex" {

  token     = "<OAuth>"

  cloud_id  = "<идентификатор облака>"

  folder_id = "<идентификатор каталога>"

  zone      = "<зона доступности по умолчанию>"

}




* это стандартный вариант файла main.tf, который мы разбирали в начале.




2. web-servers.tf:




vi web-servers.tf




data "yandex_compute_image" "lamp" {

  family = "lamp"

}



data "yandex_compute_image" "lemp" {

  family = "lemp"

}



resource "yandex_compute_instance" "vm-test1" {

  name                      = "vm-test1"

  allow_stopping_for_update = true



  resources {

    cores  = 2

    memory = 2

  }



  boot_disk {

    initialize_params {

      image_id = data.yandex_compute_image.lamp.id

    }

  }



  network_interface {

    subnet_id = yandex_vpc_subnet.subnet_terraform.id

    nat       = true

  }



}



resource "yandex_compute_instance" "vm-test2" {

  name                      = "vm-test2"

  allow_stopping_for_update = true



  resources {

    cores  = 2

    memory = 2

  }



  boot_disk {

    initialize_params {

      image_id = data.yandex_compute_image.lemp.id

    }

  }



  network_interface {

    subnet_id = yandex_vpc_subnet.subnet_terraform.id

    nat       = true

  }



}



resource "yandex_vpc_network" "network_terraform" {

  name = "network_terraform"

}



resource "yandex_vpc_subnet" "subnet_terraform" {

  name           = "subnet_terraform"

  zone           = "ru-central1-a"

  network_id     = yandex_vpc_network.network_terraform.id

  v4_cidr_blocks = ["192.168.15.0/24"]

}




* в данном примере мы создадим 2 виртуальные машины — одну с образом lamp (Apache), вторую на lemp (NGINX).




3. network-load-balancer.tf:




vi network-load-balancer.tf




resource "yandex_lb_network_load_balancer" "lb-test" {

  name = "lb-test"



  listener {

    name = "listener-web-servers"

    port = 80

    external_address_spec {

      ip_version = "ipv4"

    }

  }



  attached_target_group {

    target_group_id = yandex_lb_target_group.web-servers.id



    healthcheck {

      name = "http"

      http_options {

        port = 80

        path = "/"

      }

    }

  }

}



resource "yandex_lb_target_group" "web-servers" {

  name = "web-servers-target-group"



  target {

    subnet_id = yandex_vpc_subnet.subnet_terraform.id

    address   = yandex_compute_instance.vm-test1.network_interface.0.ip_address

  }



  target {

    subnet_id = yandex_vpc_subnet.subnet_terraform.id

    address   = yandex_compute_instance.vm-test2.network_interface.0.ip_address

  }

}




* в данном сценарии мы:







4. variables.tf:




vi variables.tf




variable "yandex_folder_id" {

  type        = string

  default     = "<folder_id>"

}




* создадим переменную с folder_id, в котором мы должны работать. Выше мы уже делали такую переменную.




5. outputs.tf:




vi outputs.tf




output "lb_ip_address" {

  value = yandex_lb_network_load_balancer.lb-test.*

}




* на самом деле, это не обязательно — информацию о созданном балансировщике можно посмотреть в контроль панели, но для примера мы решили это рассмотреть.




Готово. После применения данного сценария мы получим то, что хотели — две виртуальные машины + балансировщик сети, который будет распределять запросы между данными серверами.




Источник: https://sidmid.ru/работать-с-terraform-в-yandex-облаке/



Grafana: создание dashboard

Задача – добавить дашборд для отображения различной статистики с бекенда.




Ниже описывается процесс создания дашборды, рассматриваются примеры запросов из Grafana к Prometheus для получения данных, настройки различных типов панелей, примеры метрик, которые можно использовать.




Для примеров запросов использовалась в основном борда Node Exporter Full 0.16 для метрик EC2, и борда AWS ELB Application Load Balancer для ALB.




Добавлять будем:




  • вверху – статусы хоста:

    • часы (время с момента получения последней метрики)



    • CPU usage %



    • Load Average %



    • memory usage %



    • root, /data disks % usage




  • статусы сервисов:

    • nginx



    • php-fpm



    • rabbitmq status



    • memcached status



    • redis status



    • RDS статус




  • статистика EC2 (node_exporter):

    • CPU

      • CPU System/User/IOwait/Idle




    • Memory:

      • RAM total



      • RAM used



      • RAM free




    • Disk

      • IO time




    • Processes

      • Blocked I/O



      • Running




  • статистика Load Balancer

    • RequestCount / Latency

      • TargetResponseTime_Average



      • ActiveConnectionCount_Average




    • HTTPCode

      • HTTPCode_Target_2XX_Count_Average



      • HTTPCode_Target_3XX_Count_Average



      • HTTPCode_Target_4XX_Count_Average



      • HTTPCode_Target_5XX_Count_Average




Настройки dashboard




Переходим в Settings, задаём имя дашборды:





Переменные




Документация – тут>>> и тут>>>.




У нас есть два бекеда – Dev и Production.




Соответственно – в дашборде хочется выводить статистику и того, и другого. Для этого – добавим переменную, с помощью которой сможем переключаться между ними.




Переходим в Variables:





  • в Name задаём имя, которое будет использоваться в запросах



  • Type – оставляем Query



  • Label – имя, как оно будет отображаться в дашборде для выбора



  • Data source – Prometheus



  • Refresh – при загрузке дашборда



  • Query – собственно, сам запрос, который вернёт нам значения, и из которого будем получать список окружений
    в данном случае Prometheus-сервер, который запущен на EC2, добавляет external_label в виде env=mobilebackend-dev, его и используем
    для получения значений – используем метрику node_boot_time_seconds, фильтруем вывод по метке job="node-exporter"
    запрос получается:
    label_values(node_boot_time_seconds{job="node-exporter"}, env)





Сохраняем – Add внизу.




Статусы хоста




Первым добавим блок, в котором убдут выводить % использования CPU, Load Avareage, память и диски.




CPU Busy




node_cpu_seconds_total




Прежде, чем заниматься настройкой отображения CPU Busy – давайте вспомним /proc/stats.




Сначала – получим время с момента запуска системы:




root@bm-backed-app-dev:/opt/prometheus-client# cat /proc/uptime

2168671.61 2147672.65




Тут:




  • первая колонка – аптйам системы в секундах



  • вторая – время в сукундах, проведённое в IDLE




Проверяем:




root@bm-backed-app-dev:/opt/prometheus-client# uptime

14:21:45 up 25 days,  2:37




Считаем – кол-во секунд из /proc/uptime делим на часы и кол-во часов в сутках:




root@bm-backed-app-dev:/opt/prometheus-client# echo 2168671 / 3600 / 24 | bc

25




Хорошо, тут всё сходится.




Теперь считаем stats:




root@bm-backed-app-dev:/opt/prometheus-client# cat /proc/stat

...

cpu0 1435156 1188 466232 213091141 58015 0 29879 134098 0 0

...

btime 1529657067




Тут колонки:




  • user: normal processes executing in user mode



  • nice: niced processes executing in user mode



  • system: processes executing in kernel mode



  • idle: twiddling thumbs



  • iowait: waiting for I/O to complete



  • irq: servicing interrupts



  • softirq: servicing softirqs




Время в сотых секунды.




btime – время загрузки системы в секундах с момента January 1, 1970 (UNIX epoch).




Теперь попробуем посчитать:




root@bm-backed-app-dev:/opt/prometheus-client# echo "(1435156+1188+466232+213091141+58015+0+29879+134098) / 100 / 3600 / 24" | bc

24




Выполняем сложение всех счётчиков, делим на 100 – получаем общее кол-во секунд.




Потом, аналогично вычислениям с uptime – получаем кол-во дней, вышло 24 – один день (точнее 4 часа) “потерялся”, но не критично – в целом значения сошлись.




Теперь выведем метрики node_exporter, и сравним их с данными из /proc/stat (на самом деле метрики я вывел немного раньше, поэтому будет разница):




root@bm-backed-app-dev:/opt/prometheus-client# curl -s localhost:9100/metrics | grep node_cpu_seconds_total

HELP node_cpu_seconds_total Seconds the cpus spent in each mode.

TYPE node_cpu_seconds_total counter

node_cpu_seconds_total{cpu="0",mode="idle"} 2.13035164e+06

node_cpu_seconds_total{cpu="0",mode="iowait"} 579.98

node_cpu_seconds_total{cpu="0",mode="irq"} 0

node_cpu_seconds_total{cpu="0",mode="nice"} 11.88

node_cpu_seconds_total{cpu="0",mode="softirq"} 298.71

node_cpu_seconds_total{cpu="0",mode="steal"} 1340.68

node_cpu_seconds_total{cpu="0",mode="system"} 4660.78

node_cpu_seconds_total{cpu="0",mode="user"} 14346.37




И сравниваем с stat:




  • user: stat = 14351.56, exporter = 14346.37



  • system: stat = 4662.32, exporter = 4660.78




Окей – тут тоже всё более-менее сходится, и значение данных из node_cpu_seconds_total понятно.




Запрос




Теперь рассмотрим запрос, который будем использовать для получения CPU Busy %:




(((count(count(node_cpu_seconds_total{env="$environment"}) by (cpu))) - avg(sum by (mode)(irate(node_cpu_seconds_total{mode='idle',env="$environment"}[5m])))) * 100) / count(count(node_cpu_seconds_total{env="$environment"}) by (cpu))




Тут:




  • count – считаем кол-во элементов, полученных из запроса



  • avg: общее среднее значение, документация тут>>>



  • irate –  считает значение в секунду, основываясь на двух последних данных



  • node_cpu_seconds_total – секунды в каждом режиме (systemuseridle etc)



  • {env=~"$environment"} – выборка по значению переменной $environment




Подсчёт кол-ва ядер




Кол-во ядер мы получаем запросом ((count(count(node_cpu_seconds_total{env="$environment"}) by (cpu))).




Рассмотрим его детальнее.




Сначала сделаем выборку по node_cpu_seconds_total{env=~"mobilebackend-dev"}:





Так мы получим значения node_cpu_seconds_total по каждому типу – iowaitusersystemnice etc.




В count(node_cpu_seconds_total{env=~"mobilebackend-dev"}) считаем общее кол-во элементов (iowait, user, system, nice etc), хотя оно нам не надо – мы просто используем этот массив для следующего запроса.




А следующий запрос – count(node_cpu_seconds_total{env=~"mobilebackend-dev"}) by (cpu) возвращает нам общее кол-во node_cpu_seconds_total по типам для каждого ядра:





Например для Production это будет выглядеть так:





И в конце-концов добавив ещё один счётчик – count, и превратив запрос в count(count(node_cpu_seconds_total{env=~"mobilebackend-dev"}) by (cpu)) – мы получим кол-во ядер:





Production





Для наглядности – проверяем на серверах:




root@bm-backed-app-dev:/opt/prometheus-client# grep -c ^processor /proc/cpuinfo

1




И прод:




root@mobilebackend-production:/data/projects# grep -c ^processor /proc/cpuinfo

8




Время ядер в idle




По теме – Understanding Machine CPU usage.




Следующая часть запроса – avg(sum by (mode) (irate(node_cpu_seconds_total{mode='idle',env="$environment"}[5m]))).




Сначала выполняем irate(node_cpu_seconds_total{mode='idle',env="mobilebackend-dev"}[5m]):





Так мы получаем среднее значение времени в секундах, которое cpu0 провёл в статусе idle, т.е. бездельничал.




А “завернув” этот запрос в avg(sum by (mode)() – получим среднее значение для всех ядер:





И если для Dev разницы нет, то на Prod с его 8-ю ядрами значение будет более наглядным:





Т.е. вместе все 8 ядер провели 7.95 секунд в режиме idle.




Если принять 8 за 100%, то вычислим %, который ядра провели не в idle за 1 секунду:




>>> (8.0 - 7.95) * 100 / 8.0

0.6249999999999978




0.6% времени проведено в других режимах – systemuser etc.




Если бы, к примеру, все ядра вместе провели 8 секунд в idle (т.е. каждое ядро за 1 целую секунду провело 1 целую секунду в idle):




>>> (8.0 - 8.0) * 100 / 8.0

0.0




То нагрузка на ЦПУ была бы 0%.




И наоборот, если бы половина времени, т.е. 4 секунды в общем, были бы потрачены в idle, то результат:




>>> (8.0 - 4.0) * 100 / 8.0

50.0




50% idle, 50% – остальные режимы.




Вообще есть хорошая страничка тут – Как найти процент от числа для тех, кто как я не силён в математике 




Настройка панели




Теперь переходим к панели.




Жмём на зголовок панели – Edit:





В General задаём имя:





В Metrics добавляем наш запрос:





В Options настраиваем вид:




  • Gauge – включаем отображение шкалы



  • Spark lines – строка “истории”



  • Coloring – включаем красивую подсветку по значениям, и в Thresholds задаём значения, при которых цвет будет меняться – на оранжевый при 75%, и на красный – при 90%



  • Stat – Current



  • Unit – выбираем None > percent 1-100




Получается такое:





Возвращаемся к дашборе, добавляем ещё один елемент – Row:





Задаём имя, меняем размер панельки с CPU Busy:





Load Average




Следующая панелька будет выводить Load Average.




Можно было бы вывести просто значение node_load1{env=~"$environment"} – но на Dev сервере одно ядро, и значение node_load1 == 1 будет являться условными 100% для одного ядра, а на Production с его 8 ядрами node_load1 == 1 будет всего:




>>> 1.0 / 8 * 100

12.5




12.5%




Значит, что бы корректно отрисовывать шкалу – нам потребуется получить значение LA, поделить его на кол-во ядер и умножить на 100 – получим % от “максимального” (в кавычках, потому что LA может быть и выше 1 для 1 ядра или 8 для 8 ядер) значения.




Следовательно – используем такой запрос:




avg(node_load1{env=~"$environment"}) / count(count(node_cpu_seconds_total{env=~"$environment"}) by (cpu)) * 100





Настраиваем шкалу аналогично CPU Busy:





Перетаскиваем её в Row, меняем размер:





Проверим поведение.




Устанавливаем стресс-тест для CPU:




root@bm-backed-app-dev:/opt/prometheus-client# apt install stress




Запускаем его:




root@bm-backed-app-dev:/opt/prometheus-client# stress —cpu 8 —timeout 20





И данные из uptime:




root@bm-backed-app-dev:/opt/prometheus-client# uptime

18:03:18 up 25 days,  6:18,  1 user,  load average: 1.65, 1.13, 0.64




Memory usage




Далее добавим шкалу с отображением занятой памяти.




Проверим free на проде:




root@mobilebackend-production:/data/projects# free -h

total        used        free      shared  buff/cache   available

Mem:            15G        2.8G        7.5G         93M        4.8G         11G




15 ГБ всего, 2.8 занято активными процессами, 4.8 – кеш, свободной памяти 7.5. ОК.




Составим запрос:




((node_memory_MemTotal_bytes{env="$environment"} - node_memory_MemFree_bytes{env="$environment"}) / (node_memory_MemTotal_bytes{env="$environment"} )) * 100




  • в (node_memory_MemTotal_bytes{env="$environment"} - node_memory_MemFree_bytes{env="$environment"})  считаем общее кол-во занятой памяти (active + cache), назовём её busy



  • и считаем busy / total * 100 – получаем % от свободной памяти




В Options включаем шкалу, настраиваем аналогично примерам выше:





Получается теперь:





Disk usage




В Prometheus выполняем запрос для проверки:




node_filesystem_avail_bytes{env="mobilebackend-dev",fstype="ext4"}





Добавляем панель, добавляем в неё запрос на получение метрик о /rootfs и вычисляем % занятого места:




100 - ((node_filesystem_avail_bytes{env="$environment",mountpoint="/rootfs",fstype="ext4"} * 100) / node_filesystem_size_bytes{env="$environment",mountpoint="/rootfs",fstype="ext4"})





Настраиваем шкалу аналогично предыдущим:





Повторяем для второго диска – /rootfs/data, получаем такую картинку в дашборде:





Текущеее время




Следующим – добавим отображение текущего времени. Во-первых – просто удобно на экране (в комнате висит большой телевизор, на котором выводится борда) видеть текущее время, во-вторых – такая себе проверка на то, что браузер/дашборда не зависли, и обновляются.




Для вывода времени – опять используем Singlestat панели, и функцию timestamp(), которой передадим метрику up (можно любую – нам только требуется получить из метрики время).




Создаём панель, в Metrics указываем:




timestamp(up{instance="localhost:9090",job="prometheus"}) * 1000




В Options в Units выбираем YYYY-MM-DD HH:mm:ss и получаем текущее время (правда дата не выводится, но она и не нужна):





Сортируем по желанию, и получаем первую часть дашборды:





Статусы сервисов




Теперь – добавим простое отображение стаусов Up/Down для сервисов, которые работают на хосте и необходимы для работы приложения.




У нас это:




  • nginx



  • php-fpm



  • memcahed



  • redis



  • rabbitmq



  • AWS RDS



  • AWS ALB




Memcahed статус




Начнём с вывода статуса memcahed.




Создаём новую Row, в ней – новую Singlestat панель.




На сервере запущен quay.io/prometheus/memcached-exporter, который среди прочих метрик возвращает memcahed_up:




...

  memcached-exporter:

    image: quay.io/prometheus/memcached-exporter

    network_mode: "host"

...




memcahed на сервере один, потому можем создать простой запрос на получение кол-ва сервисов в up:




memcached_up{env="$environment",instance="localhost:9150",job="memcached-exporter"}




В Value mappings добавляем отображение статуса – Up, если memcahed_up == 1, или DOWN – если ноль:





В Options > Threshold задаём значения 1,1 (меньше одного – сразу красным) и Stat Current, получаем симпатичный статус:





RabbitMQ статус




Запущен https://github.com/kbudde/rabbitmq_exporter.




Создаём пользователя для доступа експортёра:




root@bm-backed-app-dev:/opt/prometheus-client# rabbitmqctl add_user prometheus password

Creating user "prometheus" ...




Добавляем ему тег “мониторинг”:




root@bm-backed-app-dev:/opt/prometheus-client# rabbitmqctl set_user_tags prometheus monitoring




Добавим его в переменные контейнера:




...

  rabbitmq-exporter:

    image: kbudde/rabbitmq-exporter

    network_mode: "host"

    environment:

    - PUBLISH_PORT=9419

    - RABBIT_USER=prometheus

    - RABBIT_PASSWORD=password

...




Перезапускаем сервис:




root@bm-backed-app-dev:/opt/prometheus-client# systemctl restart prometheus-client.service




Проверяем метрики:




root@bm-backed-app-dev:/home/admin# curl -s localhost:9419/metrics | grep -v # | grep _up

rabbitmq_up 1




И добавляем ещё одну Singlestat панель:





PHP-FPM stats




Повторяем для NGINX – для него всё, как в примерах выше, и добавляем ещё один статус – для PHP-FPM.




Единственное отличие тут – это количество.




Если все сервисы запущены по одному на дев/прод сервер, то php-fpm запущено 6 пулов:




root@bm-backed-app-dev:/opt/prometheus-client# ps aux | grep fpm: | grep -v grep | grep -v master | awk '{print $11, $12, $13}' | uniq

php-fpm: pool dev.admin.domain1.com

php-fpm: pool dev.admin.domain2.com

php-fpm: pool dev.domain1.com

php-fpm: pool dev.domain2.com

php-fpm: pool dev.domain3.com

php-fpm: pool dev.admin.domain3.com





Соответственно, php_fpm_up вернёт не 1, а 6 результатов – по 1 на каждый пул.




Учитывая это – формируем запрос в Metrics и используем count():




count(php_fpm_up{env="$environment",instance="localhost:9253",job="php-fpm-exporter"})




В Value mappings в Type вместо Value to text выбираем range to text:





MySQL stats




Т.к. mysql_exporter ещё не запущен – то тут кратенько пример его запуска.




В роли серверов баз данных используется AWS RDS, два мастер-инстанса.




Значит – надо запустить два експортёра, по одному на каждый RDS. В Ansible шаблон Compose файл добавляем их:




...

  mysql_exporter_db1:

    image: prom/mysqld-exporter

    networks:

    - prometheus-client

    ports:

    - 9104:9104

    environment:

    - DATA_SOURCE_NAME={{ mysql_monitoring_db1_user }}:{{ mysql_monitoring_db1_pass }}@({{ mysql_monitoring_db1_host }}:3306)/



  mysql_exporter_db2:

    image: prom/mysqld-exporter

    networks:

    - prometheus-client

    ports:

    - 9105:9104

    environment:

    - DATA_SOURCE_NAME={{ mysql_monitoring_db2_user }}:{{ mysql_monitoring_db2_pass }}@({{ mysql_monitoring_db2_host }}:3306)/




Переменные берутся из Ansible vault с зашифрованными паролями.




Добавляем джобы в конфиг Прометеус сервера:




...

  - job_name: 'mysql_exporter_db1'

    static_configs:

      - targets:

        - 'localhost:9104'



  - job_name: 'mysql_exporter_db2'

    static_configs:

      - targets:

        - 'localhost:9105'




Деплоим, проверяем DB1:




root@mobilebackend-dev:/opt/prometheus-client# curl -s localhost:9104/metrics | grep -v # | grep -w mysql_up

mysql_up 1




И DB2 (второй екпортёр слушает на порту 9105):




root@mobilebackend-dev:/opt/prometheus-client# curl -s localhost:9105/metrics | grep -v # | grep -w mysql_up

mysql_up 1




Добавляем в Grafana:




mysql_up{env="$environment",instance="localhost:9104",job="mysql_exporter_db1"}





Load Balancer statistics




Добавим ещё несколько графиков – статистику с AWS Application Load Balancer.




Тут надо добавить ещё одну переменную – Load balancer.




К сожалению – cloudformation_exporter не умеет получать теги, поэтому пока придётся использовать просто имена ALB (надо будет посмотреть – может на стороне Prometheus можно будет сделать им relabel).




Добавляем переменную, в запросе указываем:




aws_applicationelb_request_count_sum{job="aws_applicationelb"}




В регулярном выражении – получаем только имя ALB:




/.*app/(.*)"/





Добавляем Row, и в ней – новую панель, но на этот раз типа Graph, в Metrics добавим четыре запроса – на коды 2хх, 3хх, 4хх и 5хх от targets:




aws_applicationelb_httpcode_target_2_xx_count_sum{load_balancer="app/$load_balancer"}





Аналогично можно добавить статистику по времени ответа бекенда.




Добавляем панель Connections/response time – тут будем выводить кол-во активный сессий и время ответа targets.




Добавляем метрики:




aws_applicationelb_target_response_time_sum{load_balancer="app/$load_balancer"}




И активные сессии:




aws_applicationelb_active_connection_count_sum{load_balancer="app/$load_balancer"}




Series overrides




Сейчас на графике отображаются юниты по оси Y слева и внизу.




Но – на этом графике используются метрики двух типов – в одном выводится count – кол-во сессий, а на втором – время ответа от бекенда до ALB в мс.




Хочется, что слева в шкале выводились числа, снизу время получения метрики, а слева – кол-во милисекнуд ответа бекенда.




Для этого – используем ещё одну интересную возможность Grafana – Series overrides. Интересный пост на эту тему есть тут – Advanced Graphing (Part1): Style Overrides.




Переходим в Axes, и включаем отображение шкалы Y справа, в юнитах используем милисекунды:





Далее переходим в Display > Series overrides > Add override, и в Alias or regex указываем алиас метрики, в данном случае мы хотим выводить время, основываясь на данных из `aws_applicationelb_target_response_time_sum`, который в метриках указывается как response_time ms:





Кликаем на “+” – добавляем желамое действие. Тут указываем отображание времени в Y Right и заодно – можно поиграть со цветом: 





И всё вместе теперь выглядит так: 







EC2 statistics




И последним – добавим графики EC2.




В принципе – тут ничего такого, что уже не рассматривалось выше.




CPU




Сначала – статистика использования CPU – System, User, IOwait, idle.




В самом простом виде запросы выглядел бы так:




sum by (instance)(rate(node_cpu_seconds_total{mode="system",env="$environment"}[5m])) * 100




Получаем % от времени, которое CPU проёвл в режиме system/user/idle и т.д.




Но в случае, когда у нас несколько ядер – добавляем вычисление % от кол-ва ядер, аналоигчно тому, как мы это делали для отрисовки шкалы с % LA и CPU Busy:




(avg(sum by (instance)(rate(node_cpu_seconds_total{mode="idle",env="$environment"}[5m])) * 100)) / count(count(node_cpu_seconds_total{env="$environment",instance="localhost:9100"}) by (cpu))





Memory




Добавляем панель RAM.




Выводим память всего:




https://sidmid.ru/wp-content/uploads/2021/12/41-1024x494.png




Использованной памяти:




node_memory_MemTotal_bytes{env="$environment"} - node_memory_MemFree_bytes{env="$environment"} - (node_memory_Cached_bytes{env="$environment"} + node_memory_Buffers_bytes{env="$environment"})




Свободной памяти:




node_memory_MemFree_bytes{env="$environment"}





Диск




Добавим отображение времени на read-write операции:




irate(node_disk_read_time_seconds_total{env="$environment"}[5m])

irate(node_disk_write_time_seconds_total{env="$environment"}[5m])




В Legend используем {{device}}, куда будет подставлено значение из label “device“:






Получается так: 




Процессы




И последняя уже таблица – процессы в системе.




Выводим кол-во процессов в статусе run:




node_procs_running{env="$environment"}




И blocked:




node_procs_blocked{env="$environment"}





И всё вместе теперь выглядит так:





Источник: https://sidmid.ru/grafana-создание-dashboard/



2023-01-02T04:09:01
DevOps

Kubernetes. Запуск prometheus/grafana/alertmanager — запуск exporter для ingress-nginx-controller

1.Установка prometheus
2.exporter nginx(ingress-controller)
3.exporter elasticsearch
4.exporter rabbitmq
5.exporter redis
6.настройка оповещений в telegram
6.1 настройка оповещений в telegram в различные чаты(группы)
6.2. настройка оповещений в telegram разграничение оповещений по группам (исключения уведомлений)
7.Проблема с prometheus-kube-proxy
8.Настройка алерта для определённого неймспейса
9.Добавление оповещений и по email
10. Настройка графиков в grafana




Качаем репозиторий




git clone https://github.com/prometheus-community/helm-charts.git
cd helm-charts/charts/kube-prometheus-stack/
докачиваем чарты:
helm dep update




создаём namescpase в котором будет всё крутиться:
kubectl create ns monitoring




теперь рассмотрим что правим в переменных у helm chart:




[root@prod-vsrv-kubemaster1 charts]# vim kube-prometheus-stack/values.yaml




namespaceOverride: «monitoring»




для работы telegram бота:




  ## Alertmanager configuration directives

  ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file

  ##      https://prometheus.io/webtools/alerting/routing-tree-editor/

  ##

  config:

    global:

      resolve_timeout: 5m

    route:

        receiver: 'telegram'

        routes:

        - match:

            severity: critical

          repeat_interval: 48h

          continue: true

          receiver: 'telegram'

        - match:

            alertname: Watchdog

          repeat_interval: 48h

          continue: true

          receiver: 'telegram'

    receivers:

        - name: 'telegram'

          webhook_configs:

              - send_resolved: true

                url: 'http://alertmanager-bot:8080'

    templates:

    - '/etc/alertmanager/config/*.tmpl'




настраиваем ingress у alertmanager:




  ingress:                                                    

    enabled: true                                             

    hosts:                                                    

      - alertmanager.prod.test.local                       

    paths:                                                    

     - /




настраиваем volume для Alertmanager отмечу что в кластере настроен nfs-provisioner — nfs-storageclass




  ingress:                                                    

    enabled: true                                             

    hosts:                                                    

      - alertmanager.prod.test.local                       

    paths:                                                    

     - /




теперь настроим grafana




тут указываем ingress а также добавляем хранение dashboard в nfs storage-class




grafana:

  enabled: true

  namespaceOverride: "monitoring"

  ## Deploy default dashboards.

  ##

  defaultDashboardsEnabled: true

  adminPassword: prom-operator

  ingress:

    ## If true, Grafana Ingress will be created

    ##

    enabled: true

     labels: {}

    ## Hostnames.

    ## Must be provided if Ingress is enable.

    ##

    hosts:

      - grafana.prod.test.local

    #hosts: []

    ## Path for grafana ingress

    path: /

    ## TLS configuration for grafana Ingress

    ## Secret must be manually created in the namespace

    ##

    tls: []

    # - secretName: grafana-general-tls

    #   hosts:

    #   - grafana.example.com

  persistence:

    type: pvc

    enabled: true

    storageClassName: nfs-storageclass

    accessModes:

      - ReadWriteMany

    size: 5Gi

    # annotations: {}

    finalizers:

      - kubernetes.io/pvc-protection




  ## If using kubeControllerManager.endpoints only the port and targetPort are used

  ##

  service:

    port: 10252

    targetPort: 10252

    selector:

      k8s-app: kube-controller-manager

    #   component: kube-controller-manager




  ## If using kubeScheduler.endpoints only the port and targetPort are used

  ##

  service:

    port: 10251

    targetPort: 10251

    selector:

      k8s-app: kube-scheduler

    #   component: kube-scheduler




## Configuration for kube-state-metrics subchart

##

kube-state-metrics:

  namespaceOverride: "monitoring"

  rbac:

    create: true

  podSecurityPolicy:

    enabled: true




## Configuration for prometheus-node-exporter subchart

##

prometheus-node-exporter:

  namespaceOverride: "monitoring"




теперь настраиваем ingress для prometheus




  ingress:                                         

    enabled: true                                  

    annotations: {}                                

    labels: {}                                     

    ## Hostnames.                                  

    ## Must be provided if Ingress is enabled.     

    ##                                             

    hosts:                                         

      - prometheus.prod.test.local             

                                         

    ## Paths to use for ingress rules -            

    ##                                             

    paths:                                         

     - /




а так же volume:




    ## Prometheus StorageSpec for persistent data

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md

    ##

    storageSpec:                                              

      volumeClaimTemplate:                                    

        spec:                                                 

          storageClassName: nfs-storageclass                  

          accessModes: ["ReadWriteMany"]                      

          resources:                                          

            requests:                                         

              storage: 10Gi




и теперь важная фишка, добавление label который надо будет добавить на все неймспейсы:




    ## Namespaces to be selected for ServiceMonitor discovery.

    ##

    serviceMonitorNamespaceSelector:

       matchLabels:

         prometheus: enabled




    ## Log level for Alertmanager to be configured with.

    ##

    logLevel: info



    ## 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.

    replicas: 3




также правим:




    ## Enable scraping /metrics/resource from kubelet's service

    ## This is disabled by default because container metrics are already exposed by cAdvisor

    ##

    resource: true




для выставления срока хранения данных можем поменять следующее значение:




    ## Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression

    ## [0-9]+(ms|s|m|h) (milliseconds seconds minutes hours).

    ##

    retention: 120h




запускаем теперь helm chart




[root@prod-vsrv-kubemaster1 charts]# helm upgrade —install -name prometheus kube-prometheus-stack/ -f kube-prometheus-stack/values.yaml —namespace monitoring




Release "prometheus" does not exist. Installing it now.

NAME: prometheus

LAST DEPLOYED: Thu Mar  4 13:25:07 2021

NAMESPACE: monitoring

STATUS: deployed

REVISION: 1

NOTES:

kube-prometheus-stack has been installed. Check its status by running:

  kubectl --namespace monitoring get pods -l "release=prometheus"



Visit https://github.com/prometheus-operator/kube-prometheus for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator.




видим что при запуске добавился label release=prometheus — проверяем:
kubectl describe pod prometheus-kube-prometheus-operator-659d5f8674-qxrf5 -n monitoring | grep -i release
release=prometheus




смотрим label на всех неймсмейсах:
kubectl get ns —show-labels




NAME                     STATUS   AGE     LABELS

default                  Active   192d    <none>

elk                      Active   63d     <none>

ingress-nginx            Active   192d    name=ingress-nginx

keda                     Active   86d     <none>

kube-node-lease          Active   192d    <none>

kube-public              Active   192d    <none>

kube-system              Active   192d    name=kube-system

m-logstash-megabuilder   Active   12d     <none>

monitoring               Active   3h15m   <none>

terminal-soft            Active   176d    <none>




проставим на них label release=prometheus
kubectl label namespace —all «prometheus=enabled»




проверяем:
kubectl get ns —show-labels




NAME                     STATUS   AGE     LABELS

default                  Active   192d    prometheus=enabled

elk                      Active   63d     prometheus=enabled

ingress-nginx            Active   192d    name=ingress-nginx,prometheus=enabled

keda                     Active   86d     prometheus=enabled

kube-node-lease          Active   192d    prometheus=enabled

kube-public              Active   192d    prometheus=enabled

kube-system              Active   192d    name=kube-system,prometheus=enabled

m-logstash-megabuilder   Active   12d     prometheus=enabled

monitoring               Active   3h16m   prometheus=enabled

terminal-soft            Active   176d    prometheus=enabled




теперь настроим сбор метрик с ingress controller,




создаём сервис для ingress. Указываем namespace в котором работает ingress, так же необходим label app.kubernetes.io/name: ingress-nginx данный лейб смотрим так:
kubectl describe pod -n ingress-nginx ingress-nginx-controller-vqjkl | grep -A3 Labels




Labels:               app.kubernetes.io/name=ingress-nginx

                      app.kubernetes.io/part-of=ingress-nginx

                      controller-revision-hash=bd6d56f49

                      pod-template-generation=1




mkdir exporter-ingres




cat exporter-ingres/service.yaml




apiVersion: v1

kind: Service

metadata:

  labels:

    app.kubernetes.io/name: ingress-nginx

    release: prometheus

  name: ingress-nginx

  namespace: ingress-nginx

spec:

  ports:

  - name: http

    port: 80

    protocol: TCP

    targetPort: 80

  - name: https

    port: 443

    protocol: TCP

    targetPort: 443

  - name: prometheus

    port: 10254

    protocol: TCP

    targetPort: 10254

  selector:

    app.kubernetes.io/name: ingress-nginx




В данном файле так же обращаем внимание на:
name: prometheus
на это имя будет натравлен port у ServiceMonitor




теперь создаём ServiceMonitor, он будет создавать в prometheus target с метриками ingress controller:




cat exporter-ingres/service-monitor.yaml




apiVersion: monitoring.coreos.com/v1

kind: ServiceMonitor

metadata:

  labels:

    app: ingress-nginx

    release: prometheus

  name: ingress-nginx

  namespace: monitoring

spec:

  endpoints:

  - honorLabels: true

    interval: 10s

    path: /metrics

    port: prometheus

    scheme: http

    scrapeTimeout: 10s

  namespaceSelector:

     any: true

  selector:

    matchLabels:

      app.kubernetes.io/name: ingress-nginx

      release: prometheus




также правим:




    ## Enable scraping /metrics/resource from kubelet's service

    ## This is disabled by default because container metrics are already exposed by cAdvisor

    ##

    resource: true




применяем:




[root@prod-vsrv-kubemaster1 charts]# kubectl apply -f exporter-ingres/service.yaml -f exporter-ingres/service-monitor.yaml




через пару минуток проверяем в prometheus





общий  вид у файла values.yaml будет следующий:




cat helm-charts/charts/kube-prometheus-stack/values.yaml




# Default values for kube-prometheus-stack.

# This is a YAML-formatted file.

# Declare variables to be passed into your templates.



## Provide a name in place of kube-prometheus-stack for `app:` labels

##

nameOverride: ""



## Override the deployment namespace

##

namespaceOverride: "monitoring"



## Provide a k8s version to auto dashboard import script example: kubeTargetVersionOverride: 1.16.6

##

kubeTargetVersionOverride: ""



## Provide a name to substitute for the full names of resources

##

fullnameOverride: ""



## Labels to apply to all resources

##

commonLabels: {}

# scmhash: abc123

# myLabel: aakkmd



## Create default rules for monitoring the cluster

##

defaultRules:

  create: true

  rules:

    alertmanager: true

    etcd: true

    general: true

    k8s: true

    kubeApiserver: true

    kubeApiserverAvailability: true

    kubeApiserverError: true

    kubeApiserverSlos: true

    kubelet: true

    kubePrometheusGeneral: true

    kubePrometheusNodeAlerting: true

    kubePrometheusNodeRecording: true

    kubernetesAbsent: true

    kubernetesApps: true

    kubernetesResources: true

    kubernetesStorage: true

    kubernetesSystem: true

    kubeScheduler: true

    kubeStateMetrics: true

    network: true

    node: true

    prometheus: true

    prometheusOperator: true

    time: true



  ## Runbook url prefix for default rules

  runbookUrl: https://github.com/kubernetes-monitoring/kubernetes-mixin/tree/master/runbook.md#

  ## Reduce app namespace alert scope

  appNamespacesTarget: ".*"



  ## Labels for default rules

  labels: {}

  ## Annotations for default rules

  annotations: {}



  ## Additional labels for PrometheusRule alerts

  additionalRuleLabels: {}



## Deprecated way to provide custom recording or alerting rules to be deployed into the cluster.

##

# additionalPrometheusRules: []

#  - name: my-rule-file

#    groups:

#      - name: my_group

#        rules:

#        - record: my_record

#          expr: 100 * my_record



## Provide custom recording or alerting rules to be deployed into the cluster.

##

additionalPrometheusRulesMap: {}

#  rule-name:

#    groups:

#    - name: my_group

#      rules:

#      - record: my_record

#        expr: 100 * my_record



##

global:

  rbac:

    create: true

    pspEnabled: true

    pspAnnotations: {}

      ## Specify pod annotations

      ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#apparmor

      ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp

      ## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/#sysctl

      ##

      # seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'

      # seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'

      # apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'



  ## Reference to one or more secrets to be used when pulling images

  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

  ##

  imagePullSecrets: []

  # - name: "image-pull-secret"



## Configuration for alertmanager

## ref: https://prometheus.io/docs/alerting/alertmanager/

##

alertmanager:



  ## Deploy alertmanager

  ##

  enabled: true



  ## Api that prometheus will use to communicate with alertmanager. Possible values are v1, v2

  ##

  apiVersion: v2



  ## Service account for Alertmanager to use.

  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

  ##

  serviceAccount:

    create: true

    name: ""

    annotations: {}



  ## Configure pod disruption budgets for Alertmanager

  ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget

  ## This configuration is immutable once created and will require the PDB to be deleted to be changed

  ## https://github.com/kubernetes/kubernetes/issues/45398

  ##

  podDisruptionBudget:

    enabled: false

    minAvailable: 1

    maxUnavailable: ""



  ## Alertmanager configuration directives

  ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file

  ##      https://prometheus.io/webtools/alerting/routing-tree-editor/

  ##



  config:

    global:

      resolve_timeout: 5m

    route:

        receiver: 'telegram'

        routes:

        - match:

            severity: critical

          repeat_interval: 48h

          continue: true

          receiver: 'telegram'

        - match:

            alertname: Watchdog

          repeat_interval: 48h

          continue: true

          receiver: 'telegram'

    receivers:

        - name: 'telegram'

          webhook_configs:

              - send_resolved: true

                url: 'http://alertmanager-bot:8080'







#  config:

#    global:

#      resolve_timeout: 5m

#    route:

#      group_by: ['job']

#      group_wait: 30s

#      group_interval: 5m

#      repeat_interval: 12h

#      receiver: 'null'

#      routes:

#      - match:

#          alertname: Watchdog

#        receiver: 'null'

#    receivers:

#    - name: 'null'



    templates:

    - '/etc/alertmanager/config/*.tmpl'



  ## Pass the Alertmanager configuration directives through Helm's templating

  ## engine. If the Alertmanager configuration contains Alertmanager templates,

  ## they'll need to be properly escaped so that they are not interpreted by

  ## Helm

  ## ref: https://helm.sh/docs/developing_charts/#using-the-tpl-function

  ##      https://prometheus.io/docs/alerting/configuration/#tmpl_string

  ##      https://prometheus.io/docs/alerting/notifications/

  ##      https://prometheus.io/docs/alerting/notification_examples/

  tplConfig: false



  ## Alertmanager template files to format alerts

  ## By default, templateFiles are placed in /etc/alertmanager/config/ and if

  ## they have a .tmpl file suffix will be loaded. See config.templates above

  ## to change, add other suffixes. If adding other suffixes, be sure to update

  ## config.templates above to include those suffixes.

  ## ref: https://prometheus.io/docs/alerting/notifications/

  ##      https://prometheus.io/docs/alerting/notification_examples/

  ##

  templateFiles: {}

  #

  ## An example template:

  #   template_1.tmpl: |-

  #       {{ define "cluster" }}{{ .ExternalURL | reReplaceAll ".*alertmanager\.(.*)" "$1" }}{{ end }}

  #

  #       {{ define "slack.myorg.text" }}

  #       {{- $root := . -}}

  #       {{ range .Alerts }}

  #         *Alert:* {{ .Annotations.summary }} - `{{ .Labels.severity }}`

  #         *Cluster:*  {{ template "cluster" $root }}

  #         *Description:* {{ .Annotations.description }}

  #         *Graph:* <{{ .GeneratorURL }}|:chart_with_upwards_trend:>

  #         *Runbook:* <{{ .Annotations.runbook }}|:spiral_note_pad:>

  #         *Details:*

  #           {{ range .Labels.SortedPairs }} • *{{ .Name }}:* `{{ .Value }}`

  #           {{ end }}

  #       {{ end }}

  #       {{ end }}



  ingress:

    enabled: true



    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName

    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress

    # ingressClassName: nginx



    annotations: {}



    labels: {}



    ## Hosts must be provided if Ingress is enabled.

    ##

    hosts:

      - alertmanager.prod.test.local



    ## Paths to use for ingress rules - one path should match the alertmanagerSpec.routePrefix

    ##

    paths:

     - /



    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)

    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types

    # pathType: ImplementationSpecific



    ## TLS configuration for Alertmanager Ingress

    ## Secret must be manually created in the namespace

    ##

    tls: []

    # - secretName: alertmanager-general-tls

    #   hosts:

    #   - alertmanager.example.com



  ## Configuration for Alertmanager secret

  ##

  secret:

    annotations: {}



  ## Configuration for creating an Ingress that will map to each Alertmanager replica service

  ## alertmanager.servicePerReplica must be enabled

  ##

  ingressPerReplica:

    enabled: false



    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName

    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress

    # ingressClassName: nginx



    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: ""

    ## Domain that will be used for the per replica ingress

    hostDomain: ""



    ## Paths to use for ingress rules

    ##

    paths: []

    # - /



    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)

    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types

    # 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"



  ## Configuration for Alertmanager service

  ##

  service:

    annotations: {}

    labels: {}

    clusterIP: ""



    ## Port for Alertmanager Service to listen on

    ##

    port: 9093

    ## To be used with a proxy extraContainer port

    ##

    targetPort: 9093

    ## Port to expose on each node

    ## Only used if service.type is 'NodePort'

    ##

    nodePort: 30903

    ## List of IP addresses at which the Prometheus server service is available

    ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips

    ##



    ## Additional ports to open for Alertmanager service

    additionalPorts: []



    externalIPs: []

    loadBalancerIP: ""

    loadBalancerSourceRanges: []

    ## Service type

    ##

    type: ClusterIP



  ## Configuration for creating a separate Service for each statefulset Alertmanager replica

  ##

  servicePerReplica:

    enabled: false

    annotations: {}



    ## Port for Alertmanager Service per replica to listen on

    ##

    port: 9093



    ## To be used with a proxy extraContainer port

    targetPort: 9093



    ## Port to expose on each node

    ## Only used if servicePerReplica.type is 'NodePort'

    ##

    nodePort: 30904



    ## Loadbalancer source IP ranges

    ## Only used if servicePerReplica.type is "loadbalancer"

    loadBalancerSourceRanges: []

    ## Service type

    ##

    type: ClusterIP



  ## If true, create a serviceMonitor for alertmanager

  ##

  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    selfMonitor: true



    ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS.

    scheme: ""



    ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS.

    ## Of type: https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#tlsconfig

    tlsConfig: {}



    bearerTokenFile:



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



  ## Settings affecting alertmanagerSpec

  ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#alertmanagerspec

  ##

  alertmanagerSpec:

    ## Standard object’s metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata

    ## Metadata Labels and Annotations gets propagated to the Alertmanager pods.

    ##

    podMetadata: {}



    ## Image of Alertmanager

    ##

    image:

      repository: quay.io/prometheus/alertmanager

      tag: v0.21.0

      sha: ""



    ## If true then the user will be responsible to provide a secret with alertmanager configuration

    ## So when true the config part will be ignored (including templateFiles) and the one in the secret will be used

    ##

    useExistingSecret: false



    ## 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/.

    ##

    secrets: []



    ## ConfigMaps is a list of ConfigMaps in the same namespace as the Alertmanager object, which shall be mounted into the Alertmanager Pods.

    ## The ConfigMaps are mounted into /etc/alertmanager/configmaps/.

    ##

    configMaps: []



    ## ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for

    ## this Alertmanager instance. Defaults to 'alertmanager-' The secret is mounted into /etc/alertmanager/config.

    ##

    # configSecret:



    ## AlertmanagerConfigs to be selected to merge and configure Alertmanager with.

    ##

    alertmanagerConfigSelector: {}

    ## Example which selects all alertmanagerConfig resources

    ## with label "alertconfig" with values any of "example-config" or "example-config-2"

    # alertmanagerConfigSelector:

    #   matchExpressions:

    #     - key: alertconfig

    #       operator: In

    #       values:

    #         - example-config

    #         - example-config-2

    #

    ## Example which selects all alertmanagerConfig resources with label "role" set to "example-config"

    # alertmanagerConfigSelector:

    #   matchLabels:

    #     role: example-config



    ## Namespaces to be selected for AlertmanagerConfig discovery. If nil, only check own namespace.

    ##

    alertmanagerConfigNamespaceSelector: {}

    ## Example which selects all namespaces

    ## with label "alertmanagerconfig" with values any of "example-namespace" or "example-namespace-2"

    # alertmanagerConfigNamespaceSelector:

    #   matchExpressions:

    #     - key: alertmanagerconfig

    #       operator: In

    #       values:

    #         - example-namespace

    #         - example-namespace-2



    ## Example which selects all namespaces with label "alertmanagerconfig" set to "enabled"

    # alertmanagerConfigNamespaceSelector:

    #   matchLabels:

    #     alertmanagerconfig: enabled



    ## Define Log Format

    # Use logfmt (default) or json logging

    logFormat: logfmt



    ## Log level for Alertmanager to be configured with.

    ##

    logLevel: info



    ## 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.

    replicas: 3



    ## Time duration Alertmanager shall retain data for. Default is '120h', and must match the regular expression

    ## [0-9]+(ms|s|m|h) (milliseconds seconds minutes hours).

    ##

    retention: 120h



    ## Storage is the definition of how storage will be used by the Alertmanager instances.

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md

    ##

    storage:

     volumeClaimTemplate:

       spec:

         storageClassName: nfs-storageclass

         accessModes: ["ReadWriteMany"]

         resources:

           requests:

             storage: 10Gi

    #   selector: {}





    ##  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

    ##

    externalUrl:



    ##  The route prefix Alertmanager registers HTTP handlers for. This is useful, if using ExternalURL and a proxy is rewriting HTTP routes of a request, and the actual ExternalURL is still true,

    ## but the server serves requests under a different route prefix. For example for use with kubectl proxy.

    ##

    routePrefix: /



    ## If set to true all actions on the underlying managed objects are not going to be performed, except for delete actions.

    ##

    paused: false



    ## Define which Nodes the Pods are scheduled on.

    ## ref: https://kubernetes.io/docs/user-guide/node-selection/

    ##

    nodeSelector: {}



    ## Define resources requests and limits for single Pods.

    ## ref: https://kubernetes.io/docs/user-guide/compute-resources/

    ##

    resources: {}

    # requests:

    #   memory: 400Mi



    ## Pod anti-affinity can prevent the scheduler from placing Prometheus 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



    ## Assign custom affinity rules to the alertmanager instance

    ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

    ##

    affinity: {}

    # nodeAffinity:

    #   requiredDuringSchedulingIgnoredDuringExecution:

    #     nodeSelectorTerms:

    #     - matchExpressions:

    #       - key: kubernetes.io/e2e-az-name

    #         operator: In

    #         values:

    #         - e2e-az1

    #         - e2e-az2



    ## If specified, the pod's tolerations.

    ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/

    ##

    tolerations: []

    # - key: "key"

    #   operator: "Equal"

    #   value: "value"

    #   effect: "NoSchedule"



    ## If specified, the pod's topology spread constraints.

    ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/

    ##

    topologySpreadConstraints: []

    # - maxSkew: 1

    #   topologyKey: topology.kubernetes.io/zone

    #   whenUnsatisfiable: DoNotSchedule

    #   labelSelector:

    #     matchLabels:

    #       app: alertmanager



    ## SecurityContext holds pod-level security attributes and common container settings.

    ## This defaults to non root user with uid 1000 and gid 2000.       *v1.PodSecurityContext  false

    ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

    ##

    securityContext:

      runAsGroup: 2000

      runAsNonRoot: true

      runAsUser: 1000

      fsGroup: 2000



    ## ListenLocal makes the Alertmanager server listen on loopback, so that it does not bind against the Pod IP.

    ## Note this is only for the Alertmanager UI, not the gossip communication.

    ##

    listenLocal: false



    ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to an Alertmanager pod.

    ##

    containers: []



    # Additional volumes on the output StatefulSet definition.

    volumes: []



    # Additional VolumeMounts on the output StatefulSet definition.

    volumeMounts: []



    ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes

    ## (permissions, dir tree) on mounted volumes before starting prometheus

    initContainers: []



    ## Priority class assigned to the Pods

    ##

    priorityClassName: ""



    ## AdditionalPeers allows injecting a set of additional Alertmanagers to peer with to form a highly available cluster.

    ##

    additionalPeers: []



    ## PortName to use for Alert Manager.

    ##

    portName: "web"



    ## ClusterAdvertiseAddress is the explicit address to advertise in cluster. Needs to be provided for non RFC1918 [1] (public) addresses. [1] RFC1918: https://tools.ietf.org/html/rfc1918

    ##

    clusterAdvertiseAddress: false



    ## 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.

    forceEnableClusterMode: false





## Using default values from https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml

##

grafana:

  enabled: true

  namespaceOverride: "monitoring"



  ## Deploy default dashboards.

  ##

  defaultDashboardsEnabled: true



  adminPassword: prom-operator



  ingress:

    ## If true, Grafana Ingress will be created

    ##

    enabled: true



    ## Annotations for Grafana Ingress

    ##

    annotations: {}

      # kubernetes.io/ingress.class: nginx

      # kubernetes.io/tls-acme: "true"



    ## Labels to be added to the Ingress

    ##

    labels: {}



    ## Hostnames.

    ## Must be provided if Ingress is enable.

    ##

    hosts:

      - grafana.prod.test.local

    #hosts: []



    ## Path for grafana ingress

    path: /



    ## TLS configuration for grafana Ingress

    ## Secret must be manually created in the namespace

    ##

    tls: []

    # - secretName: grafana-general-tls

    #   hosts:

    #   - grafana.example.com



  sidecar:

    dashboards:

      enabled: true

      label: grafana_dashboard



      ## Annotations for Grafana dashboard configmaps

      ##

      annotations: {}

      multicluster: false

    datasources:

      enabled: true

      defaultDatasourceEnabled: true



      # If not defined, will use prometheus.prometheusSpec.scrapeInterval or its default

      # defaultDatasourceScrapeInterval: 15s



      ## Annotations for Grafana datasource configmaps

      ##

      annotations: {}



      ## Create datasource for each Pod of Prometheus StatefulSet;

      ## this uses headless service `prometheus-operated` which is

      ## created by Prometheus Operator

      ## ref: https://git.io/fjaBS

      createPrometheusReplicasDatasources: false

      label: grafana_datasource



  extraConfigmapMounts: []

  # - name: certs-configmap

  #   mountPath: /etc/grafana/ssl/

  #   configMap: certs-configmap

  #   readOnly: true



  ## Configure additional grafana datasources (passed through tpl)

  ## ref: http://docs.grafana.org/administration/provisioning/#datasources

  additionalDataSources: []

  # - name: prometheus-sample

  #   access: proxy

  #   basicAuth: true

  #   basicAuthPassword: pass

  #   basicAuthUser: daco

  #   editable: false

  #   jsonData:

  #       tlsSkipVerify: true

  #   orgId: 1

  #   type: prometheus

  #   url: https://{{ printf "%s-prometheus.svc" .Release.Name }}:9090

  #   version: 1



  ## Passed to grafana subchart and used by servicemonitor below

  ##

  service:

    portName: service



  ## If true, create a serviceMonitor for grafana

  ##

  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    selfMonitor: true



    # Path to use for scraping metrics. Might be different if server.root_url is set

    # in grafana.ini

    path: "/metrics"



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



## Component scraping the kube api server

##

kubeApiServer:

  enabled: true

  tlsConfig:

    serverName: kubernetes

    insecureSkipVerify: false



  ## If your API endpoint address is not reachable (as in AKS) you can replace it with the kubernetes service

  ##

  relabelings: []

  # - sourceLabels:

  #     - __meta_kubernetes_namespace

  #     - __meta_kubernetes_service_name

  #     - __meta_kubernetes_endpoint_port_name

  #   action: keep

  #   regex: default;kubernetes;https

  # - targetLabel: __address__

  #   replacement: kubernetes.default.svc:443



  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    jobLabel: component

    selector:

      matchLabels:

        component: apiserver

        provider: kubernetes



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



## Component scraping the kubelet and kubelet-hosted cAdvisor

##

kubelet:

  enabled: true

  namespace: kube-system



  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""



    ## Enable scraping the kubelet over https. For requirements to enable this see

    ## https://github.com/prometheus-operator/prometheus-operator/issues/926

    ##

    https: true



    ## Enable scraping /metrics/cadvisor from kubelet's service

    ##

    cAdvisor: true



    ## Enable scraping /metrics/probes from kubelet's service

    ##

    probes: true



    ## Enable scraping /metrics/resource from kubelet's service

    ## This is disabled by default because container metrics are already exposed by cAdvisor

    ##

    resource: true

    # From kubernetes 1.18, /metrics/resource/v1alpha1 renamed to /metrics/resource

    resourcePath: "/metrics/resource/v1alpha1"

    ## Metric relabellings to apply to samples before ingestion

    ##

    cAdvisorMetricRelabelings: []

    # - sourceLabels: [__name__, image]

    #   separator: ;

    #   regex: container_([a-z_]+);

    #   replacement: $1

    #   action: drop

    # - sourceLabels: [__name__]

    #   separator: ;

    #   regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)

    #   replacement: $1

    #   action: drop



    ## Metric relabellings to apply to samples before ingestion

    ##

    probesMetricRelabelings: []

    # - sourceLabels: [__name__, image]

    #   separator: ;

    #   regex: container_([a-z_]+);

    #   replacement: $1

    #   action: drop

    # - sourceLabels: [__name__]

    #   separator: ;

    #   regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)

    #   replacement: $1

    #   action: drop



    #   relabel configs to apply to samples before ingestion.

    #   metrics_path is required to match upstream rules and charts

    ##

    cAdvisorRelabelings:

      - sourceLabels: [__metrics_path__]

        targetLabel: metrics_path

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



    probesRelabelings:

      - sourceLabels: [__metrics_path__]

        targetLabel: metrics_path

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



    resourceRelabelings:

      - sourceLabels: [__metrics_path__]

        targetLabel: metrics_path

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



    metricRelabelings: []

    # - sourceLabels: [__name__, image]

    #   separator: ;

    #   regex: container_([a-z_]+);

    #   replacement: $1

    #   action: drop

    # - sourceLabels: [__name__]

    #   separator: ;

    #   regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)

    #   replacement: $1

    #   action: drop



    #   relabel configs to apply to samples before ingestion.

    #   metrics_path is required to match upstream rules and charts

    ##

    relabelings:

      - sourceLabels: [__metrics_path__]

        targetLabel: metrics_path

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



## Component scraping the kube controller manager

##

kubeControllerManager:

  enabled: true



  ## If your kube controller manager is not deployed as a pod, specify IPs it can be found on

  ##

  endpoints: []

  # - 10.141.4.22

  # - 10.141.4.23

  # - 10.141.4.24



  ## If using kubeControllerManager.endpoints only the port and targetPort are used

  ##

  service:

    port: 10252

    targetPort: 10252

    selector:

      k8s-app: kube-controller-manager

    #   component: kube-controller-manager



  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""



    ## Enable scraping kube-controller-manager over https.

    ## Requires proper certs (not self-signed) and delegated authentication/authorization checks

    ##

    https: false



    # Skip TLS certificate validation when scraping

    insecureSkipVerify: null



    # Name of the server to use when validating TLS certificate

    serverName: null



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



## Component scraping coreDns. Use either this or kubeDns

##

coreDns:

  enabled: true

  service:

    port: 9153

    targetPort: 9153

    # selector:

    #   k8s-app: kube-dns

  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



## Component scraping kubeDns. Use either this or coreDns

##

kubeDns:

  enabled: false

  service:

    dnsmasq:

      port: 10054

      targetPort: 10054

    skydns:

      port: 10055

      targetPort: 10055

    # selector:

    #   k8s-app: kube-dns

  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace

    dnsmasqMetricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    dnsmasqRelabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



## Component scraping etcd

##

kubeEtcd:

  enabled: true



  ## If your etcd is not deployed as a pod, specify IPs it can be found on

  ##

  endpoints: []

  # - 10.141.4.22

  # - 10.141.4.23

  # - 10.141.4.24



  ## Etcd service. If using kubeEtcd.endpoints only the port and targetPort are used

  ##

  service:

    port: 2379

    targetPort: 2379

    # selector:

    #   component: etcd



  ## Configure secure access to the etcd cluster by loading a secret into prometheus and

  ## specifying security configuration below. For example, with a secret named etcd-client-cert

  ##

  ## serviceMonitor:

  ##   scheme: https

  ##   insecureSkipVerify: false

  ##   serverName: localhost

  ##   caFile: /etc/prometheus/secrets/etcd-client-cert/etcd-ca

  ##   certFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client

  ##   keyFile: /etc/prometheus/secrets/etcd-client-cert/etcd-client-key

  ##

  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    scheme: http

    insecureSkipVerify: false

    serverName: ""

    caFile: ""

    certFile: ""

    keyFile: ""



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace





## Component scraping kube scheduler

##

kubeScheduler:

  enabled: true



  ## If your kube scheduler is not deployed as a pod, specify IPs it can be found on

  ##

  endpoints: []

  # - 10.141.4.22

  # - 10.141.4.23

  # - 10.141.4.24



  ## If using kubeScheduler.endpoints only the port and targetPort are used

  ##

  service:

    port: 10251

    targetPort: 10251

    selector:

      k8s-app: kube-scheduler

    #   component: kube-scheduler



  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    ## Enable scraping kube-scheduler over https.

    ## Requires proper certs (not self-signed) and delegated authentication/authorization checks

    ##

    https: false



    ## Skip TLS certificate validation when scraping

    insecureSkipVerify: null



    ## Name of the server to use when validating TLS certificate

    serverName: null



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace





## Component scraping kube proxy

##

kubeProxy:

  enabled: true



  ## If your kube proxy is not deployed as a pod, specify IPs it can be found on

  ##

  endpoints: []

  # - 10.141.4.22

  # - 10.141.4.23

  # - 10.141.4.24



  service:

    port: 10249

    targetPort: 10249

    # selector:

    #   k8s-app: kube-proxy



  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""



    ## Enable scraping kube-proxy over https.

    ## Requires proper certs (not self-signed) and delegated authentication/authorization checks

    ##

    https: false



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]





## Component scraping kube state metrics

##

kubeStateMetrics:

  enabled: true

  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    ## Override serviceMonitor selector

    ##

    selectorOverride: {}



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



## Configuration for kube-state-metrics subchart

##

kube-state-metrics:

  namespaceOverride: "monitoring"

  rbac:

    create: true

  podSecurityPolicy:

    enabled: true



## Deploy node exporter as a daemonset to all nodes

##

nodeExporter:

  enabled: true



  ## Use the value configured in prometheus-node-exporter.podLabels

  ##

  jobLabel: jobLabel



  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""



    ## How long until a scrape request times out. If not set, the Prometheus default scape timeout is used.

    ##

    scrapeTimeout: ""



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - sourceLabels: [__name__]

    #   separator: ;

    #   regex: ^node_mountstats_nfs_(event|operations|transport)_.+

    #   replacement: $1

    #   action: drop



    ##  relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



## Configuration for prometheus-node-exporter subchart

##

prometheus-node-exporter:

  namespaceOverride: "monitoring"

  podLabels:

    ## Add the 'node-exporter' label to be used by serviceMonitor to match standard common usage in rules and grafana dashboards

    ##

    jobLabel: node-exporter

  extraArgs:

    - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+|var/lib/kubelet/.+)($|/)

    - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$



## Manages Prometheus and Alertmanager components

##

prometheusOperator:

  enabled: true



  ## Prometheus-Operator v0.39.0 and later support TLS natively.

  ##

  tls:

    enabled: true

    # Value must match version names from https://golang.org/pkg/crypto/tls/#pkg-constants

    tlsMinVersion: VersionTLS13

    # The default webhook port is 10250 in order to work out-of-the-box in GKE private clusters and avoid adding firewall rules.

    internalPort: 10250



  ## Admission webhook support for PrometheusRules resources added in Prometheus Operator 0.30 can be enabled to prevent incorrectly formatted

  ## rules from making their way into prometheus and potentially preventing the container from starting

  admissionWebhooks:

    failurePolicy: Fail

    enabled: true

    ## A PEM encoded CA bundle which will be used to validate the webhook's server certificate.

    ## If unspecified, system trust roots on the apiserver are used.

    caBundle: ""

    ## If enabled, generate a self-signed certificate, then patch the webhook configurations with the generated data.

    ## On chart upgrades (or if the secret exists) the cert will not be re-generated. You can use this to provide your own

    ## certs ahead of time if you wish.

    ##

    patch:

      enabled: true

      image:

        repository: jettech/kube-webhook-certgen

        tag: v1.5.0

        sha: ""

        pullPolicy: IfNotPresent

      resources: {}

      ## Provide a priority class name to the webhook patching job

      ##

      priorityClassName: ""

      podAnnotations: {}

      nodeSelector: {}

      affinity: {}

      tolerations: []

    # Use certmanager to generate webhook certs

    certManager:

      enabled: false

      # issuerRef:

      #   name: "issuer"

      #   kind: "ClusterIssuer"



  ## Namespaces to scope the interaction of the Prometheus Operator and the apiserver (allow list).

  ## This is mutually exclusive with denyNamespaces. Setting this to an empty object will disable the configuration

  ##

  namespaces: {}

    # releaseNamespace: true

    # additional:

    # - kube-system



  ## Namespaces not to scope the interaction of the Prometheus Operator (deny list).

  ##

  denyNamespaces: []



  ## Filter namespaces to look for prometheus-operator custom resources

  ##

  alertmanagerInstanceNamespaces: []

  prometheusInstanceNamespaces: []

  thanosRulerInstanceNamespaces: []



  ## The clusterDomain value will be added to the cluster.peer option of the alertmanager.

  ## Without this specified option cluster.peer will have value alertmanager-monitoring-alertmanager-0.alertmanager-operated:9094 (default value)

  ## With this specified option cluster.peer will have value alertmanager-monitoring-alertmanager-0.alertmanager-operated.namespace.svc.cluster-domain:9094

  ##

  # clusterDomain: "cluster.local"



  ## Service account for Alertmanager to use.

  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

  ##

  serviceAccount:

    create: true

    name: ""



  ## Configuration for Prometheus operator service

  ##

  service:

    annotations: {}

    labels: {}

    clusterIP: ""



  ## Port to expose on each node

  ## Only used if service.type is 'NodePort'

  ##

    nodePort: 30080



    nodePortTls: 30443



  ## Additional ports to open for Prometheus service

  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#multi-port-services

  ##

    additionalPorts: []



  ## Loadbalancer IP

  ## Only use if service.type is "loadbalancer"

  ##

    loadBalancerIP: ""

    loadBalancerSourceRanges: []



  ## Service type

  ## NodePort, ClusterIP, loadbalancer

  ##

    type: ClusterIP



    ## List of IP addresses at which the Prometheus server service is available

    ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips

    ##

    externalIPs: []



  ## Labels to add to the operator pod

  ##

  podLabels: {}



  ## Annotations to add to the operator pod

  ##

  podAnnotations: {}



  ## Assign a PriorityClassName to pods if set

  # priorityClassName: ""



  ## Define Log Format

  # Use logfmt (default) or json logging

  # logFormat: logfmt



  ## Decrease log verbosity to errors only

  # logLevel: error



  ## If true, the operator will create and maintain a service for scraping kubelets

  ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/helm/prometheus-operator/README.md

  ##

  kubeletService:

    enabled: true

    namespace: kube-system



  ## Create a servicemonitor for the operator

  ##

  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    ## Scrape timeout. If not set, the Prometheus default scrape timeout is used.

    scrapeTimeout: ""

    selfMonitor: true



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



  ## Resource limits & requests

  ##

  resources: {}

  # limits:

  #   cpu: 200m

  #   memory: 200Mi

  # requests:

  #   cpu: 100m

  #   memory: 100Mi



  # Required for use in managed kubernetes clusters (such as AWS EKS) with custom CNI (such as calico),

  # because control-plane managed by AWS cannot communicate with pods' IP CIDR and admission webhooks are not working

  ##

  hostNetwork: false



  ## Define which Nodes the Pods are scheduled on.

  ## ref: https://kubernetes.io/docs/user-guide/node-selection/

  ##

  nodeSelector: {}



  ## Tolerations for use with node taints

  ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/

  ##

  tolerations: []

  # - key: "key"

  #   operator: "Equal"

  #   value: "value"

  #   effect: "NoSchedule"



  ## Assign custom affinity rules to the prometheus operator

  ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

  ##

  affinity: {}

    # nodeAffinity:

    #   requiredDuringSchedulingIgnoredDuringExecution:

    #     nodeSelectorTerms:

    #     - matchExpressions:

    #       - key: kubernetes.io/e2e-az-name

    #         operator: In

    #         values:

    #         - e2e-az1

    #         - e2e-az2

  dnsConfig: {}

    # nameservers:

    #   - 1.2.3.4

    # searches:

    #   - ns1.svc.cluster-domain.example

    #   - my.dns.search.suffix

    # options:

    #   - name: ndots

    #     value: "2"

  #   - name: edns0

  securityContext:

    fsGroup: 65534

    runAsGroup: 65534

    runAsNonRoot: true

    runAsUser: 65534



  ## Prometheus-operator image

  ##

  image:

    repository: quay.io/prometheus-operator/prometheus-operator

    tag: v0.45.0

    sha: ""

    pullPolicy: IfNotPresent



  ## Prometheus image to use for prometheuses managed by the operator

  ##

  # prometheusDefaultBaseImage: quay.io/prometheus/prometheus



  ## Alertmanager image to use for alertmanagers managed by the operator

  ##

  # alertmanagerDefaultBaseImage: quay.io/prometheus/alertmanager



  ## Prometheus-config-reloader image to use for config and rule reloading

  ##

  prometheusConfigReloaderImage:

    repository: quay.io/prometheus-operator/prometheus-config-reloader

    tag: v0.45.0

    sha: ""



  ## Set the prometheus config reloader side-car CPU limit

  ##

  configReloaderCpu: 100m



  ## Set the prometheus config reloader side-car memory limit

  ##

  configReloaderMemory: 50Mi



  ## Set a Field Selector to filter watched secrets

  ##

  secretFieldSelector: ""



## Deploy a Prometheus instance

##

prometheus:



  enabled: true



  ## Annotations for Prometheus

  ##

  annotations: {}



  ## Service account for Prometheuses to use.

  ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

  ##

  serviceAccount:

    create: true

    name: ""



  # Service for thanos service discovery on sidecar

  # Enable this can make Thanos Query can use

  # `--store=dnssrv+_grpc._tcp.${kube-prometheus-stack.fullname}-thanos-discovery.${namespace}.svc.cluster.local` to discovery

  # Thanos sidecar on prometheus nodes

  # (Please remember to change ${kube-prometheus-stack.fullname} and ${namespace}. Not just copy and paste!)

  thanosService:

    enabled: false

    annotations: {}

    labels: {}

    portName: grpc

    port: 10901

    targetPort: "grpc"



  ## Configuration for Prometheus service

  ##

  service:

    annotations: {}

    labels: {}

    clusterIP: ""



    ## Port for Prometheus Service to listen on

    ##

    port: 9090



    ## To be used with a proxy extraContainer port

    targetPort: 9090



    ## List of IP addresses at which the Prometheus server service is available

    ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips

    ##

    externalIPs: []



    ## Port to expose on each node

    ## Only used if service.type is 'NodePort'

    ##

    nodePort: 30090



    ## Loadbalancer IP

    ## Only use if service.type is "loadbalancer"

    loadBalancerIP: ""

    loadBalancerSourceRanges: []

    ## Service type

    ##

    type: ClusterIP



    sessionAffinity: ""



  ## Configuration for creating a separate Service for each statefulset Prometheus replica

  ##

  servicePerReplica:

    enabled: false

    annotations: {}



    ## Port for Prometheus Service per replica to listen on

    ##

    port: 9090



    ## To be used with a proxy extraContainer port

    targetPort: 9090



    ## Port to expose on each node

    ## Only used if servicePerReplica.type is 'NodePort'

    ##

    nodePort: 30091



    ## Loadbalancer source IP ranges

    ## Only used if servicePerReplica.type is "loadbalancer"

    loadBalancerSourceRanges: []

    ## Service type

    ##

    type: ClusterIP



  ## Configure pod disruption budgets for Prometheus

  ## ref: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget

  ## This configuration is immutable once created and will require the PDB to be deleted to be changed

  ## https://github.com/kubernetes/kubernetes/issues/45398

  ##

  podDisruptionBudget:

    enabled: false

    minAvailable: 1

    maxUnavailable: ""



  # Ingress exposes thanos sidecar outside the cluster

  thanosIngress:

    enabled: false



    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName

    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress

    # ingressClassName: nginx



    annotations: {}

    labels: {}

    servicePort: 10901



    ## Port to expose on each node

    ## Only used if service.type is 'NodePort'

    ##

    nodePort: 30901



    ## Hosts must be provided if Ingress is enabled.

    ##

    hosts: []

      # - thanos-gateway.domain.com



    ## Paths to use for ingress rules

    ##

    paths: []

    # - /



    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)

    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types

    # pathType: ImplementationSpecific



    ## TLS configuration for Thanos Ingress

    ## Secret must be manually created in the namespace

    ##

    tls: []

    # - secretName: thanos-gateway-tls

    #   hosts:

    #   - thanos-gateway.domain.com



  ingress:

    enabled: true



    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName

    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress

    # ingressClassName: nginx



    annotations: {}

    labels: {}



    ## Hostnames.

    ## Must be provided if Ingress is enabled.

    ##

    hosts:

      - prometheus.prod.test.local

    #hosts: []



    ## Paths to use for ingress rules - one path should match the prometheusSpec.routePrefix

    ##

    paths:

     - /



    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)

    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types

    # pathType: ImplementationSpecific



    ## TLS configuration for Prometheus Ingress

    ## Secret must be manually created in the namespace

    ##

    tls: []

      # - secretName: prometheus-general-tls

      #   hosts:

      #     - prometheus.example.com



  ## Configuration for creating an Ingress that will map to each Prometheus replica service

  ## prometheus.servicePerReplica must be enabled

  ##

  ingressPerReplica:

    enabled: false



    # For Kubernetes >= 1.18 you should specify the ingress-controller via the field ingressClassName

    # See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#specifying-the-class-of-an-ingress

    # ingressClassName: nginx



    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: ""

    ## Domain that will be used for the per replica ingress

    hostDomain: ""



    ## Paths to use for ingress rules

    ##

    paths: []

    # - /



    ## For Kubernetes >= 1.18 you should specify the pathType (determines how Ingress paths should be matched)

    ## See https://kubernetes.io/blog/2020/04/02/improvements-to-the-ingress-api-in-kubernetes-1.18/#better-path-matching-with-path-types

    # pathType: ImplementationSpecific



    ## Secret name containing the TLS certificate for Prometheus 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: "prometheus"



  ## Configure additional options for default pod security policy for Prometheus

  ## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/

  podSecurityPolicy:

    allowedCapabilities: []

    allowedHostPaths: []

    volumes: []



  serviceMonitor:

    ## Scrape interval. If not set, the Prometheus default scrape interval is used.

    ##

    interval: ""

    selfMonitor: true



    ## scheme: HTTP scheme to use for scraping. Can be used with `tlsConfig` for example if using istio mTLS.

    scheme: ""



    ## tlsConfig: TLS configuration to use when scraping the endpoint. For example if using istio mTLS.

    ## Of type: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#tlsconfig

    tlsConfig: {}



    bearerTokenFile:



    ##  metric relabel configs to apply to samples before ingestion.

    ##

    metricRelabelings: []

    # - action: keep

    #   regex: 'kube_(daemonset|deployment|pod|namespace|node|statefulset).+'

    #   sourceLabels: [__name__]



    #   relabel configs to apply to samples before ingestion.

    ##

    relabelings: []

    # - sourceLabels: [__meta_kubernetes_pod_node_name]

    #   separator: ;

    #   regex: ^(.*)$

    #   targetLabel: nodename

    #   replacement: $1

    #   action: replace



  ## Settings affecting prometheusSpec

  ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#prometheusspec

  ##

  prometheusSpec:

    ## If true, pass --storage.tsdb.max-block-duration=2h to prometheus. This is already done if using Thanos

    ##

    disableCompaction: false

    ## APIServerConfig

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#apiserverconfig

    ##

    apiserverConfig: {}



    ## Interval between consecutive scrapes.

    ## Defaults to 30s.

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/release-0.44/pkg/prometheus/promcfg.go#L180-L183

    ##

    scrapeInterval: ""



    ## Number of seconds to wait for target to respond before erroring

    ##

    scrapeTimeout: ""



    ## Interval between consecutive evaluations.

    ##

    evaluationInterval: ""



    ## ListenLocal makes the Prometheus server listen on loopback, so that it does not bind against the Pod IP.

    ##

    listenLocal: false



    ## EnableAdminAPI enables Prometheus the administrative HTTP API which includes functionality such as deleting time series.

    ## This is disabled by default.

    ## ref: https://prometheus.io/docs/prometheus/latest/querying/api/#tsdb-admin-apis

    ##

    enableAdminAPI: false



    ## Image of Prometheus.

    ##

    image:

      repository: quay.io/prometheus/prometheus

      tag: v2.24.0

      sha: ""



    ## Tolerations for use with node taints

    ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/

    ##

    tolerations: []

    #  - key: "key"

    #    operator: "Equal"

    #    value: "value"

    #    effect: "NoSchedule"



    ## If specified, the pod's topology spread constraints.

    ## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/

    ##

    topologySpreadConstraints: []

    # - maxSkew: 1

    #   topologyKey: topology.kubernetes.io/zone

    #   whenUnsatisfiable: DoNotSchedule

    #   labelSelector:

    #     matchLabels:

    #       app: prometheus



    ## Alertmanagers to which alerts will be sent

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#alertmanagerendpoints

    ##

    ## Default configuration will connect to the alertmanager deployed as part of this release

    ##

    alertingEndpoints: []

    # - name: ""

    #   namespace: ""

    #   port: http

    #   scheme: http

    #   pathPrefix: ""

    #   tlsConfig: {}

    #   bearerTokenFile: ""

    #   apiVersion: v2



    ## External labels to add to any time series or alerts when communicating with external systems

    ##

    externalLabels: {}



    ## Name of the external label used to denote replica name

    ##

    replicaExternalLabelName: ""



    ## If true, the Operator won't add the external label used to denote replica name

    ##

    replicaExternalLabelNameClear: false



    ## Name of the external label used to denote Prometheus instance name

    ##

    prometheusExternalLabelName: ""



    ## If true, the Operator won't add the external label used to denote Prometheus instance name

    ##

    prometheusExternalLabelNameClear: false



    ## External URL at which Prometheus will be reachable.

    ##

    externalUrl: ""



    ## Define which Nodes the Pods are scheduled on.

    ## ref: https://kubernetes.io/docs/user-guide/node-selection/

    ##

    nodeSelector: {}



    ## Secrets is a list of Secrets in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods.

    ## The Secrets are mounted into /etc/prometheus/secrets/. Secrets changes after initial creation of a Prometheus object are not

    ## reflected in the running Pods. To change the secrets mounted into the Prometheus Pods, the object must be deleted and recreated

    ## with the new list of secrets.

    ##

    secrets: []



    ## ConfigMaps is a list of ConfigMaps in the same namespace as the Prometheus object, which shall be mounted into the Prometheus Pods.

    ## The ConfigMaps are mounted into /etc/prometheus/configmaps/.

    ##

    configMaps: []



    ## QuerySpec defines the query command line flags when starting Prometheus.

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#queryspec

    ##

    query: {}



    ## Namespaces to be selected for PrometheusRules discovery.

    ## If nil, select own namespace. Namespaces to be selected for ServiceMonitor discovery.

    ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage

    ##

    ruleNamespaceSelector: {}



    ## If true, a nil or {} value for prometheus.prometheusSpec.ruleSelector will cause the

    ## prometheus resource to be created with selectors based on values in the helm deployment,

    ## which will also match the PrometheusRule resources created

    ##

    ruleSelectorNilUsesHelmValues: true



    ## PrometheusRules to be selected for target discovery.

    ## If {}, select all ServiceMonitors

    ##

    ruleSelector: {}

    ## Example which select all prometheusrules resources

    ## with label "prometheus" with values any of "example-rules" or "example-rules-2"

    # ruleSelector:

    #   matchExpressions:

    #     - key: prometheus

    #       operator: In

    #       values:

    #         - example-rules

    #         - example-rules-2

    #

    ## Example which select all prometheusrules resources with label "role" set to "example-rules"

    # ruleSelector:

    #   matchLabels:

    #     role: example-rules



    ## If true, a nil or {} value for prometheus.prometheusSpec.serviceMonitorSelector will cause the

    ## prometheus resource to be created with selectors based on values in the helm deployment,

    ## which will also match the servicemonitors created

    ##

    serviceMonitorSelectorNilUsesHelmValues: true



    ## ServiceMonitors to be selected for target discovery.

    ## If {}, select all ServiceMonitors

    ##

    serviceMonitorSelector: {}

    ## Example which selects ServiceMonitors with label "prometheus" set to "somelabel"

    # serviceMonitorSelector:

    #   matchLabels:

    #     prometheus: somelabel



    ## Namespaces to be selected for ServiceMonitor discovery.

    ##

    serviceMonitorNamespaceSelector:

       matchLabels:

         prometheus: enabled



    ## Example which selects ServiceMonitors in namespaces with label "prometheus" set to "somelabel"

    # serviceMonitorNamespaceSelector:

    #   matchLabels:

    #     prometheus: somelabel



    ## If true, a nil or {} value for prometheus.prometheusSpec.podMonitorSelector will cause the

    ## prometheus resource to be created with selectors based on values in the helm deployment,

    ## which will also match the podmonitors created

    ##

    podMonitorSelectorNilUsesHelmValues: true



    ## PodMonitors to be selected for target discovery.

    ## If {}, select all PodMonitors

    ##

    podMonitorSelector: {}

    ## Example which selects PodMonitors with label "prometheus" set to "somelabel"

    # podMonitorSelector:

    #   matchLabels:

    #     prometheus: somelabel



    ## Namespaces to be selected for PodMonitor discovery.

    ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage

    ##

    podMonitorNamespaceSelector: {}



    ## If true, a nil or {} value for prometheus.prometheusSpec.probeSelector will cause the

    ## prometheus resource to be created with selectors based on values in the helm deployment,

    ## which will also match the probes created

    ##

    probeSelectorNilUsesHelmValues: true



    ## Probes to be selected for target discovery.

    ## If {}, select all Probes

    ##

    probeSelector: {}

    ## Example which selects Probes with label "prometheus" set to "somelabel"

    # probeSelector:

    #   matchLabels:

    #     prometheus: somelabel



    ## Namespaces to be selected for Probe discovery.

    ## See https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#namespaceselector for usage

    ##

    probeNamespaceSelector: {}



    ## How long to retain metrics

    ##

    retention: 10d



    ## Maximum size of metrics

    ##

    retentionSize: ""



    ## Enable compression of the write-ahead log using Snappy.

    ##

    walCompression: false



    ## If true, the Operator won't process any Prometheus configuration changes

    ##

    paused: false



    ## Number of replicas of each shard to deploy for a Prometheus deployment.

    ## Number of replicas multiplied by shards is the total number of Pods created.

    ##

    replicas: 1



    ## EXPERIMENTAL: Number of shards to distribute targets onto.

    ## Number of replicas multiplied by shards is the total number of Pods created.

    ## Note that scaling down shards will not reshard data onto remaining instances, it must be manually moved.

    ## Increasing shards will not reshard data either but it will continue to be available from the same instances.

    ## To query globally use Thanos sidecar and Thanos querier or remote write data to a central location.

    ## Sharding is done on the content of the `__address__` target meta-label.

    ##

    shards: 1



    ## Log level for Prometheus be configured in

    ##

    logLevel: info



    ## Log format for Prometheus be configured in

    ##

    logFormat: logfmt



    ## Prefix used to register routes, overriding externalUrl route.

    ## Useful for proxies that rewrite URLs.

    ##

    routePrefix: /



    ## Standard object’s metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata

    ## Metadata Labels and Annotations gets propagated to the prometheus pods.

    ##

    podMetadata: {}

    # labels:

    #   app: prometheus

    #   k8s-app: prometheus



    ## Pod anti-affinity can prevent the scheduler from placing Prometheus 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



    ## Assign custom affinity rules to the prometheus instance

    ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

    ##

    affinity: {}

    # nodeAffinity:

    #   requiredDuringSchedulingIgnoredDuringExecution:

    #     nodeSelectorTerms:

    #     - matchExpressions:

    #       - key: kubernetes.io/e2e-az-name

    #         operator: In

    #         values:

    #         - e2e-az1

    #         - e2e-az2



    ## The remote_read spec configuration for Prometheus.

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#remotereadspec

    remoteRead: []

    # - url: http://remote1/read



    ## The remote_write spec configuration for Prometheus.

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#remotewritespec

    remoteWrite: []

    # - url: http://remote1/push



    ## Enable/Disable Grafana dashboards provisioning for prometheus remote write feature

    remoteWriteDashboards: false



    ## Resource limits & requests

    ##

    resources: {}

    # requests:

    #   memory: 400Mi



    ## Prometheus StorageSpec for persistent data

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/storage.md

    ##

    storageSpec:

    ## Using PersistentVolumeClaim

    ##

      volumeClaimTemplate:

        spec:

          storageClassName: nfs-storageclass

          accessModes: ["ReadWriteMany"]

          resources:

            requests:

              storage: 10Gi

    #    selector: {}



    ## Using tmpfs volume

    ##

    #  emptyDir:

    #    medium: Memory



    # Additional volumes on the output StatefulSet definition.

    volumes: []



    # Additional VolumeMounts on the output StatefulSet definition.

    volumeMounts: []



    ## AdditionalScrapeConfigs allows specifying additional Prometheus scrape configurations. Scrape configurations

    ## are appended to the configurations generated by the Prometheus Operator. Job configurations must have the form

    ## as specified in the official Prometheus documentation:

    ## https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config. As scrape configs are

    ## appended, the user is responsible to make sure it is valid. Note that using this feature may expose the possibility

    ## to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible

    ## scrape configs are going to break Prometheus after the upgrade.

    ##

    ## The scrape configuration example below will find master nodes, provided they have the name .*mst.*, relabel the

    ## port to 2379 and allow etcd scraping provided it is running on all Kubernetes master nodes

    ##

    additionalScrapeConfigs: []

    # - job_name: kube-etcd

    #   kubernetes_sd_configs:

    #     - role: node

    #   scheme: https

    #   tls_config:

    #     ca_file:   /etc/prometheus/secrets/etcd-client-cert/etcd-ca

    #     cert_file: /etc/prometheus/secrets/etcd-client-cert/etcd-client

    #     key_file:  /etc/prometheus/secrets/etcd-client-cert/etcd-client-key

    #   relabel_configs:

    #   - action: labelmap

    #     regex: __meta_kubernetes_node_label_(.+)

    #   - source_labels: [__address__]

    #     action: replace

    #     targetLabel: __address__

    #     regex: ([^:;]+):(d+)

    #     replacement: ${1}:2379

    #   - source_labels: [__meta_kubernetes_node_name]

    #     action: keep

    #     regex: .*mst.*

    #   - source_labels: [__meta_kubernetes_node_name]

    #     action: replace

    #     targetLabel: node

    #     regex: (.*)

    #     replacement: ${1}

    #   metric_relabel_configs:

    #   - regex: (kubernetes_io_hostname|failure_domain_beta_kubernetes_io_region|beta_kubernetes_io_os|beta_kubernetes_io_arch|beta_kubernetes_io_instance_type|failure_domain_beta_kubernetes_io_zone)

    #     action: labeldrop



    ## If additional scrape configurations are already deployed in a single secret file you can use this section.

    ## Expected values are the secret name and key

    ## Cannot be used with additionalScrapeConfigs

    additionalScrapeConfigsSecret: {}

      # enabled: false

      # name:

      # key:



    ## additionalPrometheusSecretsAnnotations allows to add annotations to the kubernetes secret. This can be useful

    ## when deploying via spinnaker to disable versioning on the secret, strategy.spinnaker.io/versioned: 'false'

    additionalPrometheusSecretsAnnotations: {}



    ## AdditionalAlertManagerConfigs allows for manual configuration of alertmanager jobs in the form as specified

    ## in the official Prometheus documentation https://prometheus.io/docs/prometheus/latest/configuration/configuration/#<alertmanager_config>.

    ## AlertManager configurations specified are appended to the configurations generated by the Prometheus Operator.

    ## As AlertManager configs are appended, the user is responsible to make sure it is valid. Note that using this

    ## feature may expose the possibility to break upgrades of Prometheus. It is advised to review Prometheus release

    ## notes to ensure that no incompatible AlertManager configs are going to break Prometheus after the upgrade.

    ##

    additionalAlertManagerConfigs: []

    # - consul_sd_configs:

    #   - server: consul.dev.test:8500

    #     scheme: http

    #     datacenter: dev

    #     tag_separator: ','

    #     services:

    #       - metrics-prometheus-alertmanager



    ## AdditionalAlertRelabelConfigs allows specifying Prometheus alert relabel configurations. Alert relabel configurations specified are appended

    ## to the configurations generated by the Prometheus Operator. Alert relabel configurations specified must have the form as specified in the

    ## official Prometheus documentation: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#alert_relabel_configs.

    ## As alert relabel configs are appended, the user is responsible to make sure it is valid. Note that using this feature may expose the

    ## possibility to break upgrades of Prometheus. It is advised to review Prometheus release notes to ensure that no incompatible alert relabel

    ## configs are going to break Prometheus after the upgrade.

    ##

    additionalAlertRelabelConfigs: []

    # - separator: ;

    #   regex: prometheus_replica

    #   replacement: $1

    #   action: labeldrop



    ## SecurityContext holds pod-level security attributes and common container settings.

    ## This defaults to non root user with uid 1000 and gid 2000.

    ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md

    ##

    securityContext:

      runAsGroup: 2000

      runAsNonRoot: true

      runAsUser: 1000

      fsGroup: 2000



    ##  Priority class assigned to the Pods

    ##

    priorityClassName: ""



    ## Thanos configuration allows configuring various aspects of a Prometheus server in a Thanos environment.

    ## This section is experimental, it may change significantly without deprecation notice in any release.

    ## This is experimental and may change significantly without backward compatibility in any release.

    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#thanosspec

    ##

    thanos: {}



    ## Containers allows injecting additional containers. This is meant to allow adding an authentication proxy to a Prometheus pod.

    ##  if using proxy extraContainer  update targetPort with proxy container port

    containers: []



    ## InitContainers allows injecting additional initContainers. This is meant to allow doing some changes

    ## (permissions, dir tree) on mounted volumes before starting prometheus

    initContainers: []



    ## PortName to use for Prometheus.

    ##

    portName: "web"



    ## ArbitraryFSAccessThroughSMs configures whether configuration based on a service monitor can access arbitrary files

    ## on the file system of the Prometheus container e.g. bearer token files.

    arbitraryFSAccessThroughSMs: false



    ## OverrideHonorLabels if set to true overrides all user configured honor_labels. If HonorLabels is set in ServiceMonitor

    ## or PodMonitor to true, this overrides honor_labels to false.

    overrideHonorLabels: false



    ## OverrideHonorTimestamps allows to globally enforce honoring timestamps in all scrape configs.

    overrideHonorTimestamps: false



    ## IgnoreNamespaceSelectors if set to true will ignore NamespaceSelector settings from the podmonitor and servicemonitor

    ## configs, and they will only discover endpoints within their current namespace. Defaults to false.

    ignoreNamespaceSelectors: false



    ## PrometheusRulesExcludedFromEnforce - list of prometheus rules to be excluded from enforcing of adding namespace labels.

    ## Works only if enforcedNamespaceLabel set to true. Make sure both ruleNamespace and ruleName are set for each pair

    prometheusRulesExcludedFromEnforce: false



    ## QueryLogFile specifies the file to which PromQL queries are logged. Note that this location must be writable,

    ## and can be persisted using an attached volume. Alternatively, the location can be set to a stdout location such

    ## as /dev/stdout to log querie information to the default Prometheus log stream. This is only available in versions

    ## of Prometheus >= 2.16.0. For more details, see the Prometheus docs (https://prometheus.io/docs/guides/query-log/)

    queryLogFile: false



    ## EnforcedSampleLimit defines global limit on number of scraped samples that will be accepted. This overrides any SampleLimit

    ## set per ServiceMonitor or/and PodMonitor. It is meant to be used by admins to enforce the SampleLimit to keep overall

    ## number of samples/series under the desired limit. Note that if SampleLimit is lower that value will be taken instead.

    enforcedSampleLimit: false



    ## AllowOverlappingBlocks enables vertical compaction and vertical query merge in Prometheus. This is still experimental

    ## in Prometheus so it may change in any upcoming release.

    allowOverlappingBlocks: false



  additionalRulesForClusterRole: []

  #  - apiGroups: [ "" ]

  #    resources:

  #      - nodes/proxy

  #    verbs: [ "get", "list", "watch" ]



  additionalServiceMonitors: []

  ## Name of the ServiceMonitor to create

  ##

    #- name: ""



    ## Additional labels to set used for the ServiceMonitorSelector. Together with standard labels from

    ## the chart

    ##

    # additionalLabels: {}



    ## Service label for use in assembling a job name of the form <label value>-<port>

    ## If no label is specified, the service name is used.

    ##

    # jobLabel: ""



    ## labels to transfer from the kubernetes service to the target

    ##

    # targetLabels: []



    ## labels to transfer from the kubernetes pods to the target

    ##

    # podTargetLabels: []



    ## Label selector for services to which this ServiceMonitor applies

    ##

    # selector: {}



    ## Namespaces from which services are selected

    ##

    # namespaceSelector: []

      ## Match any namespace

      ##

      # any: false



      ## Explicit list of namespace names to select

      ##

      # matchNames: []



    ## Endpoints of the selected service to be monitored

    ##

    # endpoints: []

      ## Name of the endpoint's service port

      ## Mutually exclusive with targetPort

      # - port: ""



      ## Name or number of the endpoint's target port

      ## Mutually exclusive with port

      # - targetPort: ""



      ## File containing bearer token to be used when scraping targets

      ##

      #   bearerTokenFile: ""



      ## Interval at which metrics should be scraped

      ##

      #   interval: 30s



      ## HTTP path to scrape for metrics

      ##

      #   path: /metrics



      ## HTTP scheme to use for scraping

      ##

      #   scheme: http



      ## TLS configuration to use when scraping the endpoint

      ##

      #   tlsConfig:



          ## Path to the CA file

          ##

          # caFile: ""



          ## Path to client certificate file

          ##

          # certFile: ""



          ## Skip certificate verification

          ##

          # insecureSkipVerify: false



          ## Path to client key file

          ##

          # keyFile: ""



          ## Server name used to verify host name

          ##

          # serverName: ""



  additionalPodMonitors: []

  ## Name of the PodMonitor to create

  ##

  # - name: ""



    ## Additional labels to set used for the PodMonitorSelector. Together with standard labels from

    ## the chart

    ##

    # additionalLabels: {}



    ## Pod label for use in assembling a job name of the form <label value>-<port>

    ## If no label is specified, the pod endpoint name is used.

    ##

    # jobLabel: ""



    ## Label selector for pods to which this PodMonitor applies

    ##

    # selector: {}



    ## PodTargetLabels transfers labels on the Kubernetes Pod onto the target.

    ##

    # podTargetLabels: {}



    ## SampleLimit defines per-scrape limit on number of scraped samples that will be accepted.

    ##

    # sampleLimit: 0



    ## Namespaces from which pods are selected

    ##

    # namespaceSelector:

      ## Match any namespace

      ##

      # any: false



      ## Explicit list of namespace names to select

      ##

      # matchNames: []



    ## Endpoints of the selected pods to be monitored

    ## https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/api.md#podmetricsendpoint

    ##

    # podMetricsEndpoints: []





Настроим Elasticsearch-exporter




он есть в том же репозитории:
https://github.com/prometheus-community/helm-charts.git с которого мы запускали сам prometheus, лежит он тут:




helm-charts/charts/prometheus-elasticsearch-exporter




!!!!!!!!!!!!сам elasticsearch уже должен быть установлен.




смотрим нужные нам данные:




правим переменные:




vim helm-charts/charts/prometheus-elasticsearch-exporter/values.yaml




ранее мы добавляли лейбл командой:
проставим на них label release=prometheus
kubectl label namespace —all «prometheus=enabled»




проверяем что всё ок




kubectl get ns --show-labels | grep elk

elk                      Active   71d    prometheus=enabled





теперь смотрим на какое имя нам надо будет ссылаться:




kubectl get service -n elk | grep 9200

elasticsearch-master            ClusterIP   13.100.200.219   <none>        9200/TCP,9300/TCP   28d

elasticsearch-master-headless   ClusterIP   None             <none>        9200/TCP,9300/TCP   28d




в конфиге будем указывать elasticsearch-master




смотрим какие есть лейблы на этом сервисе:




kubectl describe service -n elk elasticsearch-master | grep -A4 Labels

Labels:            app=elasticsearch-master

                   app.kubernetes.io/managed-by=Helm

                   chart=elasticsearch

                   heritage=Helm

                   release=elasticsearch




нас интересует app=elasticsearch-master




правим конфиг:




vim prometheus-elasticsearch-exporter/values.yaml




es:

  uri: http://elasticsearch-master:9200



serviceMonitor:

  ## If true, a ServiceMonitor CRD is created for a prometheus operator

  ## https://github.com/coreos/prometheus-operator

  ##

  enabled: true

  namespace: monitoring

  labels:

    app: elasticsearch-master

    release: prometheus

  interval: 10s

  scrapeTimeout: 10s

  scheme: http

  relabelings: []

  targetLabels:

    app: elasticsearch-master

    release: prometheus

  metricRelabelings: []

  sampleLimit: 0






в полном виде конфиг выглядит так:




## number of exporter instances

##

replicaCount: 1



## restart policy for all containers

##

restartPolicy: Always



image:

  repository: justwatch/elasticsearch_exporter

  tag: 1.1.0

  pullPolicy: IfNotPresent

  pullSecret: ""



## Set enabled to false if you don't want securityContext

## in your Deployment.

## The below values are the default for kubernetes.

## Openshift won't deploy with runAsUser: 1000 without additional permissions.

securityContext:

  enabled: true  # Should be set to false when running on OpenShift

  runAsUser: 1000



# Custom DNS configuration to be added to prometheus-elasticsearch-exporter pods

dnsConfig: {}

# nameservers:

#   - 1.2.3.4

# searches:

#   - ns1.svc.cluster-domain.example

#   - my.dns.search.suffix

# options:

#   - name: ndots

#     value: "2"

#   - name: edns0



log:

  format: logfmt

  level: info



resources: {}

  # requests:

  #   cpu: 100m

  #   memory: 128Mi

  # limits:

  #   cpu: 100m

  #   memory: 128Mi



priorityClassName: ""



nodeSelector: {}



tolerations: []



podAnnotations: {}



podLabels: {}



affinity: {}



service:

  type: ClusterIP

  httpPort: 9108

  metricsPort:

    name: http

  annotations: {}

  labels: {}



## Extra environment variables that will be passed into the exporter pod

## example:

## env:

##   KEY_1: value1

##   KEY_2: value2

env: {}



## The name of a secret in the same kubernetes namespace which contain values to be added to the environment

## This can be useful for auth tokens, etc

envFromSecret: ""



## A list of environment variables from secret refs that will be passed into the exporter pod

## example:

## This will set ${ES_PASSWORD} to the 'password' key from the 'my-secret' secret

## extraEnvSecrets:

##   ES_PASSWORD:

##     secret: my-secret

##     key: password

extraEnvSecrets: {}



# A list of secrets and their paths to mount inside the pod

# This is useful for mounting certificates for security

secretMounts: []

#  - name: elastic-certs

#    secretName: elastic-certs

#    path: /ssl



# A list of additional Volume to add to the deployment

# this is useful if the volume you need is not a secret (csi volume etc.)

extraVolumes: []

#  - name: csi-volume

#    csi:

#      driver: secrets-store.csi.k8s.io

#      readOnly: true

#      volumeAttributes:

#        secretProviderClass: my-spc



#  A list of additional VolumeMounts to add to the deployment

#  this is useful for mounting any other needed resource into

#  the elasticsearch-exporter pod

extraVolumeMounts: []

#  - name: csi-volume

#    mountPath: /csi/volume

#    readOnly: true



es:

  ## Address (host and port) of the Elasticsearch node we should connect to.

  ## This could be a local node (localhost:9200, for instance), or the address

  ## of a remote Elasticsearch server. When basic auth is needed,

  ## specify as: <proto>://<user>:<password>@<host>:<port>. e.g., http://admin:pass@localhost:9200.

  ##

  uri: http://elasticsearch-master:9200



  ## If true, query stats for all nodes in the cluster, rather than just the

  ## node we connect to.

  ##

  all: true



  ## If true, query stats for all indices in the cluster.

  ##

  indices: true



  ## If true, query settings stats for all indices in the cluster.

  ##

  indices_settings: true



  ## If true, query stats for shards in the cluster.

  ##

  shards: true



  ## If true, query stats for snapshots in the cluster.

  ##

  snapshots: true



  ## If true, query stats for cluster settings.

  ##

  cluster_settings: false



  ## Timeout for trying to get stats from Elasticsearch. (ex: 20s)

  ##

  timeout: 30s



  ## Skip SSL verification when connecting to Elasticsearch

  ## (only available if image.tag >= 1.0.4rc1)

  ##

  sslSkipVerify: false





  ssl:

    ## If true, a secure connection to ES cluster is used

    ##

    enabled: false



    ## If true, certs from secretMounts will be need to be referenced instead of certs below

    ##

    useExistingSecrets: false



    ca:



      ## PEM that contains trusted CAs used for setting up secure Elasticsearch connection

      ##

      # pem:



      # Path of ca pem file which should match a secretMount path

      path: /ssl/ca.pem

    client:

      ## if true, client SSL certificate is used for authentication

      ##

      enabled: true



      ## PEM that contains the client cert to connect to Elasticsearch.

      ##

      # pem:



      # Path of client pem file which should match a secretMount path

      pemPath: /ssl/client.pem



      ## Private key for client auth when connecting to Elasticsearch

      ##

      # key:



      # Path of client key file which should match a secretMount path

      keyPath: /ssl/client.key

web:

  ## Path under which to expose metrics.

  ##

  path: /metrics



serviceMonitor:

  ## If true, a ServiceMonitor CRD is created for a prometheus operator

  ## https://github.com/coreos/prometheus-operator

  ##

  enabled: true

  namespace: monitoring

  labels:

    app: elasticsearch-master

    release: prometheus

  interval: 10s

  scrapeTimeout: 10s

  scheme: http

  relabelings: []

  targetLabels:

    app: elasticsearch-master

    release: prometheus

  metricRelabelings: []

  sampleLimit: 0



prometheusRule:

  ## If true, a PrometheusRule CRD is created for a prometheus operator

  ## https://github.com/coreos/prometheus-operator

  ##

  ## The rules will be processed as Helm template, allowing to set variables in them.

  enabled: false

  #  namespace: monitoring

  labels: {}

  rules: []

    # - record: elasticsearch_filesystem_data_used_percent

    #   expr: |

    #     100 * (elasticsearch_filesystem_data_size_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}"} - elasticsearch_filesystem_data_free_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}"})

    #     / elasticsearch_filesystem_data_size_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}"}

    # - record: elasticsearch_filesystem_data_free_percent

    #   expr: 100 - elasticsearch_filesystem_data_used_percent{service="{{ template "elasticsearch-exporter.fullname" . }}"}

    # - alert: ElasticsearchTooFewNodesRunning

    #   expr: elasticsearch_cluster_health_number_of_nodes{service="{{ template "elasticsearch-exporter.fullname" . }}"} < 3

    #   for: 5m

    #   labels:

    #     severity: critical

    #   annotations:

    #     description: There are only {{ "{{ $value }}" }} < 3 ElasticSearch nodes running

    #     summary: ElasticSearch running on less than 3 nodes

    # - alert: ElasticsearchHeapTooHigh

    #   expr: |

    #     elasticsearch_jvm_memory_used_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}", area="heap"} / elasticsearch_jvm_memory_max_bytes{service="{{ template "elasticsearch-exporter.fullname" . }}", area="heap"}

    #     > 0.9

    #   for: 15m

    #   labels:

    #     severity: critical

    #   annotations:

    #     description: The heap usage is over 90% for 15m

    #     summary: ElasticSearch node {{ "{{ $labels.node }}" }} heap usage is high



# Create a service account

# To use a service account not handled by the chart, set the name here

# and set create to false

serviceAccount:

  create: false

  name: default



# Creates a PodSecurityPolicy and the role/rolebinding

# allowing the serviceaccount to use it

podSecurityPolicies:

  enabled: false





можем устанавливать:




helm install elasticsearch-exporter —values prometheus-elasticsearch-exporter/values.yaml prometheus-elasticsearch-exporter/ -n elk




через какое-то время появится target





4.exporter rabbitmq




прогоняем label по всем namespace
kubectl label namespace —all «prometheus=enabled»




у меня уже установлен rabbitmq в кластере в namespace rabbitmq, прометеус в namespace monitoring




пароль от rabbitmq у меня закрыт в секрете:




kubectl get secrets -n rabbitmq  | grep pass

secret-admin-password            Opaque                                1      4d22h





vim prometheus-rabbitmq-exporter/values.yaml




loglevel: info

rabbitmq:

  url: http://rabbitmq-headless.rabbitmq.svc.test.local:15672

  user: admin

  password: secret-admin-password

  # If existingPasswordSecret is set then password is ignored

  existingPasswordSecret: ~







prometheus:

  monitor:

    enabled: true

    additionalLabels:

      release: prometheus

    interval: 15s

    namespace: []




helm install rabbitmq-exporter prometheus-rabbitmq-exporter/ -n monitoring —values prometheus-rabbitmq-exporter/values.yaml




5. exporter redis




прогоняем label по всем namespace
kubectl label namespace —all «prometheus=enabled»




у меня уже установлен redis в кластере в namespace redis, прометеус в namespace monitoring




пароль от redis у меня закрыт в секрете:




[root@prod-vsrv-kubemaster1 charts]# kubectl get secrets -n redis  | grep -E 'NAME|password'

NAME                                                   TYPE                                  DATA   AGE

redis-password                                         Opaque                                1      27h





vim prometheus-redis-exporter/values.yaml




redisAddress: redis://redis-cluster-headless.redis.svc.test.local:6379



serviceMonitor:

  enabled: true

  namespace: monitoring

  # Set labels for the ServiceMonitor, use this to define your scrape label for Prometheus Operator

  labels:

    release: prometheus



auth:

  # Use password authentication

  enabled: true

  # Use existing secret (ignores redisPassword)

  secret:

    name: redis-password

    key: redis-password





helm install redis-exporter prometheus-redis-exporter/ -n redis —values prometheus-redis-exporter/values.yaml




6. настройка оповещений в telegram




Для начала создадим telegram bot





идём на  @BotFather




нажимаем start и получаем список команд:





 /newbot — отправляем ему и бот просит придумать имя нашему новому боту. Единственное ограничение на имя — оно должно оканчиваться на «bot». В случае успеха BotFather возвращает токен бота и ссылку для быстрого добавления бота в контакты, иначе придется поломать голову над именем.





всё мы зарегались, теперь этот токен можно использовать при подключении нашего алертменеджера к телеграму




cat default.tmpl




{{ define "telegram.default" }}

{{ range .Alerts }}

{{ if eq .Status "firing"}}?  <b>{{ .Status | toUpper }}</b> ? {{ else }}<b>{{ .Status | toUpper }}</b>{{ end }}

<b>{{ .Labels.alertname }}</b>

{{ .Annotations.message }} {{ .Annotations.description }}

<b>Duration:</b> {{ duration .StartsAt .EndsAt }}{{ if ne .Status "firing"}}

<b>Ended:</b> {{ .EndsAt | since }}{{ end }}

{{ end }}

{{ end }}





cat Dockerfile




FROM metalmatze/alertmanager-bot:0.4.2



COPY ./default.tmpl /templates/default.tmpl




собираем образ пушим в наш гитлаб




далее идём в телеграмм в канал:




userinfobot
печатаем старт и получаем наш id




далее выполняем:




echo -n «4196184» | base64
получаем хэш
NDE5NjE4NA==




а так же получаем хэш нашего телеграм токена:




echo -n «1788359733:AAFf3cK6dfEPHV5e7ePXnHP6x6GHWzEQoSw» | base64
MTc4ODM1OTczMzpBQUZmM2NLNmRmRVBIVjVlN2VQWG5IUDZ4NkdIV3pFUW9Tdw==




создаём deployment




cat telegrambot.yml




apiVersion: v1

items:

- apiVersion: v1

  data:

    admin1: NDE5NjE4NA

    admin2: NTY

    admin3: NDE5

    token: MTc4ODM1OTczMzpBQUZmM2NLNmRmRVBIVjVlN2VQWG5IUDZ4NkdIV3pFUW9Tdw==

  kind: Secret

  metadata:

    labels:

      app.kubernetes.io/name: alertmanager-bot

    name: alertmanager-bot

    namespace: monitoring

  type: Opaque

- apiVersion: v1

  kind: Service

  metadata:

    labels:

      app.kubernetes.io/name: alertmanager-bot

    name: alertmanager-bot

    namespace: monitoring

  spec:

    ports:

    - name: http

      port: 8080

      targetPort: 8080

    selector:

      app.kubernetes.io/name: alertmanager-bot

- apiVersion: apps/v1

  kind: StatefulSet

  metadata:

    labels:

      app.kubernetes.io/name: alertmanager-bot

    name: alertmanager-bot

    namespace: monitoring

  spec:

    podManagementPolicy: OrderedReady

    replicas: 1

    selector:

      matchLabels:

        app.kubernetes.io/name: alertmanager-bot

    serviceName: alertmanager-bot

    template:

      metadata:

        labels:

          app.kubernetes.io/name: alertmanager-bot

        name: alertmanager-bot

        namespace: monitoring

      spec:

        containers:

        - args:

          - --alertmanager.url=http://alertmanager-operated:9093

          - --log.level=info

          - --store=bolt

          - --bolt.path=/data/bot.db

          - --telegram.admin=4196184

          - --telegram.admin=56

          - --telegram.admin=41

          env:

     #     - name: TELEGRAM_ADMIN

     #       valueFrom:

     #         secretKeyRef:

     #           key: admin

     #           name: alertmanager-bot

          - name: TELEGRAM_TOKEN

            valueFrom:

              secretKeyRef:

                key: token

                name: alertmanager-bot

          image: gitlab.test.local:4567/monitoring/alertbot

          imagePullPolicy: IfNotPresent

          name: alertmanager-bot

          ports:

          - containerPort: 8080

            name: http

          resources:

            limits:

              cpu: 100m

              memory: 128Mi

            requests:

              cpu: 25m

              memory: 64Mi

          volumeMounts:

          - mountPath: /data

            name: alertmanager-bot

        restartPolicy: Always

        imagePullSecrets:

        - name: regcred



    volumeClaimTemplates:

    - metadata:

        labels:

          app.kubernetes.io/name: alertmanager-bot

        name: alertmanager-bot

        namespace: monitoring

      spec:

        accessModes:

        - ReadWriteMany

        resources:

          requests:

            storage: 1Gi

        storageClassName: nfs-storageclass

kind: List





admin1 — тут указываю хэши id пользователей которые будут заходить
token — тут указываем токен нашего телеграм бота (хэш)
namespace — тут указываем неймспейс в котором у нас запущен prometheus
image — тут указываем образ телеграмбота пересобранного и  загруженного в наш гитлаб
— —telegram.admin — тут id пользователей в открытом виде




можем запускать:
kubectl apply -f telegrambot.yml




всё можно проверять:
пишем /start
и бот отвечает:





6.1 настройка оповещений в telegram, в различные чаты(группы)




Задача — настроить оповещения в разные чаты телеграмма




за основу будет взят телеграм бот:
https://github.com/inCaller/prometheus_bot
который был заточен под helm chart
https://github.com/gvych/telegram-bot-helm-chart
отмечу сразу что его надо дописывать в values так как с нуля он не стартует.




приступим, создаём в телеграм новую группу:





добавляем нашего бота которого мы создали в предыдущем пункте, так как я дополняю статью позже, то имя бота у меня другое:






далее добавляем к группе бота который позволит увидеть chatid








вот мы получили chatid запомним его.




Выкачиваем репозиторий:




git clone https://github.com/gvych/telegram-bot-helm-chart.git




cd telegram-bot-helm-chart




правим версию для deployment и выславляем selector изначально их нету в гите, общий вид будет такой:




cat telegram-bot/templates/deployment.yaml




{{- if not .Values.application.initializeCommand -}}

apiVersion: apps/v1

kind: Deployment

metadata:

  name: {{ template "trackableappname" . }}

  labels:

    app: {{ template "appname" . }}

    track: "{{ .Values.application.track }}"

    tier: "{{ .Values.application.tier }}"

    chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"

    release: {{ .Release.Name }}

    heritage: {{ .Release.Service }}

spec:

  replicas: {{ .Values.replicaCount }}

  selector:

    matchLabels:

      app: {{ template "appname" . }}

  template:

    metadata:

      annotations:

        checksum/application-secrets: "{{ .Values.application.secretChecksum }}"

      labels:

        app: {{ template "appname" . }}

        track: "{{ .Values.application.track }}"

        tier: "{{ .Values.application.tier }}"

        release: {{ .Release.Name }}

    spec:

      imagePullSecrets:

{{ toYaml .Values.image.secrets | indent 10 }}

      volumes:

      - configMap:

          defaultMode: 420

          name: {{ template "trackableappname" . }}.config

        name: config-volume



      containers:

      - name: {{ .Chart.Name }}

        image: "moghaddas/prometheus_bot"

        imagePullPolicy: {{ .Values.image.pullPolicy }}

        volumeMounts:

        - mountPath: /config.yaml

          name: config-volume

          subPath: config.yaml

        - mountPath: /alert.tmpl

          name: config-volume

          subPath: alert.tmpl

        ports:

        - name: "{{ .Values.service.name }}"

          containerPort: {{ .Values.service.internalPort }}

        livenessProbe:

          tcpSocket:

            port: {{ .Values.service.internalPort }}

          initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}

          timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}

        readinessProbe:

          tcpSocket:

            port: {{ .Values.service.internalPort }}

          initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}

          timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}

        resources:

{{ toYaml .Values.resources | indent 12 }}

{{- end -}}





также правим конфиг, чтобы в уведомлении видно было alertname, description,  message — по умолчанию их нету в дефолте.




telegram-bot-helm/templates/configmap.yaml




apiVersion: v1

kind: ConfigMap

metadata:

  name: {{ template "trackableappname" . }}.config

  labels:

    app: {{ template "appname" . }}

    chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}"

    release: {{ .Release.Name }}

    heritage: {{ .Release.Service }}

data:

  config.yaml: |-

    telegram_token: "{{ .Values.telegram.token }}"

    template_path: "/alert.tmpl"

    time_zone: "UTC"

    split_token: "|"

    split_msg_byte: 4000

  alert.tmpl: |-

    {{ "{{" }} if eq .Status "firing" {{ "}}" }} <b>[PROBLEM]</b> {{ "{{" }} else {{ "}}" }} <b>[RECOVERY]</b> {{ "{{" }} end {{ "}}" }}

    {{ "{{" }} index (index .Alerts 0).Labels "alertname" {{ "}}" }}

    {{ "{{" }} index (index .Alerts 0).Annotations "description"{{ "}}" }}

    {{ "{{" }} index (index .Alerts 0).Annotations "message"{{ "}}" }}





теперь правим файл с переменными:




cat telegram-bot/values.yaml




# Default values for chart.

# This is a YAML-formatted file.

# Declare variables to be passed into your templates.

replicaCount: 1

telegram:

  token: "139453456058954:AAFaZIepDdfggTql0dfgdfPT6dq1Edqu5dfggxFD6Wr08j0g"

  chat_id: "-567616984" #not used at the moment



releaseOverride: alertmanager-bot-chat-id

image:

  pullPolicy: Always

application:

  track: stable

  tier: web

  migrateCommand:

  initializeCommand:

  secretName:

  secretChecksum:

service:

  enabled: true

  name: web

  type: ClusterIP

  url: http://alertmanager-operated:9093

  additionalHosts:

  commonName:

  externalPort: 9087

  internalPort: 9087



livenessProbe:

  initialDelaySeconds: 15

readinessProbe:

  initialDelaySeconds: 5





resources:

  limits:

    cpu: 100m

    memory: 128Mi

  requests:

    cpu: 10m

    memory: 8Mi





здесь token — это токен нашего телеграм бота мы его получаем при его регистрации в botfather




chat_id — это id нашей группы




url: http://alertmanager-operated:9093  это наш адрес alermanager увидеть его можно следующим образом:




kubectl get service -n monitoring | grep alertmanager-operated

alertmanager-operated                            ClusterIP   None             <none>        9093/TCP,9094/TCP,9094/UDP   57d





для каждой группы мы будем запускать свой телеграмбот, вот второй:




cat telegram-bot/values-test.yaml




# Default values for chart.

# This is a YAML-formatted file.

# Declare variables to be passed into your templates.

replicaCount: 1

telegram:

  token: "139453456058954:AAFaZIepDdfggTql0dfgdfPT6dq1Edqu5dfggxFD6Wr08j0g"

  chat_id: "-480100545" #not used at the moment



releaseOverride: alertmanager-bot-test

image:

  pullPolicy: Always

application:

  track: stable

  tier: web

  migrateCommand:

  initializeCommand:

  secretName:

  secretChecksum:

service:

  enabled: true

  name: web

  type: ClusterIP

  url: http://alertmanager-operated:9093

  additionalHosts:

  commonName:

  externalPort: 9087

  internalPort: 9087



livenessProbe:

  initialDelaySeconds: 15

readinessProbe:

  initialDelaySeconds: 5





resources:

  limits:

    cpu: 100m

    memory: 128Mi

  requests:

    cpu: 10m

    memory: 8Mi





ставим первый:
helm upgrade —install -name telegram-bot-chat-id telegram-bot/ -f telegram-bot/values.yaml —namespace monitoring
и второй:
helm upgrade —install -name telegram-bot-test telegram-bot/ -f telegram-bot/values-test.yaml —namespace monitoring




далее создаём своё кастомное правило:




cat prometheus-alert-rule.yaml




apiVersion: monitoring.coreos.com/v1

kind: PrometheusRule

metadata:

  annotations:

    meta.helm.sh/release-name: prometheus

    meta.helm.sh/release-namespace: monitoring

    prometheus-operator-validated: "true"

  labels:

    app: kube-prometheus-stack

    release: prometheus

  name: my-test-prometheus-alertmanager.rules

  namespace: monitoring

  selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/prometheusrules/my-test-prometheus-alertmanager.rules

spec:

  groups:

  - name: my-test-alertmanager.rules

    rules:

    - alert: EBNULSA_CONTAINER

      annotations:

        message: |

          CONTAINER_UMER

          Namespace: {{ $labels.namespace }} and

          Podname: {{ $labels.pod }}

      expr: sum_over_time(kube_pod_container_status_ready{namespace="my-site"}[5m])

        <1

      for: 1m

      labels:

        severity: critical

        team: namespace-my-site





и второе:




cat prometheus-alert-rule-test.yaml




apiVersion: monitoring.coreos.com/v1

kind: PrometheusRule

metadata:

  annotations:

    meta.helm.sh/release-name: prometheus

    meta.helm.sh/release-namespace: monitoring

    prometheus-operator-validated: "true"

  labels:

    app: kube-prometheus-stack

    release: prometheus

  name: test-prometheus-alertmanager.rules

  namespace: monitoring

  selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/prometheusrules/test-prometheus-alertmanager.rules

spec:

  groups:

  - name: test-alertmanager.rules

    rules:

    - alert: EBNULSA_CONTAINER-namespace-test

      annotations:

        message: |

          CONTAINER_UMER

          Namespace: {{ $labels.namespace }} and

          Podname: {{ $labels.pod }}

      expr: sum_over_time(kube_pod_container_status_ready{namespace="test"}[5m])

        <1

      for: 1m

      labels:

        severity: critical

        team: namespace-test





тут обращаем внимание на разное название лейблов




team: namespace-my-site




и




team: namespace-test




согласно данным лейблам алертменеджер будет раскидывать в нужные группы.




смотрим что данные правила создались:




kubectl -n monitoring get prometheusrules.monitoring.coreos.com




NAME                                                              AGE

my-test-prometheus-alertmanager.rules                             19h

prometheus-kube-prometheus-alertmanager.rules                     57d

prometheus-kube-prometheus-etcd                                   57d

prometheus-kube-prometheus-general.rules                          57d

prometheus-kube-prometheus-k8s.rules                              57d

prometheus-kube-prometheus-kube-apiserver-availability.rules      57d

prometheus-kube-prometheus-kube-apiserver-slos                    57d

prometheus-kube-prometheus-kube-apiserver.rules                   57d

prometheus-kube-prometheus-kube-prometheus-general.rules          57d

prometheus-kube-prometheus-kube-prometheus-node-recording.rules   57d

prometheus-kube-prometheus-kube-scheduler.rules                   57d

prometheus-kube-prometheus-kube-state-metrics                     57d

prometheus-kube-prometheus-kubelet.rules                          57d

prometheus-kube-prometheus-kubernetes-apps                        57d

prometheus-kube-prometheus-kubernetes-resources                   57d

prometheus-kube-prometheus-kubernetes-storage                     57d

prometheus-kube-prometheus-kubernetes-system                      57d

prometheus-kube-prometheus-kubernetes-system-apiserver            57d

prometheus-kube-prometheus-kubernetes-system-controller-manager   57d

prometheus-kube-prometheus-kubernetes-system-kubelet              57d

prometheus-kube-prometheus-kubernetes-system-scheduler            57d

prometheus-kube-prometheus-node-exporter                          57d

prometheus-kube-prometheus-node-exporter.rules                    57d

prometheus-kube-prometheus-node-network                           57d

prometheus-kube-prometheus-node.rules                             57d

prometheus-kube-prometheus-prometheus                             57d

prometheus-kube-prometheus-prometheus-operator                    57d

test-prometheus-alertmanager.rules                                18h






далее правим конфиг алертменеджера, не забываем что в нашем случае это гит:
https://github.com/prometheus-community/helm-charts.git




правим файл:
helm-charts/charts/kube-prometheus-stack/values.yaml




alertmanager:

  ## Deploy alertmanager

  enabled: true

  apiVersion: v2

  serviceAccount:

    create: true

    name: ""

    annotations: {}

  podDisruptionBudget:

    enabled: false

    minAvailable: 1

    maxUnavailable: ""



  config:

    global:

      resolve_timeout: 5m

      smtp_smarthost: 10.230.144.56:25

    route:

       # receiver: 'telegram'

        receiver: 'email_unixadmins'

        routes:

        - receiver: "telegram"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            severity: "critical|warning"

          continue: true

        - receiver: "telegram"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            alertname: "Watchdog"

          continue: true

        - receiver: "email_unixadmins"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            severity: "critical"

          continue: true

        - receiver: "telegram-my-site"

          match_re:

            severity: "critical"

            team: "namespace-my-site"

        - receiver: "telegram-test"

          match_re:

            severity: "critical"

            team: "namespace-test"



    receivers:

        - name: 'telegram'

          webhook_configs:

              - send_resolved: true

#                url: 'http://alertmanager-bot:8080'

                url: 'http://alertmanager-bot-chat-id:9087/alert/-567616984'



        - name: 'telegram-my-site'

          webhook_configs:

              - send_resolved: true

                url: 'http://alertmanager-bot-for-my-site:9087/alert/-581835428'



        - name: 'telegram-test'

          webhook_configs:

              - send_resolved: true

                url: 'http://alertmanager-bot-test:9087/alert/-480100545'





        - name: 'email_unixadmins'

          email_configs:

              - to: 'admin1@test.ru'

                from: 'prod-vsrv-kuber-alertmanager@test.ru'

                require_tls: false

                send_resolved: true

              - to: 'admin2@test.ru'

                from: 'prod-vsrv-kuber-alertmanager@test.ru'

                require_tls: false

                send_resolved: true









обращаю внимание, что установить несколько типов severity можно в таком виде:




severity: «critical|warning»




запись вида:
continue: true
(по умолчанию она false) означает что после первого совпадения надо продолжать роутить сообщения




всё дальше можно апдейтить:




helm upgrade —install -name prometheus kube-prometheus-stack/ -f kube-prometheus-stack/values.yaml —namespace monitoring




6.2. настройка оповещений в telegram разграничение оповещений по группам (исключения уведомлений)




Вводная: есть админский чат и есть чат разработчиков. при настройке как в пункте 6.1 уведомления приходящие в чат разрабочиков дублируются и в чат админов.




данная ситуация происходит вообще потому, что alertmanager  со следующим конфигом:




  config:

    global:

      resolve_timeout: 5m

      smtp_smarthost: 10.230.144.56:25

    route:

       # receiver: 'telegram'

        receiver: 'email_unixadmins'

        routes:

        - receiver: "telegram-admins"

          group_wait: 10s

          repeat_interval: 1h

          match_re:

            severity: "critical|warning"

          continue: true

        - receiver: "telegram-admins"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            alertname: "Watchdog"

          continue: true



        - receiver: "telegram-terminal-soft"

          group_wait: 10s

          repeat_interval: 1h

          match_re:

            severity: "critical"

            team: "terminal-soft"

          continue: true





имеет настройку
continue: true  (по дефолту false)
благодаря которой уведомления попав под первое правило не прекращаются а отправляются дальше по route и отправляются по другим receiver (когда совпадают по label)




ВАЖНО!!!!!!!!!!!!!!  в записи:




          match_re:

            severity: "critical"

            team: "terminal-soft"




правила совпадения работают не как OR а как AND (т.е. должны совпасть ВСЕ лейблы)




Задача, исключить из чата админов сообщения отправляемые в чат разрабочиков, чтобы админам прилетали все дефолтные




Решение — возможно тупенькое но я другого не нашёл, работать будет так:




прилетает сообщение, с лейблами:
severity: «critical»
team: «terminal-soft»




значит оно должно попасть только в группу terminal-soft, поэтому для receiver: «telegram-terminal-soft»   оставляем
match_re:
team: «terminal-soft»




но так как в уведомлении будет прителать лейбл
severity: «critical»  то он будет попадать под совпадение receiver: «telegram-admins» у которого
match_re:
severity: «critical|warning»




нам этого не нужно поэтому для
receiver: «telegram-terminal-soft»
ставим  continue: false  и тогда обработка следующих routes не будет происходить.




вывод перед админским чатом правило должно быть с условием:
continue: false
а админский чат последний в списке.




теперь рассмотрим всё это по конфигам:




правило по которому будет срабатывать алерт:




test.rule.yml




apiVersion: monitoring.coreos.com/v1

kind: PrometheusRule

metadata:

  annotations:

    meta.helm.sh/release-name: prometheus

    meta.helm.sh/release-namespace: monitoring

    prometheus-operator-validated: "true"

  labels:

    app: kube-prometheus-stack

    release: prometheus

  name: mega-mega24-cloud-prometheus-alertmanager.rules

  namespace: monitoring

  selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/prometheusrules/mega-mega24-cloud-prometheus-alertmanager.rules

spec:

  groups:

  - name: mega-mega24-cloud-alertmanager.rules

    rules:

    - alert: EBNULSA_CONTAINER

      annotations:

        message: |

          CONTAINER_UMER

          Namespace: {{ $labels.namespace }} and

          Podname: {{ $labels.pod }}

      expr: sum_over_time(kube_pod_container_status_ready{namespace="mega-mega24-cloud"}[2m])

        <1

      for: 1m

      labels:

        team: "terminal-soft"





тут обращаем внимание на наличие лейбла team: «terminal-soft» и отсутствие лейбла severity: critical




конфиг алерт менеджера:




cat helm-charts/charts/kube-prometheus-stack/values.yaml




  ## Alertmanager configuration directives

  ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file

  ##      https://prometheus.io/webtools/alerting/routing-tree-editor/

  ##



  config:

    global:

      resolve_timeout: 5m

      smtp_smarthost: 10.230.144.56:25

    route:

       # receiver: 'telegram'

        receiver: 'email_unixadmins'

        routes:



        - receiver: "email_unixadmins"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            severity: "critical"

          continue: true



        - receiver: "telegram-admins"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            alertname: "Watchdog"

          continue: true



        - receiver: "telegram-terminal-soft"

          group_wait: 10s

          repeat_interval: 1h

          match_re:

            team: "terminal-soft"

          continue: false



        - receiver: "telegram-admins"

          group_wait: 10s

          repeat_interval: 1h

          match_re:

            severity: "critical|warning"

          continue: true





    receivers:

        - name: 'telegram-admins'

          webhook_configs:

              - send_resolved: true

                url: 'http://telegram-admins-group:9087/alert/-1001441100259'



        - name: 'telegram-terminal-soft'

          webhook_configs:

              - send_resolved: true

                url: 'http://telegram-terminal-soft:9087/alert/-597056946'





        - name: 'email_unixadmins'

          email_configs:

              - to: 'user1@test.ru'

                from: 'prod-vsrv-kuber-alertmanager@test.ru'

                require_tls: false

                send_resolved: true

              - to: 'user2@test.ru'

                from: 'prod-vsrv-kuber-alertmanager@test.ru'

                require_tls: false

                send_resolved: true





тут видим что предпоследнее правило имеет вид:




— receiver: «telegram-terminal-soft»
group_wait: 10s
repeat_interval: 1h
match_re:
team: «terminal-soft»
continue: false




а последнее правило для работы дефолтных правил (которые есть в prometheus  по умолчанию)




— receiver: «telegram-admins»
group_wait: 10s
repeat_interval: 1h
match_re:
severity: «critical|warning»
continue: true




7.Проблема с prometheus-kube-proxy




столкнулся со следующей проблемой, после запуска прометеуса не отображаются метрики с kube-proxy





прикол в следующем, сам kube-proxy стартанул на 127,0,0,1




[root@kub-worker-2 ~]# netstat -ntpl | grep 10249

tcp        0      0 127.0.0.1:10249         0.0.0.0:*               LISTEN      2537/kube-proxy





а прометеус лезет на айпишник т.е. щимится на ноды а там ни кто не отвечает:
[root@kub-master-1 charts]# telnet 192.168.1.205 10249
Trying 192.168.1.205…
telnet: connect to address 192.168.1.205: Connection refused




что для исправления делаем, НА ВСЕХ НОДАХ правим:




[root@kub-master-1 charts]# vim /etc/kubernetes/kube-proxy-config.yaml
c
metricsBindAddress: 127.0.0.1:10249
на
metricsBindAddress: 0.0.0.0:10249




общий вид у файла такой:




apiVersion: kubeproxy.config.k8s.io/v1alpha1

kind: KubeProxyConfiguration

bindAddress: 0.0.0.0

clientConnection:

 acceptContentTypes:

 burst: 10

 contentType: application/vnd.kubernetes.protobuf

 kubeconfig: /etc/kubernetes/kube-proxy-kubeconfig.yaml

 qps: 5

clusterCIDR: 10.0.0.0/16

configSyncPeriod: 15m0s

conntrack:

 maxPerCore: 32768

 min: 131072

 tcpCloseWaitTimeout: 1h0m0s

 tcpEstablishedTimeout: 24h0m0s

enableProfiling: False

healthzBindAddress: 127.0.0.1

hostnameOverride: kub-master-1

iptables:

 masqueradeAll: False

 masqueradeBit: 14

 minSyncPeriod: 0s

 syncPeriod: 30s

ipvs:

 excludeCIDRs: []

 minSyncPeriod: 0s

 scheduler: rr

 syncPeriod: 30s

 strictARP: False

metricsBindAddress: 0.0.0.0:10249

mode: iptables

nodePortAddresses: []

oomScoreAdj: -999

portRange:

udpIdleTimeout: 250ms




далее перезапускаем:




[root@kub-master-1 charts]# kubectl delete pod -n kube-system kube-proxy-kub-master-1 kube-proxy-kub-master-2 kube-proxy-kub-master-3 kube-proxy-kub-worker-1 kube-proxy-kub-worker-2
pod «kube-proxy-kub-master-1» deleted
pod «kube-proxy-kub-master-2» deleted
pod «kube-proxy-kub-master-3» deleted
pod «kube-proxy-kub-worker-1» deleted
pod «kube-proxy-kub-worker-2» deleted




Проверяем доступность:




[root@kub-master-1 charts]# telnet 192.168.1.205 10249
Trying 192.168.1.205…
Connected to 192.168.1.205.
Escape character is ‘^]’.
^]
telnet> quit
Connection closed.




и как видим метрики теперь отображаются:





8.Настройка алерта для определённого namespace




У меня есть тестовый сервис:




cat my-site-ingress.yaml




---

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

  name: my-ingress

  namespace: my-site

spec:

  rules:

  - host: test.ru  #тут указывается наш домен

    http:

      paths:  #список путей которые хотим обслуживать(он дефолтный и все запросы будут отправляться на бэкенд, т.е. на сервис my-service-apache)

      - backend:

          serviceName: my-service-apache  #тут указывается наш сервис

          servicePort: 80 #порт на котором сервис слушает

#        path: /  все запросы на корень '/' будут уходить на наш сервис





cat my-site-service.yaml




---

apiVersion: v1

kind: Service

metadata:

  name: my-service-apache # имя сервиса

  namespace: my-site

spec:

  ports:

  - port: 80  # принимать на 80

    targetPort: 80 # отправлять на 80

  selector:

    app: apache  #отправлять на все поды с данным лейблом

  type: ClusterIP





cat my-site.yaml




---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-deployment-apache

  namespace: my-site

spec:

  replicas: 1

  selector:

    matchLabels:

      app: apache # по вот этому лейблу репликасет цепляет под

# тут описывается каким мокаром следует обновлять поды

  strategy:

    rollingUpdate:

      maxSurge: 1  # указывает на какое количество реплик можно увеличить

      maxUnavailable: 1 # указывает на какое количество реплик можно уменьшить

#т.е. в одно время при обновлении, будет увеличено на один (новый под) и уменьшено на один (старый под)

    type: RollingUpdate

## тут начинается описание контейнера

  template:

    metadata:

      labels:

        app: apache  # по вот этому лейблу репликасет цепляет под

    spec:

      containers:

        - image: httpd:2.4.43

          name: apache

          ports:

            - containerPort: 80

# тут начинаются проверки по доступности

          readinessProbe: # проверка готово ли приложение

            failureThreshold: 3 #указывает количество провалов при проверке

            httpGet:  # по сути дёргает курлом на 80 порт

              path: /

              port: 80

            periodSeconds: 10 #как часто должна проходить проверка (в секундах)

            successThreshold: 1 #сбрасывает счётчик неудач, т.е. при 3х проверках если 1 раз успешно прошло, то счётчик сбрасывается и всё ок

            timeoutSeconds: 1 #таймаут на выполнение пробы 1 секунда

          livenessProbe: #проверка на жизнь приложения, живо ли оно

            failureThreshold: 3

            httpGet:

              path: /

              port: 80

            periodSeconds: 10

            successThreshold: 1

            timeoutSeconds: 1

            initialDelaySeconds: 10 #означает что первую проверку надо сделать только после 10 секунд



# тут начинается описание лимитов для пода

          resources:

            requests: #количество ресурсов которые резервируются для pod на ноде

              cpu: 60m

              memory: 200Mi

            limits: #количество ресурсов которые pod может использовать(верхняя граница)

              cpu: 120m

              memory: 300Mi





применяем
kubectl create ns my-site
kubectl apply -f my-site-ingress.yaml -f my-site-service.yaml -f my-site.yaml
проверяем




[root@kub-master-1 ~]# kubectl get pod -n my-site

NAME                                    READY   STATUS    RESTARTS   AGE

my-deployment-apache-859486bd8c-zk99f   1/1     Running   0          11m





как видим всё ок.
теперь сделаем так чтобы сервис постоянно падал и перезапускался, для этого подправим в деплойменте проверки(readinessProbe/livenessProbe) порта не 80 а 81:




cat my-site.yaml

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: my-deployment-apache

  namespace: my-site

spec:

  replicas: 1

  selector:

    matchLabels:

      app: apache # по вот этому лейблу репликасет цепляет под

# тут описывается каким мокаром следует обновлять поды

  strategy:

    rollingUpdate:

      maxSurge: 1  # указывает на какое количество реплик можно увеличить

      maxUnavailable: 1 # указывает на какое количество реплик можно уменьшить

#т.е. в одно время при обновлении, будет увеличено на один (новый под) и уменьшено на один (старый под)

    type: RollingUpdate

## тут начинается описание контейнера

  template:

    metadata:

      labels:

        app: apache  # по вот этому лейблу репликасет цепляет под

    spec:

      containers:

        - image: httpd:2.4.43

          name: apache

          ports:

            - containerPort: 80

# тут начинаются проверки по доступности

          readinessProbe: # проверка готово ли приложение

            failureThreshold: 3 #указывает количество провалов при проверке

            httpGet:  # по сути дёргает курлом на 80 порт

              path: /

              port: 81

            periodSeconds: 10 #как часто должна проходить проверка (в секундах)

            successThreshold: 1 #сбрасывает счётчик неудач, т.е. при 3х проверках если 1 раз успешно прошло, то счётчик сбрасывается и всё ок

            timeoutSeconds: 1 #таймаут на выполнение пробы 1 секунда

          livenessProbe: #проверка на жизнь приложения, живо ли оно

            failureThreshold: 3

            httpGet:

              path: /

              port: 81

            periodSeconds: 10

            successThreshold: 1

            timeoutSeconds: 1

            initialDelaySeconds: 10 #означает что первую проверку надо сделать только после 10 секунд



# тут начинается описание лимитов для пода

          resources:

            requests: #количество ресурсов которые резервируются для pod на ноде

              cpu: 60m

              memory: 200Mi

            limits: #количество ресурсов которые pod может использовать(верхняя граница)

              cpu: 120m

              memory: 300Mi





и применим:




kubectl apply -f my-site.yaml




как видим pod перезапускается:




[root@kub-master-1 ~]# kubectl get pod -n my-site

NAME                                    READY   STATUS    RESTARTS   AGE

my-deployment-apache-85978bf68f-mbwlm   0/1     Running   1          41s





но не может пройти проверки.




посмотрим что в метриках на prometheus:




применим promql запрос:




kube_pod_container_status_ready{namespace=»my-site»}[5m]




который смотрит статус контейнеров по namespace my-site за последние 5 минут.





как видим у нас 2 разных имени контейнера:
my-deployment-apache-859486bd8c-zk99f   (который был запущен ранее и с ним было всё нормально)
и
my-deployment-apache-85978bf68f-mbwlm (текущий, который был специально сломан через неправильные проверки)




теперь нам надо получить результат, были ли за последние 5 минуть незапущенные контейнеры, для этого используем следующий запрос:




sum_over_time(kube_pod_container_status_ready{namespace=»my-site»}[5m]) <1




который смотрит были ли контейнеры со статусом МЕНЬШЕ 1 (т.е. не запущенные) за 5 минут





для проверки можем увеличить время до 900 минут и глянем что он выведет:





как видим таких было 3 контейнера




возвращаем проверки в деплойменте ждём 5 минут и проверяем статус:





как видим за 5 минут упавших контейнеров не было.




теперь привяжем это к alertmanager.




правим имеющееся правила прометеуса:




kubectl -n monitoring edit prometheusrules prometheus-kube-prometheus-alertmanager.rules




и в общий список где перечисляются правила:




spec:

  groups:

  - name: alertmanager.rules

    rules:

    - alert: AlertmanagerConfigInconsistent

      annotations:

        message: |

          The configuration of the instances of the Alertmanager cluster `{{ $labels.namespace }}/{{ $labels.service }}` are out of sync.

          {{ range printf "alertmanager_config_hash{namespace="%s",service="%s"}" $labels.namespace $labels.service | query }}

          Configuration hash for pod {{ .Labels.pod }} is "{{ printf "%.f" .Value }}"

          {{ end }}

      expr: count by(namespace,service) (count_values by(namespace,service) ("config_hash",

        alertmanager_config_hash{job="prometheus-kube-prometheus-alertmanager",namespace="monitoring"}))

        != 1

      for: 5m

      labels:

        severity: critical

    - alert: AlertmanagerFailedReload

      annotations:

        message: Reloading Alertmanager's configuration has failed for {{ $labels.namespace

          }}/{{ $labels.pod}}.

      expr: alertmanager_config_last_reload_successful{job="prometheus-kube-prometheus-alertmanager",namespace="monitoring"}

        == 0

      for: 10m

      labels:

        severity: warning

    - alert: AlertmanagerMembersInconsistent

      annotations:

        message: Alertmanager has not found all other members of the cluster.

      expr: |-

        alertmanager_cluster_members{job="prometheus-kube-prometheus-alertmanager",namespace="monitoring"}

          != on (service) GROUP_LEFT()

        count by (service) (alertmanager_cluster_members{job="prometheus-kube-prometheus-alertmanager",namespace="monitoring"})

      for: 5m

      labels:

        severity: critical





добавляем наше:




    - alert: EBNULSA_CONTAINER

      annotations:

        message: CONTAINER_UMER

      expr: sum_over_time(kube_pod_container_status_ready{namespace="my-site"}[5m])

        <1

      for: 1m

      labels:

        severity: critical




выходим сохраняемся.




в прометеусе переходим на вкладку alerts и видим наше правило:





всё теперь можно снова ломать проверки в нашем деплойменте и проверять полетел ли алерт:





как видим полетел.




проверяем наш телеграм бот и видим:





в таком вот виде настраивается алертинг.




Теперь рассмотрим как нам добавлять свой алертинг а не править имеющийся.




смотрим имеющие правила:




[root@kub-master-1 ~]# kubectl -n monitoring get prometheusrules.monitoring.coreos.com

NAME                                                              AGE

prometheus-kube-prometheus-alertmanager.rules                     3d

prometheus-kube-prometheus-etcd                                   3d

prometheus-kube-prometheus-general.rules                          3d

prometheus-kube-prometheus-k8s.rules                              3d

prometheus-kube-prometheus-kube-apiserver-availability.rules      3d

prometheus-kube-prometheus-kube-apiserver-slos                    3d

prometheus-kube-prometheus-kube-apiserver.rules                   3d

prometheus-kube-prometheus-kube-prometheus-general.rules          3d

prometheus-kube-prometheus-kube-prometheus-node-recording.rules   3d

prometheus-kube-prometheus-kube-scheduler.rules                   3d

prometheus-kube-prometheus-kube-state-metrics                     3d

prometheus-kube-prometheus-kubelet.rules                          3d

prometheus-kube-prometheus-kubernetes-apps                        3d

prometheus-kube-prometheus-kubernetes-resources                   3d

prometheus-kube-prometheus-kubernetes-storage                     3d

prometheus-kube-prometheus-kubernetes-system                      3d

prometheus-kube-prometheus-kubernetes-system-apiserver            3d

prometheus-kube-prometheus-kubernetes-system-controller-manager   3d

prometheus-kube-prometheus-kubernetes-system-kubelet              3d

prometheus-kube-prometheus-kubernetes-system-scheduler            3d

prometheus-kube-prometheus-node-exporter                          3d

prometheus-kube-prometheus-node-exporter.rules                    3d

prometheus-kube-prometheus-node-network                           3d

prometheus-kube-prometheus-node.rules                             3d

prometheus-kube-prometheus-prometheus                             3d

prometheus-kube-prometheus-prometheus-operator                    3d





добавляем наше:




cat prometheus-alert-rule.yaml




apiVersion: monitoring.coreos.com/v1

kind: PrometheusRule

metadata:

  annotations:

    meta.helm.sh/release-name: prometheus

    meta.helm.sh/release-namespace: monitoring

    prometheus-operator-validated: "true"

  labels:

    app: kube-prometheus-stack

    release: prometheus

  name: my-test-prometheus-alertmanager.rules

  namespace: monitoring

  selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/prometheusrules/my-test-prometheus-alertmanager.rules

spec:

  groups:

  - name: my-test-alertmanager.rules

    rules:

    - alert: EBNULSA_CONTAINER

      annotations:

        message: |

          CONTAINER_UMER

          Namespace: {{ $labels.namespace }} and

          Podname: {{ $labels.pod }}

      expr: sum_over_time(kube_pod_container_status_ready{namespace="my-site"}[5m])

        <1

      for: 1m

      labels:

        severity: critical





применяем:
[root@kub-master-1 ~]# kubectl apply -f prometheus-alert-rule.yaml




проверяем:




[root@kub-master-1 ~]# kubectl -n monitoring get prometheusrules.monitoring.coreos.com | grep my

my-test-prometheus-alertmanager.rules                             91m






как видим наше правило добавилось.




запись вида:
Namespace: {{ $labels.namespace }}
Podname: {{ $labels.pod }}




выведет имя неймспейса и имя пода.




в телеграме это будет отображаться следующим образом:





9.Добавление оповещений и по email




правим файл:
vim charts/kube-prometheus-stack/values.yaml




  ## Alertmanager configuration directives

  ## ref: https://prometheus.io/docs/alerting/configuration/#configuration-file

  ##      https://prometheus.io/webtools/alerting/routing-tree-editor/

  ##



  config:

    global:

      resolve_timeout: 5m

      smtp_smarthost: 10.20.44.56:25

    route:

       # receiver: 'telegram'

        receiver: 'email_unixadmins'

        routes:

        - receiver: "telegram"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            severity: "critical"

          continue: true

        - receiver: "telegram"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            alertname: "Watchdog"

          continue: true

        - receiver: "email_unixadmins"

          group_wait: 10s

          repeat_interval: 48h

          match_re:

            severity: "critical"

          continue: true

    receivers:

        - name: 'telegram'

          webhook_configs:

              - send_resolved: true

                url: 'http://alertmanager-bot:8080'



        - name: 'email_unixadmins'

          email_configs:

              - to: 'admin1@test.ru'

                from: 'prod-vsrv-kuber-alertmanager@test.ru'

                require_tls: false

                send_resolved: true

              - to: 'admin2@test.ru'

                from: 'prod-vsrv-kuber-alertmanager@test.ru'

                require_tls: false

                send_resolved: true




smtp_smarthost: 10.20.44.56:25  это наш smtp хост через который мы шлём почту.




receiver: ’email_unixadmins’  — на него будут идти оповещения вне зависимости от критичности алерта, для остальных можно выставлять уровень критичности.




и применяем:




helm upgrade —install -name prometheus kube-prometheus-stack/ -f kube-prometheus-stack/values.yaml —namespace monitoring




10. Настройка графиков в grafana




создаём новый дашборд






переходим к созданию панели




она будет отображать только наш неймспейс terminal-soft
создадим панель которая будет отображать сколько процессорного времени использует namespace
запрос выглядит следующим образом:




sum(rate(container_cpu_usage_seconds_total{namespace=»terminal-soft»}[5m]))





настраиваем отображение:





сохраняем:





теперь добавим panel по использованию оперативной памяти в namespace terminal-soft




также создаём новую панель, и используем запрос:




sum(rate(container_memory_usage_bytes{namespace=»terminal-soft»}[5m]))





в левой колонке ставим параметр, в чём измеряем (в нашем случае в байтах)





и настраиваем отображаему легенду а именно минимальные максимальные значение и т.д.





всё можно сохраняться





как видим 2 графика у нас уже отображаются нормально:





теперь отобразим занятое дисковое пространство persistantvolume




создаём новую панель




запрос будет выглядеть следующим образом:
(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim=»$volume»} — kubelet_volume_stats_available_bytes{persistentvolumeclaim=»$volume»}) / kubelet_volume_stats_capacity_bytes{persistentvolumeclaim=»$volume»} * 100




у нас повилась переменная volume  рассмотрим как её создать:




переходим в настройки dasboard






добавим несколько переменных,
первая cluster  запрос:
label_values(kubelet_volume_stats_capacity_bytes, cluster)




не забываем ставить Hide Variables чтобы в панели он не отображался





вторая namespace, запрос:




label_values(kubelet_volume_stats_capacity_bytes{cluster=»$cluster», job=»kubelet», metrics_path=»/metrics»}, namespace)





и третья volume запрос:




label_values(kubelet_volume_stats_capacity_bytes{cluster=»$cluster», job=»kubelet», metrics_path=»/metrics», namespace=»$namespace»}, persistentvolumeclaim)





вот наши 3 переменные:





теперь смотрим на нашу панель:





добавляем legend в описании пишем {{namespace}} (чтоб отображался наш неймспейс)




также видим что вверху появились НЕ СКРЫТЫЕ переменные которые мы можем выбирать.




Отображение сети (входящий/исходящий трафик)




используем 2 метрики:
входящий трафик для namespace terminal soft:
sum(rate(container_network_receive_bytes_total{pod=~»deployment.+»,namespace=»terminal-soft»}[1m]))




исходящий трафик для namespace terminal soft:
sum(rate(container_network_transmit_bytes_total{pod=~»deployment.+»,namespace=»terminal-soft»}[1m]))







Отображение кодов ответа на nginx ingress controller




создаём ещё одну панель.




дёргаем метрику:




sum(increase(nginx_ingress_controller_request_duration_seconds_count{namespace=»terminal-soft»}[1m])) by (status) > 0




в качестве legend ставим
{{status}} code





можно сохранять.





ещё добавим несколько графиков для отображения количества ответов по статусам

200(2**)
300(3**)
400(4**)
500(5**)




создаём панель и добавляем запрос:
sum(increase(nginx_ingress_controller_requests{namespace=»terminal-soft»,status=~»2.*»}[1m]))





добавляем ещё несколько панелей запросы будут аналогичны первому:




sum(increase(nginx_ingress_controller_requests{namespace=»terminal-soft»,status=~»3.*»}[1m]))




sum(increase(nginx_ingress_controller_requests{namespace=»terminal-soft»,status=~»4.*»}[1m]))




sum(increase(nginx_ingress_controller_requests{namespace=»terminal-soft»,status=~»5.*»}[1m]))




по итогу у нас получился вот такой dasboard





рассмотрим ещё один дашборд где при выборе namespace будут отображаться Проц/оперативка/сеть  как на весь неймспейс так и на каждый под в отдельности





вот так оно будет выглядеть по итогу




переходим в настройки:





далее создаём переменные:





cluster
label_values(kube_pod_info, cluster)





namespace
label_values(kube_pod_info{cluster=»$cluster»}, namespace)





перейдём к настройке самих дашбордов — первый по перативке:





sum(rate(container_memory_usage_bytes{namespace=»$namespace»}[5m]))
all MEMORY in $namespace




sum(rate(container_memory_working_set_bytes{namespace=»$namespace», container!=»», image!=»»}[5m])) by (pod)
{{pod}}




далее проц





sum(rate(container_cpu_usage_seconds_total{namespace=»$namespace»}[5m]))
all CPU in $namespace




sum(rate(container_cpu_usage_seconds_total{namespace=»$namespace», container!=»», image!=»»}[5m])) by (pod)
{{pod}}




далее рассмотрим сеть:






sum(rate(container_network_receive_bytes_total{namespace=»$namespace»}[1m]))
INPUT in ALL $namespace




sum(rate(container_network_transmit_bytes_total{namespace=»$namespace»}[1m]))
OUTPUT in ALL $namespace




sum(rate(container_network_receive_bytes_total{namespace=»$namespace», container!=»», image!=»»}[5m])) by (pod)
input in {{pod}}




sum(rate(container_network_transmit_bytes_total{namespace=»$namespace», container!=»», image!=»»}[5m])) by (pod)
output in {{pod}}







Источник: https://sidmid.ru/kubernetes-запуск-prometheus-grafana-alertmanager-запуск-exporter-для-ingress-nginx-controller/#grafana