Захист збору метрик Prometheus для sidecar і шлюзів Istio

Це завдання демонструє, як безпечно збирати метрики sidecar і шлюзів Istio за допомогою Prometheus через Istio mTLS. Типово Prometheus збирає метрики з робочих навантажень і шлюзів Istio через звичайний HTTP. У цьому завданні ви налаштовуєте Istio та Prometheus так, щоб метрики збиралися безпечно через взаємно автентифіковані TLS-зʼєднання. Цей документ зосереджується на телеметрії, створеній Envoy та Istio, яку експонують sidecar і шлюзи. Щодо загальної інтеграції Prometheus з Istio, включно з метриками застосунків, дивіться документацію інтеграції Prometheus.

Розуміння типового збору метрик

Як правило, Istio надає доступ до метрик через точку доступу /stats/prometheus:

  • Метрики робочих навантажень надаються через порт телеметрії sidecar (15020) або порт, призначений виключно для Envoy (15090).
  • Метрики шлюзу надаються через порт телеметрії пoда шлюзу.
  • Ці точки доступу не захищені взаємним TLS, тому не рекомендується здійснювати збір даних безпосередньо через HTTPS.

Підхід у цьому завданні додає виділені прослуховувачі, захищені mTLS, щоб Prometheus збирав метрики через зашифроване, взаємно автентифіковане зʼєднання.

Перед початком

Налаштування Prometheus для збору метрик через mTLS

Prometheus має надавати дійсний сертифікат, якому довіряє CA мережі, під час збору даних з захищених портів. Найпростіший спосіб надати ці облікові дані — впровадити sidecar Istio в pod Prometheus і використати OUTPUT_CERTS, щоб записати сертифікат робочого навантаження у спільний том.

Приклад prometheus-secure-metrics (samples/addons/extras/prometheus-secure-metrics.yaml) — це автономна заміна для samples/addons/prometheus.yaml з впровадженням sidecar, експортом сертифікатів і попередньо налаштованими завданнями збору через mTLS.

  1. Розгорніть Prometheus із попередньо налаштованим збором через mTLS:

    Zip
    $ kubectl apply -n istio-system -f @samples/addons/extras/prometheus-secure-metrics.yaml@
    $ kubectl rollout status deployment/prometheus -n istio-system

    Приклад налаштовує наступні ключові параметри порівняно зі стандартною надбудовою Prometheus:

    • мітка sidecar.istio.io/inject: "true" — перевизначає типове значення "false" на podʼі Prometheus, увімкнувши інʼєкцію sidecar.
    • OUTPUT_CERTS: /etc/istio-certs — вказує sidecar записувати сертифікат робочого навантаження, ключ і кореневий CA у спільний том, щоб Prometheus міг читати їх для збору через mTLS.
    • INBOUND_CAPTURE_PORTS: "" — запобігає перехопленню sidecar вхідного трафіку Prometheus; sidecar використовується виключно для надання сертифікатів.
    • sidecar.istio.io/userVolumeMount — монтує том сертифікатів у контейнер istio-proxy, щоб він міг записувати сертифікати. Той самий том також монтується в prometheus-server, щоб він міг їх читати. Обидва монтування є обовʼязковими.
    • Завдання збору — ConfigMap містить два попередньо налаштовані завдання збору даних через mTLS (istio-secure-merged-metrics на порту 15092, istio-secure-envoy-metrics на порту 15091), які виявляють podʼи через анотації prometheus.istio.io/secure-port і prometheus.istio.io/secure-envoy-port.
  2. Перевірте, що pod Prometheus має впроваджений sidecar Istio та працює:

    $ kubectl get pod -n istio-system -l app.kubernetes.io/name=prometheus
    NAME                          READY   STATUS    RESTARTS   AGE
    prometheus-6c647c84c8-gpxt4   3/3     Running   0          75s

Увімкнення рідних портів метрик mTLS (Istio 1.31+)

У версії Istio 1.31 було введено дві змінні середовища, які вбудовують захищені mTLS статичні прослуховувачі завантаження безпосередньо в кожен проксі-сервер Envoy — як проксі sidecar, так і gateway:

