首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从 /sys/fs/cgroup 到 SLO:云计算的技术纵深与责任纵深

从 /sys/fs/cgroup 到 SLO:云计算的技术纵深与责任纵深

原创
作者头像
用户12502707
发布于 2026-09-25 11:05:18
发布于 2026-09-25 11:05:18
1780
举报

一、先纠正一个常见误解:云不是"虚拟化",而是"内核能力的产品化"

很多人把云计算理解为"把物理机切成虚拟机卖"。这个理解在 2010 年成立,在今天已经严重过时。

现代云的本质是:用 Linux 内核提供的一组隔离、计量、调度与可观测原语,把物理资源切分成可计费、可编排、可自愈的逻辑单元,再用控制面软件把这些单元组织成服务。

拆开看,云的每一层都对应内核的具体能力:

云的能力

内核/系统机制

租户隔离

namespaces、cgroups v2、seccomp、IOMMU

资源计量与计费

cgroups v2 统计、CPU/内存/IO 压力指标

弹性伸缩

cgroup 动态调整、快速冷启动(微虚机/容器)

软件定义网络

netfilter/nftables、tc、veth/bridge、VXLAN、eBPF

软件定义存储

device-mapper、NVMe、io_uring、文件系统/对象存储

安全与审计

audit、eBPF tracing、LSM(SELinux/AppArmor)

性能诊断

perf、eBPF/bpftrace、PSI、/proc 与 /sys 接口

因此,"学 Linux 云计算"的正确顺序不是先学 K8s,而是先理解内核给你了哪些原语、它们的边界在哪。 K8s 只是把这些原语包装成 API 的一层;不理解底层,故障排查就只能靠猜。


二、内核基石:四个必须亲手摸过的机制

2.1 namespaces:隔离"视图"

Linux 提供 mount / pid / net / ipc / uts / user / cgroup / time 等命名空间。容器的"隔离感"主要来自这里。

代码语言:javascript
复制
1# 新建一个 mount + pid + net 隔离的环境,进去看就是"另一台机器"
2sudo unshare --mount --pid --net --fork --mount-proc bash
3
4# 进去后验证
5echo $$            # PID 可能是 1
6ip a               # 只有 lo,没有宿主网卡
7cat /proc/mounts | wc -l

关键认知:

  • namespace 隔离的是视图,不是资源量。你在容器里看到的 CPU 核数、内存大小默认仍是宿主机的(除非用 cgroups 限制 + 工具改写 /proc)。这就是很多 Java/Go 应用"按宿主机核数开线程池"导致超卖的根因。
  • user namespace 是多租户安全的关键:容器内 root 映射到宿主非特权 UID,逃逸后权限受限。
  • 网络 namespace 之间默认不通,需要 veth pair + bridge 或路由打通——这正是 CNI 插件做的事。

2.2 cgroups v2:隔离"资源量",也是计量的来源

cgroup v2 是统一层级(unified hierarchy),所有控制器挂在一棵树上,比 v1 的分散层级更清晰,也是当前主流发行版默认。

代码语言:javascript
复制
1# 创建一个 cgroup 并限制 CPU/内存/IO
2sudo mkdir -p /sys/fs/cgroup/mywork
3echo "+cpu +memory +io +pids" | sudo tee /sys/fs/cgroup/mywork/cgroup.subtree_control
4
5echo 200000 > /sys/fs/cgroup/mywork/cpu.max        # 每 100ms 周期最多用 200ms => 2 核
6echo 1073741824 > /sys/fs/cgroup/mywork/memory.max # 1 GiB
7echo 4096 > /sys/fs/cgroup/mywork/pids.max         # 防 fork 炸弹
8
9# 把进程放进去(写 PID 而不是 cgroup.procs 的旧写法)
10echo $! | sudo tee /sys/fs/cgroup/mywork/cgroup.procs
11
12# 观察实际用量与压力
13cat /sys/fs/cgroup/mywork/cpu.stat        # usage_usec, nr_throttled, throttled_usec
14cat /sys/fs/cgroup/mywork/memory.current
15cat /sys/fs/cgroup/mywork/memory.pressure # PSI:some/full avg10/60/300
16cat /sys/fs/cgroup/mywork/io.stat

