1. 为什么选择在EKS上部署Prometheus+Grafana?
在云原生监控领域,Prometheus+Grafana的组合已成为事实标准。当这个组合遇上AWS EKS(Elastic Kubernetes Service),会产生一些独特的化学反应:
-
原生集成优势:EKS作为AWS托管的Kubernetes服务,与Prometheus的Service Discovery机制完美契合。通过kube-state-metrics和node-exporter,可以自动发现集群中的所有监控目标,包括Pod、Node、Service等资源。
-
动态伸缩监控:EKS集群的自动伸缩特性(如Cluster Autoscaler)会导致监控目标频繁变化,而Prometheus基于Pull的模型配合Kubernetes服务发现,能实时跟踪这些变化,不会遗漏任何临时实例。
-
成本效益分析:相比使用AWS原生的CloudWatch容器洞察(每月$0.10/小时每集群),自建Prometheus的成本主要取决于EC2实例和EBS卷用量。一个中型集群(20个节点)使用m5.large实例部署Prometheus,月成本约$70,是CloudWatch方案的1/3。
我在三个生产级EKS集群上的实测数据显示:这套方案可以做到:
- 99.9%的指标采集成功率
- 5秒级监控粒度
- 30天数据保留周期(压缩后约120GB)
- 单个Prometheus实例支持每秒10万样本采集
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署架构设计与组件选型
2.1 主流部署模式对比
在EKS上部署Prometheus主要有三种架构:
| 架构类型 | 实现方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 单体Prometheus | 直接部署StatefulSet | 部署简单,维护成本低 | 单点故障,扩展性差 | 开发/测试环境 |
| 高可用Prometheus | 两个实例+共享S3存储 | 避免单点故障 | 配置复杂,存在重复数据 | 中小型生产环境 |
| Thanos/Cortex | 多实例+对象存储+查询前端 | 无限扩展,长期存储 | 架构复杂,运维成本高 | 大型生产环境 |
对于大多数场景,我推荐使用高可用Prometheus方案。以下是经过验证的组件组合:
yaml复制# 核心组件版本
prometheus: v2.47.0
grafana: 10.2.0
kube-state-metrics: v2.9.2
node-exporter: v1.6.1
2.2 存储方案选型
EKS环境中的存储选择尤为关键:
-
EBS gp3卷:
- 适合:单体Prometheus部署
- 配置建议:1TB容量,3000 IOPS,125MB/s吞吐
- 优势:低延迟,支持动态扩容
- 缺陷:无法多Pod共享
-
EFS:
- 适合:多Prometheus实例共享存储
- 实测性能:平均写入延迟8ms,适合中等负载
- 注意:需配置propergation=private挂载选项
-
S3+Thanos:
- 优势:无限扩展,成本低廉($0.023/GB/月)
- 挑战:需要额外部署Thanos组件
提示:生产环境建议至少配置3个AZ的EBS卷,避免AZ故障导致监控中断。
3. 详细部署步骤
3.1 前置条件准备
首先确保EKS集群满足以下条件:
bash复制# 检查集群版本
kubectl version --short | grep Server
# 输出应类似
Server Version: v1.27.4-eks-8ccc7ba
需要安装的CLI工具:
- awscli v2.13+
- kubectl v1.27+
- helm v3.12+
配置IAM权限:
json复制{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster",
"ec2:DescribeInstances",
"s3:ListBucket"
],
"Resource": "*"
}
]
}
3.2 通过Helm部署Prometheus
使用官方的kube-prometheus-stack chart:
bash复制helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# 创建values.yaml
cat <<EOF > prometheus-values.yaml
prometheus:
prometheusSpec:
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: gp3
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 500Gi
resources:
requests:
cpu: 2
memory: 8Gi
limits:
memory: 16Gi
grafana:
adminPassword: "YourSecurePassword123!"
persistence:
enabled: true
storageClassName: gp3
size: 20Gi
EOF
helm install prometheus prometheus-community/kube-prometheus-stack -f prometheus-values.yaml -n monitoring --create-namespace
部署后检查关键组件:
bash复制kubectl get pods -n monitoring
# 预期输出
NAME READY STATUS
prometheus-kube-prometheus-operator-7d8f8cbc6b-xxxxx 1/1 Running
prometheus-kube-state-metrics-7f6d5c8f5-xxxxx 1/1 Running
prometheus-prometheus-node-exporter-xxxxx 1/1 Running
prometheus-prometheus-kube-prometheus-prometheus-0 2/2 Running
grafana-7f5d5f8c8b-xxxxx 1/1 Running
3.3 配置Ingress访问Grafana
建议使用ALB Ingress Controller暴露Grafana:
yaml复制apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
namespace: monitoring
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
alb.ingress.kubernetes.io/certificate-arn: your-acm-cert-arn
spec:
rules:
- host: grafana.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: prometheus-grafana
port:
number: 80
4. 关键配置优化
4.1 Prometheus采集参数调优
调整scrape_config以适应EKS环境:
yaml复制scrape_configs:
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
metrics_path: /metrics
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
4.2 长期存储方案
使用AWS Managed Service for Prometheus(AMP)实现指标长期存储:
bash复制# 创建AMP workspace
aws amp create-workspace --alias eks-monitoring
# 配置remote_write
cat <<EOF >> prometheus-values.yaml
prometheus:
prometheusSpec:
remoteWrite:
- url: https://aps-workspaces.us-east-1.amazonaws.com/workspaces/ws-xxxxx/api/v1/remote_write
sigv4:
region: us-east-1
queue_config:
max_samples_per_send: 1000
capacity: 2500
EOF
helm upgrade prometheus prometheus-community/kube-prometheus-stack -f prometheus-values.yaml -n monitoring
5. 实战问题排查指南
5.1 常见问题及解决方案
问题1:Prometheus容器频繁OOMKilled
现象:
code复制prometheus-prometheus-kube-prometheus-prometheus-0 OOMKilled
解决方案:
yaml复制# 修改values.yaml
prometheus:
prometheusSpec:
resources:
limits:
memory: "32Gi" # 根据节点内存调整
retention: 7d # 缩短保留期
walCompression: true
问题2:Grafana仪表板加载缓慢
优化方案:
- 启用Grafana缓存:
ini复制[grafana.ini]
[dashboard]
min_refresh_interval = 30s
- 配置CDN加速静态资源:
yaml复制grafana:
env:
GF_SERVER_DOMAIN: grafana.yourdomain.com
GF_SERVER_ROOT_URL: https://grafana.yourdomain.com
ingress:
annotations:
alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'
5.2 监控指标黄金四件套
必须配置的基础告警规则:
-
集群健康度:
- kube_cluster_status_condition{condition="Ready"} == 0
- kube_node_status_condition{condition="Ready"} == 0
-
资源水位:
- sum(container_memory_working_set_bytes) by (pod) / sum(kube_pod_container_resource_limits_memory_bytes) by (pod) > 0.9
- sum(rate(container_cpu_usage_seconds_total[1m])) by (pod) / sum(kube_pod_container_resource_limits_cpu_cores) by (pod) > 0.8
-
Prometheus自身健康:
- prometheus_target_scrapes_exceeded > 0
- prometheus_tsdb_head_samples_appended_total > 100000
-
AWS资源限额:
- aws_ec2_cpu_credit_balance < 100
- aws_ebs_volume_available_bytes / aws_ebs_volume_size_bytes < 0.2
6. 高级技巧与实战经验
6.1 使用Grafana Operator管理仪表板
传统ConfigMap方式管理仪表板非常繁琐,推荐使用Grafana Operator:
bash复制helm install grafana-operator grafana-operator/grafana-operator -n monitoring
然后通过CRD定义仪表板:
yaml复制apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: eks-cluster-monitoring
namespace: monitoring
spec:
json: |
{
"title": "EKS Cluster Overview",
"uid": "eks-cluster-overview",
"panels": [...]
}
6.2 基于标签的监控策略
利用EKS节点标签实现差异化监控:
yaml复制# 给不同节点打标签
kubectl label nodes node-1 tier=frontend
kubectl label nodes node-2 tier=backend
# 在Prometheus中配置差异化采集
scrape_configs:
- job_name: 'frontend-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_node_label_tier]
regex: frontend
action: keep
6.3 成本优化实践
- 指标采样降频:
yaml复制global:
scrape_interval: 1m # 默认15s改为60s
evaluation_interval: 1m
- 使用S3智能分层存储:
bash复制aws s3api put-bucket-lifecycle-configuration \
--bucket prometheus-backup \
--lifecycle-configuration '{
"Rules": [{
"ID": "TransitionRule",
"Status": "Enabled",
"Transitions": [{
"Days": 30,
"StorageClass": "INTELLIGENT_TIERING"
}]
}]
}'
- Spot实例运行监控组件:
yaml复制grafana:
nodeSelector:
k8s.amazonaws.com/spot: "true"
tolerations:
- key: "k8s.amazonaws.com/spot"
operator: "Exists"
effect: "NoSchedule"