ЗміннаТипове значенняОпис
ENVOY_SECURE_METRICS_PORT0 (вимкнено)Додає прослуховувача mTLS, який проксіює до порту статистики лише Envoy (15090)
ENVOY_SECURE_MERGED_METRICS_PORT0 (вимкнено)Додає прослуховувача mTLS, який проксіює до порту обʼєднаних метрик (15020, включає статистику застосунку та агента)

Коли вони встановлені, Envoy додає налаштовані прослуховувачі під час початкового завантаження. Збирачі мають надавати сертифікат, якому довіряє CA мережі; це може бути сертифікат робочого навантаження Istio (як надано вище) або будь-який сертифікат, виданий довіреним CA, таким як cert-manager.

Увімкнення на робочому навантаженні sidecar

Цей приклад використовує httpbin як робоче навантаження. Маніфест нижче базується на прикладі httpbin з доданими анотаціями захищених метрик до Deployment.

  1. Розгорніть httpbin з увімкненими портами захищених метрик:

    $ kubectl label namespace default istio-injection=enabled --overwrite
    $ kubectl apply -f - <<EOF
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
        service: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 8080
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
          annotations:
            proxy.istio.io/config: |
              proxyMetadata:
                ENVOY_SECURE_METRICS_PORT: "15091"
                ENVOY_SECURE_MERGED_METRICS_PORT: "15092"
            prometheus.io/path: "/stats/prometheus"
        spec:
          serviceAccountName: httpbin
          containers:
          - image: docker.io/mccutchen/go-httpbin:v2.15.0
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 8080
    EOF
    • ENVOY_SECURE_METRICS_PORT (15091) — це порт прослуховувача mTLS для статистики лише Envoy.
    • ENVOY_SECURE_MERGED_METRICS_PORT (15092) — це порт прослуховувача mTLS для обʼєднаних метрик (Envoy + застосунок + агент).
  2. Встановіть змінні середовища, які використовуються в наступних кроках перевірки:

    $ export HTTPBIN_POD=$(kubectl get pod -n default -l app=httpbin -o jsonpath='{.items[0].metadata.name}')
    $ export HTTPBIN_IP=$(kubectl get pod -n default -l app=httpbin -o jsonpath='{.items[0].status.podIP}')
    $ export PROM_POD=$(kubectl get pod -n istio-system -l app.kubernetes.io/name=prometheus -o jsonpath='{.items[0].metadata.name}')
  3. Перевірте, що захищені прослуховувачі налаштовані на sidecar httpbin:

    $ istioctl proxy-config listeners "$HTTPBIN_POD" -n default | grep -E "15090|15091|15092"
    0.0.0.0       15090 ALL                                                                                     Inline Route: /stats/prometheus*
    0.0.0.0       15091 Trans: tls                                                                              Inline Route: /stats/prometheus*
    0.0.0.0       15092 Trans: tls                                                                              Inline Route: /stats/prometheus*, /metrics*

    Trans: tls на портах 15091 і 15092 підтверджує, що прослуховувачі mTLS активні.

Увімкнення на шлюзі

Ті самі змінні працюють однаково на проксі шлюзів, оскільки вони використовують той самий шлях початкового завантаження pilot-agent.

  1. Виправте Deployment вхідного шлюзу:

    $ cat <<EOF > /tmp/gateway-secure-metrics-patch.yaml
    

spec: template: metadata: annotations: prometheus.istio.io/secure-port: "15092" prometheus.io/path: "/stats/prometheus" spec: containers: - name: istio-proxy env: - name: ENVOY_SECURE_METRICS_PORT value: "15091" - name: ENVOY_SECURE_MERGED_METRICS_PORT value: "15092" EOF $ kubectl patch deployment istio-ingressgateway -n istio-system –type=strategic –patch-file=/tmp/gateway-secure-metrics-patch.yaml $ kubectl rollout status deployment/istio-ingressgateway -n istio-system

  1. Перевірте, що захищені прослуховувачі налаштовані на вхідному шлюзі:

    $ export GW_POD=$(kubectl get pod -n istio-system -l app=istio-ingressgateway -o jsonpath='{.items[0].metadata.name}')
    

