K8s 监控与日志
监控体系架构
Metrics Server
Metrics Server 采集 Node 和 Pod 的 CPU/内存使用量,是 kubectl top 和 HPA 的数据来源。
# 安装 Metrics Server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 使用
kubectl top nodes
kubectl top pods -A --sort-by=memory
注意
Metrics Server 只保留最近的指标数据(不持久化),不适合历史查询。生产环境需要 Prometheus 做持久监控。
Prometheus + Grafana
kube-prometheus-stack
生产环境推荐使用 kube-prometheus-stack(Helm Chart),一键部署完整监控栈:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespace \
--set grafana.adminPassword=admin \
--set prometheus.prometheusSpec.retention=30d \
--set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=50Gi
包含组件:
- Prometheus Operator:管理 Prometheus 实例
- Prometheus:指标采集和存储
- Alertmanager:告警管理
- Grafana:可视化(预置 K8s Dashboard)
- node-exporter:Node 指标采集
- kube-state-metrics:K8s 对象状态指标
核心监控指标
| 层级 | 关键指标 | PromQL 示例 |
|---|---|---|
| Node | CPU 使用率 | 100 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 |
| Node | 内存使用率 | (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 |
| Node | 磁盘使用率 | (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 |
| Pod | CPU 使用 | rate(container_cpu_usage_seconds_total[5m]) |
| Pod | 内存使用 | container_memory_working_set_bytes |
| Pod | 重启次数 | kube_pod_container_status_restarts_total |
| Service | 请求速率 | rate(http_requests_total[5m]) |
| Service | 错误率 | rate(http_requests_total{code=~"5.."}[5m]) / rate(http_requests_total[5m]) |
| Service | P99 延迟 | histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) |
告警规则
PrometheusRule 示例
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: k8s-alerts
namespace: monitoring
spec:
groups:
- name: pod-alerts
rules:
# Pod 频繁重启
- alert: PodCrashLooping
expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.pod }} 频繁重启"
# Pod 长时间 Pending
- alert: PodPending
expr: kube_pod_status_phase{phase="Pending"} == 1
for: 15m
labels:
severity: warning
annotations:
summary: "Pod {{ $labels.pod }} Pending 超过 15 分钟"
- name: node-alerts
rules:
# Node CPU 过高
- alert: NodeHighCPU
expr: 100 - avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 > 85
for: 10m
labels:
severity: critical
annotations:
summary: "Node {{ $labels.instance }} CPU 使用率 {{ $value }}%"
# Node 磁盘即将满
- alert: NodeDiskFull
expr: (1 - node_filesystem_avail_bytes{fstype!~"tmpfs|fuse.*"} / node_filesystem_size_bytes) * 100 > 85
for: 5m
labels:
severity: critical
Alertmanager 配置
alertmanager.yaml
global:
resolve_timeout: 5m
route:
receiver: default
group_by: [alertname, namespace]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- match:
severity: critical
receiver: pager
repeat_interval: 1h
receivers:
- name: default
webhook_configs:
- url: http://alertbot:8080/webhook
- name: pager
webhook_configs:
- url: http://alertbot:8080/pager
日志方案
方案对比
| 方案 | 架构 | 存储 | 优势 | 劣势 |
|---|---|---|---|---|
| EFK | Fluent Bit → ES → Kibana | Elasticsearch | 功能强大,全文搜索 | 资源消耗大 |
| PLG | Promtail → Loki → Grafana | Loki(对象存储) | 轻量,成本低 | 不支持全文搜索 |
Loki + Grafana(推荐轻量方案)
# 安装 Loki Stack
helm install loki grafana/loki-stack \
--namespace logging --create-namespace \
--set promtail.enabled=true \
--set grafana.enabled=false # 复用监控的 Grafana
Loki 只索引标签(label),不索引日志内容,存储成本远低于 Elasticsearch。
# Grafana 中的 LogQL 查询示例
{namespace="default", app="myapp"} # 按标签过滤
{namespace="default"} |= "error" # 包含 error
{namespace="default"} | json | status >= 500 # JSON 日志解析
{namespace="default"} | json | latency_ms > 1000 | line_format "slow: {{.path}}"
EFK Stack
Fluent Bit ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: logging
data:
fluent-bit.conf: |
[SERVICE]
Flush 5
Daemon Off
Log_Level info
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser cri
Refresh_Interval 5
Mem_Buf_Limit 5MB
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Merge_Log On
K8S-Logging.Exclude On
[OUTPUT]
Name es
Match *
Host elasticsearch
Port 9200
Index k8s-logs
Type _doc
常见面试问题
Q1: K8s 监控使用什么方案?
答案:
生产标准方案是 kube-prometheus-stack:
- Prometheus:采集和存储指标
- Grafana:可视化仪表盘(预置 K8s Dashboard)
- Alertmanager:告警管理和路由
- node-exporter + kube-state-metrics:数据采集
关键监控维度:Node 资源(CPU/内存/磁盘)、Pod 状态(重启/OOM)、应用指标(QPS/延迟/错误率)。
Q2: K8s 日志方案怎么选?
答案:
| 场景 | 推荐 |
|---|---|
| 小规模 / 成本敏感 | Loki + Grafana(轻量,只索引标签) |
| 大规模 / 全文搜索 | EFK(Elasticsearch 强大但吃资源) |
| 云托管 | CloudWatch / Stackdriver / 阿里云 SLS |
共同点:都使用 DaemonSet(Promtail/Fluent Bit)在每个 Node 采集容器日志。
Q3: 如何监控 Pod 的 OOM 和频繁重启?
答案:
# Pod 频繁重启
rate(kube_pod_container_status_restarts_total[15m]) > 0
# 容器 OOM Killed
kube_pod_container_status_last_terminated_reason{reason="OOMKilled"}
# 内存接近 limit
container_memory_working_set_bytes / kube_pod_container_resource_limits{resource="memory"} > 0.9
结合 Alertmanager 配置告警规则,关键告警发送到即时通讯工具或值班系统。