必须理解的三个点:

  1. cpu.max 是配额不是保证。想保证独占,要用 cpu.weight(相对权重)配合宿主整体负载,或直接做 CPU 亲和绑定(见第六节)。
  2. nr_throttled / throttled_usec 是排查"莫名变慢"的第一现场。应用没有报错、CPU 使用率看着不高,但被 CFS 限流了,延迟会呈周期性尖刺。
  3. PSI(Pressure Stall Information)比使用率更有诊断价值。memory.pressure 的 full 表示所有任务都被内存阻塞,这是 OOM 前兆;io.pressure 能提前发现存储瓶颈。云上的自动扩缩容如果只看 CPU 使用率,会漏掉内存与 IO 压力型故障。

2.3 eBPF:可观测性与数据面的现代基座

eBPF 允许在内核中安全运行沙箱化程序,无需写内核模块、无需重启。它同时是观测工具(perf 级采样、系统调用追踪)和数据面引擎(Cilium 用它替代 iptables/iptables 做网络策略与负载均衡)。

代码语言:javascript
复制
1# 一行看谁在频繁触发 OOM kill 前的内存回收
2sudo bpftrace -e 'tracepoint:mm_vmscan:mm_vmscan_direct_reclaim_begin { @reclaim = count(); }
3                  interval:s:5 { print(@reclaim); }'
4
5# 追踪某进程的系统调用耗时分布(微秒)
6sudo bpftrace -e 'tracepoint:syscalls:sys_enter_read /pid == 1234/ { @start[tid] = nsecs; }
7                  tracepoint:syscalls:sys_exit_read /@start[tid]/ {
8                    @us = hist((nsecs - @start[tid]) / 1000); delete(@start[tid]); }'
9
10# 统计 TCP 连接建立(用于判断连接风暴)
11sudo bpftrace -e 'kprobe:tcp_connect { @connects = count(); }
12                  interval:s:10 { print(@connects); }'

为什么它对云很重要:

  • 传统 netfilter/iptables 规则数增长会带来线性性能衰减,大规模集群(数万 Service)下 conntrack 表与规则链成为瓶颈;eBPF 数据面把查找复杂度降到哈希级别,这是 Cilium 等方案的核心卖点。
  • 无侵入 profiling(火焰图、off-CPU 分析)让"生产环境性能问题"第一次可以在不完全重启的前提下定位。
  • 安全检测(Falco 类)基于 syscall 与 eBPF,比日志分析更早发现异常。

代价也要说清:eBPF 程序本身有 bug 可能拖垮内核( verifier 只能保证基本安全,不能保证逻辑正确);调试门槛高;不同内核版本特性差异大(CO-RE 缓解了部分问题)。

2.4 seccomp / LSM:把攻击面收窄

代码语言:javascript
复制
1// 极简 seccomp 白名单片段:只允许必要系统调用
2{
3  "defaultAction": "SCMP_ACT_ERRNO",
4  "architectures": ["SCMP_ARCH_X86_64"],
5  "syscalls": [
6    { "names": ["read","write","exit","exit_group","futex","mmap","munmap","brk","rt_sigreturn"],
7      "action": "SCMP_ACT_ALLOW" }
8  ]
9}

生产实践:容器运行时默认启用 runtime 内置 seccomp profile(屏蔽 ptrace、mount、reboot、kexec_load 等高危调用);配合 AppArmor/SELinux 做强制访问控制;再配合 user namespace 与 rootless 容器,构成纵深防御。任何一层单独都不够。


三、虚拟化 vs 容器 vs 微虚机:选型不是站队,是权衡

方案

隔离强度

启动速度

密度

典型场景

KVM/QEMU 全虚机

强(硬件辅助虚拟化)

秒~十秒级

中

多租户强隔离、需跑异构 OS、合规要求

Firecracker / Cloud Hypervisor 微虚机

强(最小设备模型)

百毫秒级

高

Serverless、多租户函数、容器逃逸兜底

Kata Containers

强(容器语义 + 虚机隔离)

亚秒~秒

中

需要容器生态又要虚机隔离

runc / containerd 容器

中(共享内核)

几十~百毫秒

很高

微服务、CI、绝大多数云原生负载

gVisor

中强(用户态内核拦截 syscall)

快

高

不可信代码、在线代码执行