$ istioctl proxy-config listeners "$GW_POD" -n istio-system | grep -E "15090|15091|15092" 0.0.0.0 15090 ALL Inline Route: /stats/prometheus* 0.0.0.0 15091 Trans: tls Inline Route: /stats/prometheus* 0.0.0.0 15092 Trans: tls Inline Route: /stats/prometheus*, /metrics*

`Trans: tls` на портах `15091` і `15092` підтверджує, що прослуховувачі mTLS активні на шлюзі.

Повністю посилена конфігурація

Для повністю посиленого розгортання поєднайте захищені порти з METRICS_LOCALHOST_ACCESS_ONLY. Це обмежує базові порти відкритого тексту (15090 і 15020) localhost, роблячи прослуховувачі mTLS єдиною зовнішньо доступною поверхнею збору:

$ cat <<EOF > /tmp/httpbin-hardened-patch.yaml
spec:
  template:
    metadata:
      annotations:
        proxy.istio.io/config: |
          proxyMetadata:
            ENVOY_SECURE_METRICS_PORT: "15091"
            ENVOY_SECURE_MERGED_METRICS_PORT: "15092"
            METRICS_LOCALHOST_ACCESS_ONLY: "true"
        prometheus.io/path: "/stats/prometheus"
EOF
$ kubectl patch deployment httpbin -n default --type=merge --patch-file=/tmp/httpbin-hardened-patch.yaml

Перевірка

Перевірка захищеного збору метрик за допомогою Prometheus

