<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>运维 on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/%E8%BF%90%E7%BB%B4/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Wed, 12 Feb 2025 10:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/%E8%BF%90%E7%BB%B4/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>☸️ Kubernetes 学习总结与避坑指南</title>
      <link>https://ftmao.com/blog/bookstore/kubernetes-authoritative-guide-notes/</link>
      <pubDate>Wed, 12 Feb 2025 10:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/bookstore/kubernetes-authoritative-guide-notes/</guid>
      <description>&lt;h1 id=&#34;-kubernetes-学习总结与避坑指南&#34;&gt;☸️ Kubernetes 学习总结与避坑指南&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;参考书籍：龚正 等《Kubernetes 权威指南：从 Docker 到 Kubernetes 实践全接触》、Marko Lukša《Kubernetes in Action》
目标读者：会一点 Docker、刚接触 K8s，或者「YAML 会抄但一出问题就懵」的同学。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kubernetes（简称 K8s，因为 K 和 s 之间有 8 个字母）是 Google 开源的容器编排系统，解决了「成百上千个容器跑在成百上千台机器上，谁来调度、谁来扩容、挂了谁来拉起」的问题。它不是一门「背完概念就会」的技术——新人最常见的状态是：每个名词都听过，但它们之间怎么串起来的说不清楚，Pod 一挂就不知道该看哪里。&lt;/p&gt;
&lt;p&gt;这篇文章帮你建立&lt;strong&gt;主干知识框架&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;K8s 集群整体长什么样？Master 和 Node 各自干什么？&lt;/li&gt;
&lt;li&gt;Pod、Node、Service、Ingress、ConfigMap 这些核心对象到底是什么关系？&lt;/li&gt;
&lt;li&gt;Istio 服务网格在解决什么问题？&lt;/li&gt;
&lt;li&gt;共享存储（PV/PVC/NAS）怎么用，有哪些坑？&lt;/li&gt;
&lt;li&gt;排查 K8s 问题需要补哪些 Unix 网络编程基础知识？&lt;/li&gt;
&lt;li&gt;生产环境如何做内外网访问隔离（私网端点 / 内网 LB / NetworkPolicy）？&lt;/li&gt;
&lt;li&gt;在阿里云 ACK（以及 AWS EKS）上落地时要注意什么？&lt;/li&gt;
&lt;li&gt;Jenkins 如何与 K8s 打通，实现自动化部署、验证与失败回滚？&lt;/li&gt;
&lt;li&gt;遇到 CrashLoopBackOff、OOMKilled、502、DNS 慢这些经典问题，该按什么思路排查？&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一k8s-整体架构一个中心化大脑--一群干活的节点&#34;&gt;一、K8s 整体架构：一个「中心化大脑 + 一群干活的节点」&lt;/h2&gt;
&lt;p&gt;K8s 集群在逻辑上分为两大部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;控制平面（Control Plane，俗称 Master）&lt;/strong&gt;：集群的大脑，负责「决策」——调度、扩缩容、故障自愈。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工作节点（Node）&lt;/strong&gt;：真正跑容器的机器，负责「执行」。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    subgraph 控制平面[&amp;#34;控制平面 Control Plane（阿里云 ACK 托管，用户不可见）&amp;#34;]
        APIServer[kube-apiserver&amp;lt;br/&amp;gt;集群唯一入口，所有操作都经过它]
        ETCD[(etcd&amp;lt;br/&amp;gt;分布式 KV 存储&amp;lt;br/&amp;gt;集群所有状态都在这里)]
        Scheduler[kube-scheduler&amp;lt;br/&amp;gt;决定 Pod 调度到哪个 Node]
        CM[kube-controller-manager&amp;lt;br/&amp;gt;各种控制器：副本数维持、节点监控等]
        CCM[cloud-controller-manager&amp;lt;br/&amp;gt;对接云厂商：SLB/EBS/路由]
    end

    subgraph 节点1[&amp;#34;Worker Node 1&amp;#34;]
        K1[kubelet&amp;lt;br/&amp;gt;节点上的「包工头」]
        P1[kube-proxy&amp;lt;br/&amp;gt;维护 Service 网络规则]
        C1[容器运行时&amp;lt;br/&amp;gt;containerd]
        Pod1[Pod A] ~~~ Pod2[Pod B]
    end

    subgraph 节点2[&amp;#34;Worker Node 2&amp;#34;]
        K2[kubelet]
        P2[kube-proxy]
        C2[containerd]
        Pod3[Pod C]
    end

    APIServer --&amp;gt; ETCD
    Scheduler --&amp;gt; APIServer
    CM --&amp;gt; APIServer
    CCM --&amp;gt; APIServer
    K1 --&amp;gt; APIServer
    K2 --&amp;gt; APIServer
    User[kubectl / CI/CD] --&amp;gt; APIServer&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;记住这条主线：&lt;strong&gt;所有组件只跟 apiserver 说话，apiserver 把状态写进 etcd&lt;/strong&gt;。你敲的每一条 &lt;code&gt;kubectl&lt;/code&gt; 命令、每一个控制器的决策，都是「读/写 apiserver」这个动作。理解了这一点，后面所有概念都好串了。&lt;/p&gt;
&lt;p&gt;K8s 的核心设计思想是&lt;strong&gt;声明式 API + 控制器循环&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[你提交 YAML&amp;lt;br/&amp;gt;期望状态：3 个副本] --&amp;gt; B[apiserver 存进 etcd]
    B --&amp;gt; C{控制器不断对比&amp;lt;br/&amp;gt;期望状态 vs 实际状态}
    C --&amp;gt;|实际只有 2 个| D[再创建 1 个 Pod]
    D --&amp;gt; C
    C --&amp;gt;|一致| E[什么都不做]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;这就是「自愈」的本质：不是有人盯着修，而是控制器永远在循环纠偏。所以 K8s 里的对象是「期望状态」的描述，不是一条条命令。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二node干活的机器&#34;&gt;二、Node：干活的机器&lt;/h2&gt;
&lt;h3 id=&#34;21-node-上有什么&#34;&gt;2.1 Node 上有什么&lt;/h3&gt;
&lt;p&gt;每个 Node 上必装三个组件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;kubelet&lt;/strong&gt;：节点代理。接收 apiserver 下发的 Pod 定义（PodSpec），调用容器运行时把容器拉起来，并持续上报节点和 Pod 状态。Pod 挂了重启、探针检测，都是 kubelet 干的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;容器运行时&lt;/strong&gt;：真正拉镜像、跑容器的软件。Docker 已在 K8s 1.24 后被移除，现在主流是 &lt;strong&gt;containerd&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kube-proxy&lt;/strong&gt;：维护节点上的网络规则（iptables/IPVS），让 Service 的虚拟 IP 能转发到真实 Pod。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;22-节点相关的避坑点&#34;&gt;2.2 节点相关的避坑点&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;节点 NotReady&lt;/strong&gt;：最常见的原因是 kubelet 挂了、节点磁盘满（DiskPressure）、内存不足（MemoryPressure）或网络不通。排查顺序：先 &lt;code&gt;kubectl describe node &amp;lt;名字&amp;gt;&lt;/code&gt; 看 Conditions，再登节点看 &lt;code&gt;systemctl status kubelet&lt;/code&gt; 和日志 &lt;code&gt;journalctl -u kubelet&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;磁盘压力&lt;/strong&gt;：容器日志、镜像、emptyDir 都在吃节点磁盘。务必给应用日志配轮转（logrotate 或运行时自带的日志上限 &lt;code&gt;containerLogMaxSize&lt;/code&gt;），否则磁盘写满会把节点上所有 Pod 驱逐（Evicted）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不要随意登节点手工改东西&lt;/strong&gt;：K8s 期望节点是「牛」不是「宠物」——可替换、不特殊。手工装的 Agent、改的 iptables 规则，节点一重建全没了。需要节点级能力请用 DaemonSet。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三podk8s-的最小调度单元&#34;&gt;三、Pod：K8s 的最小调度单元&lt;/h2&gt;
&lt;h3 id=&#34;31-为什么不是直接调度容器&#34;&gt;3.1 为什么不是直接调度容器&lt;/h3&gt;
&lt;p&gt;Pod 是一组&lt;strong&gt;共享网络和存储&lt;/strong&gt;的容器集合。同一个 Pod 里的容器：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;共享同一个 IP 和端口空间（通过 &lt;code&gt;localhost&lt;/code&gt; 直接互通）&lt;/li&gt;
&lt;li&gt;可以共享 Volume&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    subgraph Pod[&amp;#34;Pod（10.0.1.15）&amp;#34;]
        direction LR
        C1[主容器&amp;lt;br/&amp;gt;app:8080]
        C2[边车容器&amp;lt;br/&amp;gt;日志采集]
        V[(共享 Volume&amp;lt;br/&amp;gt;日志目录)]
        C1 --&amp;gt; V
        C2 --&amp;gt; V
    end
    C1 -.-&amp;gt;|localhost:8080| C2&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;这个设计的经典用途就是 &lt;strong&gt;Sidecar（边车）模式&lt;/strong&gt;：日志采集、流量代理（Istio 的 Envoy）都以边车容器形式注入 Pod，主容器无感知。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;新人直觉「一个 Pod 跑一个容器」，这对 90% 的场景是对的。只有容器之间必须同生共死、共享 localhost 或共享文件时，才放进同一个 Pod。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;32-pod-生命周期与探针&#34;&gt;3.2 Pod 生命周期与探针&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;stateDiagram-v2
    [*] --&amp;gt; Pending: 创建，等调度/拉镜像
    Pending --&amp;gt; Running: 调度成功，容器启动
    Running --&amp;gt; Succeeded: 正常退出（Job 类）
    Running --&amp;gt; Failed: 异常退出
    Running --&amp;gt; Running: 探针失败→kubelet 重启容器&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三个探针，新人人手必配：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;探针&lt;/th&gt;
					&lt;th&gt;作用&lt;/th&gt;
					&lt;th&gt;配错的后果&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;livenessProbe&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;判断容器是否活着，失败则&lt;strong&gt;重启容器&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;太灵敏 → 无限重启循环&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;readinessProbe&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;判断是否能接流量，失败则从 Service 摘除&lt;/td&gt;
					&lt;td&gt;不配 → 启动期请求打到没 ready 的 Pod，报 502&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;startupProbe&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;启动探针，成功前禁用另外两个&lt;/td&gt;
					&lt;td&gt;慢启动应用（如老 Java 服务）不配 → 被 liveness 误杀&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;33-资源-requestslimits-与-qos最容易被忽视的重灾区&#34;&gt;3.3 资源 requests/limits 与 QoS：最容易被忽视的重灾区&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;requests&lt;/span&gt;:        &lt;span style=&#34;color:#75715e&#34;&gt;# 调度依据：保证分到这么多&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;cpu&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;250m&amp;#34;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# 0.25 核&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;memory&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;512Mi&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;limits&lt;/span&gt;:          &lt;span style=&#34;color:#75715e&#34;&gt;# 使用上限&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;cpu&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;500m&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;memory&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1Gi&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;requests 是调度的唯一依据&lt;/strong&gt;：节点剩余可分配资源 ≥ Pod 的 requests 总和，Pod 才调度得上去。不配 requests，调度就是瞎排，节点超载。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU 超 limit → 被限流（throttle），容器变慢但不死；内存超 limit → OOMKilled，直接杀&lt;/strong&gt;。这是两种完全不同的失败模式，排查时先分清。&lt;/li&gt;
&lt;li&gt;QoS 等级：requests=limits 为 &lt;code&gt;Guaranteed&lt;/code&gt;（最后被驱逐）；都不配为 &lt;code&gt;BestEffort&lt;/code&gt;（节点资源紧张时最先被杀）。生产核心服务至少配 &lt;code&gt;Burstable&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四工作负载不要直接创建裸-pod&#34;&gt;四、工作负载：不要直接创建裸 Pod&lt;/h2&gt;
&lt;p&gt;实际工作中你几乎不会手写 Pod，而是使用「管理 Pod 的控制器」：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;对象&lt;/th&gt;
					&lt;th&gt;适用场景&lt;/th&gt;
					&lt;th&gt;一句话&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Deployment&lt;/td&gt;
					&lt;td&gt;无状态服务（Web/API）&lt;/td&gt;
					&lt;td&gt;副本数 + 滚动更新 + 回滚&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;StatefulSet&lt;/td&gt;
					&lt;td&gt;有状态服务（MySQL/Kafka）&lt;/td&gt;
					&lt;td&gt;稳定的名字和网络标识、按序启停&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;DaemonSet&lt;/td&gt;
					&lt;td&gt;节点级 Agent（日志/监控）&lt;/td&gt;
					&lt;td&gt;每个 Node 跑一个&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Job / CronJob&lt;/td&gt;
					&lt;td&gt;一次性/定时任务&lt;/td&gt;
					&lt;td&gt;跑完即退&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Deployment 滚动更新过程：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant U as 用户
    participant D as Deployment
    participant RS1 as ReplicaSet v1
    participant RS2 as ReplicaSet v2

    U-&amp;gt;&amp;gt;D: kubectl set image 更新镜像
    D-&amp;gt;&amp;gt;RS2: 创建新 RS，先拉起 1 个新 Pod
    RS2--&amp;gt;&amp;gt;D: 新 Pod ready
    D-&amp;gt;&amp;gt;RS1: 缩掉 1 个旧 Pod
    Note over D,RS2: 循环：新 +1 → 旧 -1
    D-&amp;gt;&amp;gt;RS1: 缩到 0（旧 RS 保留，可回滚）
    U-&amp;gt;&amp;gt;D: kubectl rollout undo（随时回滚）&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;避坑点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;maxSurge / maxUnavailable&lt;/strong&gt; 控制滚动节奏。默认 25%/25%，意味着更新中可能瞬间少 25% 的可用副本——容量紧张的服务要调小 maxUnavailable。&lt;/li&gt;
&lt;li&gt;回滚靠旧 ReplicaSet 保留的 Pod 模板，&lt;code&gt;revisionHistoryLimit&lt;/code&gt; 默认 10，别设成 0 否则无法回滚。&lt;/li&gt;
&lt;li&gt;镜像 tag 不要用 &lt;code&gt;latest&lt;/code&gt;：无法回滚、无法审计，且 &lt;code&gt;imagePullPolicy&lt;/code&gt; 行为反直觉。用 git commit 号或语义化版本。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五k8s-网络模型与必备的-unix-网络编程知识&#34;&gt;五、K8s 网络模型与必备的 Unix 网络编程知识&lt;/h2&gt;
&lt;p&gt;K8s 的网络问题占了线上故障的一半以上。而很多「K8s 网络问题」本质上是 &lt;strong&gt;Unix 网络编程/TCP 协议问题&lt;/strong&gt;，只是发生在容器环境里。这一节把两边打通。&lt;/p&gt;
&lt;h3 id=&#34;51-k8s-网络的三条铁律&#34;&gt;5.1 K8s 网络的三条铁律&lt;/h3&gt;
&lt;p&gt;K8s 对网络模型只有三个基本要求（具体实现交给 CNI 插件，如 Flannel、Calico、阿里云 Terway）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;每个 Pod 有自己的独立 IP&lt;/li&gt;
&lt;li&gt;任意两个 Pod 之间可以直接通信（不经过 NAT）&lt;/li&gt;
&lt;li&gt;Node 和 Pod 之间可以直接通信&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    subgraph 节点A[&amp;#34;Node A&amp;#34;]
        PA[&amp;#34;Pod A&amp;lt;br/&amp;gt;10.244.1.5&amp;#34;]
    end
    subgraph 节点B[&amp;#34;Node B&amp;#34;]
        PB[&amp;#34;Pod B&amp;lt;br/&amp;gt;10.244.2.8&amp;#34;]
    end
    PA &amp;lt;--&amp;gt;|&amp;#34;Pod 网络（CNI：Terway/Flannel/Calico）&amp;lt;br/&amp;gt;直连，无 NAT&amp;#34;| PB&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;52-service一组-pod-的稳定入口&#34;&gt;5.2 Service：一组 Pod 的稳定入口&lt;/h3&gt;
&lt;p&gt;Pod 会漂移（重建后 IP 就变了），所以不能在代码里写死 Pod IP。Service 提供&lt;strong&gt;一个固定虚拟 IP（ClusterIP）+ DNS 名字&lt;/strong&gt;，负载均衡到后端 Pod。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    Client[客户端 Pod] --&amp;gt;|&amp;#34;访问 my-svc:80&amp;lt;br/&amp;gt;DNS 解析为 10.96.0.10&amp;#34;| SVC[&amp;#34;Service: my-svc&amp;lt;br/&amp;gt;ClusterIP 10.96.0.10&amp;#34;]
    SVC --&amp;gt;|kube-proxy 的 iptables/IPVS 规则转发| P1[Pod 1]
    SVC --&amp;gt; P2[Pod 2]
    SVC --&amp;gt; P3[Pod 3]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三种 Service 类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ClusterIP&lt;/strong&gt;（默认）：仅集群内可达&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NodePort&lt;/strong&gt;：在每个节点开一个高端口（30000-32767），可从集群外访问&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LoadBalancer&lt;/strong&gt;：对接云厂商负载均衡器（阿里云 CLB/SLB、AWS NLB/ALB），对外暴露的标准姿势&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;53-为什么排查-k8s-网络要懂-unix-网络编程&#34;&gt;5.3 为什么排查 K8s 网络要懂 Unix 网络编程&lt;/h3&gt;
&lt;p&gt;下面这几组知识，是在 K8s 环境里排查连接问题的「元技能」：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;（1）TCP 连接状态与 TIME_WAIT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;TCP 挥手后主动关闭方会进入 TIME_WAIT 状态，默认保持 2MSL（Linux 上约 60s）。在高并发短连接场景（比如服务间大量 HTTP/1.0 式短调用），客户端端口会被 TIME_WAIT 大量占用，最终 &lt;code&gt;Cannot assign requested address&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;stateDiagram-v2
    ESTABLISHED --&amp;gt; FIN_WAIT1: 主动方 close()
    FIN_WAIT1 --&amp;gt; FIN_WAIT2: 收到对端 ACK
    FIN_WAIT2 --&amp;gt; TIME_WAIT: 收到对端 FIN
    TIME_WAIT --&amp;gt; CLOSED: 2MSL 超时（约60s）
    ESTABLISHED --&amp;gt; CLOSE_WAIT: 对端先 close()
    CLOSE_WAIT --&amp;gt; LAST_ACK: 我方 close()
    LAST_ACK --&amp;gt; CLOSED&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;K8s 里的对应症状与解法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;症状：服务间调用偶发超时，&lt;code&gt;ss -s&lt;/code&gt; 看到 timewait 几万。&lt;/li&gt;
&lt;li&gt;正解：&lt;strong&gt;应用层用长连接 + 连接池&lt;/strong&gt;（HTTP keep-alive、gRPC），别依赖 &lt;code&gt;net.ipv4.tcp_tw_reuse&lt;/code&gt; 这类内核参数硬扛。&lt;/li&gt;
&lt;li&gt;另一个常见坑是 &lt;strong&gt;CLOSE_WAIT 堆积&lt;/strong&gt;：对端关了连接但你的代码没 close()（连接泄漏），&lt;code&gt;ss -ant | grep CLOSE_WAIT&lt;/code&gt; 一查便知。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;（2）socket、backlog 与「连接被 Reset」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;服务端 &lt;code&gt;listen(fd, backlog)&lt;/code&gt; 的 backlog 是「已完成三次握手但应用还没 accept」的队列长度。K8s 场景下突发流量打到刚重启的 Pod，如果应用 backlog 太小（或迟迟不 accept），内核会直接 RST，客户端看到的是 &lt;code&gt;Connection reset by peer&lt;/code&gt;。这类问题在 Pod 扩容瞬间、探针刚通过时高发——&lt;strong&gt;readinessProbe 通过 ≠ 应用真的能扛流量&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;（3）epoll 与 I/O 多路复用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个进程通过 &lt;code&gt;epoll&lt;/code&gt; 可以管理数万连接（C10K 问题的解法）。Nginx Ingress、Envoy 都是 epoll 模型。要懂的点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;进程能开的连接数受 &lt;strong&gt;文件描述符上限&lt;/strong&gt;限制：&lt;code&gt;ulimit -n&lt;/code&gt;。容器里同样生效，高并发服务记得确认 limit（&lt;code&gt;cat /proc/&amp;lt;pid&amp;gt;/limits&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;每个 TCP 连接 = 一个四元组（源IP:源端口 → 目标IP:目标端口）。客户端对单一目标的并发连接数理论上受源端口数（约 2.8 万个可用）限制——这又回到「必须用连接池复用连接」。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;（4）conntrack：K8s 特有的网络坑&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;kube-proxy 的 iptables 模式依赖内核 conntrack（连接跟踪表）。节点上连接数巨大时 conntrack 表被打满（默认 &lt;code&gt;nf_conntrack_max&lt;/code&gt; 往往不够），表现为&lt;strong&gt;新建连接随机丢包、无日志&lt;/strong&gt;，极难排查。解法：调大 &lt;code&gt;net.netfilter.nf_conntrack_max&lt;/code&gt;，或干脆把 kube-proxy 切到 IPVS 模式。阿里云 ACK 的 Terway 模式在这方面压力小很多。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;（5）DNS：K8s 里的「隐形依赖」&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;集群内所有服务名解析都靠 CoreDNS。两个经典坑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;glibc 的 DNS 解析是串行的&lt;/strong&gt;，且默认 &lt;code&gt;ndots:5&lt;/code&gt; 导致集群内短域名先查 5 次后缀。症状：应用偶发解析慢 5s（一次超时重传）。解法：FQDN 写法 &lt;code&gt;my-svc.my-ns.svc.cluster.local.&lt;/code&gt;（结尾加点）或调整 Pod 的 &lt;code&gt;dnsConfig&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Java 应用默认&lt;strong&gt;永久缓存 DNS 结果&lt;/strong&gt;（&lt;code&gt;networkaddress.cache.ttl=-1&lt;/code&gt;），Service 后端 IP 变了 JVM 不知道。容器里务必显式设置 DNS 缓存 TTL（如 30s）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;54-内外网访问隔离哪些服务能暴露哪些必须藏住&#34;&gt;5.4 内外网访问隔离：哪些服务能暴露，哪些必须藏住&lt;/h3&gt;
&lt;p&gt;生产集群的基本安全原则：&lt;strong&gt;默认所有东西都不出集群，只开必要的口子&lt;/strong&gt;。K8s 默认网络是「全通」的（任何 Pod 可以访问任何 Pod，LoadBalancer 一不小心就开到公网），隔离要靠自己显式配置。隔离分三个层面，从外到内：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    Internet[公网用户] --&amp;gt;|只放行 443| WAF[WAF / 安全组&amp;lt;br/&amp;gt;云平台层]
    WAF --&amp;gt; PubLB[公网 ALB/CLB&amp;lt;br/&amp;gt;仅 Web 入口服务]
    PubLB --&amp;gt; PubIng[Ingress Controller&amp;lt;br/&amp;gt;公网命名空间]
    PubIng --&amp;gt; WebSvc[Web Service&amp;lt;br/&amp;gt;ClusterIP]

    Office[办公网/运维] --&amp;gt;|VPN/跳板机| IntLB[内网 LoadBalancer&amp;lt;br/&amp;gt;intranet 类型]
    IntLB --&amp;gt; AdminSvc[管理后台 / 监控&amp;lt;br/&amp;gt;Grafana / Jenkins]

    subgraph 集群内[&amp;#34;集群内部（东西向流量）&amp;#34;]
        WebSvc --&amp;gt;|NetworkPolicy 允许| AppSvc[业务 Service]
        AppSvc --&amp;gt;|NetworkPolicy 允许| DBSvc[数据库 Proxy Service]
        AppSvc -.-&amp;gt;|NetworkPolicy 拒绝| Other[其他 namespace]
    end&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;第一层：云网络边界（VPC / 安全组）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API Server 用私网端点&lt;/strong&gt;：阿里云 ACK 创建集群时选择「专有网络（私网）」API Server 访问，或只绑定内网 EIP，运维通过 VPN/跳板机访问；公网端点即便有证书认证也是攻击面。AWS EKS 对应 endpoint private access。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;节点安全组收紧入方向&lt;/strong&gt;：只放行 NodePort 范围给内网、放行 LB 健康检查来源，其余一律拒绝。ACK 的节点安全组默认规则要审一遍。&lt;/li&gt;
&lt;li&gt;数据库、Redis 这类云产品走 VPC 内网地址，安全组只对集群节点网段开放。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;第二层：Service 暴露方式——内外网分流的关键&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;LoadBalancer 类型 Service 默认创建的是&lt;strong&gt;公网 LB&lt;/strong&gt;，这是最常见的「误暴露」事故。面向内部的服务要用注解显式声明内网 LB：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 阿里云：内网 CLB（VPC 内可达，公网不可达）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;internal-admin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;annotations&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;intranet&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;LoadBalancer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;AWS EKS 对应注解：&lt;code&gt;service.beta.kubernetes.io/aws-load-balancer-internal: &amp;quot;true&amp;quot;&lt;/code&gt;（NLB）或 &lt;code&gt;aws-load-balancer-scheme: internal&lt;/code&gt;（ALB Controller）。&lt;/p&gt;
&lt;p&gt;经验法则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对外服务：公网 ALB/CLB + Ingress，前面最好再挂 WAF。&lt;/li&gt;
&lt;li&gt;对内服务（管理后台、监控、Jenkins）：内网 LB 或纯 ClusterIP，配合 VPN/跳板机访问。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;默认用 ClusterIP&lt;/strong&gt;，需要出集群时再显式升级类型——把「暴露」当成一个需要评审的动作。&lt;/li&gt;
&lt;li&gt;Ingress 上还可以用注解做来源 IP 白名单（如 &lt;code&gt;nginx.ingress.kubernetes.io/whitelist-source-range: 10.0.0.0/8&lt;/code&gt;），给内部接口再加一道闸。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;第三层：NetworkPolicy——集群内部的东西向隔离&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;即使流量不出集群，「测试 namespace 的 Pod 误连生产数据库」这类事故也常见。NetworkPolicy 是 Pod 级的防火墙（需要 CNI 支持，ACK 的 Terway、Calico 都支持，Flannel 不支持）：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 第一步：namespace 默认全拒（白名单模式的起点）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;NetworkPolicy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;default-deny&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;podSelector&lt;/span&gt;: {}          &lt;span style=&#34;color:#75715e&#34;&gt;# 选中 namespace 内所有 Pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;policyTypes&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Ingress&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Egress&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 第二步：只放行需要的流量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;NetworkPolicy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;allow-web-to-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;podSelector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;matchLabels&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;order-svc}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;policyTypes&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Ingress&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ingress&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;podSelector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;matchLabels&lt;/span&gt;: {&lt;span style=&#34;color:#f92672&#34;&gt;app&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;web-frontend}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;避坑点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;NetworkPolicy 是&lt;strong&gt;白名单累加&lt;/strong&gt;模型：任何一条 policy 选中某 Pod，该 Pod 未被放行的方向就被默认拒绝。写漏了 DNS（Egress 到 kube-dns 的 53 端口）会导致全 namespace 解析失败——默认拒绝后记得显式放行 DNS。&lt;/li&gt;
&lt;li&gt;策略&lt;strong&gt;只对选中后新建立的连接生效&lt;/strong&gt;，且 Flannel 下写了也不生效（静默失效，最坑的一种）。&lt;/li&gt;
&lt;li&gt;云安全组管的是「节点/LB 维度」，NetworkPolicy 管的是「Pod 维度」，两者互补不替代。&lt;/li&gt;
&lt;li&gt;上了 Istio 的话，还可以用 AuthorizationPolicy 做带身份（mTLS 服务身份）的七层鉴权，比纯 IP/端口的 NetworkPolicy 更细。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六ingresshttp-流量的统一入口&#34;&gt;六、Ingress：HTTP 流量的统一入口&lt;/h2&gt;
&lt;p&gt;Service 解决的是四层（TCP）负载均衡；Ingress 解决的是七层（HTTP/HTTPS）路由：按域名、按路径把外部流量分发到不同 Service。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    User[外部用户] --&amp;gt;|HTTPS| LB[云负载均衡&amp;lt;br/&amp;gt;阿里云 ALB/CLB]
    LB --&amp;gt; IC[Ingress Controller&amp;lt;br/&amp;gt;Nginx / ALB Ingress]
    IC --&amp;gt;|&amp;#34;a.example.com/api/*&amp;#34;| S1[Service: api]
    IC --&amp;gt;|&amp;#34;a.example.com/web/*&amp;#34;| S2[Service: web]
    IC --&amp;gt;|&amp;#34;b.example.com/*&amp;#34;| S3[Service: admin]
    S1 --&amp;gt; P1[api Pod]
    S2 --&amp;gt; P2[web Pod]
    S3 --&amp;gt; P3[admin Pod]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;注意分清两层：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ingress 资源&lt;/strong&gt;（YAML 对象）：只是路由规则的声明，本身不做任何事。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ingress Controller&lt;/strong&gt;（真正干活的组件）：如 ingress-nginx、阿里云 ALB Ingress Controller。它 watch Ingress 资源，把规则翻译成 Nginx 配置并热加载。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;避坑点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pathType: Prefix&lt;/code&gt; 和 &lt;code&gt;Exact&lt;/code&gt; 的区别，&lt;code&gt;/api&lt;/code&gt; 配 Prefix 会把 &lt;code&gt;/apiserver&lt;/code&gt; 也匹配进去。&lt;/li&gt;
&lt;li&gt;后端重写（&lt;code&gt;rewrite-target&lt;/code&gt;）是最容易写错的注解，先想清楚「客户端路径 → 后端真实路径」的映射。&lt;/li&gt;
&lt;li&gt;HTTPS 证书放在 Secret 里，过期忘续是经典事故——建议上 cert-manager 自动签发续期。&lt;/li&gt;
&lt;li&gt;502 的第一排查动作：看 Ingress Controller 日志里 upstream 是「连接拒绝」（Pod 没 ready）还是「超时」（应用卡死）。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七configmap-与-secret配置和代码分离&#34;&gt;七、ConfigMap 与 Secret：配置和代码分离&lt;/h2&gt;
&lt;p&gt;十二要素应用的第一条就是「配置存环境」。K8s 里对应两个对象：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ConfigMap&lt;/strong&gt;：普通配置（应用参数、配置文件、特性开关）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secret&lt;/strong&gt;：敏感配置（密码、密钥、证书），etcd 中 Base64 编码（注意：&lt;strong&gt;Base64 不是加密&lt;/strong&gt;，生产环境要开 etcd 静态加密或对接 KMS）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;两种注入方式：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 方式一：环境变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;env&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;DB_HOST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;valueFrom&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;configMapKeyRef&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;app-config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;key&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;db_host&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 方式二：挂载为文件（推荐，支持热更新）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;volumeMounts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;mountPath&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/etc/app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;configMap&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;app-config&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;两个必踩的坑，提前告诉你：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;环境变量注入的配置，改了 ConfigMap 不会生效&lt;/strong&gt;，必须重启 Pod。文件挂载方式会自动更新（kubelet 定期同步，有分钟级延迟），但应用要支持 reload。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;subPath&lt;/code&gt; 挂载的 ConfigMap 不会自动更新&lt;/strong&gt;。这是用了 subPath 挂单个配置文件的同学必踩的坑——改完 ConfigMap 发现容器里还是旧的。解法：挂载整个目录，或接受重启 Pod 的事实。&lt;/li&gt;
&lt;li&gt;ConfigMap 有 1MB 大小限制，别把大文件塞进去。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八共享存储pv--pvc--storageclass&#34;&gt;八、共享存储：PV / PVC / StorageClass&lt;/h2&gt;
&lt;p&gt;容器是临时的，数据要持久化就必须落到外部存储。K8s 的存储抽象分三层：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    subgraph 管理员/云平台侧
        SC[StorageClass&amp;lt;br/&amp;gt;定义「用什么盘」&amp;lt;br/&amp;gt;如 alicloud-disk-essd / nas]
        PV[PersistentVolume&amp;lt;br/&amp;gt;一块真实的存储&amp;lt;br/&amp;gt;云盘/NAS 文件系统]
    end
    subgraph 应用侧
        PVC[PersistentVolumeClaim&amp;lt;br/&amp;gt;「我要 100Gi 存储」的申请单]
        Pod[Pod 挂载 PVC]
    end
    PVC --&amp;gt;|绑定| PV
    SC --&amp;gt;|动态供给：PVC 一创建&amp;lt;br/&amp;gt;自动开出对应 PV| PV
    Pod --&amp;gt; PVC&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;现代用法几乎全是&lt;strong&gt;动态供给&lt;/strong&gt;：你只需要写 PVC 声明要多少空间，StorageClass 自动调用云厂商 API 创建云盘/NAS，不用手工建 PV。&lt;/p&gt;
&lt;p&gt;三种访问模式（Access Modes）是高频考点：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;模式&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
					&lt;th&gt;典型存储&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;ReadWriteOnce (RWO)&lt;/td&gt;
					&lt;td&gt;只能挂到一个节点&lt;/td&gt;
					&lt;td&gt;云盘（阿里云 ESSD、AWS EBS）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ReadWriteMany (RWX)&lt;/td&gt;
					&lt;td&gt;多节点共享读写&lt;/td&gt;
					&lt;td&gt;文件存储（阿里云 NAS、AWS EFS）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ReadOnlyMany (ROX)&lt;/td&gt;
					&lt;td&gt;多节点只读&lt;/td&gt;
					&lt;td&gt;对象存储挂载、只读数据卷&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;共享存储的避坑清单：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;云盘（RWO）不能跨可用区挂载&lt;/strong&gt;。PV 创建在可用区 A，Pod 被调度到可用区 B 就永远 Pending。解法：用 &lt;code&gt;WaitForFirstConsumer&lt;/code&gt; 模式的 StorageClass（等 Pod 定好节点再开盘），并用拓扑约束调度。&lt;/li&gt;
&lt;li&gt;要&lt;strong&gt;多副本共享文件&lt;/strong&gt;（如多个 Web Pod 共享上传目录），必须用 NAS/EFS 这类 RWX 存储，云盘做不到。&lt;/li&gt;
&lt;li&gt;NAS 挂载注意&lt;strong&gt;权限问题&lt;/strong&gt;：容器内进程 UID 和 NAS 目录属主不匹配会 Permission denied，用 &lt;code&gt;securityContext.fsGroup&lt;/code&gt; 或挂载参数解决。&lt;/li&gt;
&lt;li&gt;删除 PVC 会不会丢数据，取决于 PV 的 &lt;code&gt;persistentVolumeReclaimPolicy&lt;/code&gt;（Retain 保留 / Delete 连盘一起删）。&lt;strong&gt;生产数据盘务必确认是 Retain&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;StatefulSet 用 &lt;code&gt;volumeClaimTemplates&lt;/code&gt; 给每个副本独立开盘，扩缩容时数据卷跟着 Pod 名字走，这是有状态服务的标准姿势。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九istio-服务网格把网络能力从业务代码里剥出来&#34;&gt;九、Istio 服务网格：把「网络能力」从业务代码里剥出来&lt;/h2&gt;
&lt;p&gt;微服务多了之后，每个服务都要自己实现超时重试、熔断、灰度、流量监控——这些和业务无关。Istio 的思路：给每个 Pod 注入一个 &lt;strong&gt;Envoy 边车代理&lt;/strong&gt;，接管所有进出流量，上述能力全部在代理层实现，业务代码零侵入。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    subgraph 控制平面[&amp;#34;Istio 控制平面（istiod）&amp;#34;]
        Pilot[配置下发&amp;lt;br/&amp;gt;流量规则]
        Citadel[证书管理&amp;lt;br/&amp;gt;mTLS]
    end
    subgraph 数据平面
        subgraph PodA[&amp;#34;Pod A&amp;#34;]
            App1[业务容器] --- E1[Envoy 边车]
        end
        subgraph PodB[&amp;#34;Pod B&amp;#34;]
            App2[业务容器] --- E2[Envoy 边车]
        end
    end
    Pilot -.-&amp;gt;|xDS 配置下发| E1
    Pilot -.-&amp;gt;|xDS 配置下发| E2
    E1 &amp;lt;--&amp;gt;|&amp;#34;mTLS 加密流量&amp;lt;br/&amp;gt;（应用无感知）&amp;#34;| E2&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;核心能力速览：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;流量管理&lt;/strong&gt;：VirtualService + DestinationRule 实现按权重灰度（v1 90% / v2 10%）、按 Header 路由、超时重试、熔断&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;安全&lt;/strong&gt;：服务间自动 mTLS 加密 + 身份认证（AuthorizationPolicy）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观测&lt;/strong&gt;：不用改代码就拿到全链路指标、调用拓扑、访问日志&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;入口&lt;/strong&gt;：Istio Gateway 替代/补充原生 Ingress，作为网格的南北向入口&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;避坑点（Istio 坑不少，挑最重要的）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;边车有成本&lt;/strong&gt;：每个 Pod 多一份 Envoy 的 CPU/内存（默认 requests 约 100m/128Mi），上千 Pod 规模要算这笔账，必要时调小。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sidecar 启动顺序&lt;/strong&gt;：业务容器可能比 Envoy 先起来导致启动瞬间网络不通（现在 &lt;code&gt;holdApplicationUntilProxyStarts&lt;/code&gt; 可解）；Job 类任务跑完 Envoy 不退导致 Job 永不结束，需要显式退出或关掉注入。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;协议识别&lt;/strong&gt;：Service 端口名要带协议前缀（&lt;code&gt;name: http-xxx&lt;/code&gt;），否则 Istio 按 TCP 处理，七层能力全部失效。这是网格内路由不生效的第一嫌疑。&lt;/li&gt;
&lt;li&gt;排障三板斧：&lt;code&gt;istioctl analyze&lt;/code&gt;（静态检查配置）、&lt;code&gt;istioctl proxy-config&lt;/code&gt;（看 Envoy 实际生效配置）、Envoy 的 &lt;code&gt;:15000/stats&lt;/code&gt; 和 &lt;code&gt;:15000/clusters&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;新人别一上来就上全量 Istio。先在非核心 namespace 开注入练手，理解 VirtualService 再说。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十云上落地阿里云-ack-为主aws-eks-对照&#34;&gt;十、云上落地：阿里云 ACK 为主，AWS EKS 对照&lt;/h2&gt;
&lt;p&gt;自己从零搭一套生产级 K8s（etcd 高可用、证书、网络插件）成本极高，生产环境几乎都用云厂商托管服务。&lt;/p&gt;
&lt;h3 id=&#34;101-阿里云-ack-关键点&#34;&gt;10.1 阿里云 ACK 关键点&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    subgraph 阿里云托管[&amp;#34;ACK 托管层（免费/Pro）&amp;#34;]
        MA[控制平面：apiserver/etcd/scheduler&amp;lt;br/&amp;gt;阿里云托管，SLA 保障]
    end
    subgraph 你的账号[&amp;#34;你的 VPC 内&amp;#34;]
        N1[ECS 节点池 1&amp;lt;br/&amp;gt;按量/抢占式]
        N2[ECS 节点池 2&amp;lt;br/&amp;gt;弹性伸缩 ESS]
    end
    MA --&amp;gt; N1
    MA --&amp;gt; N2
    N1 -.对接.-&amp;gt; CLB[CLB/ALB&amp;lt;br/&amp;gt;负载均衡]
    N1 -.对接.-&amp;gt; NAS[云盘 ESSD / NAS&amp;lt;br/&amp;gt;持久存储]
    N1 -.对接.-&amp;gt; SLS[SLS 日志 / ARMS 监控&amp;lt;br/&amp;gt;可观测]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;实践经验：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;网络插件选 Terway&lt;/strong&gt;：Pod 直接用 VPC 弹性网卡 IP，无 overlay 开销、conntrack 压力小，还能配 NetworkPolicy；Flannel 适合小规模简单场景。Terway 模式下&lt;strong&gt;规划 VPC 网段要留够&lt;/strong&gt;，每个 Pod 占一个真实 IP。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;节点池 + 弹性伸缩&lt;/strong&gt;：按业务波峰波谷自动扩缩节点；抢占式实例（Spot）跑无状态任务能省 70% 成本，但要容忍随时被回收。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ingress 用 ALB Ingress Controller&lt;/strong&gt;：比自建 Nginx Ingress 省心，ALB 本身按量弹性，且和 ACK 深度集成。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;日志和监控开箱即用&lt;/strong&gt;：日志服务 SLS（采集容器 stdout 和文件日志）、ARMS Prometheus 监控，别再自己搭 ELK 了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;镜像仓库 ACR&lt;/strong&gt;：用 ACR EE（企业版）+ ACK 免密拉取插件，避免在 YAML 里配 imagePullSecret。&lt;/li&gt;
&lt;li&gt;存储选 &lt;strong&gt;CNFS/云盘 ESSD（有状态单副本）+ NAS（共享文件）+ OSS（静态资源、备份）&lt;/strong&gt; 的组合。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;102-aws-eks-速查对照&#34;&gt;10.2 AWS EKS 速查对照&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;需求&lt;/th&gt;
					&lt;th&gt;阿里云 ACK&lt;/th&gt;
					&lt;th&gt;AWS EKS&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;网络插件&lt;/td&gt;
					&lt;td&gt;Terway（VPC 网卡直连）&lt;/td&gt;
					&lt;td&gt;aws-vpc-cni（同理）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;七层入口&lt;/td&gt;
					&lt;td&gt;ALB Ingress&lt;/td&gt;
					&lt;td&gt;AWS Load Balancer Controller (ALB/NLB)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;块存储&lt;/td&gt;
					&lt;td&gt;云盘 ESSD&lt;/td&gt;
					&lt;td&gt;EBS (gp3)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;共享文件存储&lt;/td&gt;
					&lt;td&gt;NAS&lt;/td&gt;
					&lt;td&gt;EFS&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;日志&lt;/td&gt;
					&lt;td&gt;SLS&lt;/td&gt;
					&lt;td&gt;CloudWatch&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;监控&lt;/td&gt;
					&lt;td&gt;ARMS Prometheus&lt;/td&gt;
					&lt;td&gt;Managed Prometheus / Grafana&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;镜像仓库&lt;/td&gt;
					&lt;td&gt;ACR&lt;/td&gt;
					&lt;td&gt;ECR&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;无服务器节点&lt;/td&gt;
					&lt;td&gt;虚拟节点（ECI）&lt;/td&gt;
					&lt;td&gt;Fargate&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;概念完全互通，换云只是换 Controller 和注解。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十一典型问题排查手册&#34;&gt;十一、典型问题排查手册&lt;/h2&gt;
&lt;h3 id=&#34;111-通用排查流程&#34;&gt;11.1 通用排查流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[发现问题] --&amp;gt; B{Pod 状态？&amp;lt;br/&amp;gt;kubectl get pods}
    B --&amp;gt;|Pending| C[kubectl describe pod&amp;lt;br/&amp;gt;看 Events]
    C --&amp;gt; C1{原因}
    C1 --&amp;gt;|资源不足| C2[加节点/降 requests&amp;lt;br/&amp;gt;或开弹性伸缩]
    C1 --&amp;gt;|存储挂载失败| C3[检查 PVC 绑定/可用区]
    C1 --&amp;gt;|镜像拉取失败| C4[ImagePullBackOff：查镜像名/凭证/网络]
    B --&amp;gt;|CrashLoopBackOff| D[kubectl logs --previous&amp;lt;br/&amp;gt;看上一个容器的临终日志]
    D --&amp;gt; D1{原因}
    D1 --&amp;gt;|应用自身报错| D2[修代码/配置]
    D1 --&amp;gt;|Exit 137| D3[OOMKilled：调大 memory limit&amp;lt;br/&amp;gt;或查内存泄漏]
    D1 --&amp;gt;|Exit 143| D4[被优雅终止：查探针/滚动更新]
    B --&amp;gt;|Running 但访问异常| E[分层验证]
    E --&amp;gt; E1[1. 进 Pod 内 curl localhost 通吗？]
    E1 --&amp;gt; E2[2. curl Pod IP 通吗？]
    E2 --&amp;gt; E3[3. curl Service ClusterIP 通吗？&amp;lt;br/&amp;gt;查 Endpoints 是否有后端]
    E3 --&amp;gt; E4[4. Ingress 域名通吗？&amp;lt;br/&amp;gt;查 Controller 日志]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;112-高频问题速查表&#34;&gt;11.2 高频问题速查表&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;症状&lt;/th&gt;
					&lt;th&gt;最常见原因&lt;/th&gt;
					&lt;th&gt;第一动作&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;ImagePullBackOff&lt;/td&gt;
					&lt;td&gt;镜像名/tag 错、私有仓库无凭证、节点无公网&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;describe pod&lt;/code&gt; 看 Events 报错原文&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;CrashLoopBackOff&lt;/td&gt;
					&lt;td&gt;配置错、依赖没起来、探针误杀&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;kubectl logs --previous&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;OOMKilled (137)&lt;/td&gt;
					&lt;td&gt;内存 limit 太小或泄漏&lt;/td&gt;
					&lt;td&gt;看监控曲线，调 limit；Java 服务注意堆外内存&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Pod 一直 Pending&lt;/td&gt;
					&lt;td&gt;资源不够、PVC 未绑定、污点/亲和性&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;describe pod&lt;/code&gt; 看调度失败原因&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;服务间偶发超时&lt;/td&gt;
					&lt;td&gt;conntrack 满、DNS 慢、TIME_WAIT 耗尽&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ss -s&lt;/code&gt;、CoreDNS 日志、查连接池配置&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;滚动更新后 502&lt;/td&gt;
					&lt;td&gt;没配 readinessProbe / 没处理 SIGTERM 优雅退出&lt;/td&gt;
					&lt;td&gt;配探针 + preStop + 应用优雅关闭&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;ConfigMap 改了不生效&lt;/td&gt;
					&lt;td&gt;环境变量注入 / subPath 挂载&lt;/td&gt;
					&lt;td&gt;重启 Pod 或改为目录挂载&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;跨可用区挂载失败&lt;/td&gt;
					&lt;td&gt;云盘和节点不在同一 AZ&lt;/td&gt;
					&lt;td&gt;WaitForFirstConsumer + 拓扑约束&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;113-优雅退出滚动更新不断流的完整姿势&#34;&gt;11.3 优雅退出：滚动更新不断流的完整姿势&lt;/h3&gt;
&lt;p&gt;Pod 被删除时的标准流程（很多人只知道一半）：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant K as kubelet
    participant P as Pod
    participant EP as Endpoints

    K-&amp;gt;&amp;gt;EP: 把 Pod 从 Service 摘除（不再接新流量）
    K-&amp;gt;&amp;gt;P: 执行 preStop 钩子（如 sleep 5，等摘流量生效）
    K-&amp;gt;&amp;gt;P: 发送 SIGTERM
    P-&amp;gt;&amp;gt;P: 应用应：停止接新请求，处理完存量请求后退出
    Note over K,P: 超过 terminationGracePeriodSeconds（默认30s）
    K-&amp;gt;&amp;gt;P: SIGKILL 强杀&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三个缺一不可：readinessProbe 保证新 Pod ready 才切流量；preStop/优雅关闭保证老 Pod 处理完存量请求；&lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; 给够时间。Java/Go 服务请确认框架注册了 SIGTERM 处理器（Spring Boot 的 &lt;code&gt;server.shutdown=graceful&lt;/code&gt;、Go 的 &lt;code&gt;signal.Notify&lt;/code&gt;）。&lt;/p&gt;
&lt;h3 id=&#34;114-kubectl-排障速查&#34;&gt;11.4 kubectl 排障速查&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl get pods -o wide -n &amp;lt;ns&amp;gt;          &lt;span style=&#34;color:#75715e&#34;&gt;# 看状态和所在节点&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl describe pod &amp;lt;pod&amp;gt; -n &amp;lt;ns&amp;gt;        &lt;span style=&#34;color:#75715e&#34;&gt;# 看 Events（排障第一步）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl logs &amp;lt;pod&amp;gt; -c &amp;lt;container&amp;gt; --previous   &lt;span style=&#34;color:#75715e&#34;&gt;# 崩溃前的日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl get endpoints &amp;lt;svc&amp;gt; -n &amp;lt;ns&amp;gt;       &lt;span style=&#34;color:#75715e&#34;&gt;# Service 后面到底有没有 Pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl exec -it &amp;lt;pod&amp;gt; -- sh              &lt;span style=&#34;color:#75715e&#34;&gt;# 进容器内验证网络&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl run debug --rm -it --image&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;busybox:1.36 -- sh   &lt;span style=&#34;color:#75715e&#34;&gt;# 临时网络调试 Pod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl top pod / kubectl top node        &lt;span style=&#34;color:#75715e&#34;&gt;# 资源占用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;kubectl get events --sort-by&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;.lastTimestamp -n &amp;lt;ns&amp;gt;     &lt;span style=&#34;color:#75715e&#34;&gt;# 按时间看事件&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;hr&gt;
&lt;h2 id=&#34;十二cicdjenkins-与-k8s-打通实现自动化部署与验证&#34;&gt;十二、CI/CD：Jenkins 与 K8s 打通，实现自动化部署与验证&lt;/h2&gt;
&lt;p&gt;手工 &lt;code&gt;kubectl apply&lt;/code&gt; 只适合学习。生产环境的标准做法是把「构建 → 推镜像 → 部署 → 验证 → 失败回滚」串成流水线，代码合并后自动完成发布。&lt;/p&gt;
&lt;h3 id=&#34;121-整体流水线长什么样&#34;&gt;12.1 整体流水线长什么样&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    Dev[开发者 git push] --&amp;gt; Hook[Webhook 触发 Jenkins]
    Hook --&amp;gt; Build[阶段1: 构建&amp;lt;br/&amp;gt;单测 + Docker 镜像]
    Build --&amp;gt; Push[阶段2: 推送镜像&amp;lt;br/&amp;gt;到 ACR/ECR&amp;lt;br/&amp;gt;tag = git commit]
    Push --&amp;gt; Deploy[阶段3: 部署&amp;lt;br/&amp;gt;kubectl set image&amp;lt;br/&amp;gt;更新 K8s]
    Deploy --&amp;gt; Verify[阶段4: 验证&amp;lt;br/&amp;gt;rollout status + 冒烟测试]
    Verify --&amp;gt;|成功| Done[发布完成&amp;lt;br/&amp;gt;钉钉/邮件通知]
    Verify --&amp;gt;|失败| RB[自动回滚&amp;lt;br/&amp;gt;rollout undo] --&amp;gt; Alarm[告警通知]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;关键认知：&lt;strong&gt;K8s 侧不需要装任何 Jenkins 插件或 Agent 也能被部署&lt;/strong&gt;——Jenkins 只要有目标集群的 kubeconfig（访问凭证），用 &lt;code&gt;kubectl&lt;/code&gt; 就能驱动 apiserver 完成一切。打通的本质就两件事：凭证怎么管、流水线脚本怎么写。&lt;/p&gt;
&lt;h3 id=&#34;122-jenkins-的两种部署形态&#34;&gt;12.2 Jenkins 的两种部署形态&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;形态&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;适用&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Jenkins 在集群外（独立服务器/另一集群）&lt;/td&gt;
					&lt;td&gt;通过 kubeconfig 远程操作业务集群&lt;/td&gt;
					&lt;td&gt;一套 Jenkins 管多个集群，最常见&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Jenkins 跑在 K8s 集群内&lt;/td&gt;
					&lt;td&gt;配合 Kubernetes 插件，每次构建动态拉起一个 Pod 作为构建 agent，用完即销毁&lt;/td&gt;
					&lt;td&gt;构建任务多、想弹性利用集群资源&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TB
    subgraph Jenkins侧[&amp;#34;Jenkins（集群外或集群内）&amp;#34;]
        J[Jenkins Master]
        C1[凭据1: kubeconfig&amp;lt;br/&amp;gt;Secret file 类型]
        C2[凭据2: ACR 账号&amp;lt;br/&amp;gt;Username/Password 类型]
        J --&amp;gt; C1
        J --&amp;gt; C2
    end
    subgraph 阿里云[&amp;#34;阿里云&amp;#34;]
        J --&amp;gt;|docker push| ACR[ACR 镜像仓库]
        J --&amp;gt;|&amp;#34;kubectl（走内网 API Server 端点）&amp;#34;| API[ACK apiserver]
        API --&amp;gt; Pod[滚动更新业务 Pod]
        Pod --&amp;gt;|免密拉取| ACR
    end&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;推荐做法：Jenkins 与 ACK 在&lt;strong&gt;同一 VPC 内&lt;/strong&gt;，kubectl 直接走 API Server 的&lt;strong&gt;内网端点&lt;/strong&gt;（安全且免公网流量）；镜像仓库用 ACR 企业版 + ACK 免密拉取，业务侧零凭证。&lt;/p&gt;
&lt;h3 id=&#34;123-最小权限的部署凭证别把-admin-kubeconfig-给-jenkins&#34;&gt;12.3 最小权限的部署凭证：别把 admin kubeconfig 给 Jenkins&lt;/h3&gt;
&lt;p&gt;这是 CI/CD 安全的第一课。给 Jenkins 一个&lt;strong&gt;只能操作特定 namespace、只能改 Deployment&lt;/strong&gt; 的 ServiceAccount：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ServiceAccount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;jenkins-deployer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Role 只在 prod namespace 内生效&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Role&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deployer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;rules&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;apiGroups&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;apps&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;resources&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;deployments&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;verbs&lt;/span&gt;: [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;get&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;list&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;watch&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;patch&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;update&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;apiVersion&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;RoleBinding&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;jenkins-deployer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;subjects&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ServiceAccount&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;jenkins-deployer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;prod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;roleRef&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;kind&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Role&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deployer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;apiGroup&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;rbac.authorization.k8s.io&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;然后为这个 SA 生成 token，做成只含该 token 的 kubeconfig，存进 Jenkins 的 &lt;strong&gt;Secret file 凭据&lt;/strong&gt;。好处：凭证泄露也只影响一个 namespace 的 Deployment，且可以随时 &lt;code&gt;kubectl delete rolebinding&lt;/code&gt; 吊销。&lt;/p&gt;
&lt;h3 id=&#34;124-完整-jenkinsfile-示例&#34;&gt;12.4 完整 Jenkinsfile 示例&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipeline &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    agent any
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    environment &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        IMAGE     &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;registry.cn-hangzhou.aliyuncs.com/mycompany/order-svc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        TAG       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${env.GIT_COMMIT.take(8)}&amp;#34;&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;// 用 git commit 做 tag，可回滚可追溯
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        KUBECONFIG &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; credentials&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ack-prod-kubeconfig&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;   &lt;span style=&#34;color:#75715e&#34;&gt;// Secret file 凭据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stages &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;构建&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;mvn -q test&amp;#39;&lt;/span&gt;                       &lt;span style=&#34;color:#75715e&#34;&gt;// 先跑单测，挂了直接终止
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;docker build -t ${IMAGE}:${TAG} .&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;推送镜像&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                withCredentials&lt;span style=&#34;color:#f92672&#34;&gt;([&lt;/span&gt;usernamePassword&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    credentialsId: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;acr-account&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    usernameVariable: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;U&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;,&lt;/span&gt; passwordVariable: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;P&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)])&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;echo $P | docker login registry.cn-hangzhou.aliyuncs.com -u $U --password-stdin&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;docker push ${IMAGE}:${TAG}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;部署到 ACK&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;kubectl --kubeconfig=$KUBECONFIG -n prod \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                    set image deployment/order-svc order-svc=${IMAGE}:${TAG}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        stage&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;验证&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            steps &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#75715e&#34;&gt;// 阻塞等待滚动更新完成；超时/失败会非零退出
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;kubectl --kubeconfig=$KUBECONFIG -n prod \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                    rollout status deployment/order-svc --timeout=300s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#75715e&#34;&gt;// 冒烟测试：走内网 SLB 打健康检查和关键接口
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;curl -fsS --retry 5 --retry-delay 3 \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                    http://order-svc-internal.prod.svc.cluster.local/healthz || exit 1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    post &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        failure &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// 部署验证失败自动回滚到上一个版本
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            sh &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;kubectl --kubeconfig=$KUBECONFIG -n prod \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;                rollout undo deployment/order-svc || true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;125-验证环节的正确姿势&#34;&gt;12.5 「验证」环节的正确姿势&lt;/h3&gt;
&lt;p&gt;很多流水线只做到 &lt;code&gt;kubectl apply&lt;/code&gt; 就算「发布成功」，这是自欺欺人。&lt;code&gt;apply&lt;/code&gt; 返回成功只代表 apiserver 收下了 YAML，Pod 起不起得来是另一回事。可靠的验证链：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;rollout status 阻塞等待&lt;/strong&gt;：确认所有新副本 ready（背后靠的就是 readinessProbe——再次体现探针的重要性）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;冒烟测试&lt;/strong&gt;：对真实入口打 &lt;code&gt;/healthz&lt;/code&gt; 和一两个核心业务接口，确认「能起来」且「能干活」。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失败自动回滚&lt;/strong&gt;：&lt;code&gt;rollout undo&lt;/code&gt; 依赖旧 ReplicaSet 还在（&lt;code&gt;revisionHistoryLimit&lt;/code&gt; 别设 0）且镜像 tag 可追溯——这就是前面说「不要用 latest」的根本原因。&lt;/li&gt;
&lt;li&gt;更严谨的做法是&lt;strong&gt;灰度验证&lt;/strong&gt;：先用 Istio 把 5% 流量切到新版本观察指标，确认无误再全量（见第九章）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;126-cicd-避坑清单&#34;&gt;12.6 CI/CD 避坑清单&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;镜像 tag 必须唯一可追溯&lt;/strong&gt;：git commit 短哈希或构建号，杜绝 &lt;code&gt;latest&lt;/code&gt;，否则回滚时根本不知道该回滚到哪个镜像。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;凭据最小化 + 分环境&lt;/strong&gt;：dev/staging/prod 用不同的 SA 和 Jenkins 凭据，prod 的部署动作加人工审批（Jenkins 的 &lt;code&gt;input&lt;/code&gt; 步骤）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;声明式优先&lt;/strong&gt;：服务变多后，把 &lt;code&gt;kubectl set image&lt;/code&gt; 换成 Helm/Kustomize（YAML 也进 Git 仓库，可审计可 diff）；再进一步上 &lt;strong&gt;GitOps（ArgoCD/Flux）&lt;/strong&gt;——Jenkins 只负责构建推镜像，部署由集群内的 ArgoCD 从 Git 仓库自动同步，Jenkins 不再需要生产集群的任何凭证，安全性大幅提升。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jenkins 到集群的网络&lt;/strong&gt;：kubectl 走内网 API Server 端点；如果 Jenkins 在另一个 VPC，用云企业网/对等连接打通，不要把 API Server 暴露公网给 Jenkins 用。&lt;/li&gt;
&lt;li&gt;构建产物（镜像）与部署配置分离管理，避免「同一个 tag 被覆盖推送」导致回滚失效——ACR 里给 prod 仓库开&lt;strong&gt;镜像 tag 不可变&lt;/strong&gt;（immutable）开关。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十三学习路线建议&#34;&gt;十三、学习路线建议&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;第一周&lt;/strong&gt;：本地装 minikube 或 kind，把 Deployment/Service/ConfigMap 各玩一遍，亲手制造一次 CrashLoopBackOff 并修好它。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第二周&lt;/strong&gt;：搞懂网络——Pod 网络、Service 转发（iptables）、Ingress、NetworkPolicy 内外网隔离，配合 &lt;code&gt;tcpdump&lt;/code&gt;/&lt;code&gt;ss&lt;/code&gt; 在容器里抓包看真实流量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第三周&lt;/strong&gt;：上云。开一套阿里云 ACK（按量付费，玩完就删），跑通「ACR 推镜像 → ACK 部署 → ALB Ingress 暴露 → NAS 挂共享盘 → SLS 看日志」全流程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第四周&lt;/strong&gt;：打通 CI/CD。用 Jenkins + 最小权限 SA 实现「推代码 → 自动构建 → 自动部署 → rollout 验证 → 失败回滚」完整流水线。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;进阶&lt;/strong&gt;：Helm 包管理、HPA 自动扩缩容、Istio 灰度发布、GitOps（ArgoCD）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后送一句《Kubernetes 权威指南》反复强调的心法：&lt;strong&gt;K8s 的一切都是声明式的——你描述「我要什么」，控制器负责「做到」&lt;/strong&gt;。排查问题时永远先问：期望状态（YAML/Spec）是什么？实际状态（Status/Events）是什么？两者的差距就是答案所在。&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;参考资料：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;《Kubernetes 权威指南：从 Docker 到 Kubernetes 实践全接触（第 4 版）》龚正 等&lt;/li&gt;
&lt;li&gt;《Kubernetes in Action》Marko Lukša&lt;/li&gt;
&lt;li&gt;《Unix 网络编程 卷1》W. Richard Stevens（网络排障内功）&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://kubernetes.io/zh-cn/docs/&#34;&gt;Kubernetes 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://help.aliyun.com/product/85222.html&#34;&gt;阿里云 ACK 文档&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
</description>
    </item>
    <item>
      <title>Google SRE 工作手册详细总结：写给从未接触过 SRE 的人</title>
      <link>https://ftmao.com/blog/bookstore/google-sre-workbook-summary/</link>
      <pubDate>Tue, 26 Oct 2021 10:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/bookstore/google-sre-workbook-summary/</guid>
      <description>&lt;h1 id=&#34;google-sre-工作手册详细总结写给从未接触过-sre-的人&#34;&gt;Google SRE 工作手册详细总结：写给从未接触过 SRE 的人&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;参考书籍：Google SRE 团队《The Site Reliability Workbook》（《SRE 工作手册》，2018）
目标读者：第一次听说 &amp;ldquo;SRE&amp;rdquo; 这个词，想知道它到底是什么、解决什么问题、能不能用在自己团队的人。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;这本书是什么&#34;&gt;〇、这本书是什么？&lt;/h2&gt;
&lt;p&gt;Google 在 2016 年出版了《Site Reliability Engineering》（第一本 SRE 书），讲的是 &lt;strong&gt;SRE 的原理&lt;/strong&gt;——Google 是怎么想的。2018 年这本《Workbook》（工作手册）是它的姊妹篇，讲的是 &lt;strong&gt;怎么落地&lt;/strong&gt;——两本书的章节基本一一对应（比如第一本书第 4 章&amp;quot;服务级别目标&amp;quot;对应本书第 2 章&amp;quot;实施 SLO&amp;quot;）。&lt;/p&gt;
&lt;p&gt;这本书最有价值的一点是：它故意收录了大量 &lt;strong&gt;Google 之外的公司&lt;/strong&gt; 的落地案例——Evernote、Home Depot（家得宝）、《纽约时报》、Spotify、Waze、PagerDuty——就是为了破除&amp;quot;SRE 只在 Google 那种规模和文化下才玩得转&amp;quot;的误解。全书由 100 多人贡献完成。&lt;/p&gt;
&lt;p&gt;用前言里 Mark Burgess 的话说，整本书可以浓缩成三句话：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;承诺：明确地设定服务的目标、期望和水平；&lt;/li&gt;
&lt;li&gt;评估：根据指标和预算约束持续评估这些承诺；&lt;/li&gt;
&lt;li&gt;反应：快速做出反应以兑现承诺。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;一sre-到底是什么和-devops-什么关系&#34;&gt;一、SRE 到底是什么？和 DevOps 什么关系？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;SRE = Site Reliability Engineering，网站可靠性工程&lt;/strong&gt;。这个词由 Google 工程副总裁 Ben Treynor Sloss 创造。一句话概括：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SRE 就是让软件工程师去做运维团队的工作&lt;/strong&gt;——&amp;ldquo;运维是一个软件问题&amp;rdquo;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;传统模式里，开发团队（追求快速出新功能）和运维团队（追求稳定别出事）天然对立：开发想&amp;quot;快发&amp;quot;，运维想&amp;quot;别动&amp;quot;。SRE 用一套&lt;strong&gt;量化的工程方法&lt;/strong&gt;消解这个矛盾，而不是靠开会吵架。&lt;/p&gt;
&lt;p&gt;那它和 DevOps 是什么关系？第 1 章的标题本身就是一行代码，堪称全书最著名的梗：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SRE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; DevOps&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;DevOps 是一套文化和哲学，SRE 是它的一种具体实现&lt;/strong&gt;——就像极限编程（XP）是敏捷（Agile）的一种具体实现。Puppet 前 VP Andrew Clay Shafer 在前言里甚至说：如果第一本 SRE 书早几年出版，社区会团结在&amp;quot;消除琐事&amp;quot;的旗帜下，&amp;ldquo;DevOps&amp;quot;这个词可能根本不会存在。&lt;/p&gt;
&lt;p&gt;DevOps 的五个关键思想与 SRE 的对应实现：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;DevOps 思想&lt;/th&gt;
					&lt;th&gt;SRE 的具体做法&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;不再有孤岛&lt;/td&gt;
					&lt;td&gt;SRE 与开发共享所有权、用相同的工具&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;事故是正常的，指责无用&lt;/td&gt;
					&lt;td&gt;对事不对人的事后总结（blameless postmortem）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;变更应该小步快跑&lt;/td&gt;
					&lt;td&gt;金丝雀发布、CI/CD、降低失败成本（MTTR）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;工具和文化相互关联&lt;/td&gt;
					&lt;td&gt;统一的工具链本身就是文化载体&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;度量至关重要&lt;/td&gt;
					&lt;td&gt;SLI / SLO / 错误预算&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;SRE 的七条核心原则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;运维是一个软件问题&lt;/strong&gt;——用写代码的方式消灭重复劳动；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;按 SLO 管理&lt;/strong&gt;——不追求 100% 可用性（为什么，下面细讲）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;努力减少琐事（toil）&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动化今年的工作&lt;/strong&gt;——Google 硬性规定 SRE 花在琐事上的时间不超过 50%，而且要把它当成&amp;quot;保证&amp;quot;而不是&amp;quot;上限&amp;rdquo;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通过降低失败成本来加快开发速度&lt;/strong&gt;——恢复快（MTTR 低）比不出事更重要；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;与开发者共享所有权&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无论头衔如何，都使用相同的工具&lt;/strong&gt;。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这里有一个值得记住的反面案例：2017 年 5 月英国航空大停运，被书中引为&amp;quot;把运维当成本中心拼命压缩&amp;quot;的失败典型——一场大事故抵消了低成本运营省下的所有钱。&lt;/p&gt;
&lt;h2 id=&#34;二全书的地基slislosla-和错误预算&#34;&gt;二、全书的地基：SLI、SLO、SLA 和错误预算&lt;/h2&gt;
&lt;p&gt;第 2 章被作者称为&amp;quot;本书最重要的章节&amp;quot;，金句是：&lt;strong&gt;&amp;ldquo;没有 SLO，就不需要 SRE&amp;rdquo;&lt;/strong&gt;。这一节是全书的地基，务必看懂。&lt;/p&gt;
&lt;h3 id=&#34;21-三个容易混淆的概念&#34;&gt;2.1 三个容易混淆的概念&lt;/h3&gt;
&lt;p&gt;用一个&amp;quot;外卖小哥&amp;quot;的比喻：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SLI（Service Level Indicator，服务级别指标）&lt;/strong&gt;：你实际测出来的数字。比如&amp;quot;过去 30 天，99.2% 的外卖在 40 分钟内送达&amp;quot;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SLO（Service Level Objective，服务级别目标）&lt;/strong&gt;：你给自己定的目标。比如&amp;quot;我们承诺 99% 的订单 40 分钟内送达&amp;quot;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SLA（Service Level Agreement，服务级别协议）&lt;/strong&gt;：和客户签的、&lt;strong&gt;违约要赔钱&lt;/strong&gt;的商业合同。通常比 SLO 宽松，SLO 是内部&amp;quot;提前预警线&amp;quot;，SLA 是&amp;quot;最后底线&amp;quot;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;工程上的标准写法：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;SLI = 好事件数 / 总事件数        （0% ~ 100% 之间）
错误预算 = 100% − SLO&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;错误预算（Error Budget）&lt;/strong&gt; 是全书最重要的发明。它的逻辑是：既然 100% 不可靠也不必要，那么&amp;quot;允许出错的额度&amp;quot;就是一种&lt;strong&gt;可以花掉的预算&lt;/strong&gt;——你可以用它来快速发布新功能、做架构实验；预算花光了，就冻结发布，全员回头修可靠性。开发和运维的矛盾，从&amp;quot;立场之争&amp;quot;变成了&amp;quot;看数据说话&amp;quot;。&lt;/p&gt;
&lt;h3 id=&#34;22-为什么不追求-100-可用性&#34;&gt;2.2 为什么不追求 100% 可用性？&lt;/h3&gt;
&lt;p&gt;书中给了四个理由：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;组件同时故障的概率永远不为零，100% 在数学上就做不到；&lt;/li&gt;
&lt;li&gt;用户访问你的服务要经过很长的链路（手机 → 运营商 → 公网 → 机房），你把可用性从 99.9% 提到 99.99%，用户的实际体验提升微乎其微——边际效用递减；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;100% 意味着你不能做任何变更&lt;/strong&gt;，而变更是功能迭代的前提；&lt;/li&gt;
&lt;li&gt;100% 的 SLO 只是&amp;quot;运维团队的 SLO&amp;quot;，不是一种工程文化。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;还有一个很直观的乘法效应：如果你的服务依赖 9 个可用性 99.99% 的关键上游，你的总可用性 ≈ 0.9999¹⁰ ≈ &lt;strong&gt;99.9%&lt;/strong&gt;——4 个 9 直接掉到 3 个 9。第 19 章还有一个更扎心的数字：客户在 99.999% 的平台上自己只做到 99%，最终用户感受到的是 99% × 99.999% = &lt;strong&gt;98.99901%&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;23-一个完整的例子手机游戏后端&#34;&gt;2.3 一个完整的例子：手机游戏后端&lt;/h3&gt;
&lt;p&gt;第 2 章用一个手机游戏案例贯穿始终，非常适合入门者理解。架构如下：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph LR
    A[&amp;#34;📱 手机 App&amp;#34;] --&amp;gt; B[&amp;#34;HTTP API 服务&amp;#34;]
    B --&amp;gt; C[(&amp;#34;永久存储&amp;lt;br/&amp;gt;游戏状态/排行榜&amp;#34;)]
    A --&amp;gt; D[(&amp;#34;用户数据存储&amp;lt;br/&amp;gt;头像等&amp;#34;)]
    C --&amp;gt; E[&amp;#34;⏰ 定时管道&amp;lt;br/&amp;gt;生成今日/本周/历史排行榜&amp;#34;]
    E --&amp;gt; F[(&amp;#34;排行榜数据存储&amp;#34;)]
    G[&amp;#34;🌐 网站&amp;#34;] --&amp;gt; F&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;先量现状：过去 4 周 API 总请求 3,663,253 次，成功 3,557,865 次（可用性 97.123%），P90 延迟 432ms，P99 延迟 891ms。据此定出&lt;strong&gt;入门级 SLO&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可用性：97% 请求成功&lt;/li&gt;
&lt;li&gt;延迟：90% 请求 &amp;lt; 450ms，99% 请求 &amp;lt; 900ms&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对应的错误预算：每四周允许失败约 109,897 个请求。&lt;/p&gt;
&lt;p&gt;然后看两个真实事故的&amp;quot;预算消耗&amp;quot;对比，这是全书最有说服力的算账方式：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;事故&lt;/th&gt;
					&lt;th&gt;错误数&lt;/th&gt;
					&lt;th&gt;消耗预算&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;一次坏发布，NullPointerException 持续 4 小时&lt;/td&gt;
					&lt;td&gt;14,066&lt;/td&gt;
					&lt;td&gt;13%&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;唯一的状态数据库故障，从备份恢复花了 20 小时&lt;/td&gt;
					&lt;td&gt;~72,000&lt;/td&gt;
					&lt;td&gt;65%&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;结论很反直觉：&lt;strong&gt;五年只发生一次的数据库故障，远没有每年 2~3 次的坏发布值得投入&lt;/strong&gt;——改进发布流程的优先级应该高于调查服务器故障。这就是错误预算的意义：它把&amp;quot;该把工程资源投到哪&amp;quot;从拍脑袋变成了算术题。&lt;/p&gt;
&lt;h3 id=&#34;24-落地-slo-的完整流程&#34;&gt;2.4 落地 SLO 的完整流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[&amp;#34;绘制服务架构图&amp;#34;] --&amp;gt; B[&amp;#34;组件分类：&amp;lt;br/&amp;gt;请求驱动 / 管道 / 存储&amp;#34;]
    B --&amp;gt; C[&amp;#34;为每类组件选 SLI 规范&amp;lt;br/&amp;gt;（不超过 5 种）&amp;#34;]
    C --&amp;gt; D[&amp;#34;选择 SLI 实现方式&amp;lt;br/&amp;gt;（日志 → 探针 → 客户端插桩，精度递增）&amp;#34;]
    D --&amp;gt; E[&amp;#34;基于历史数据定初始 SLO&amp;#34;]
    E --&amp;gt; F{&amp;#34;三方达成一致？&amp;lt;br/&amp;gt;产品：对用户够用&amp;lt;br/&amp;gt;开发：预算耗尽愿意行动&amp;lt;br/&amp;gt;SRE：不靠英雄主义守得住&amp;#34;}
    F -- 否 --&amp;gt; E
    F -- 是 --&amp;gt; G[&amp;#34;白纸黑字写错误预算政策&amp;lt;br/&amp;gt;（预算耗尽怎么办）&amp;#34;]
    G --&amp;gt; H[&amp;#34;监控 + 告警上线&amp;#34;]
    H --&amp;gt; I[&amp;#34;定期审查迭代 SLO&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三类组件各自推荐的 SLI：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;请求驱动型&lt;/strong&gt;（API 服务）：可用性、延迟、品质；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;管道/流水线型&lt;/strong&gt;（数据处理）：新鲜度、正确性、覆盖范围；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存储型&lt;/strong&gt;：耐用性（数据丢不丢）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;错误预算政策里要事先写清楚&amp;quot;预算耗尽怎么办&amp;quot;：可靠性 bug 最优先、冻结生产变更（P0 问题和安全补丁除外），极端时宣布&amp;quot;紧急状态&amp;quot;，直到服务回到 SLO 以内。附录 B 还有一个值得抄的细节：&lt;strong&gt;单个事件消耗超过四周预算的 20% → 必须做事后调查，且至少包含一个 P0 行动项；对错误预算计算有分歧 → 上报 CTO 裁决&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&#34;三非-google-公司怎么落地两个完整案例&#34;&gt;三、非 Google 公司怎么落地？两个完整案例&lt;/h2&gt;
&lt;h3 id=&#34;31-evernote和云厂商打破-slo-的墙&#34;&gt;3.1 Evernote：和云厂商&amp;quot;打破 SLO 的墙&amp;quot;&lt;/h3&gt;
&lt;p&gt;背景：全球 2.2 亿用户、存储 120 亿条信息、750+ 个 MySQL 实例，从自建数据中心迁往 GCP。传统&amp;quot;开发 vs 运维&amp;quot;两种模式（&amp;ldquo;you build it, you run it&amp;rdquo; 和 &amp;ldquo;you build it, we run it&amp;rdquo;）都试过了，都不满意，于是在 Google CRE（客户可靠性工程）团队帮助下落地 SLO。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;首版 SLO：按月窗口、99.95% 正常运行时间；用第三方探针 Pingdom 每分钟轮询，需两个地理独立的探针连续失败才算&amp;quot;停机&amp;quot;；&lt;strong&gt;维护窗口也算停机&lt;/strong&gt;（用户不知情就是不可用）；&lt;/li&gt;
&lt;li&gt;治理节奏：每月与 Google 团队审查一次 SLO，每 6 个月修订一次，9 个月迭代了 3 版；指导原则是&amp;quot;&lt;strong&gt;完美是良好的敌人&lt;/strong&gt;&amp;quot;——先有再优；&lt;/li&gt;
&lt;li&gt;一个漂亮的故事：2017 年讨论是否压缩发布窗口时，双方用 SLO 计算把发布窗口从 5 个减到 2 个，&lt;strong&gt;量化了客户影响，消除了主观争论&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;最创新的一点：与 Google 共享实时 SLO 仪表板。于是 Google 的告警从泛泛的&amp;quot;GCP 负载均衡今天有点慢&amp;quot;变成&amp;quot;该问题影响 Evernote SLO 的 5%&amp;quot;，重大事件双方作为联合 P1 故障单处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;32-home-depot家得宝传统企业的规模化推广&#34;&gt;3.2 Home Depot（家得宝）：传统企业的规模化推广&lt;/h3&gt;
&lt;p&gt;背景：北美 2,200+ 门店、近 40 万员工、每年 15 亿+ 交易——证明 SRE 不是互联网公司专利。&lt;/p&gt;
&lt;p&gt;他们发明了 &lt;strong&gt;VALET 框架&lt;/strong&gt;（呼应 Google 的四大黄金信号，连批处理系统都能套用）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;V&lt;/strong&gt;olume 容量（流量/处理记录数）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A&lt;/strong&gt;vailability 可用性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L&lt;/strong&gt;atency 延迟&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;E&lt;/strong&gt;rrors 错误&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;T&lt;/strong&gt;ickets 故障单（人工介入次数）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;推广靠四板斧：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    subgraph 推广四支柱
        A[&amp;#34;通用语言&amp;lt;br/&amp;gt;VALET 缩写，人人会说&amp;#34;]
        B[&amp;#34;布道&amp;lt;br/&amp;gt;内部博客/路演/T恤贴纸&amp;lt;br/&amp;gt;FiRE 学院培训&amp;#34;]
        C[&amp;#34;自动化&amp;lt;br/&amp;gt;TPS Report 自动采集指标&amp;lt;br/&amp;gt;VALET 仪表板 + 聊天机器人&amp;#34;]
        D[&amp;#34;激励&amp;lt;br/&amp;gt;SLO 纳入开发经理年度目标&amp;#34;]
    end
    A &amp;amp; B &amp;amp; C &amp;amp; D --&amp;gt; E[&amp;#34;一年从 0 到 800 个服务&amp;lt;br/&amp;gt;每月新增约 50 个&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;给产品经理的简化分级表也很实用：99.5% = MVP/内部工具；99.9% = 大多数非销售系统；99.95% = 销售系统；99.99% = 共享基础设施。他们的原话值得引用：&amp;ldquo;我们是一家传统企业；如果我们能成功引入这么大的变化，您也可以。&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;四监控与告警在预算烧光之前叫醒你&#34;&gt;四、监控与告警：在预算烧光之前叫醒你&lt;/h2&gt;
&lt;h3 id=&#34;41-监控的基本盘&#34;&gt;4.1 监控的基本盘&lt;/h3&gt;
&lt;p&gt;监控的五大用途：告警、诊断、可视化、长期趋势/容量规划、变更前后对比。&lt;strong&gt;指标和日志要分工&lt;/strong&gt;：指标近实时但粒度低（告警、仪表板用它），日志有延迟但精确（根因分析用它）。数据新鲜度很关键——超过 4~5 分钟的失效数据会严重影响事件响应。&lt;/p&gt;
&lt;p&gt;现代监控栈是松散耦合的：Prometheus（采集/规则）→ InfluxDB（长期存储）→ Alertmanager（告警聚合）→ Grafana（仪表板）。&lt;/p&gt;
&lt;h3 id=&#34;42-告警的正确姿势盯着错误预算的消耗率&#34;&gt;4.2 告警的正确姿势：盯着错误预算的&amp;quot;消耗率&amp;quot;&lt;/h3&gt;
&lt;p&gt;新手最常见的告警写法是&amp;quot;错误率超过 X% 就报警&amp;quot;，书第 5 章用一整章论证这有多糟糕，并给出了演进路径：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    M1[&amp;#34;方法1：错误率≥SLO 就告警&amp;lt;br/&amp;gt;❌ 太敏感：10 分钟 0.1% 错误率就告警&amp;lt;br/&amp;gt;实际只消耗月预算 0.02%，每天可收 144 条&amp;#34;]
    M2[&amp;#34;方法2：加大告警窗口&amp;lt;br/&amp;gt;❌ 检测太慢，大事故发现太晚&amp;#34;]
    M3[&amp;#34;方法3：加持续时间参数 for:1h&amp;lt;br/&amp;gt;❌ 每 10 分钟一次 5 分钟的 100% 错误尖峰&amp;lt;br/&amp;gt;累计烧掉 35% 预算却永不触发&amp;#34;]
    M4[&amp;#34;方法4：按消耗率 burn rate 告警&amp;lt;br/&amp;gt;⚠️ 进步明显，但重置时间长&amp;#34;]
    M5[&amp;#34;方法5：多消耗率分档&amp;lt;br/&amp;gt;⚠️ 快烧/慢烧分开告警&amp;#34;]
    M6[&amp;#34;方法6：多窗口多消耗率 ✅&amp;lt;br/&amp;gt;长窗保证精确度，短窗保证灵敏度&amp;#34;]
    M1 --&amp;gt; M2 --&amp;gt; M3 --&amp;gt; M4 --&amp;gt; M5 --&amp;gt; M6&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;消耗率（burn rate）&lt;/strong&gt; = 当前错误率相对 SLO 允许错误率的倍数。对照表（99.9% SLO，30 天窗口）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;消耗率&lt;/th&gt;
					&lt;th&gt;错误率&lt;/th&gt;
					&lt;th&gt;耗尽预算需时&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;0.1%&lt;/td&gt;
					&lt;td&gt;30 天&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;10&lt;/td&gt;
					&lt;td&gt;1%&lt;/td&gt;
					&lt;td&gt;3 天&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;1000&lt;/td&gt;
					&lt;td&gt;100%&lt;/td&gt;
					&lt;td&gt;43 分钟&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;最终推荐的&amp;quot;多窗口多消耗率&amp;quot;参数（针对 99.9% SLO，可直接抄）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;呼叫值班（紧急）&lt;/strong&gt;：1 小时长窗 + 5 分钟短窗，消耗率 14.4（约 2% 预算/小时）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;呼叫值班（次紧急）&lt;/strong&gt;：6 小时 + 30 分钟，消耗率 6&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工单（不紧急）&lt;/strong&gt;：3 天 + 6 小时，消耗率 1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;短窗口取长窗口的 1/12。两个极端情况的提醒：低流量服务（每小时 10 个请求时，1 个失败就是 10% 错误率）要合并请求或拉长时间窗；99.999% 的服务 100% 中断 &lt;strong&gt;26 秒&lt;/strong&gt;就耗尽预算——比大多数监控采集间隔还短，只能靠自愈。&lt;/p&gt;
&lt;h2 id=&#34;五消除琐事toilsre-的时间去哪了&#34;&gt;五、消除琐事（Toil）：SRE 的时间去哪了&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;琐事（toil）&lt;/strong&gt; 的六大特征：手动、重复、可自动化、被动应对、无持久价值、随服务规模线性增长。Google 规定 SRE 花在琐事上的时间不超过 50%，保证至少一半时间做&amp;quot;让明天比今天更好&amp;quot;的工程。&lt;/p&gt;
&lt;p&gt;书中几个精彩案例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;John Looney 修内核&lt;/strong&gt;：2005 年他入职 Google 时的活儿是修坏机器——任何时候都有超过 20,000 台坏机器。发现大量机器是日志把根分区填满，他本想写个脚本&amp;quot;截断大日志 + 重启 syslog&amp;quot;了事，被队友拦下要求修根因。最终他向 Linux 内核提交补丁，并用&amp;quot;这个问题导致 Google 每小时损失约 1000 美元&amp;quot;的成本分析说服了内核团队。&lt;strong&gt;修症状是琐事，修根因才是工程。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;不完美的自动化就够了&amp;rdquo;&lt;/strong&gt;：Google 数据中心网络维修自动化（Saturn/Jupiter 项目）中，内存错误诊断被过度分析了三年（收集了 650+ 个离散问题数据），后来发现多数错误是暂时性的，重启重装即可恢复——完美的自动化不值得，&amp;ldquo;足够好&amp;quot;的自动化先跑起来。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;ldquo;买下那个侏儒&amp;rdquo;&lt;/strong&gt;：早年 Froogle 搜索&amp;quot;跑鞋&amp;quot;会返回一个穿跑鞋的花园侏儒（eBay 商品），修不掉这个 bug，团队干脆在 eBay 上把侏儒买了下来。引申义：&lt;strong&gt;有时改变现实去适应代码，比反过来便宜。&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;遗留系统的四阶段处理路径：&lt;strong&gt;避免 → 封装/增强（高息技术债转低息）→ 替换/重构 → 退役/监护&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;与琐事相关的第 7 章&amp;quot;简单化&amp;quot;还有两个名案例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Borg vs Omega&lt;/strong&gt;：Omega 本想做成&amp;quot;更干净的 Borg&amp;quot;重写版，但 Borg 持续演进让 Omega 永远追不上移动的目标，迁移成本高到不可行。结局：Omega 的想法回流 Borg，概念最终催生了开源的 &lt;strong&gt;Kubernetes&lt;/strong&gt;。教训：重写前先算一算&amp;quot;同样的精力投入改进现有系统会怎样&amp;rdquo;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;pDNS 循环依赖&lt;/strong&gt;：客户端查服务 IP 依赖 Svelte，Svelte 依赖 pDNS，pDNS 的负载均衡器又依赖 Svelte——&amp;ldquo;我们就像洞穴居民，只能用上一次篝火点燃的火炬点火&amp;rdquo;（系统冷启动成为不可能）。解法：低级组件本地缓存关键 IP 列表，打破环路。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;六值班与事件响应像消防队一样打仗&#34;&gt;六、值班与事件响应：像消防队一样打仗&lt;/h2&gt;
&lt;h3 id=&#34;61-可持续的值班体系&#34;&gt;6.1 可持续的值班体系&lt;/h3&gt;
&lt;p&gt;关键数字：轮班不超过 12 小时；&lt;strong&gt;每 12 小时班次最多 2 个事件&lt;/strong&gt;（再多就处理不过来了）；多站点 24/7 值班每站点至少 5 人；保证 ≥50% 的时间留给项目工作。警惕&amp;quot;温水煮青蛙&amp;quot;式的运维过载——值班负载用 21 天移动平均来看趋势。&lt;/p&gt;
&lt;p&gt;Evernote 的事件分级很清爽：&lt;strong&gt;P1 立即处理&lt;/strong&gt;（呼叫值班、影响 SLO）、&lt;strong&gt;P2 下一工作日&lt;/strong&gt;（邮件通知）、&lt;strong&gt;P3 仅供参考&lt;/strong&gt;（只看仪表板）。&lt;/p&gt;
&lt;h3 id=&#34;62-事件指挥体系icsimag&#34;&gt;6.2 事件指挥体系（ICS/IMAG）&lt;/h3&gt;
&lt;p&gt;大规模事件的打法直接借用了消防系统：1968 年消防员为应对野火创建的&lt;strong&gt;事件指挥系统（ICS）&lt;/strong&gt;，Google 内部叫 IMAG。核心思想：混乱中最大的敌人不是故障本身，而是&amp;quot;谁说了算都不知道&amp;quot;。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    IC[&amp;#34;🎖️ 事件指挥官 IC&amp;lt;br/&amp;gt;总负责，做决策，默认承担未委派的角色&amp;#34;]
    CL[&amp;#34;📢 沟通主管 CL&amp;lt;br/&amp;gt;对用户/领导/媒体发通告&amp;#34;]
    OL[&amp;#34;🔧 运维主管 OL&amp;lt;br/&amp;gt;带领团队执行技术操作&amp;#34;]
    IC --&amp;gt; CL
    IC --&amp;gt; OL&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;事件管理围绕&amp;quot;三个 C&amp;quot;：&lt;strong&gt;Coordinate（协调）、Communicate（沟通）、Control（控制）&lt;/strong&gt;。四条基本原则：保持命令清晰、明确角色、实时记录、&lt;strong&gt;尽早且频繁地宣布事件&lt;/strong&gt;。行动顺序永远是&amp;quot;缓解优先&amp;quot;：评估影响 → 缓解影响 → 根因分析 → 修复与事后报告。&lt;/p&gt;
&lt;p&gt;三个真实案例，一正一反一个惊险：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;反例：Google Home/Assistant 事件（2017）&lt;/strong&gt;：一个 bug 让文件获取频率比预期高 50 倍，5 月 22 日就发现 QPS 异常，但误判了根因，而且&lt;strong&gt;在周六把灰度推到了 100%&lt;/strong&gt;（违反&amp;quot;首次上线仅在工作日&amp;quot;的铁律），用户丢了一半请求，靠开发者周末&amp;quot;英雄主义&amp;quot;硬扛。教训：没有尽早宣布事件、缓解后没定根因就继续推送。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;惊险：GKE CreateCluster 中断&lt;/strong&gt;：欧洲集群创建失败率超 60%，根因竟是从 DockerHub 拉取的一个镜像损坏（美国正常）。伦敦 SRE 6:41 被呼叫，9:10 才正式建立 IMAG 结构（太晚了），最后发现用现成的 GCR 镜像站点（&lt;code&gt;--registry-mirror=https://mirror.gcr.io&lt;/code&gt;）就能缓解——&lt;strong&gt;镜像其实早就就位了&lt;/strong&gt;。总中断 6 小时 40 分钟，41 人参与，事后报告列出 28 个行动项。最大教训：发现大致位置后就该先用&amp;quot;通用缓解&amp;quot;（回滚到已知良好状态），而不是继续深挖根因。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;正面：比利时数据中心雷击（2015）&lt;/strong&gt;：两分钟内 4 次雷击，UPS 电池在第 3、4 次雷击间隔太近时未能切换，磁盘托盘断电。事件指挥得当：IC 定了三个明确目标，沟通主管对四类受众（公司领导、依赖团队、外部客户、工单客户）分别通报。最终数据丢失仅 &lt;strong&gt;0.000001%&lt;/strong&gt;——管理良好的事件，损失可以极小。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;七事后总结文化从失败中学习&#34;&gt;七、事后总结文化：从失败中学习&lt;/h2&gt;
&lt;p&gt;SRE 文化的灵魂是&lt;strong&gt;对事不对人的事后总结（blameless postmortem）&lt;/strong&gt;。第 10 章用同一个真实事故的&amp;quot;坏版本&amp;quot;和&amp;quot;好版本&amp;quot;两版报告做对比，极其有教育意义。&lt;/p&gt;
&lt;p&gt;事故本身（2014-08-11，Google 卫星擦除事故）：Google 在托管机房部署的代理/缓存机架叫&amp;quot;卫星&amp;quot;。一次机架退役流程中，自动化中途失败，工程师手动重跑——重跑时 &lt;code&gt;GetMachines()&lt;/code&gt; 返回了空列表，而 API 有个 bug：&lt;strong&gt;空列表被当作&amp;quot;无过滤条件&amp;quot;，而不是&amp;quot;不操作任何机器&amp;quot;&lt;/strong&gt;。于是全球所有卫星机器在几分钟内被磁盘擦除。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[&amp;#34;机架退役自动化失败&amp;#34;] --&amp;gt; B[&amp;#34;工程师手动重跑流程&amp;#34;]
    B --&amp;gt; C[&amp;#34;GetMachines() 返回空列表&amp;#34;]
    C --&amp;gt; D[&amp;#34;API bug：空列表 = 无过滤条件&amp;lt;br/&amp;gt;（而不是不操作任何机器）&amp;#34;]
    D --&amp;gt; E[&amp;#34;全球所有卫星进入退役流程&amp;#34;]
    E --&amp;gt; F[&amp;#34;磁盘被全部擦除 💥&amp;#34;]
    F --&amp;gt; G[&amp;#34;边缘流量切到核心集群&amp;lt;br/&amp;gt;用户延迟上升约两天&amp;#34;]
    G -.-&amp;gt;|&amp;#34;容量规划良好，&amp;lt;br/&amp;gt;用户几乎无感知&amp;#34;| H[&amp;#34;几天后恢复&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;两版事后报告的对比：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;坏版本&lt;/th&gt;
					&lt;th&gt;好版本&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;发布时间&lt;/td&gt;
					&lt;td&gt;拖了 4 个月&lt;/td&gt;
					&lt;td&gt;4 天内（8/11 出事，8/15 发布）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;根本原因&lt;/td&gt;
					&lt;td&gt;&amp;ldquo;dylanfour@ 粗心大意忽略自动化&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;深入分析 API 语义缺陷与流程漏洞&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;行动项&lt;/td&gt;
					&lt;td&gt;全是 P2，措辞含糊（&amp;ldquo;使自动化更好&amp;rdquo;）&lt;/td&gt;
					&lt;td&gt;每项有唯一所有者、优先级、bug 号，含 P0 级&amp;quot;大红色按钮&amp;quot;（紧急停止开关）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;分享范围&lt;/td&gt;
					&lt;td&gt;团队小范围&lt;/td&gt;
					&lt;td&gt;全公司工程师&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;后续更有说服力：三年后类似事件重演，但第一次事后总结落实的行动项大幅缩小了爆炸半径。Google 运维副总裁 Ben Treynor Sloss 的原话：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;没有后续行动的事后总结等于没写事后总结。所有影响用户的停机事后总结必须至少关联一个 P0/P1 bug，例外由我亲自审批，例外极少。&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;事后总结文化崩塌的信号也要警惕：工程师回避参与、高管说指责性语言、没时间写、同类事故重复发生。&lt;/p&gt;
&lt;h2 id=&#34;八管理负载pokémon-go-的惊险一课&#34;&gt;八、管理负载：Pokémon GO 的惊险一课&lt;/h2&gt;
&lt;p&gt;Google 管理流量的三层工具：&lt;strong&gt;负载均衡 + 自动扩缩容 + 减载（load shedding）&lt;/strong&gt;。核心警告是：&lt;strong&gt;必须把它们当作一个整体系统设计，否则工具之间会形成灾难性的反馈回路。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;81-案例pokémon-go2016真实&#34;&gt;8.1 案例：Pokémon GO（2016，真实）&lt;/h3&gt;
&lt;p&gt;上线前按最乐观估计的 5 倍做了负载测试，实际流量是估计的近 &lt;strong&gt;50 倍&lt;/strong&gt;。随后发生的级联故障堪称教科书：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[&amp;#34;真实流量超预期 50 倍&amp;#34;] --&amp;gt; B[&amp;#34;Niantic 前端代理跟不上入站连接&amp;#34;]
    B --&amp;gt; C[&amp;#34;后端变慢但不拒绝请求&amp;#34;]
    C --&amp;gt; D[&amp;#34;负载均衡层自动重试 GET&amp;#34;]
    D --&amp;gt; E[&amp;#34;GFE 的 SSL 客户端代码被打到极限&amp;#34;]
    E --&amp;gt; F[&amp;#34;GCLB 全球容量实际下降 50% ⚠️&amp;#34;]
    C --&amp;gt; G[&amp;#34;客户端立即重试 + 固定退避&amp;lt;br/&amp;gt;错误时所有客户端同步重试（雷群）&amp;#34;]
    G --&amp;gt; H[&amp;#34;同步峰值达此前全球 RPS 峰值的 20 倍&amp;#34;]
    F &amp;amp; H --&amp;gt; I[&amp;#34;Google SRE 三步止血：&amp;lt;br/&amp;gt;①隔离 Pokémon GO 专用池 ②扩容 ③限流&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;事后双方各自改进：Niantic 给客户端加了&lt;strong&gt;抖动（jitter）+ 截断指数退避&lt;/strong&gt;；Google 学会把 GFE 后端当潜在负载源、建立准入负载测试。共同教训：&lt;strong&gt;尽可能靠近客户端测量负载&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&#34;82-案例dressy-减载反馈回路虚构但典型&#34;&gt;8.2 案例：Dressy 减载反馈回路（虚构但典型）&lt;/h3&gt;
&lt;p&gt;三区域部署，A 区流量上涨先触发减载（CPU 超阈值直接拒绝请求）→ 被拒请求几乎不耗 CPU → 负载均衡器一看&amp;quot;A 区每个请求成本只有 B/C 的 1/10，效率最高！&amp;quot;→ 把更多流量发给 A → A 区 503 爆炸。恶性循环的根源：&lt;strong&gt;配减载的和配负载均衡的是两拨人，没人把它们当统一的负载管理系统检查&lt;/strong&gt;。修法很巧妙：让被拒绝的请求按 120% CPU 计入利用率，A 区立刻&amp;quot;显得&amp;quot;过载，流量自然流向 B/C。&lt;/p&gt;
&lt;h2 id=&#34;九nalsd把白板上的架构图翻译成数字&#34;&gt;九、NALSD：把白板上的架构图翻译成数字&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;NALSD（Non-Abstract Large System Design，非抽象大型系统设计）&lt;/strong&gt; 是 Google 要求的系统设计方法：从问题出发迭代设计，每一步都必须把架构图翻译成具体的资源估算（多少台机器、多少字节、多少 IOPS），并回答四个问题——&amp;ldquo;可能吗？能做得更好吗？可行吗（钱和硬件）？有弹性吗（故障怎么办）？&amp;rdquo;&lt;/p&gt;
&lt;p&gt;书中用 AdWords 点击率统计系统做了五轮完整迭代：每秒 50 万次搜索查询、1 万次广告点击，为数百万广告主出实时仪表板（SLO：99.9% 的查询 1 秒内完成，数据延迟不超过 5 分钟）。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    I1[&amp;#34;迭代1 单机方案&amp;lt;br/&amp;gt;100TB/天日志&amp;lt;br/&amp;gt;需 2500 块 HDD 或 1563 台机器&amp;lt;br/&amp;gt;❌ 单点故障一串&amp;#34;] --&amp;gt; I2[&amp;#34;迭代2 MapReduce 批处理&amp;lt;br/&amp;gt;❌ 做不到 5 分钟内可见&amp;#34;]
    I2 --&amp;gt; I3[&amp;#34;迭代3 LogJoiner&amp;lt;br/&amp;gt;流式 join 查询日志与点击日志&amp;lt;br/&amp;gt;⚠️ IOPS 单机扛不住&amp;#34;]
    I3 --&amp;gt; I4[&amp;#34;迭代4 分片 + 副本&amp;lt;br/&amp;gt;hash(query_id) mod N&amp;lt;br/&amp;gt;⚠️ 单数据中心仍是单点&amp;#34;]
    I4 --&amp;gt; I5[&amp;#34;迭代5 多数据中心 + Paxos ✅&amp;lt;br/&amp;gt;每 DC 约 4TB RAM、64 台机器&amp;lt;br/&amp;gt;网络带宽只用 25%&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;给面试和日常设计的启发：每轮迭代不是&amp;quot;画个更复杂的图&amp;quot;，而是&lt;strong&gt;算一笔账&lt;/strong&gt;——日数据量 = QPS × 86400 × 条目大小；磁盘数 = QPS ÷ 单盘 IOPS；Paxos 顺序吞吐 = 1000ms ÷ 跨机房 RTT。假设不必完美，有价值的是把多个不完美但合理的估算组合起来做决策。&lt;/p&gt;
&lt;h2 id=&#34;十数据处理管道配置与金丝雀发布&#34;&gt;十、数据处理管道、配置与金丝雀发布&lt;/h2&gt;
&lt;h3 id=&#34;101-把管道当服务运营spotify-案例&#34;&gt;10.1 把管道当服务运营（Spotify 案例）&lt;/h3&gt;
&lt;p&gt;数据管道也要定 SLO：新鲜度（&amp;ldquo;99% 的数据 30 分钟内处理完&amp;rdquo;）、正确性、完整性。Spotify 的事件传递系统每天收集&lt;strong&gt;数千亿条事件&lt;/strong&gt;（听歌、点广告……），用于向艺术家支付版税——可靠性是财务级要求。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[&amp;#34;Spotify 客户端事件&amp;#34;] --&amp;gt; B[&amp;#34;Cloud Pub/Sub 主题&amp;lt;br/&amp;gt;（按事件类型完全隔离）&amp;#34;]
    B --&amp;gt; C[&amp;#34;消费微服务&amp;#34;]
    C --&amp;gt; D[&amp;#34;分区微服务&amp;lt;br/&amp;gt;分配到小时桶&amp;#34;]
    D --&amp;gt; E[&amp;#34;Dataproc 批作业去重&amp;#34;]
    E --&amp;gt; F[(&amp;#34;GCS 小时桶&amp;lt;br/&amp;gt;与下游的唯一接口&amp;#34;)]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;三个值得抄的设计决策：时间戳用&lt;strong&gt;服务器接收时间&lt;/strong&gt;而非客户端时间（用户可以离线缓冲 30 天、可以改设备时间）；只给&amp;quot;财务相关&amp;quot;事件承诺偏度/完整性 SLO，&lt;strong&gt;刻意不提供数据质量 SLO&lt;/strong&gt;——&amp;ldquo;我们是邮政服务：负责按时完整送达，包裹里的内容质量归寄件人&amp;rdquo;；容量规划留安全边际，高峰 CPU 不超 50%。&lt;/p&gt;
&lt;h3 id=&#34;102-配置最好的人机界面是没有配置&#34;&gt;10.2 配置：最好的人机界面是&amp;quot;没有配置&amp;quot;&lt;/h3&gt;
&lt;p&gt;配置三要素哲学：理想配置是&lt;strong&gt;完全没有配置&lt;/strong&gt;（系统自动识别正确值）；以用户为中心（用户说&amp;quot;我要热的绿茶&amp;quot;，而不是指定水量/温度/浸泡时间）；动态默认值（线程数默认 = CPU 核数）。任何配置变更必须满足安全三属性：&lt;strong&gt;逐步部署、可回滚、失控时自动回滚&lt;/strong&gt;（想想多少人用防火墙规则把自己锁在服务器外面过）。&lt;/p&gt;
&lt;h3 id=&#34;103-金丝雀发布用小部分错误预算买安全感&#34;&gt;10.3 金丝雀发布：用小部分错误预算买安全感&lt;/h3&gt;
&lt;p&gt;术语来自煤矿里的金丝雀。核心是一笔账：一个缺陷导致 20% 请求出错，直接全量发布就是 20% 总错误率；先部署到 5% 的金丝雀集群，&lt;strong&gt;总错误率只有 5% × 20% = 1%&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[&amp;#34;新版本部署到 5% 金丝雀集群&amp;#34;] --&amp;gt; B[&amp;#34;细分指标对比：&amp;lt;br/&amp;gt;金丝雀组 vs 对照组&amp;#34;]
    B --&amp;gt; C{&amp;#34;错误率/延迟显著偏离？&amp;#34;}
    C -- 是 --&amp;gt; D[&amp;#34;暂停发布 + 回滚&amp;lt;br/&amp;gt;通知人工介入&amp;#34;]
    C -- 否 --&amp;gt; E[&amp;#34;逐步扩大：1%→10%→50%→100%&amp;#34;]
    E --&amp;gt; F[&amp;#34;全量发布 ✅&amp;#34;]
    D -.-&amp;gt;|&amp;#34;修复后重来&amp;#34;| A&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;两个容易踩的坑：监控指标的聚合间隔必须&lt;strong&gt;小于等于金丝雀时长&lt;/strong&gt;（30 分钟的金丝雀用&amp;quot;每小时错误数&amp;quot;评估，噪声会淹没信号）；金丝雀指标首选 SLI，且&lt;strong&gt;总数不要超过 12 个&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&#34;十一人的部分过载恢复团队建设与组织变革&#34;&gt;十一、人的部分：过载恢复、团队建设与组织变革&lt;/h2&gt;
&lt;p&gt;第三部分&amp;quot;流程&amp;quot;处理的是书中最&amp;quot;软&amp;quot;也最难的部分。&lt;/p&gt;
&lt;h3 id=&#34;111-识别过载并恢复第-17-章&#34;&gt;11.1 识别过载并恢复（第 17 章）&lt;/h3&gt;
&lt;p&gt;过载分两种：&lt;strong&gt;真实过载&lt;/strong&gt;（任务量客观超支）和&lt;strong&gt;感知过载&lt;/strong&gt;（沟通不足导致的主观感受）——书中强调，感知过载的实际危害和真实过载一样大，而且会传染。恶性循环是这样的：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[&amp;#34;运维过载&amp;#34;] --&amp;gt; B[&amp;#34;心理压力&amp;#34;]
    B --&amp;gt; C[&amp;#34;犯错增多&amp;#34;]
    C --&amp;gt; D[&amp;#34;可靠性下降&amp;#34;]
    D --&amp;gt; E[&amp;#34;更多运维工作&amp;#34;]
    E --&amp;gt; A
    B --&amp;gt; F[&amp;#34;心理安全下降&amp;lt;br/&amp;gt;协作与信息共享停滞&amp;#34;]
    F --&amp;gt; G[&amp;#34;效率更低&amp;#34;]
    G --&amp;gt; E&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;真实案例：Google 一个支撑 Gmail/Drive 后端的存储 SRE 团队，2016 年&lt;strong&gt;三分之二的成员&lt;/strong&gt;短期相继转岗。恢复方法朴素得出奇：全队进一个房间把所有职责写上白板分类，两天时间（一天分类、一天写文档/做自动化）清理了几个月的积压；之后每两周分类一次，&lt;strong&gt;每人最多 10 张打开的工单&lt;/strong&gt;，超了就有五种干预动作。另一个感知过载团队（悉尼/苏黎世两地）的恢复路线是分三档：短期先减压（圆桌吐槽会、删掉垃圾警报、&amp;ldquo;慷慨地静音&amp;rdquo;）、中期减负（把一项服务交还开发团队、补员）、长期治本（SLO 对齐、服务统一化）。约一年后匿名调查显示团队重回&amp;quot;高效且安全&amp;quot;。&lt;/p&gt;
&lt;h3 id=&#34;112-sre-怎么参与一个服务第-18-章&#34;&gt;11.2 SRE 怎么参与一个服务（第 18 章）&lt;/h3&gt;
&lt;p&gt;SRE 永远是稀缺资源（Google 把 SRE:开发比例控制在 1:10 左右），所以要主动选择参与模式。服务的生命周期：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[&amp;#34;架构与设计&amp;#34;] --&amp;gt; B[&amp;#34;积极开发&amp;lt;br/&amp;gt;（生产化）&amp;#34;] --&amp;gt; C[&amp;#34;有限可用 Beta&amp;lt;br/&amp;gt;GA 前必须定 SLO&amp;#34;] --&amp;gt; D[&amp;#34;一般可用 GA&amp;lt;br/&amp;gt;通过 PRR 生产准备审查&amp;#34;] --&amp;gt; E[&amp;#34;弃用&amp;lt;br/&amp;gt;SRE 同时运维新旧两套&amp;#34;] --&amp;gt; F[&amp;#34;放弃&amp;lt;br/&amp;gt;运维交还开发团队&amp;#34;] --&amp;gt; G[&amp;#34;不支持&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;两个一正一反的收场案例：&lt;strong&gt;Ares 团队（好聚）&lt;/strong&gt;——反滥用团队 CAT 内部建立了具备生产知识的 Ares 小组，SRE 通过&amp;quot;交流计划&amp;quot;转移知识后体面退出，CAT 开发速度反而提升；&lt;strong&gt;数据分析管道（好散）&lt;/strong&gt;——合作十年后关系恶化（旧系统到极限、沟通破裂），最终解散 SRE 团队、平稳移交，教训是&amp;quot;如果关系健康，本可以暂时交还再取回&amp;quot;。&lt;/p&gt;
&lt;h3 id=&#34;113-sre-团队生命周期第-20-章&#34;&gt;11.3 SRE 团队生命周期（第 20 章）&lt;/h3&gt;
&lt;p&gt;从 0 到 1 的路径，三条原则贯穿：&lt;strong&gt;①SRE 需要有结果的 SLO；②SRE 必须有时间让明天比今天更好；③SRE 团队必须能调节自身工作量。&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[&amp;#34;没有 SRE？&amp;lt;br/&amp;gt;先用 SLO：承认不要 100% → 定 SLO → 写错误预算政策 → 测量并执行&amp;#34;] --&amp;gt; B[&amp;#34;招第一个 SRE&amp;lt;br/&amp;gt;考察：运维/软件工程/监控/自动化/架构&amp;#34;]
    B --&amp;gt; C[&amp;#34;组建 SRE 团队&amp;lt;br/&amp;gt;Tuckman 模型：组建 → 震荡 → 规范 → 表现&amp;#34;]
    C --&amp;gt; D[&amp;#34;多团队：按产品域或技术栈拆分&amp;lt;br/&amp;gt;⚠️ 警惕无人认领的组件&amp;#34;]
    D --&amp;gt; E[&amp;#34;地理分布式&amp;lt;br/&amp;gt;时区间隔 6-8 小时最佳，避开凌晨值班&amp;#34;]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;警告：&lt;strong&gt;不要在还没实践 SRE 原则之前，把&amp;quot;运维团队&amp;quot;改名成&amp;quot;SRE 团队&amp;quot;&lt;/strong&gt;——品牌一旦失败，组织会彻底否定 SRE 这个概念。&lt;/p&gt;
&lt;h3 id=&#34;114-组织变革管理waze-的逆袭第-21-章&#34;&gt;11.4 组织变革管理：Waze 的逆袭（第 21 章）&lt;/h3&gt;
&lt;p&gt;Waze（2013 年被 Google 收购）的消息队列是全公司组件的通信命脉。吞吐量暴增后可靠性崩溃，最糟时&lt;strong&gt;整个 SRE 团队连续两周 24/7 救火，每小时手动重启部分组件&lt;/strong&gt;才能维持数千万用户的服务。&lt;/p&gt;
&lt;p&gt;变革路径（完美对应 Kotter 八步模型）：2 名 SRE + 1 名高级工程师组成&amp;quot;指导联盟&amp;quot;；评估现成产品后决定自研；招募志愿军先给占 30% 以上流量的单个组件建专用队列，挤出两个月的原型窗口；重写客户端库实现新旧系统流量切换；先迁低流量高重要性的消息流，双写提供备份路径。最终新系统承载旧系统 &lt;strong&gt;1000 倍以上&lt;/strong&gt;的负载，且几乎无需人工干预。第二轮变革是部署流程：引入 Spinnaker 持续交付，如今 &lt;strong&gt;Waze 超过 95% 的服务持续部署&lt;/strong&gt;，几乎无人工干预。&lt;/p&gt;
&lt;p&gt;书里还有一条推广通用工具的朴素经验：迁移成本必须接近零（&amp;ldquo;重新编译就能用上&amp;rdquo;），收益必须明确（&amp;ldquo;现在你已经不受某某漏洞影响&amp;rdquo;），衡量推广成功的第一指标是&lt;strong&gt;采用率&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&#34;十二结语把这本书带走的五句话&#34;&gt;十二、结语：把这本书带走的五句话&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;没有 SLO，就不需要 SRE&lt;/strong&gt;——先量化&amp;quot;什么叫足够可靠&amp;quot;，再谈可靠性工程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;错误预算是开发速度与稳定性的通用货币&lt;/strong&gt;——预算充足就大胆发布，花光就冻结变更，不用吵架。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;琐事不超过 50%，修根因不修症状&lt;/strong&gt;——每小时损失多少钱，把账算给决策的人听。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓解优先于根因，对事不对人&lt;/strong&gt;——先把用户救回来，再写一份有 P0 行动项的事后总结。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SRE 不是 Google 专利&lt;/strong&gt;——Home Depot 一年从 0 到 800 个服务，&amp;ldquo;如果我们能做到，您也可以。&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最后用全书结尾的祝福语收个尾：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;愿你的查询流畅，愿你的传呼机保持沉默。&lt;/strong&gt;
（May your queries flow and your pagers stay silent.）&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    </item>
    
  </channel>
</rss>