几个工程要点:

  • virtio 是性能关键。半虚拟化驱动(virtio-net / virtio-blk / virtio-scsi)远优于全模拟设备;现代云实例基本都用 virtio 或 NVMe 直通。
  • SR-IOV / 网卡直通能把网络开销降到接近物理机,代价是失去热迁移能力(迁移需要设备状态可保存)。要热迁移就不能直通,这是明确的取舍。
  • GPU 场景:整卡直通最简单;MIG(多实例 GPU)可做硬件级切分;软件级共享(时间片/显存配额)灵活但隔离弱。多租户 AI 训练/推理的隔离方案选择直接决定安全边界。
  • 容器逃逸的现实路径:内核漏洞、错误挂载(/、/proc、docker socket)、特权容器、capabilities 过宽、共享宿主 PID/网络命名空间。默认配置 + 最小权限 + 定期内核升级能挡掉绝大多数。
代码语言:javascript
复制
1# 检查一个容器是否被过度授权(常见危险信号)
2docker inspect <cid> --format '{{.HostConfig.Privileged}} {{.HostConfig.CapAdd}} {{json .HostConfig.Binds}}'
3# 期望:false / 空 / 不含 docker.sock、/、/proc、/sys

四、网络:从 iptables 到 eBPF 数据面,以及排障方法论

4.1 云网络的三层结构

  1. Underlay:物理网络 + BGP/ECMP,负责高带宽低延迟互联;大规模集群常用 RoCE/RDMA 做存储与 AI 训练网络。
  2. Overlay:VXLAN/Geneve 封装,让租户网络在共享物理网络上隔离;OVS 或 eBPF 做转发。
  3. 服务层:Service/负载均衡、DNS、Ingress、NetworkPolicy。

4.2 一个典型痛点:conntrack

代码语言:javascript
复制
1# 查看 conntrack 表使用与是否溢出
2sudo conntrack -S | head
3cat /proc/sys/net/netfilter/nf_conntrack_max
4sudo dmesg -T | grep -i "conntrack: table full"
5
6# 调优(示例,需按并发量评估)
7sudo sysctl -w net.netfilter.nf_conntrack_max=1048576
8sudo sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=900

conntrack 表满是高并发服务偶发丢包的经典原因,且只在压力下出现,测试环境很难复现。eBPF 数据面(如 Cilium 的 --disable-conntrack 对部分流量)可以绕开,但要注意无状态转发对某些协议的影响。

4.3 NetworkPolicy 的正确理解

Kubernetes 的 NetworkPolicy 是白名单语义:一旦某 Pod 被任意一条策略选中,未被显式放行的流量即被拒绝。

代码语言:javascript
复制
1apiVersion: networking.k8s.io/v1
2kind: NetworkPolicy
3metadata:
4  name: api-only-from-frontend
5spec:
6  podSelector:
7    matchLabels: { app: api }
8  policyTypes: ["Ingress"]
9  ingress:
10    - from:
11        - podSelector:
12            matchLabels: { app: frontend }
13      ports:
14        - protocol: TCP
15          port: 8080

常见事故:只写了 Ingress 策略,忘了 Pod 需要访问外部(DNS、对象存储),导致解析失败或调用超时;或者 CNI 不支持策略,YAML 生效但实际不拦截——必须实测验证,不能只看 apply 成功。

代码语言:javascript
复制
1# 验证策略是否真的生效(从非 frontend Pod 访问)
2kubectl run probe --rm -it --image=curlimages/curl --restart=Never -- \
3  curl -sv --max-time 5 http://api-svc:8080/healthz

五、存储:指标先行,别被"容量"迷惑

5.1 三类存储与选型

  • 块存储(云盘 / NVMe 本地盘):低延迟、随机 IO 好,适合数据库。本地盘性能最好但实例销毁即数据丢失,需要应用层副本。
  • 对象存储:海量、廉价、HTTP 语义、最终一致(多数实现),适合备份、媒体、数据湖。不适合当数据库磁盘用。
  • 文件存储(NFS/并行文件系统):共享读写,适合多节点共享场景;注意锁语义与性能抖动。

5.2 必须测的四个指标

