最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Kubernetes 实战:用 Prometheus 提高 K8s 集群弹性伸缩能力的准确性

网站源码admin4浏览0评论

Kubernetes 实战:用 Prometheus 提高 K8s 集群弹性伸缩能力的准确性

导语:本文主要通过 Prometheus 在观测 Kubernetes 方面的独特优势,来阐述如何利用 Prometheus 提高 kubernetes 自动弹性伸缩能力的准确性。

Kubernetes 自主扩缩容概述

当我们在 kubernetes 容器部署服务的时候,可能会有如下的困惑:

我的服务需要几个 Pod?资源怎么分配?

在业务高峰的时候对于资源的需求和低谷的时候的需求不同,如何调整?

我怎么知道业务目前处于高峰还是低谷?

给 Pod 分配多少 CPU 和内存才能保证我的服务正常运行,并且性能最佳?

在我们不了解 Kubernetes 提供的垂直 Pod 自动扩缩器(VPA)和水平 Pod 自动扩缩器(HPA)之前,大部分运维同学会采取监控随着业务高峰低谷的变化,CPU、内存使用率等指标,来沉淀经验从而手动扩缩容:比如晚上业务压力小,我们可以通过指令或者 UI 将 Pod 副本数调整为 2 个,当白天高峰期的时候,我们再将 Pod 的副本数调整为 4 个,但是这些操作都是人为介入,很耗费精力。

1.png

这个时候,如果不想再过多的人为干预资源的分布,而是想把有限的精力投放到应用开发,我们就开始了寻找自动扩缩能力之旅,了解到了 Kubernetes 自动扩缩能力:

集群层级自动扩缩(CA): 集群自动伸缩,Node 级别自动扩缩容。

垂直 Pod 自动扩缩(VPA):扩缩 Pod 配置,比如 CPU、内存配置。

水平 Pod 自动扩缩容(HPA):Pod 水平自动伸缩,根据资源使用率或者自定义指标自动调整 Pod 的个数。

这三种自动扩缩器中,CA 代表的 Node 增减容易引起 Kubernetes 集群的稳定性,一旦出现问题会影响部署在集群的所有业务,故而生产环境不会选择 CA,而 VPA 目前的技术成熟度还远远不够,可能会导致 Pod 的重建,也有可能被调度到其他的节点上。故而我们优先考虑 HPA,用来做 Pod 的水平自动伸缩,根据资源使用率或者自定义指标自动调整 Pod 的个数。

但是这个时候又有了新的问题:传统的扩缩容方案往往依赖资源使用率,也就是简单的 CPU 和内存指标,但是难以应对复杂的业务场景,具体有以下几个方面的考虑:

维度单一:比如 A 应用目前可能 CPU 的使用率并不高,但是请求队列积压,导致延迟升高,这个时候,基于 CPU 的扩缩就不会触发,导致性能问题。

缺乏灵活性:基于 HPA 去做静态阈值扩缩的时候往往会设定:CPU>80% 则扩容,缺乏动态调整和场景适配能力。

  • 周期性业务:拿目前中小学生都会使用到的在线教育平台来举例子,工作日晚上6点到8点的流量是白天的三倍,周末却是白天的流量更大,若采用固定的阈值,要么在低峰的时候资源被浪费,要么在高峰期的时候资源扩缩延迟。
  • 突发流量:电商秒杀活动,就可能会在很短的时间内涌入大量的请求,静态资源的扩缩难以及时响应。

所以我们本篇文章主要落脚于:腾讯云托管 Prometheus 作为云原生监控领域的标杆产品,如何通过多维度的监控能力,协同HPA弹性伸缩原理,为用户提供更智能,更高效的弹性扩缩解决方案。

一、原理说明

2.png

1.数据采集

Prometheus 通过采集集群多维指标来判断扩缩容情况,包括:

  • 基础资源(CPU、内存、I/O、网络)
  • 自定义业务指标(请求量、错误率、响应延迟等)

2.数据存储与查询

