Назад | Перейти на главную страницу

Конечная точка метрик узла Kubernetes возвращает 401

У меня есть кластер GKE, который для простоты запускает только Prometheus, отслеживая каждый узел-член. Недавно я обновил сервер API до версии 1.6 (которая представляет RBAC), и у меня не было проблем. Затем я добавил новый узел, на котором запущена версия 1.6 kubelet. Prometheus не смог получить доступ к API метрик этого нового узла.

Итак, я добавил ClusterRole, ClusterRoleBinding и ServiceAccount в мое пространство имен и настроил развертывание для использования нового ServiceAccount. Затем я удалил капсулу на всякий случай:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
---

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
  - configmaps
  verbs: ["get"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: default
---

apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: default
secrets:
- name: prometheus-token-xxxxx

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: prometheus-prometheus
    component: server
    release: prometheus
  name: prometheus-server
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus-prometheus
      component: server
      release: prometheus
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: prometheus-prometheus
        component: server
        release: prometheus
    spec:
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      serviceAccount: prometheus
      serviceAccountName: prometheus
      ...

Но ситуация не изменилась.

Конечная точка метрик возвращает HTTP/1.1 401 Unauthorized, и когда я изменяю развертывание, чтобы включить в него другой контейнер с установленным bash + curl и сделать запрос вручную, я получаю:

# curl -vsSk -H "Authorization: Bearer $(</var/run/secrets/kubernetes.io/serviceaccount/token)" https://$NODE_IP:10250/metrics
*   Trying $NODE_IP...
* Connected to $NODE_IP ($NODE_IP) port 10250 (#0)
* found XXX certificates in /etc/ssl/certs/ca-certificates.crt
* found XXX certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
*    server certificate verification SKIPPED
*    server certificate status verification SKIPPED
*    common name: node-running-kubelet-1-6@000000000 (does not match '$NODE_IP')
*    server certificate expiration date OK
*    server certificate activation date OK
*    certificate public key: RSA
*    certificate version: #3
*    subject: CN=node-running-kubelet-1-6@000000000
*    start date: Fri, 07 Apr 2017 22:00:00 GMT
*    expire date: Sat, 07 Apr 2018 22:00:00 GMT
*    issuer: CN=node-running-kubelet-1-6@000000000
*    compression: NULL
* ALPN, server accepted to use http/1.1
> GET /metrics HTTP/1.1
> Host: $NODE_IP:10250
> User-Agent: curl/7.47.0
> Accept: */*
> Authorization: Bearer **censored**
>
< HTTP/1.1 401 Unauthorized
< Date: Mon, 10 Apr 2017 20:04:20 GMT
< Content-Length: 12
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host $NODE_IP left intact

Я столкнулся с той же проблемой и создал билет https://github.com/prometheus/prometheus/issues/2606 для этого и вне его обсуждения обновили примеры конфигурации через PR https://github.com/prometheus/prometheus/pull/2641.

Вы можете увидеть обновленную перемаркировку для кубернетес-узлы работа в https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml#L76-L84

Скопировано для справки:

  relabel_configs:
  - action: labelmap
    regex: __meta_kubernetes_node_label_(.+)
  - target_label: __address__
    replacement: kubernetes.default.svc:443
  - source_labels: [__meta_kubernetes_node_name]
    regex: (.+)
    target_label: __metrics_path__
    replacement: /api/v1/nodes/${1}/proxy/metrics

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

apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: default

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

spec:
  serviceAccount: prometheus

И затем Kubernetes манифестирует для настройки соответствующей роли RBAC и привязки, чтобы предоставить учетной записи службы prometheus доступ к необходимым конечным точкам API на https://github.com/prometheus/prometheus/blob/master/documentation/examples/rbac-setup.yml

Скопировано для справки

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: default

Замените пространство имен во всех манифестах, чтобы оно соответствовало тому, в котором вы запускаете Prometheus, а затем примените манифест с учетной записью с правами администратора кластера.

Я не тестировал это в кластере без резервной версии ABAC, поэтому в роли RBAC все еще может отсутствовать что-то важное.

Согласно обсуждению в заявке @JorritSalverda; https://github.com/prometheus/prometheus/issues/2606#issuecomment-294869099

Поскольку GKE не позволяет вам получить сертификаты клиентов, которые позволят вам аутентифицировать себя с помощью kubelet, лучшее решение для пользователей GKE, похоже, использует сервер API Kubernetes в качестве прокси-запросов к узлам.

Для этого (цитируя @JorritSalverda);

"Мой сервер Prometheus, работающий внутри GKE, теперь работает со следующей перемаркировкой:

relabel_configs:
- action: labelmap
  regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
  replacement: kubernetes.default.svc.cluster.local:443
- target_label: __scheme__
  replacement: https
- source_labels: [__meta_kubernetes_node_name]
  regex: (.+)
  target_label: __metrics_path__
  replacement: /api/v1/nodes/${1}/proxy/metrics

И следующая ClusterRole привязана к учетной записи службы, используемой Prometheus:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]

Поскольку в кластере GKE все еще есть резервный режим ABAC на случай отказа RBAC, я не уверен на 100%, но это покрывает все необходимые разрешения.