代码语言:javascript
复制
1# 随机读 IOPS(4K,QD 32,模拟 OLTP)
2fio --name=randread --ioengine=libaio --direct=1 --rw=randread \
3    --bs=4k --iodepth=32 --numjobs=4 --size=4G --runtime=60 \
4    --group_reporting --filename=/mnt/data/testfile
5
6# 顺序写带宽(模拟日志/备份)
7fio --name=seqwrite --ioengine=libaio --direct=1 --rw=write \
8    --bs=1M --iodepth=16 --numjobs=2 --size=8G --runtime=60 --group_reporting
9
10# 关注:IOPS、带宽、p99/p999 延迟(不只是平均延迟!)

关键提醒:看 p99/p999 而不是平均延迟。云盘在多租户环境下存在"邻居噪音",平均值正常但尾延迟抖动,会直接放大上层服务的超时与重试风暴。

5.3 Kubernetes 存储:CSI 与常见坑

1apiVersion: storage.k8s.io/v1 2kind: StorageClass 3metadata: 4 name: ssd-sc 5provisioner: ebs.csi.aws.com # 换成你的 CSI 驱动 6parameters: 7 type: gp3 8 volumeSizeBytes: "107374182400" 9reclaimPolicy: Delete 10volumeBindingMode: WaitForFirstConsumer # 重要:避免跨可用区绑定 11allowVolumeExpansion: true

volumeBindingMode: WaitForFirstConsumer 几乎是必选项:否则 PVC 会在 Pod 调度前就绑定到某个可用区的盘,Pod 被调度到别的可用区时直接挂不上(跨 AZ 云盘不可挂载)。

其他高频坑:

  • 数据库用 ReadWriteOnce + 副本时,需要正确的拓扑与反亲和,否则副本挤在同一节点。
  • 本地盘 PV 需要节点亲和与数据重建策略,节点故障即数据丢失。
  • 快照与备份要定期做恢复演练,没验证过的备份等于没有备份。

六、编排:Kubernetes 的正确心智模型

6.1 控制面 = 一组控制器循环

理解 K8s 只需要抓住一个模式:期望状态(Spec)+ 实际状态(Status)+ 调谐循环(Reconcile Loop)。

代码语言:javascript
复制
1// 极简 Reconcile 骨架(controller-runtime 语义)
2func (r *MyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
3    var obj myv1.Widget
4    if err := r.Get(ctx, req.NamespacedName, &obj); err != nil {
5        return ctrl.Result{}, client.IgnoreNotFound(err) // 已删除,无需处理
6    }
7
8    // 1. 读取实际状态
9    actual, err := r.observe(ctx, &obj)
10    if err != nil {
11        return ctrl.Result{RequeueAfter: 10 * time.Second}, err // 可重试错误:退避重试
12    }
13
14    // 2. 计算差异并收敛(幂等!重复执行结果必须一致)
15    if diff := plan(obj.Spec, actual); len(diff) > 0 {
16        if err := r.apply(ctx, &obj, diff); err != nil {
17            return ctrl.Result{}, err
18        }
19    }
20
21    // 3. 回写状态,供上层与用户观测
22    obj.Status.Ready = actual.Ready
23    obj.Status.ObservedGeneration = obj.Generation
24    return ctrl.Result{}, r.Status().Update(ctx, &obj)
25}

三条工程铁律:

  1. Reconcile 必须幂等,因为会被重复触发(事件重放、重启、resync)。
  2. 不要在一个循环里做长阻塞操作,会拖垮整个控制面吞吐;长任务用 Job/Workflow 或异步 + 状态回写。
  3. 必须写 Status 与事件,否则故障时无法定位是"没执行"还是"执行了但失败"。

6.2 调度:不只是"哪个节点空闲"

生产调度需要考虑:

  • 资源请求与限制:requests 决定调度与容量规划,limits 决定隔离与限流。只设 limits 不设 requests 会导致调度器误判容量,节点超卖后集体抖动。
  • QoS 等级:Guaranteed / Burstable / BestEffort 决定了节点内存压力下的驱逐顺序。核心服务至少 Burstable,理想是 Guaranteed。
  • 拓扑感知:NUMA 亲和、GPU 拓扑、可用区分布、机架/故障域打散(topologySpreadConstraints)。
  • CPU 管理策略:延迟敏感服务用 cpuManagerPolicy: static + 整数核 requests,避免被 CFS 调度和跨 NUMA 迁移影响。
代码语言:javascript
复制
1resources:
2  requests: { cpu: "4", memory: 8Gi }   # 整数核,配合 static policy
3  limits:   { cpu: "4", memory: 8Gi }   # Guaranteed QoS