腾讯云托管 Prometheus 采集存储都是高可用架构,支持通过 PromQL 进行复杂分析(如计算速率、聚合统计)。

3.png

3.指标适配与 HPA 集成

利用 Prometheus Adapter 将原始指标(如 http_requests_total)转换为 HPA 可识别的格式(如 http_requests_per_second),突破 HPA 对自定义指标的支持限制。

4.动态扩缩策略

基于业务场景定义弹性规则:

  • 请求速率 > 100/s 时扩容
  • 结合响应时间与错误率综合判定
  • 周期性流量预判(如周末自动扩容)

二、操作流程

1.选择腾讯云 Prometheus

登陆腾讯云可观测平台,选择 Prometheus:

4.png

根据业务部署地域,购买 Prometheus 实例:

5.png

新建完成后,就可以开始使用了。

2.上报自定义指标

这个时候需要部署上报自定义指标,以 Python 为例子,先写一个:

Python + Flask 示例

代码语言:javascript代码运行次数:0运行复制
from flask import Flask
from prometheus_client import Counter, generate_latest, CONTENT_TYPE_LATEST

app = Flask(__name__)
# 定义一个计数器来统计 HTTP 请求总数
http_requests_total = Counter('http_requests_total', 'Total HTTP requests')

@app.route('/')
defhello_world():
# 每次请求时计数器加 1
    http_requests_total.inc()
return'Hello, World!'

@app.route('/metrics')
defmetrics():
# 暴露 Prometheus 可采集的指标数据
return generate_latest(), 200, {'Content-Type': CONTENT_TYPE_LATEST}

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

将上述代码保存为 myapp.py,同时创建 Dockerfile,在 Dockerfile 中构建包含该应用的镜像:

代码语言:javascript代码运行次数:0运行复制
FROM python:3.9-slim
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir -r requirements.txt
EXPOSE 5000
CMD ["python", "myapp.py"]

并创建 requirements.txt 文件,内容如下:

代码语言:javascript代码运行次数:0运行复制
flask
prometheus_client

依赖刚刚创建的 Dockerfile,构建 myapp 的镜像文件,从而推送到腾讯云 TCR 上:

6.png

结束后可以在腾讯云容器服务->镜像仓库看到以下结果:

7.png

部署 myapp 的应用以及服务 service,接下来就是最重要的自定义指标上报了,我们先构建对应的应用:my-flask-app.yaml 如下:

代码语言:javascript代码运行次数:0运行复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-flask-app
  labels:
    app: my-flask-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-flask-app
  template:
    metadata:
      labels:
        app: my-flask-app
    spec:
      containers:
      - name: my-flask-app
        image: your-flask-app-image:latest  # 替换为实际的镜像名称和标签
        ports:
        - containerPort: 5000 # 暴露指标端口
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "200m"
            memory: "256Mi"

然后部署 service:

代码语言:javascript代码运行次数:0运行复制
apiVersion: v1
kind: Service
metadata:
  name: my-flask-app-service
  labels:
    app: my-flask-app
spec:
  selector:
    app: my-flask-app
  ports:
  - name: metric #暴露指标端口
    port: 80
    targetPort: 5000

在 TKE 容器环境直接使用 yaml 部署,部署完成后可查看:

8.png

后续为了用腾讯云可观测平台的云压测来做压测从而触发 HPA 工作,我们将该 my-flask-app-service 修改成为内网 CLB 可访问的形式,这样在配置压测任务的时候就可以直接压测内网 CLB:80,就可以实现通过 HPA 进行弹性扩缩容的目的,此为后话。

接着就是通过腾讯云托管 Prometheus 进行自定义指标的上报:打开 Prometheus 控制台,选择数据采集->集成容器服务->数据采集配置。

选择新建自定义监控:

10.png

yaml 编辑:

11.png

确认后展示目前指标的采集情况:

12.png

指标详情中,我们进一步验证:http_requests_total 指标:

13.png

