Kubernetes中uWSGI应用Prometheus指标Pod删除后留存方案咨询
嘿,我来帮你梳理下这个问题——你遇到的其实是两个相关但不同的点:一是Prometheus里已经采集到的历史指标能不能保住,二是uWSGI自身的累计型指标(比如请求计数)在Pod重建后会不会重置,导致数据断档。结合你给出的配置,我给你具体的解决步骤:
一、先确认Prometheus的历史指标留存逻辑
你已经给Prometheus配了持久化存储(azurefile PVC)和2200小时的 retention 时间,这部分配置是对的!只要Prometheus的TSDB存储没出问题,已经采集到的历史指标绝对不会因为Pod删除而消失——Prometheus会把所有在留存周期内的时间序列都存在持久化存储里,哪怕对应的Pod已经被删掉了。
如果真的发现历史指标没了,你可以先排查这两点:
- 进Prometheus Pod里看看
/prometheus/目录有没有正常挂载PVC,重启Prometheus Pod后数据还在不在 - 访问Prometheus的
/status端点,确认--storage.tsdb.retention参数确实生效了
二、解决uWSGI指标重置的问题(Pod重建后累计数据延续)
你的uWSGI已经加了--metrics-dir=/storage和--metrics-dir-restore,这说明uWSGI会把指标数据持久化到/storage目录,而且这个目录也绑了app-storage PVC,思路是对的,但有个细节要注意:
- 你的Deployment有2个replicas,所以
app-storagePVC的访问模式必须是ReadWriteMany,不然第二个Pod挂载的时候会失败,uWSGI也就没法恢复之前的指标了 - 你可以进Pod里看看
/storage目录有没有生成指标文件,重启Pod后再检查uWSGI的指标(比如uwsgi_requests_total)是不是从之前的数值继续累加,而不是从0开始
如果你的存储不支持ReadWriteMany,那可以考虑把Deployment改成StatefulSet,给每个Pod分配独立的PVC——这样每个Pod的指标分开存,不会互相影响,后续在Prometheus里用app标签聚合就行。
三、优化Prometheus采集配置,避免时间序列断档
默认情况下,Prometheus采集Kubernetes Pod时,会用Pod的IP作为instance标签。Pod删除重建后,新Pod的IP肯定不一样,这就会生成新的时间序列,导致图表里的数据看起来断了。你可以修改Prometheus的scrape_configs来优化标签规则:
找到你的prometheus-server-conf ConfigMap,调整Kubernetes服务发现的relabel规则,用更稳定的标识做instance标签,比如Pod名称(如果是StatefulSet的话,Pod名称是稳定的,比如api-app-0、api-app-1):
scrape_configs: - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: # 把app标签保留下来,方便后续聚合 - source_labels: [__meta_kubernetes_pod_label_app] target_label: app # 用Pod名称作为instance标签,StatefulSet的Pod名称不会变 - source_labels: [__meta_kubernetes_pod_name] target_label: instance # 只采集api-app的Pod,过滤掉其他无关目标 - source_labels: [__meta_kubernetes_pod_label_app] action: keep regex: api-app
要是你还是用Deployment,Pod名称会变,但可以通过app标签把所有Pod的指标聚合起来,这样看整体趋势就不会断档。
四、可选:改用StatefulSet部署应用
如果你的应用适合用StatefulSet(哪怕是无状态应用也可以用),把api-app的Deployment改成StatefulSet是个不错的选择。StatefulSet的每个Pod会有稳定的网络标识和Pod名称,Prometheus采集的instance标签也会稳定,同时还能给每个Pod分配独立的PVC,避免多Pod共享存储的问题:
apiVersion: apps/v1 kind: StatefulSet metadata: name: api-app spec: serviceName: api-app # 必须指定对应的Headless Service,你现有的api-app Service可以改成Headless(clusterIP: None) replicas: 2 selector: matchLabels: app: api-app template: metadata: labels: app: api-app spec: # 这里直接用你原来Deployment里的template.spec内容就行,包括容器、卷配置 containers: - name: nginx ... - name: api-app ... volumeClaimTemplates: - metadata: name: storage spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi
注意:StatefulSet需要对应的Headless Service,你可以把现有的api-app Service改成Headless,也就是把spec.clusterIP设为None。
最后总结一下
- 已采集的历史指标:靠Prometheus的TSDB持久化,你当前配置已经满足,只要确认存储正常就行
- uWSGI指标延续:要么把
app-storage改成ReadWriteMany,要么用StatefulSet给每个Pod分配独立存储 - 数据连续性:通过Prometheus的relabel规则用稳定标签,或者直接换StatefulSet
内容的提问来源于stack exchange,提问作者user1334557