6.3 弹性:HPA 的常见失效

代码语言:javascript
复制
1apiVersion: autoscaling/v2
2kind: HorizontalPodAutoscaler
3metadata: { name: api-hpa }
4spec:
5  scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: api }
6  minReplicas: 3
7  maxReplicas: 30
8  metrics:
9    - type: Resource
10      resource: { name: cpu, target: { type: Utilization, averageUtilization: 60 } }
11  behavior:
12    scaleDown:
13      stabilizationWindowSeconds: 300   # 防止抖动
14      policies: [{ type: Percent, value: 25, periodSeconds: 60 }]

失效原因清单:

  • 没装 metrics-server 或指标未采集 → HPA 显示 <unknown>,静默不扩容。
  • 用 CPU 做指标,但瓶颈在内存/IO/下游依赖 → 扩了也没用(指标必须与真实瓶颈相关)。
  • 没有 requests → 利用率无法计算。
  • 扩容速度跟不上流量陡增 → 需要基于队列长度/请求速率的自定义指标(KEDA 类)或预热副本。
  • 缩容抖动 → 必须设 stabilization window。

七、性能调优:从"玄学参数"到"有依据的动作"

7.1 方法论:先定位瓶颈层级,再动手

代码语言:javascript
复制
1应用逻辑 → 运行时(GC/线程池) → 系统调用/IO → 内核调度 → 硬件(CPU/内存/网卡/盘)

每一步都要有数据支撑,不要凭感觉调 vm.swappiness。

代码语言:javascript
复制
1# 1. 全局快照:先看是 CPU、内存还是 IO 瓶颈
2vmstat 1 5                 # r 列(运行队列)、bi/bo、si/so、wa
3mpstat -P ALL 1 3          # 各核是否均衡,%iowait / %soft
4iostat -xz 1 3             # %util、await、r/s w/s(注意 %util 对 SSD 无意义)
5pidstat -d 1 3             # 定位到进程
6
7# 2. 内存压力与回收
8cat /proc/pressure/memory
9cat /proc/meminfo | grep -E "MemAvailable|SwapTotal|SwapFree|Dirty"
10sar -B 1 3                 # pgscan/pgsteal 高说明在回收,可能引发延迟尖刺
11
12# 3. 网络
13ss -s                      # 连接总数、TIME_WAIT
14ss -ti                     # 重传、RTT
15ethtool -S eth0 | grep -i -E "drop|error|miss"
16cat /proc/interrupts | head -20   # 中断是否集中在单核
17
18# 4. 内核级定位(有 eBPF 时优先用它)
19sudo perf top              # CPU 热点
20sudo offcputime-bpfcc 30   # 阻塞在哪(on-CPU 正常但慢时特别有用)

7.2 几个真正有效的调整(附适用条件)

调整

适用条件

风险

CPU 亲和绑定 + 关闭 NUMA 自动迁移

延迟敏感、整数核分配

降低整体利用率弹性

透明大页(THP)设为 madvise 或关闭

数据库、低延迟服务(THP 整理会导致延迟尖刺)

大内存应用可能损失吞吐

vm.swappiness 调低 + 启用 zswap

内存紧张但希望避免直接 OOM

过度调低可能提前触发 OOM killer

关闭 swap 的容器场景改用 PSI 驱动的驱逐

K8s 节点

需配好 eviction 阈值

中断亲和(RSS/RPS)+ 多队列网卡

高网络吞吐

配置错误反而更慢

noatime、合理 readahead

大量小文件读

依赖具体负载

io_uring 替代 libaio/同步 IO

高并发 IO 应用(需应用支持)

内核版本与安全面考量

核心原则:任何调优都要有 before/after 的压测数据与回滚方案。没有基线的调优只是随机游走。

7.3 一个高频真实故障模式

症状:服务周期性延迟尖刺,CPU 使用率不高,日志无异常。

排查路径:

  1. cat /sys/fs/cgroup/<pod>/cpu.stat → 看 nr_throttled 是否持续增长 → CPU 限流(limits 太低或 burst 不足)。
  2. cat /sys/fs/cgroup/<pod>/memory.pressure 的 full → 内存回收阻塞。
  3. iostat + io.stat 的 await 尖刺 → 存储尾延迟。
  4. dmesg 中的 OOM kill / 内核 soft lockup。
  5. GC 日志(Java/Go)与连接池等待。

