1. 项目概述与背景
在云原生时代,Kubernetes已经成为容器编排的事实标准,而监控则是保障系统稳定性的关键环节。本文将详细介绍如何在Kubernetes集群上为Flask论坛项目集成Prometheus+Grafana监控系统,实现从基础设施到应用层的全方位可观测性。
这个方案特别适合以下场景:
- 已经容器化部署的Python Web应用(如Flask/Django)
- 需要监控Kubernetes集群及其上运行的业务应用
- 希望建立统一的可视化监控平台
- 需要灵活扩展自定义业务指标监控
2. 技术架构解析
2.1 整体架构设计
我们的监控系统采用kube-prometheus-stack方案,这是目前社区最成熟的Kubernetes监控解决方案之一。架构主要包含以下组件:
| 组件 | 作用 | 部署方式 |
|---|---|---|
| Prometheus | 指标采集与存储 | StatefulSet |
| Grafana | 数据可视化 | Deployment |
| Alertmanager | 告警管理 | Deployment |
| Node Exporter | 节点指标采集 | DaemonSet |
| kube-state-metrics | Kubernetes对象状态转换 | Deployment |
| Prometheus Operator | 管理监控组件 | Deployment |
2.2 监控对象覆盖
系统设计监控以下五个层面的指标:
- 基础设施层:通过Node Exporter采集主机CPU、内存、磁盘等指标
- Kubernetes组件层:监控API Server、etcd、kubelet等核心组件
- 应用容器层:通过cAdvisor获取容器资源使用情况
- 业务应用层:Flask应用的自定义业务指标
- 数据库层:外部MariaDB的性能指标
2.3 关键技术选型理由
选择kube-prometheus-stack的主要原因:
- 开箱即用:预置30+ Grafana仪表盘,减少配置工作
- 自动发现:自动监控Kubernetes集群组件和Pod
- 扩展性强:通过ServiceMonitor可轻松添加自定义监控
- 社区支持:CNCF毕业项目,版本更新及时
3. 部署准备
3.1 环境要求
- Kubernetes集群(v1.20+)
- Helm 3.x
- 可访问的容器镜像仓库
- 集群管理员权限
3.2 镜像准备
由于国内拉取quay.io等国外镜像较慢,我们采用阿里云ACR作为镜像仓库中转。准备步骤如下:
- 创建ACR个人版实例
- 获取访问凭证(用户名+密码)
- 使用以下脚本同步所需镜像:
bash复制#!/bin/bash
# 镜像同步脚本
USERNAME="your_acr_username"
PASSWORD="your_acr_password"
REGISTRY_DOMAIN="your_acr_domain"
# 登录ACR
echo "$PASSWORD" | docker login --username="$USERNAME" --password-stdin "$REGISTRY_DOMAIN"
# 镜像列表
images=(
"quay.io/prometheus-operator/prometheus-operator:v0.77.0"
"prom/prometheus:v2.50.1"
"grafana/grafana:10.4.3"
# 其他所需镜像...
)
# 同步镜像
for img in "${images[@]}"; do
echo "Syncing $img"
# 拉取原始镜像
docker pull $img
# 重新打标签
new_tag="${REGISTRY_DOMAIN}/mirrors/$(echo $img | sed 's/[\/:]/-/g')"
docker tag $img $new_tag
# 推送到ACR
docker push $new_tag
done
注意事项:
- 建议使用企业版ACR以获得更好稳定性
- 镜像同步可能需要较长时间,建议后台运行
- 定期检查并更新镜像版本
4. 部署监控系统
4.1 创建监控命名空间
bash复制kubectl create namespace monitoring
4.2 配置镜像拉取密钥
bash复制kubectl create secret docker-registry acr-secret \
--namespace monitoring \
--docker-server=your_acr_domain \
--docker-username="your_username" \
--docker-password="your_password"
4.3 准备Helm values文件
创建fix-monitor-final.yaml配置文件:
yaml复制global:
imagePullSecrets:
- name: acr-secret
prometheusOperator:
image:
registry: your_acr_domain
repository: mirrors/quay-io-prometheus-operator-prometheus-operator
tag: v0.77.0
prometheus:
prometheusSpec:
image:
registry: your_acr_domain
repository: mirrors/prom-prometheus
tag: v2.50.1
grafana:
image:
registry: your_acr_domain
repository: mirrors/grafana-grafana
tag: 10.4.3
service:
type: NodePort
adminPassword: "your_secure_password"
4.4 使用Helm部署
bash复制helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm upgrade --install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring \
-f fix-monitor-final.yaml \
--version 81.6.9 \
--wait
常见问题排查:
- 如果部署卡住,检查Pod事件:
kubectl describe pod -n monitoring <pod-name>- 镜像拉取失败时,验证secret是否正确:
kubectl get secret -n monitoring acr-secret -o yaml- CRD未注册时,可手动应用:
kubectl apply -f https://github.com/prometheus-community/helm-charts/raw/kube-prometheus-stack-81.6.9/charts/kube-prometheus-stack/crds/crd-all.yaml
5. 配置Flask应用监控
5.1 集成Prometheus客户端
在Flask应用中添加监控端点:
python复制from prometheus_client import make_wsgi_app, Counter, Histogram
from werkzeug.middleware.dispatcher import DispatcherMiddleware
# 定义指标
REQUEST_COUNT = Counter(
'flask_http_request_count_total',
'Total HTTP Request Count',
['method', 'endpoint', 'status']
)
REQUEST_LATENCY = Histogram(
'flask_http_request_latency_seconds',
'HTTP Request Latency',
['method', 'endpoint']
)
# 添加监控中间件
app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {
'/metrics': make_wsgi_app()
})
# 在路由中添加监控
@app.before_request
def before_request():
request.start_time = time.time()
@app.after_request
def after_request(response):
latency = time.time() - request.start_time
REQUEST_COUNT.labels(
method=request.method,
endpoint=request.path,
status=response.status_code
).inc()
REQUEST_LATENCY.labels(
method=request.method,
endpoint=request.path
).observe(latency)
return response
5.2 创建ServiceMonitor
定义ServiceMonitor资源来发现和监控Flask应用:
yaml复制apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: flask-app-monitor
namespace: monitoring
spec:
selector:
matchLabels:
app: flask-forum # 匹配你的Flask Service标签
endpoints:
- port: web # 对应Service的端口名称
path: /metrics # 指标端点路径
interval: 15s # 采集间隔
namespaceSelector:
matchNames:
- default # Flask应用所在的命名空间
6. 监控外部MariaDB
6.1 部署MySQL Exporter
对于集群外的MariaDB,我们需要单独部署mysqld-exporter:
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-exporter
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: mysql-exporter
template:
metadata:
labels:
app: mysql-exporter
spec:
containers:
- name: mysql-exporter
image: prom/mysqld-exporter:v0.15.1
env:
- name: DATA_SOURCE_NAME
value: "exporter:password@(192.168.56.109:3306)/"
ports:
- containerPort: 9104
6.2 创建对应的Service和ServiceMonitor
yaml复制# Service
apiVersion: v1
kind: Service
metadata:
name: mysql-exporter
namespace: monitoring
spec:
selector:
app: mysql-exporter
ports:
- name: metrics
port: 9104
targetPort: 9104
# ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mysql-monitor
namespace: monitoring
spec:
selector:
matchLabels:
app: mysql-exporter
endpoints:
- port: metrics
interval: 30s
7. 访问与使用监控系统
7.1 访问Prometheus
bash复制kubectl port-forward -n monitoring svc/monitoring-kube-prometheus-prometheus 9090:9090
访问 http://localhost:9090 可以:
- 查看采集目标状态
- 查询指标数据
- 测试告警规则
7.2 访问Grafana
获取管理员密码:
bash复制kubectl get secret -n monitoring monitoring-grafana -o jsonpath="{.data.admin-password}" | base64 -d
端口转发:
bash复制kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80
访问 http://localhost:3000 使用admin和上面获取的密码登录。
7.3 预置仪表盘
kube-prometheus-stack自带多个有用的仪表盘:
- Kubernetes / Nodes (ID: 6417)
- Kubernetes / Pods (ID: 315)
- Kubernetes / Deployment (ID: 11074)
- Node Exporter Full (ID: 1860)
可以通过Grafana的"+" > "Import"输入这些ID快速导入。
8. 高级配置与优化
8.1 数据持久化
默认情况下Prometheus数据是非持久化的,生产环境应该配置持久卷:
yaml复制prometheus:
prometheusSpec:
storageSpec:
volumeClaimTemplate:
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
8.2 告警配置
通过Alertmanager配置告警通知,示例配置发送到邮件:
yaml复制alertmanager:
config:
global:
resolve_timeout: 5m
smtp_from: alertmanager@example.com
smtp_smarthost: smtp.example.com:587
smtp_auth_username: "user"
smtp_auth_password: "password"
route:
group_by: ['alertname']
group_wait: 30s
group_interval: 5m
repeat_interval: 3h
receiver: 'email'
receivers:
- name: 'email'
email_configs:
- to: 'alerts@example.com'
8.3 资源限制
为监控组件设置合理的资源限制:
yaml复制prometheus:
prometheusSpec:
resources:
limits:
cpu: 2
memory: 4Gi
requests:
cpu: 500m
memory: 2Gi
grafana:
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 100m
memory: 512Mi
9. 故障排查与维护
9.1 常见问题排查
-
指标无法采集:
- 检查ServiceMonitor的selector是否匹配Service标签
- 验证Pod的/metrics端点是否可以访问
- 查看Prometheus的Targets页面获取具体错误
-
Grafana无数据:
- 确认数据源配置正确(应指向http://monitoring-kube-prometheus-prometheus.monitoring.svc:9090)
- 检查时间范围设置
- 验证PromQL查询语法
-
高资源占用:
- 调整采集间隔(interval)
- 减少不必要的指标采集
- 增加资源限制
9.2 日常维护建议
-
版本升级:
- 定期检查新版本
- 先在测试环境验证
- 备份重要数据(Grafana仪表盘、Prometheus规则)
-
数据清理:
- 设置Prometheus数据保留策略
yaml复制prometheus: prometheusSpec: retention: 15d -
监控系统自身监控:
- 为Prometheus、Grafana等组件设置基础监控
- 配置关键告警(如Prometheus宕机)
10. 经验总结与优化建议
在实际部署和使用过程中,我们积累了一些有价值的经验:
-
镜像管理:
- 使用企业级镜像仓库提高稳定性
- 定期扫描镜像漏洞
- 建立内部镜像缓存策略
-
性能优化:
- 对于大规模集群,考虑使用Thanos或VictoriaMetrics替代原生Prometheus存储
- 启用Prometheus的远程写功能将数据转发到长期存储
- 合理设置采集间隔(基础设施30s,业务指标1-5分钟)
-
安全加固:
- 为Grafana配置SSO集成
- 启用Prometheus和Grafana的HTTPS
- 限制监控系统的网络访问
-
成本控制:
- 根据集群规模调整Prometheus资源分配
- 清理不用的指标和仪表盘
- 考虑使用云托管的Prometheus服务(如阿里云ARMS)
这个监控方案经过生产环境验证,能够满足大多数中小规模Kubernetes集群的监控需求。随着业务增长,可以考虑引入日志监控(如Loki)和分布式追踪(如Jaeger)来构建更完整的可观测性体系。