• 排查 Kubernetes HPA 通过 Prometheus 获取不到 http_requests 指标的问题


    部署好了 kube-prometheus 与 k8s-prometheus-adapter (详见之前的博文 k8s 安装 prometheus 过程记录),使用下面的配置文件部署 HPA(Horizontal Pod Autoscaling) 却失败。

    apiVersion: autoscaling/v2beta2 
    kind: HorizontalPodAutoscaler
    metadata: 
      name: blog-web
    spec: 
      scaleTargetRef: 
        apiVersion: apps/v1 
        kind: Deployment 
        name: blog-web
      minReplicas: 2
      maxReplicas: 12 
      metrics: 
        - type: Pods
          pods:
            metric:
              name: http_requests
            target:
              type: AverageValue
              averageValue: 100
    

    错误信息如下:

    unable to get metric http_requests: unable to fetch metrics from custom metrics API: the server could not find the metric http_requests for pods
    

    通过下面的命令查看 custom.metrics.k8s.io api 支持的 http_requests(每秒请求数QPS)监控指标:

    $kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ | jq . | egrep pods/.*http_requests 
          "name": "pods/alertmanager_http_requests_in_flight",
          "name": "pods/prometheus_http_requests"
    

    发现只有 prometheus_http_requests 指标 ,没有所需的 http_requests 开头的指标。

    打开 prometheus 控制台,发现 /service-discovery 中没有出现我们想监控的应用 blog-web ,网上查找资料后知道了需要部署 ServiceMonitor 让 prometheus 发现所监控的 service 。

    添加下面的 ServiceMonitor 配置文件:

    kind: ServiceMonitor
    apiVersion: monitoring.coreos.com/v1
    metadata:
      name: blog-web-monitor
      labels:
        app: blog-web-monitor
    spec:
      selector:
        matchLabels:
          app: blog-web
      endpoints: 
      - port: http
    

    部署后还是没有被 prometheus 发现,查看 prometheus 的日志发现下面的错误:

    Failed to list *v1.Pod: pods is forbidden: User "system:serviceaccount:monitoring:prometheus-k8s" cannot list resource "pods" in API group "" at the cluster scope
    

    在园子里的博文 PrometheusOperator服务自动发现-监控redis样例 中找到了解决方法,将 prometheus-clusterRole.yaml 改为下面的配置:

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

    重新部署即可

    kubectl apply -f prometheus-clusterRole.yaml
    

    注1:如果采用上面的方法还是没被发现,需要强制刷新 prometheus 的配置,参考 部署 ServiceMonitor 之后如何让 Prometheus 立即发现
    注2:也可以将 prometheus 配置为自动发现 service 与 pod ,参考园子里的博文 prometheus配置pod和svc的自动发现和监控PrometheusOperator服务自动发现-监控redis样例

    但是这时还有问题,虽然 service 被 prometheus 发现了,但 service 所对应的 pod 一个都没被发现。

    production/blog-web-monitor/0 (0/19 active targets)
    

    排查后发现是因为 ServiceMonitor 与 Service 配置不对应,Service 配置文件中缺少 ServiceMonitor 配置中 matchLabels 所对应的 label ,ServiceMonitor 中的 port 没有对应 Service 中的 ports 配置,修正后的配置如下:
    service-blog-web.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: blog-web
      labels:
        app: blog-web
    spec:
      type: NodePort
      selector:
        app: blog-web
      ports:
      - name: http-blog-web 
        nodePort: 30080
        port: 80
        targetPort: 80
    

    servicemonitor-blog-web.yaml

    kind: ServiceMonitor
    apiVersion: monitoring.coreos.com/v1
    metadata:
      name: blog-web-monitor 
      labels:
        app: blog-web
    spec:
      selector:
        matchLabels:
          app: blog-web
      endpoints: 
      - port: http-blog-web
    

    用修正后的配置部署后,pod 终于被发现了:

    production/blog-web-monitor/0 (0/5 up) 
    

    但是这些 pod 全部处于 down 状态。

    Endpoint	                      State	 Scrape Duration	Error
    http://192.168.107.233:80/metrics DOWN	 server returned HTTP status 400 Bad Request
    

    通过园子里的博文 使用Kubernetes演示金丝雀发布 知道了原来需要应用自己提供 metrics 监控指标数据让 prometheus 抓取。

    标准Tomcat自带的应用没有/metrics这个路径,prometheus获取不到它能识别的格式数据,而指标数据就是从/metrics这里获取的。所以我们使用标准Tomcat不行或者你就算有这个/metrics这个路径,但是返回的格式不符合prometheus的规范也是不行的。

    我们的应用是用 ASP.NET Core 开发的,所以选用了 prometheus-net ,由它提供 metrics 数据给 prometheus 抓取。

    • 安装 nuget 包
    dotnet add package prometheus-net.AspNetCore
    
    • 添加 HttpMetrics 中间件
    app.UseRouting();
    app.UseHttpMetrics();
    
    • 添加 MapMetric 路由
    app.UseEndpoints(endpoints =>
    {
       endpoints.MapMetrics();
    };
    

    当通过下面的命令确认通过 /metrics 路径可以获取监控数据时,

    $ docker exec -t $(docker ps -f name=blog-web_blog-web -q | head -1) curl 127.0.0.1/metrics | grep http_request_duration_seconds_sum
    http_request_duration_seconds_sum{code="200",method="GET",controller="AggSite",action="SiteHome"} 0.44973779999999997
    http_request_duration_seconds_sum{code="200",method="GET",controller="",action=""} 0.0631272
    

    Prometheus 控制台 /targets 页面就能看到 blog-web 对应的 pod 都处于 up 状态。

    production/blog-web-monitor/0 (5/5 up)
    

    这时通过 custom metrics api 可以查询到一些 http_requests 相关的指标。

    $ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ | jq . | egrep pods/*/http_requests 
          "name": "pods/http_requests_in_progress",
          "name": "pods/http_requests_received"
    

    这里的 http_requests_received 就是 QPS(每秒请求数) 指标数据,用下面的命令请求 custom metrics api 获取数据:

    kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/production/pods/*/http_requests_received | jq .
    

    其中1个 pod 的 http_requests_received 指标数据如下:

    {
      "kind": "MetricValueList",
      "apiVersion": "custom.metrics.k8s.io/v1beta1",
      "metadata": {
        "selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/production/pods/%2A/http_requests_received"
      },
      "items": [
        {
          "describedObject": {
            "kind": "Pod",
            "namespace": "production",
            "name": "blog-web-65f7bdc996-8qp5c",
            "apiVersion": "/v1"
          },
          "metricName": "http_requests_received",
          "timestamp": "2020-01-18T14:35:34Z",
          "value": "133m",
          "selector": null
        }
      ]
    }
    

    其中的 133m 表示 0.133

    然后就可以在 HPA 配置文件中基于这个指标进行自动伸缩

    apiVersion: autoscaling/v2beta2 
    kind: HorizontalPodAutoscaler
    metadata: 
      name: blog-web
    spec: 
      scaleTargetRef: 
        apiVersion: apps/v1 
        kind: Deployment 
        name: blog-web
      minReplicas: 5
      maxReplicas: 12 
      metrics: 
      - type: Pods
        pods:
          metric:
            name: http_requests_received
          target:
            type: AverageValue
            averageValue: 100
    

    终于搞定了!

    # kubectl get hpa
    NAME       REFERENCE             TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
    blog-web   Deployment/blog-web   133m/100   5         12        5          4d
    
  • 相关阅读:
    1. shiro-用户认证
    Salt 盐值
    使用ajax向后台发送请求跳转页面无效的原因
    @RequestParam和@RequestBody的区别
    JavaSE:Java11的新特性
    JavaSE: Java10的新特性
    JavaSE:Java9 新特性
    JavaSE:Java8新特性
    JavaSE:Java8新特性
    JavaSE:Java8 新特性
  • 原文地址:https://www.cnblogs.com/dudu/p/12197646.html
Copyright © 2020-2023  润新知