结论:这类问题的根因 90% 在资源限额设置与真实需求不匹配,而不是内核参数。


八、可观测性:三个信号 + 一个原则

  • 指标(Metrics):适合趋势与告警,Prometheus + 拉取模型;关键是基数控制(不要把用户 ID、请求 ID 放进 label,会炸掉时序库)。
  • 日志(Logs):适合事后取证,必须结构化(JSON)+ 关联 ID;控制采样与保留期,否则成本失控。
  • 追踪(Traces):适合跨服务定位慢在哪一跳,OpenTelemetry 已成事实标准。

一个原则:告警要基于用户可感知的症状(SLO 错误率、延迟分位),而不是基于机器指标。"CPU 80%"不是告警,"p99 延迟超过 500ms 持续 5 分钟且影响 1% 请求"才是。

代码语言:javascript
复制
1# SLO 驱动的告警示例(Prometheus 语义)
2- alert: ApiLatencySloBurn
3  expr: |
4    (
5      sum(rate(http_request_duration_seconds_bucket{le="0.5",job="api"}[5m]))
6      / sum(rate(http_request_duration_seconds_count{job="api"}[5m]))
7    ) < 0.99
8  for: 5m
9  labels: { severity: page }
10  annotations:
11    summary: "5 分钟内 p99 延迟 SLO 达成率低于 99%"

多租户/大规模下的额外要求:全链路 trace ID 贯穿网关→服务→数据库;每个租户/服务有独立看板;容量与成本按标签归因。


九、安全与多租户:把边界画清楚

分层防御清单:

  1. 主机层:最小化安装、及时打内核补丁、SSH 密钥 + 禁用密码、fail2ban/网络 ACL、审计日志集中。
  2. 容器层:非 root 运行、只读根文件系统、drop 全部 capabilities 后按需加、seccomp + AppArmor/SELinux、禁止挂载 docker.sock 与宿主敏感目录。
  3. 网络层:默认拒绝的 NetworkPolicy、服务网格 mTLS、Ingress 侧 WAF 与速率限制。
  4. 数据层:静态加密 + 传输加密、密钥托管(KMS/Vault)、最小权限 IAM(不要用长期 AK/SK 硬编码,用实例角色/工作负载身份联合)。
  5. 供应链:镜像签名验证(cosign/sigstore)、SBOM 生成、基础镜像定期重建、CI 中做依赖与密钥扫描、禁止 latest 标签。
  6. 运行时检测:eBPF 基础的异常行为检测(提权、反弹 shell、敏感文件访问)。

云 IAM 是最常被低估的攻击面:一个过宽的实例角色权限,可能让一次容器逃逸升级为整个账号沦陷。原则是按最小权限拆分角色 + 定期权限审计 + 关键操作二次确认。


十、可靠性工程:把"不宕机"变成可度量的承诺

  • SLO 与错误预算:为每个服务定义可用性/延迟目标(如 99.9% / p99<300ms),把剩余预算作为发布与变更的闸门——预算耗尽时冻结新功能,只做稳定性工作。这让稳定性决策从"吵架"变成"算术"。
  • 冗余与故障域:多可用区、反亲和、副本数 ≥ 2 且分布在不同故障域;单点(数据库主、消息队列 broker、DNS)必须有明确故障方案。
  • 优雅降级:非核心依赖超时时降级而非级联失败;熔断 + 超时 + 重试(重试必须带抖动与上限,否则重试风暴会打死下游)。
  • 容量与压测:定期全链路压测,验证限流阈值与扩容速度;知道系统的真实拐点在哪。
  • 混沌工程:主动注入故障(杀 Pod、断网、加延迟、打满磁盘),验证假设而不是制造事故;从小规模、可控、可回滚开始。
  • 变更管理:绝大多数生产事故来自变更。灰度发布 + 自动回滚 + 变更冻结窗口,比任何监控都更能减少事故。
  • 演练恢复:备份恢复、跨区切换、密钥轮换都要实际演练过,并记录 RTO/RPO 实测值。

