通过mTLS采集网格内应用的监控指标

在服务网格启用mTLS(mutual TLS)的场景中,由于Sidecar代理会拦截所有应用的入向流量,应用公开的监控指标端口也必须通过mTLS进行加密访问。对于一些关键业务,除了业务通信本身加密之外,加密采集监控指标也十分必要。本文以Prometheus Operator自建Prometheus的场景为例,介绍如何通过mTLS采集网格内应用的监控指标。

前提条件

已部署Bookinfo应用示例。具体操作,请参见在ASM实例关联的集群中部署应用

配置Prometheus实例采集TLS指标说明

为了使Prometheus能够通过Sidecar代理的TLS认证,Prometheus需要使用一个由ASM实例根证书签发的证书。您可以借助Sidecar代理的证书挂载能力来实现这一目的。通过为Prometheus Pod定义约定的Annotation,可以使Sidecar代理将ASM控制平面为其签发的证书挂载至共享卷,Prometheus容器通过挂载该共享卷即可得到证书和密钥,具体操作步骤如下:

  1. 为Prometheus Pod增加卷istio-certs。

    volumes:
    - emptyDir:
        medium: Memory
      name: istio-certs
  2. 为Prometheus Pod添加如下2个annotation

    annotations:
      proxy.istio.io/config: |
        proxyMetadata:
          OUTPUT_CERTS: /etc/istio-output-certs
      sidecar.istio.io/userVolumeMount: '[{"name": "istio-certs", "mountPath": "/etc/istio-output-certs"}]'
    • proxy.istio.io/config:指定代理配置,其中proxyMetadata.OUTPUT_CERTS指定将证书和密钥存储至/etc/istio-output-certs路径下。

    • sidecar.istio.io/userVolumeMount:将卷挂载到Sidecar代理容器的/etc/istio-output-certs路径下。

  3. 为Prometheus容器挂载istio-certs卷至/etc/prom-certs/路径,便于Prometheus从该路径获取由Sidecar代理写入的证书和密钥。

    volumeMounts:
    - mountPath: /etc/prom-certs/
      name: istio-certs
  4. 在采集配置中指定哪些工作负载使用TLS(只有注入了Sidecar的工作负载需要)发起指标抓取请求,并为TLS指定使用的证书路径。

    本文以Prometheus Operator环境为例。

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: productpage
      labels:
        app: productpage
        team: bookinfo
    spec:
      selector:
        matchLabels:
          app: productpage
      endpoints:
      - port: http-9080
        interval: 30s
        path: /metrics
        scheme: https
        tlsConfig:
          caFile: /etc/prom-certs/root-cert.pem
          certFile: /etc/prom-certs/cert-chain.pem
          keyFile: /etc/prom-certs/key.pem
          insecureSkipVerify: true

    在以上YAML中,通过labels指定对productpage应用进行指标采集,并对其采集端点进行了定义。在端点定义中,与TLS相关的配置如下:

    • scheme: https:指定使用HTTPS发起请求。

    • tlsConfig:指定证书、CA证书和密钥的文件路径。

    • insecureSkipVerify: true:由于Prometheus不支持Istio的身份命名方式,所以此处允许不安全的认证访问。

以上配置可以使Prometheus挂载Sidecar提供的证书和密钥,并使用该证书和密钥发起TLS请求。

操作步骤

步骤一:安装Prometheus Operator

  1. 执行以下命令,从GitHub上克隆Prometheus Operator项目的源代码仓库到本地计算机。

    git clone https://github.com/prometheus-operator/prometheus-operator.git
  2. 使用K8s集群的KubeConfig,执行以下命令,安装Prometheus Operator。

    cd prometheus-operator/
    kubectl create -f bundle.yaml
  3. 执行以下命令,查看Pod状态。

    kubectl get pods

    预期输出:

    NAME                                     READY   STATUS        RESTARTS   
    prometheus-operator-58dd988c9c-qhrrp     2/2     Running       0      

    预期输出表明Prometheus Operator已安装成功。