打开与托管 Prometheus 绑定的 Grafana 面板,选择 explore,验证指标 http_requests_total 是存在的,且携带了:namespace、Pod、app 的标签:

14.png

并且通过 curl 的动作,验证 http_requests_total 是随着访问而递增的计数器。

3.创建 Prometheus adapter

Prometheus Adapter 是一个 Kubernetes API 的扩展,用于将 Prometheus 的指标 http_requests_total 暴露并转化为 kubernetes 集群,Kubernetes API server可识别的指标:http_requests_per_second,以便 HPA 可以使用这些指标,去进行弹性扩缩容。在腾讯云 TKE 容器环境创建 Prometheus-adapter 的步骤如下:

1.打开 TKE 容器集群,选择配置管理,点击“新建”:

15.png

2.输入一下 config.yaml 并确认

16.png
代码语言:javascript代码运行次数:0运行复制
rules:
- seriesQuery: 'http_requests_total{namespace!="",pod!=""}'  # 必须包含namespace和pod标签
  resources:
    overrides:
      namespace: { resource: "namespace" }
      pod: { resource: "pod" }
  name:
    matches: "^(http_requests_total)$"  # 匹配原始指标名称
    as: "http_requests_per_second"      # 转换为HPA可用的指标名称
  metricsQuery: 'sum(rate(http_requests_total{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)'

3. 直接利用腾讯云 TKE 容器环境的 Prometheus-adapter 公共镜像,创建Prometheus-adapter 工作负载:

代码语言:javascript代码运行次数:0运行复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-adapter
  namespace: custom-metrics
  labels:
    app.kubernetes.io/component: metrics
    app.kubernetes.io/instance: prometheus-adapter
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: prometheus-adapter
    app.kubernetes.io/part-of: prometheus-adapter
    app.kubernetes.io/version: v0.12.0
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app.kubernetes.io/instance: prometheus-adapter
      app.kubernetes.io/name: prometheus-adapter
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
type: RollingUpdate
  template:
    metadata:
      labels:
        app.kubernetes.io/component: metrics
        app.kubernetes.io/instance: prometheus-adapter
        app.kubernetes.io/managed-by: Helm
        app.kubernetes.io/name: prometheus-adapter
        app.kubernetes.io/part-of: prometheus-adapter
        app.kubernetes.io/version: v0.12.0
    spec:
      serviceAccountName: prometheus-adapter
      containers:
      - name: prometheus-adapter
        image: ccrs.tencentyun/halewang/prometheus-adapter:v0.11.2
        args:
        - /adapter
        - --secure-port=6443
        - --cert-dir=/tmp/cert
        - --prometheus-url=http://172.16.64.16:9090
        - --metrics-relist-interval=1m
        - --v=6
        - --config=/etc/adapter/config.yaml
        - --prometheus-header=Authorization=Basic MTI1MTc2Mzg2ODooN2dBMmd+T0RXTW5rUD09RlRGOEk5Z3RNUnk=
        ports:
        - containerPort: 6443
          name: https
          protocol: TCP
        volumeMounts:
        - name: config
          mountPath: /etc/adapter/
          readOnly: true
        - name: tmp
          mountPath: /tmp
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 10001
      volumes:
      - name: config
        configMap:
          name: prometheus-adapter
      - name: tmp
        emptyDir: {}

注意:将 Prometheus-url 替换成自己在腾讯云可观测平台创建的 Prometheus 的url,将 Prometheus 的 appid:token 按照 Base64 转换后,作为 args 添加如上

部署完成后,检查日志:确保没有鉴权和 404 的报错:

17.png

4.定义 HPA 策略

创建一个 HPA 资源,让其根据自定义指标去进行弹性扩缩容,我们配置 http_requests_per_second 指标,HPA 资源如下:

代码语言:javascript代码运行次数:0运行复制
# my-flask-app-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-flask-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-flask-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: 100

部署完成后,在 TKE 容器环境进行检查:

18.png