十一、成本工程:云上最容易被浪费的地方

  1. 右尺寸(rightsizing):大量实例长期低利用率。用实际 CPU/内存/网络峰值 + 冗余系数重新选型,而不是沿用初始配置。
  2. 计费模式组合:稳定基线用预留/承诺折扣,弹性部分用按需,可中断负载(批处理、CI、训练 checkpoint 化任务)用竞价实例——但必须假设它随时会被回收,任务要可断点续跑。
  3. 存储分层:热数据 SSD、温数据标准对象、冷数据归档;生命周期策略自动化,避免"数据只增不减"。
  4. 网络出口费用:跨可用区/跨区域流量、公网出口是隐形大头;就近部署、缓存、压缩能显著降本。
  5. K8s 层面:requests 设置过高会浪费调度容量(花钱买了不用),过低会抖动;用 VPA 推荐值 + 人工校准,配合 Cluster Autoscaler / Karpenter 做节点级弹性。
  6. 可观测性成本:日志全量采集与高基数指标是隐性大头,做采样与保留分级。

度量方式:建立单位业务成本(每千次请求成本、每用户成本),而不是只看账单总额——账单下降可能只是业务量下降。


十二、故障排查的通用流程(可直接当 SOP 用)

代码语言:javascript
复制
11. 止血优先:先恢复服务(回滚变更 / 扩容 / 切流量 / 降级),再查根因
22. 界定范围:影响哪些服务/租户/地域?从什么时候开始?最近有什么变更?
33. 分层定位:
4   - 客户端/网关:DNS、TLS、超时、限流
5   - 应用层:错误率、依赖调用、GC、连接池
6   - 编排层:Pod 状态、事件(kubectl describe / get events)、探针失败、驱逐
7   - 节点层:资源压力、磁盘满、内核日志、kubelet 日志
8   - 网络层:Service/Endpoint 是否就绪、策略是否拦截、conntrack、丢包
9   - 存储层:挂载状态、IO 延迟、配额
104. 保留证据:core dump、日志快照、指标截图(在清理前)
115. 复盘:时间线 + 根因 + 检测为什么慢 + 如何防止复发(要落到代码/配置/流程)

代码语言:javascript
复制
1# 一组高频有用的 K8s 排查命令
2kubectl get pods -A --field-selector=status.phase!=Running
3kubectl describe pod <pod> -n <ns>          # 看 Events:调度失败、镜像拉取、探针
4kubectl get events -n <ns> --sort-by=.lastTimestamp | tail -30
5kubectl top pod -n <ns> --containers        # 需要 metrics-server
6kubectl logs <pod> -c <container> --previous # 上一次崩溃的日志
7kubectl debug node/<node> -it --image=busybox  # 进节点排障(受限环境)
8journalctl -u kubelet --since "10 min ago"

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、先纠正一个常见误解:云不是"虚拟化",而是"内核能力的产品化"
  • 二、内核基石:四个必须亲手摸过的机制
    • 2.1 namespaces:隔离"视图"
    • 2.2 cgroups v2:隔离"资源量",也是计量的来源
    • 2.3 eBPF:可观测性与数据面的现代基座
    • 2.4 seccomp / LSM:把攻击面收窄
  • 三、虚拟化 vs 容器 vs 微虚机:选型不是站队,是权衡
  • 四、网络:从 iptables 到 eBPF 数据面,以及排障方法论
    • 4.1 云网络的三层结构
    • 4.2 一个典型痛点:conntrack
    • 4.3 NetworkPolicy 的正确理解
  • 五、存储:指标先行,别被"容量"迷惑
    • 5.1 三类存储与选型
    • 5.2 必须测的四个指标
    • 5.3 Kubernetes 存储:CSI 与常见坑
  • 六、编排:Kubernetes 的正确心智模型
    • 6.1 控制面 = 一组控制器循环
    • 6.2 调度:不只是"哪个节点空闲"
    • 6.3 弹性:HPA 的常见失效
  • 七、性能调优:从"玄学参数"到"有依据的动作"
    • 7.1 方法论:先定位瓶颈层级,再动手
    • 7.2 几个真正有效的调整(附适用条件)
    • 7.3 一个高频真实故障模式
  • 八、可观测性:三个信号 + 一个原则
  • 九、安全与多租户:把边界画清楚
  • 十、可靠性工程:把"不宕机"变成可度量的承诺
  • 十一、成本工程:云上最容易被浪费的地方
  • 十二、故障排查的通用流程(可直接当 SOP 用)
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档