K8s Lab 把当前仓库文档整理成一个可阅读的网页站点

Repository Reading Site

监控与可观测 — 看见集群的一切

| 支柱 | 工具 | 回答什么问题 | |------|------|-------------| | **Metrics(指标)** | Prometheus + Grafana | CPU 多少?内存多少?QPS 多少? | | **Logs(日志)** | Loki + Promtail | 报了什么错?什么时候报的? | | **Traces(追踪

Markdownphase-2/04-monitoring-observability.md2026年4月9日 12:02

监控与可观测 — 看见集群的一切

监控三支柱

支柱 工具 回答什么问题
Metrics(指标) Prometheus + Grafana CPU 多少?内存多少?QPS 多少?
Logs(日志) Loki + Promtail 报了什么错?什么时候报的?
Traces(追踪) Jaeger/Tempo 一个请求经过了哪些服务?每步耗时多少?

我们部署了前两个。

Prometheus 架构

┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│ node-exporter│     │kube-state-   │     │ 应用自定义    │
│ (每节点)     │     │metrics       │     │ /metrics     │
└──────┬──────┘     └──────┬───────┘     └──────┬───────┘
       │                   │                     │
       └──────────┬────────┘─────────────────────┘
                  │  Prometheus 定期 pull
           ┌──────▼──────┐
           │  Prometheus  │ ← 存储时序数据(10Gi NFS)
           │  Server      │ ← PromQL 查询引擎
           └──────┬───────┘
                  │
           ┌──────▼──────┐     ┌──────────────┐
           │   Grafana    │     │ Alertmanager │
           │  (可视化)     │     │ (告警路由)    │
           └──────────────┘     └──────────────┘

Pull vs Push 模型

Prometheus 用 Pull 模型:Prometheus 主动去各个 target 的 /metrics 端点抓取数据。

为什么不用 Push?

  • Pull 可以感知 target 是否存活(pull 失败 = 服务挂了)
  • Pull 不需要 target 知道 Prometheus 的地址(低耦合)
  • Pull 可以控制采集频率(避免 target 推太多数据淹没 Prometheus)

三个数据源的区别

组件 采集什么 部署方式
node-exporter 节点 CPU/内存/磁盘/网络 DaemonSet(每节点一个)
kube-state-metrics K8s 对象状态(Pod 数/Deployment 状态/PVC 状态) Deployment(一个)
metrics-server 实时 CPU/内存(给 kubectl top 和 HPA 用) Deployment(一个)

面试易混淆: metrics-server 和 Prometheus 的 node-exporter 都采集 CPU/内存,区别是:

  • metrics-server:实时快照,不存储历史,给 HPA 做决策
  • node-exporter + Prometheus:存储时序数据,给人看趋势图

安装详情

helm install monitoring prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --set prometheus.prometheusSpec.retention=7d \           # 数据保留 7 天
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName=nfs-dynamic \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=10Gi \
  --set grafana.persistence.enabled=true \
  --set grafana.persistence.storageClassName=nfs-dynamic \
  --set grafana.service.type=NodePort \
  --set grafana.service.nodePort=30300

访问信息

服务 URL 凭据
Grafana http://107.148.176.193:30300 admin / XXALH7sLZeubHVTofib3E3U9n6VgWTv0fbBq7KZ1

Grafana 内置了大量仪表盘:节点概览、Pod 资源、集群整体。

PromQL 常用查询

# 节点 CPU 使用率
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 节点内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# Pod 重启次数
kube_pod_container_status_restarts_total

# Pending 的 Pod
kube_pod_status_phase{phase="Pending"}

# 按 namespace 统计 Pod 数
count by(namespace) (kube_pod_info)

Loki — 日志收集

helm install loki grafana/loki-stack \
  --namespace monitoring \
  --set promtail.enabled=true \
  --set loki.persistence.enabled=true \
  --set loki.persistence.storageClassName=nfs-dynamic \
  --set loki.persistence.size=10Gi

Promtail 以 DaemonSet 运行在每个节点,收集容器日志发送给 Loki。在 Grafana 中添加 Loki 数据源后可以查询:

# 查看 dev 空间的日志
{namespace="dev"}

# 过滤错误
{namespace="dev"} |= "error"

# 特定 Pod
{pod="nginx-xxx"} | json | status >= 400

面试题: "Loki 和 Elasticsearch 的区别?"

  • Elasticsearch:全文索引,查询强大,但资源消耗大(内存杀手)
  • Loki:只索引标签(namespace, pod),日志内容不索引,资源省很多
  • 选择:日志量不大或预算有限用 Loki,需要复杂搜索用 EFK

HPA 自动伸缩 — 基于 metrics-server

实验过程

# 创建 HPA
kubectl -n dev autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

# 加压前:1 个副本,CPU < 50%
# 加压后:CPU 59%,自动扩到 3 个副本

HPA 算法

期望副本数 = ceil(当前副本数 × (当前指标值 / 目标指标值))

例如:当前 1 副本,CPU 300m,目标 100m (50% of 200m requests)
期望 = ceil(1 × (300/100)) = 3

面试重点

Q: HPA 和 VPA 能同时用吗? 可以,但不能同时基于 CPU。推荐:HPA 基于自定义指标(QPS),VPA 调整 CPU/内存 requests。

Q: HPA 扩容后流量下降,多久缩回来? 默认稳定窗口 5 分钟(--horizontal-pod-autoscaler-downscale-stabilization)。这防止指标波动导致频繁缩扩(flapping)。

etcd 备份

ETCDCTL_API=3 etcdctl snapshot save /tmp/etcd-backup.db \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

备份结果: 31 MB, 3087 keys, revision 16251

面试题: "etcd 备份了什么?" 所有集群状态:节点、Pod、Service、ConfigMap、Secret、RBAC 规则、CRD。丢了 etcd = 丢了整个集群。生产环境应该定期自动备份(CronJob)。

Phase 3: 高级生产技能