这里需要注意的是:在my_flask_app_hpa 的配置中指标名称:http_requests_per_second 要与 Prometheus-adapter 的 config.yaml 中转化后,即“as”后的指标名称保持一致,并且在 Prometheus-adapter 的日志中能够看到 http_requests_per_second 被采集且返回:200

19.png

5.压测验证

这里结合我们腾讯云可观测平台的云压测来做对应的验证动作,打开腾讯云可观测平台->云压测,创建自己的项目名称,即可在该项目下选择“简单模式”来做相应的压测动作,在压测过程中,通过不停的访问 http_requests_total 的计数,从而http_requests_per_second 达到他扩缩的门限:

20.png

我们选择 my-flask-app-service 所在的 VPC 的发压机来做本次压测动作:

21.png

设置最大 VUs:200,通过 2 步在 1 分钟内压到最大并发,且压测 3 分钟:

22.png

在这个压测过程中,持续地关注 my-flask-app 工作负载 pod 数的变化:

从指令来看,Pod 数从之前的 1 个变成了 4 个,且还在变化:

23.png

从 TKE 控制台直接观察 Deployment 的事件以及 Pod 个数,也非常直观:

24.png
25.png

当压测结束,Pod 数又随着 http_requests_per_second 变小(每秒变化的速率降低),最终变为一个 Pod:

26.png
27.png
28.png

直接从 Grafana 直观地感受 Pod 数的变化:

29.png

至此验证了 Prometheus 基于自定义指标助力 K8s 集群进行弹性扩缩容的灵活性。

核心价值与思考

在业务运营的关键节点,例如大促活动筹备阶段或者业务升级的重要时刻,可观测平台都发挥着极为关键的作用,我们推动用户将可观测平台的各项产品灵活搭配的运用起来,比如云压测与托管 Prometheus,将两者精妙地整合起来,从而为 TKE 容器环境构建起一道坚实的资源管理纽带。

当然,我们也有不少客户已经切实感受到了这种整合带来的优势,比如可观测平台的全模块覆盖用户:某零售厂商,正是巧妙地运用了我们 APM 与 Prometheus 监控系统的无缝对接。在此基础上,配合云压测产品,达成了全链路压测(APM、云压测)、Prometheus 监控与 TKE 容器服务之间的高效联动,在新业务推出或者大促活动期间,即便遭遇如汹涌潮水般的流量高峰冲击,也能够镇定自若,游刃有余地应对各类挑战并确保业务的稳定运行。

结论

腾讯云托管 Prometheus 与容器环境 TKE 的结合,不仅仅实现了从“经验驱动”到“数据驱动”的运维转型,也通过实时监控、动态策略与自动化扩展,帮助企业不仅能够快速响应业务波动,提升用户体验。而且可以优化资源利用率,降低运营成本。

联系我们

如有任何疑问,欢迎加入官方技术交流群

关于腾讯云可观测平台

腾讯云可观测平台(Tencent Cloud Observability Platform,TCOP)基于指标、链路、日志、事件的全类型监控数据,结合强大的可视化和告警能力,为您提供一体化监控解决方案。满足您全链路、端到端的统一监控诉求,提高运维排障效率,为业务的健康和稳定保驾护航。功能模块有:

  • Prometheus 监控:开箱即用的 Prometheus 托管服务;
  • 应用性能监控 APM:支持无侵入式探针,零配置获得开箱即用的应用观测能力;
  • 云拨测 CAT:利用分布于全球的监测网络,提供模拟终端用户体验的拨测服务;
  • 前端/终端性能监控 RUM:Web、小程序、iOS、Android 端等大前端质量、性能监控;
  • Grafana 可视化服务:提供免运维、免搭建的 Grafana 托管服务;
  • 云压测 PTS:模拟海量用户的真实业务场景,全方位验证系统可用性和稳定性;
  • ......等等
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-27,如有侵权请联系 cloudcommunity@tencent 删除集群监控弹性伸缩kubernetesprometheus
发布评论

评论列表(0)

  1. 暂无评论