步骤二:定义Prometheus CR部署Prometheus实例

  1. 将以下YAML保存至本地,命名为prometheus.yaml。

    YAML包含Prometheus实例声明及其依赖的相关ServiceAccount、ClusterRole和ClusterRoleBinding。在Deployment配置中,可以看到配置Prometheus实例采集TLS指标说明中提及的相关证书卷挂载的配置。

    说明

    本文提供的Prometheus相关CR仅用于演示,请您根据实际生产环境进行调整。

    展开查看prometheus.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: prometheus-full-access
      namespace: default
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: prometheus-full-access
    rules:
    - apiGroups: [""]
      resources:
      - nodes
      - nodes/metrics
      - services
      - endpoints
      - pods
      verbs: ["get", "list", "watch"]
    - apiGroups:
      - extensions
      - apps
      resources:
      - deployments
      - replicasets
      verbs: ["get", "list", "watch"]
    - apiGroups: [""]
      resources:
      - configmaps
      verbs: ["get"]
    - nonResourceURLs: ["/metrics"]
      verbs: ["get"]
    ---
    apiVersion: monitoring.coreos.com/v1
    kind: Prometheus
    metadata:
      name: default
      labels:
        prometheus: default
    spec:
      logLevel: debug
      podMetadata:
        annotations:
          traffic.sidecar.istio.io/includeInboundPorts: ""
          traffic.sidecar.istio.io/includeOutboundIPRanges: ""
          proxy.istio.io/config: |  # configure an env variable `OUTPUT_CERTS` to write certificates to the given folder
            proxyMetadata:
              OUTPUT_CERTS: /etc/istio-output-certs
          sidecar.istio.io/userVolumeMount: '[{"name": "istio-certs", "mountPath": "/etc/istio-output-certs"}]'
      volumes:
      - emptyDir:
          medium: Memory
        name: istio-certs
      volumeMounts:
      - mountPath: /etc/prom-certs/
        name: istio-certs
      replicas: 2
      version: v2.26.0
      serviceAccountName: prometheus-full-access
      serviceMonitorSelector:
        matchLabels:
          team: bookinfo
      ruleSelector:
        matchLabels:
          role: alert-rules
          prometheus: example
  2. 使用K8s集群的KubeConfig,执行以下命令,应用prometheus.yaml到K8s集群。

    kubectl apply -f prometheus.yaml
  3. 执行以下命令,检查Prometheus实例是否正确被拉起。

    kubectl get pods

    预期输出:

    NAME                                   READY   STATUS    RESTARTS
    prometheus-default-0                   3/3     Running   0 
    prometheus-default-1                   3/3     Running   0  
    prometheus-operator-58dd988c9c-qhrrp   2/2     Running   0  

    可以看到prometheus-default-0和prometheus-default-1两个Pod已经启动。

步骤三:定义ServiceMonitor CR声明采集规则

  1. 将以下YAML保存至本地,命名为service-monitor.yaml。

    YAML包含ServiceMonitor API的声明,描述了如何从工作负载采集监控指标。在YAML中可以看到在配置Prometheus实例采集TLS指标说明中提及的证书路径和scheme的设置。

    说明

    本文提供的Prometheus相关CR仅用于演示,请您根据实际生产环境进行调整。

    iVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: productpage
      labels:
        app: productpage
        team: bookinfo
    spec:
      selector:
        matchLabels:
          app: productpage
      endpoints:
      - port: http-9080
        interval: 30s
        path: /metrics
        scheme: https
        tlsConfig:
          caFile: /etc/prom-certs/root-cert.pem
          certFile: /etc/prom-certs/cert-chain.pem
          keyFile: /etc/prom-certs/key.pem
          insecureSkipVerify: true
  2. 使用K8s集群KubeConfig,执行以下命令,应用service-monitor.yaml到K8s集群。

    kubectl apply -f service-monitor.yaml

步骤四:将本地端口映射到Prometheus Operator服务,查看Prometheus采集到的指标

  1. 执行以下命令,创建端口转发,将本地端口9090映射到Prometheus Operator服务的9090端口。

    kubectl port-forward svc/prometheus-operated 9090
  2. 在浏览器输入localhost:9090,打开Prometheus的Web UI。

    image

  3. 在顶部菜单栏,选择Status > Target,查看监控目标的状态。

    说明

    如果某个目标通过TLS加密,在界面上可能会显示为“Unavailable”(不可用),这可能是因为配置了TLS但没有正确设置TLS认证。

    如下图所示,可以看到目标StateUp,表示指标成功被抓取。

    image

  4. 在顶部菜单栏,单击Graph返回查询页面,在查询文本框中输入python_gc_objects_collected_total指标名,单击右侧的Execute

    如下图所示,可以看到上报的指标数据。

    image