Задача
Нужно настроить:
- Выделенный сервер логирования Prometheus + Grafanana
- Настроить сбор метрик из подов, работающих в двух кластерах k8s.
- Настроить дашборды в Grafana.
- Сделать это всё все в соответствии с IaC, чтобы можно было быстро реплицировать и масштабировать.
Настройки в кластере k8s с опубликованными приложениями
Я предполагаю, что работы идут в уже настроенном кластере, в котором есть Ingress Controller и из которого можно публиковать сервисы (prometheus) наружу.
В кластере в котором работают приложения нужно:
- Развернуть оператор Prometheus, который будет управлять объектами Prometheus и ServiceMonitor
- Создать необходимые для работы объекты (сервис-аккаунт, роль, rolebinding)
- Опубликовать Prometheus через Ingress (в том числе настроить basic-аутентифкацию для доступа к метрикам)
- Создать ServiceMonitor'ы для сбора метрик
Установка оператора prometheus
https://grafana.com/docs/grafana-cloud/kubernetes/prometheus/prometheus_operator/
Создаем CRD's и устанавливаем оператора:
NS=monitoring kubectl create ns $NS wget https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/master/bundle.yaml sed -i "s/ namespace: default/ namespace: $NS/g" ./bundle.yaml kubectl create -f ./bundle.yaml
Создаем сервис-аккаунт, роль и даем права:
kubectl apply -n $NS -f -<<EOF apiVersion: v1 kind: ServiceAccount metadata: name: prometheus --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] resources: - nodes - nodes/metrics - services - endpoints - pods verbs: ["get", "list", "watch"] - apiGroups: [""] resources: - configmaps verbs: ["get"] - apiGroups: - networking.k8s.io resources: - ingresses verbs: ["get", "list", "watch"] - nonResourceURLs: ["/metrics"] verbs: ["get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: $NS EOF
Создаем Prometheus:
https://github.com/prometheus-operator/prometheus-operator/issues/2382
kubectl apply -n monitoring -f - <<EOF apiVersion: monitoring.coreos.com/v1 kind: Prometheus metadata: name: prometheus labels: app: prometheus spec: externalUrl: https://ingress.domain.com/prometheus/ routePrefix: /prometheus image: quay.io/prometheus/prometheus:v2.22.1 nodeSelector: kubernetes.io/os: linux replicas: 2 resources: requests: memory: 400Mi securityContext: fsGroup: 2000 runAsNonRoot: true runAsUser: 1000 serviceAccountName: prometheus version: v2.22.1 ruleNamespaceSelector: matchLabels: monitoring: prometheus serviceMonitorNamespaceSelector: matchLabels: monitoring: prometheus serviceMonitorSelector: {} --- apiVersion: v1 kind: Service metadata: name: prometheus-web labels: prometheus: prometheus spec: ports: - name: web port: 9090 targetPort: web selector: prometheus: prometheus sessionAffinity: ClientIP type: ClusterIP EOF
Тут важно обратить внимание на параметры externalUrl и routePrefix. Они должны соответветствовать тому, что будет прописано в Ingress. Они же параметры командной строки prometheus - –web.external-url и –web.route-prefix соответственно.
Пометим неймспйесы, которые должны мониториться этим прометиусом
kubectl label ns monitoring monitoring=prometheus
Публикация prometheus через Ingress
Prometheus будет опубликован наружу через Ingress и защищен basic-аутентификацией.
Создадим секрет для basic-аутентификации:
kubectl create -n monitoring secret generic prometheus-basic-auth --from-literal=auth=username:$(openssl passwd -5 superpassword)
И теперь можем создать ингресс:
https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/exposing-prometheus-and-alertmanager.md#ingress
kubectl apply -n monitoring -f - <<EOF apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: prometheus-metrics annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: prometheus-basic-auth nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required' spec: rules: - host: ingress.domain.com http: paths: - backend: service: name: prometheus-web port: number: 9090 path: /prometheus pathType: Prefix tls: - hosts: - ingress.domain.com secretName: ingress-domain-com-tls EOF
Тут важно - path должен быть таким же как и в настройках prometheus, имя секрета в аннотации - соответствовать имени созданного серкрета с учеткой basic-auth. Можно проверить:
curl -u 'username:superpassword' https://ingress.domain.com/prometheus/metrics
Или какие-то более осмысленные метрики:
curl -u 'username:superpassword' -g 'https://ai-eu-1.voximplant.com/prometheus/federate?match[]={container="gateway-container"}'
Настройка ServiceMonitors
kubectl apply -n monitoring -f -<<EOF apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: gateway spec: selector: matchLabels: app: gateway namespaceSelector: matchNames: - nlu-prod endpoints: - targetPort: 8080 path: /metrics scheme: http interval: 10s EOF
Траблшутинг проблем с сервис-мониторами: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/troubleshooting.md#troubleshooting-servicemonitor-changes Что тут важно:
- У сервисов должны быть прописаны метки, которые затем прописываются в селектор сервисмониторов.
- Эндпоинт с метриками задаем с помощью либо по имени порта (параметр port), либо - по номеру порта (параметр targetPort) в конфиге сервиса.
Настройки на основном сервере логирования
На основоном сервере логирования но настроить federation
Примерно так: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config
# https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config - job_name: 'kubernetes-pods-aws' scrape_interval: 15s honor_labels: true metrics_path: '/prometheus/federate' basic_auth: username: username password: superpassword scheme: https params: match[]: - '{job=~".+"}' static_configs: - targets: - 'remote.prometheus.domain.com:443' labels: cluster: remote_prometheus_domain_com
И на основном сервере логирования можно выполнить запрос какого-либо значения, указав в качестве параметра фильтрации - метку для данного таргета:
curl -g 'http://127.0.0.1:9090/api/v1/query?query=system_cpu_usage{container="container_name",cluster="remote_prometheus_domain_com"}'
Discussion