Після завершення конфігурації перевірте, що Prometheus успішно збирає метрики через взаємний TLS.

  1. Перевірте, що збір через mTLS працює, виконавши curl до захищеного порту з podʼа Prometheus, використовуючи його сертифікат робочого навантаження:

    $ kubectl exec -n istio-system "$PROM_POD" -c istio-proxy -- \
        curl -s -o /dev/null -w "%{http_code}" --max-time 5 \
        --cacert /etc/istio-certs/root-cert.pem \
        --cert /etc/istio-certs/cert-chain.pem \
        --key /etc/istio-certs/key.pem \
        --insecure \
        https://"$HTTPBIN_IP":15092/stats/prometheus
    200

    Відповідь HTTP 200 підтверджує, що pod Prometheus успішно виконав рукостискання mTLS з портом 15092 httpbin і отримав метрики. Прапорець --insecure пропускає лише перевірку імені хосту — сертифікати робочих навантажень Istio використовують URI SAN SPIFFE (наприклад, spiffe://cluster.local/ns/default/sa/httpbin), а не IP-адреси, тому curl не може зіставити IP podʼа з сертифікатом. Рукостискання взаємного TLS та обмін сертифікатами все одно відбуваються, саме тому --cacert, --cert і --key все ще обовʼязкові. Це також причина, чому завдання збору Prometheus використовує insecure_skip_verify: true.

  2. Перевірте цілі збору в інтерфейсі Prometheus

    Відкрийте дашборд Prometheus за допомогою istioctl dashboard prometheus -n istio-system, потім перейдіть до Status → Targets. Перевірте, що завдання istio-secure-merged-metrics і istio-secure-envoy-metrics перелічують pod httpbin зі статусом UP і точками доступу у вигляді https://<pod-ip>:15092/stats/prometheus.

  3. Перевірте, що mTLS застосовується, підтвердивши, що звичайний HTTP-запит до захищеного порту відхиляється:

    $ kubectl exec -n default "$HTTPBIN_POD" -c istio-proxy -- curl -s --max-time 3 http://"$HTTPBIN_IP":15091/stats/prometheus
    upstream connect error or disconnect/reset before headers. reset reason: connection termination

    Помилка завершення зʼєднання підтверджує, що порт приймає лише TLS-зʼєднання — звичайний HTTP-запит відхиляється негайно.

Це підтверджує, що Prometheus збирає метрики за допомогою HTTPS через Istio mTLS через рідні захищені порти, а не отримує прямий доступ до портів телеметрії відкритого тексту (15020 або 15090).

Очищення

ZipZip
$ kubectl delete -n istio-system -f @samples/addons/extras/prometheus-secure-metrics.yaml@
$ kubectl delete -f @samples/httpbin/httpbin.yaml@
$ kubectl label namespace default istio-injection-

Застарілий обхідний шлях (Istio < 1.31)

Якщо ви запускаєте Istio старіший за 1.31, рідний підхід на основі змінних середовища недоступний. Кроки нижче демонструють один із способів досягнення захищеного збору метрик за допомогою CRD Istio: захищений TLS-фронтенд створюється на порту 15091 (відкритий для Prometheus), який маршрутизує всередину або на порт 15020 (обʼєднані метрики — Envoy + застосунок + агент), або на 15090 (метрики лише Envoy). Збирачі підключаються до 15091 через TLS ISTIO_MUTUAL; ServiceEntry і VirtualService обробляють внутрішню маршрутизацію до бекенду відкритого тексту.

Застарілий: захищені метрики для sidecar

  1. Розгорніть httpbin і створіть ресурс Sidecar із захищеним вхідним слухачем на порту 15091:

    Zip
    $ kubectl label namespace default istio-injection=enabled --overwrite
    $ kubectl apply -f @samples/httpbin/httpbin.yaml@
    $ cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: Sidecar
    metadata:
      name: secure-metrics
      namespace: default
    spec:
      ingress:
      - port:
          number: 15091
          name: https-metrics
          protocol: HTTP
        defaultEndpoint: 127.0.0.1:15020 # Change to 15090 for Envoy-only metrics
    EOF
  2. Додайте анотації до podʼа робочого навантаження для виявлення Prometheus:

    $ kubectl annotate pod -n default \
      -l app=httpbin \
      prometheus.io/scrape="true" \
      prometheus.io/path="/stats/prometheus" \
      prometheus.istio.io/secure-port="15091" \
      --overwrite

Застарілий: захищені метрики для шлюзів

  1. Створіть Gateway із захищеним HTTPS-слухачем на порту 15091:

    $ cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: Gateway
    metadata:
      name: metrics-gateway
      namespace: istio-system
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 15091
          name: https-metrics
          protocol: HTTPS
        tls:
          mode: ISTIO_MUTUAL
        hosts: ["*"]
    EOF
  2. Створіть ServiceEntry, щоб відкрити порт телеметрії шлюзу всередині мережі:

    $ cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: gateway-admin
      namespace: istio-system
    spec:
      hosts: [gateway-admin.local]
      location: MESH_INTERNAL
      ports:
      - number: 15020  # Change to 15090 for Envoy-only metrics
        name: http-metrics
        protocol: HTTP
      resolution: STATIC
      endpoints:
      - address: 127.0.0.1
    EOF
  3. Створіть VirtualService, щоб маршрутизувати запити від захищеного прослуховувача до порту телеметрії:

    $ cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: gateway-metrics
      namespace: istio-system
    spec:
      hosts: ["*"]
      gateways: [metrics-gateway]
      http:
      - match:
        - uri:
            prefix: /stats/prometheus
        route:
        - destination:
            host: gateway-admin.local
            port:
              number: 15020  # Change to 15090 for Envoy-only metrics
    EOF
  4. Додайте анотації до podʼа шлюзу для виявлення Prometheus:

    $ kubectl annotate pod -n istio-system \
      -l app=istio-ingressgateway \
      prometheus.istio.io/secure-port=15091 \
      --overwrite

Застарілий: очищення

ZipZip
$ kubectl delete sidecar secure-metrics -n default
$ kubectl delete gateway metrics-gateway -n istio-system
$ kubectl delete serviceentry gateway-admin -n istio-system
$ kubectl delete virtualservice gateway-metrics -n istio-system
$ kubectl delete -n istio-system -f @samples/addons/extras/prometheus-secure-metrics.yaml@
$ kubectl delete -f @samples/httpbin/httpbin.yaml@
$ kubectl label namespace default istio-injection-
Чи була ця інформація корисною?
Чи є у вас пропозиції щодо покращення?

Дякуємо за ваш відгук!