1 K8s 网络要回答什么
把订单 API 部署到 Kubernetes 后,部署成功只是起点。顾客点击“提交订单”,请求先进入集群,再到某个正在运行的副本;订单 API 还可能访问库存服务与数据库。此时需要回答的是:调用方用什么名字寻找服务,请求如何到达可用副本,哪些调用应该放行,以及失败时到哪里找证据。K8s 网络把这些问题拆成对象和约定,但不会替应用自动决定所有边界。
先把集群想成承载应用的计算环境。节点是运行工作负载的机器,Pod 是部署和调度的基本单位,可以包含共享网络空间的容器。订单 API 的 3 个副本通常对应 3 个 Pod,它们可能分布在不同节点。发布、故障恢复或扩缩容都会让 Pod 被替换,新的 Pod 可能获得新的地址。因此,调用方直接保存某个 Pod IP,等于把业务联系绑在临时住址上。
网络方案需要区分身份与位置。应用身份可以是“订单服务”,运行位置则是此刻承担请求的 Pod。Service 提供相对稳定的访问入口,把调用者与副本变化隔开;DNS 让调用者使用服务名称。这里的稳定是对象生命周期内的稳定,并非承诺删除重建后地址永远相同。应用应配置服务名称和必要端口,避免把临时分配的数字地址写进代码。
同样需要区分集群内部和外部。库存服务访问订单服务属于内部调用,顾客从公网访问订单 API 则需要外部入口。外部入口可能经过云负载均衡器、Ingress 控制器或网关,再进入 Service 和 Pod。每层都有自己的配置、健康检查和日志。看到“连接超时”时,不能立刻认定是 Pod 网络故障,因为请求可能尚未到达集群,也可能已到应用却一直没有返回。

学习本课时,可以围绕 4 个问题阅读:地址属于谁,转发由谁完成,访问由谁允许,结果由谁证明。K8s 提供期望状态,集群中的网络组件负责把它落实为数据路径。下面会用订单 API 说明这些边界,不要求先理解报文封装、内核规则或路由协议。那些实现细节会影响性能和运维,但入门阶段先画对对象和依赖关系,才能提出可检验的问题。
2 Pod 网络、Service 与 kube-proxy 边界
Pod 内的容器共享网络命名空间,通常使用同 1 个 Pod IP,也共享端口空间。应用容器可以通过 localhost 访问同 Pod 的辅助容器,但不能让 2 个进程同时占用相同的监听地址和端口。另 1 个 Pod 中的 localhost 指向它自己,不会指向订单 API。排查之前先确认调用者究竟在宿主机、目标 Pod,还是另外的 Pod 中运行,这是解释地址的前提。
在常见的 Kubernetes 网络模型中,Pod 之间应能通过 Pod IP 通信,跨节点连通由网络实现负责。CNI 是容器网络接口,集群通过相关插件为 Pod 配置网络;实际如何跨节点传送,取决于选用的网络方案与部署环境。这里先把它看成“让 Pod 地址能够互达的基础设施”。这个模型不代表所有访问都被安全策略允许,也不代表外部网络天然认识 Pod 地址。
Service 定义逻辑入口。假设订单 Pod 带有 app=orders 标签,Service 的选择器匹配这个标签,控制面就能根据匹配到的 Pod 维护后端信息。EndpointSlice 用来记录服务端点及其状态,供相关组件使用。通常只有满足就绪条件的端点参与正常服务;特殊配置可能改变这一行为。Service 对象存在、选择器匹配、端点可用,是 3 个不同的检查点。
ClusterIP 是常见 Service 类型,它给集群内部调用提供虚拟地址。Service 的 port 是调用方看到的端口,targetPort 是请求最终交给后端的端口。例如客户端访问 Service 的 80,应用实际监听 Pod 的 8080。容器声明了 containerPort 并不等于进程已经监听,也不会自动修复 targetPort。协议也必须一致,TCP 与 UDP 不能只凭数字端口相同就视为相同服务。
在许多集群中,kube-proxy 观察 Service 与端点变化,并在节点上维护转发所需的规则。普通数据包不一定经过某个 kube-proxy 用户态进程逐包转发;具体数据路径由实现模式决定。也有网络实现用自己的机制替代这部分功能。因此应把“Service 的逻辑行为”和“本集群如何实现它”分开记录,不能仅凭组件名称推断每个数据包走过哪些进程。

Service 主要解决稳定发现与后端转发,不承担完整的业务路由。普通 Service 不会因为 HTTP 路径是 /orders 就选择订单后端,也不会理解登录状态、订单金额或访问者权限。现有 TCP 连接通常会继续关联原来的后端,增加副本不会自动把连接中的请求平均拆开。判断是否均衡,应结合连接方式和观察窗口,而不是连续刷新 3 次就期待每个 Pod 恰好收到 1 次请求。
3 Ingress、网关与南北向流量
南北向流量指跨越集群边界进入或离开的流量,东西向流量常用于描述服务之间的内部通信。对顾客而言,入口是 orders.example.test 这样的域名;对集群而言,需要有组件接住连接,再根据规则把请求交给正确服务。域名解析、入口地址、TLS 证书、HTTP 路由和后端端点相互关联,但并不是创建 1 个 Service 就会全部完成。
Ingress 是描述 HTTP、HTTPS 入口路由的 Kubernetes API 对象,常见规则根据域名和路径选择 Service。Ingress 对象本身不处理请求,需要相应的 Ingress 控制器观察并落实配置。控制器如何获得外部可达地址,可能依靠 LoadBalancer 类型的 Service,也可能采用环境提供的其他接入方式。看到 Ingress 清单被接受,只能证明对象进入控制面,还要验证控制器是否接管、入口是否可达。
Gateway API 提供了另一组描述网关与路由的资源,可以更明确地分开基础设施管理和应用路由配置。例如平台团队管理 Gateway,应用团队通过 HTTPRoute 描述订单服务路由。Gateway API 同样需要兼容的实现,并非换个对象名称就自动获得所有能力。入门时先认识职责分离即可,具体支持哪些协议、过滤器和策略,应查当前实现的能力及状态反馈。
TLS 在哪里结束,会改变后续链路的安全假设。假设顾客到入口使用 HTTPS,而入口到订单 Pod 使用 HTTP,则公网链路被加密,但不能由此推出集群内部链路也被加密。若要求入口到应用继续使用 TLS,就要补充后端协议、证书信任和健康检查约定。应用日志中的客户端地址也可能受到代理影响,不能未经信任边界校验就把任意转发请求头当成真实身份。
外部流量还可能通过 LoadBalancer 或 NodePort 类型的 Service 进入,这些入口与 Ingress 的职责不同。LoadBalancer 通常由环境中的实现配置外部负载均衡资源;NodePort 则开放节点上的指定端口,并依赖外部网络能到达节点。它们不自动提供按 HTTP 域名和路径分流的业务规则。入口方案应按协议、暴露范围和维护责任选择,避免为了“能访问”同时开启多个无人管理的入口。
对订单 API,可以先采用清晰的链路:域名指向已管理的入口,入口处理 TLS 与 /orders 路由,Service 选择订单后端,Pod 处理请求。验收时分别记录 DNS 结果、证书名称、路由命中和后端响应。若返回 404,要区分入口没有匹配到路由,还是应用没有这个资源;若返回 502 或 503,也要结合实现含义和日志确认后端连接或可用性问题,不能仅凭状态码下最终结论。
4 动手:画一条 Service 到 Pod 的路径
下面在有权限的练习命名空间中画路径,先做只读观察。假设命名空间为 shop,已有名为 orders 的 Service 和订单 Pod。示例中的名称需要按实际环境替换。如果对象尚未部署,先把它们当作纸面对象理解,不要为了执行观察命令就在生产环境临时创建资源。练习目标是说明每段连接的证据,而不是背诵命令输出。
kubectl -n shop get service orders -o wide
kubectl -n shop get service orders -o yaml
kubectl -n shop get pods -l app=orders -o wide
kubectl -n shop get endpointslices -l kubernetes.io/service-name=orders -o yaml
先从 Service 记录 type、clusterIP、selector、port 和 targetPort,再对照 Pod 标签。不要只看 Pod 名称是否包含 orders,选择器匹配的是标签。接着观察 EndpointSlice 中的地址、端口以及 ready 等状态,确认端点与预期 Pod 对得上。若 Service 使用命名 targetPort,还要核对 Pod 中相应端口名称的定义,不能仅凭名字看起来相似就认为映射成立。
把纸面路径写成:调用 Pod → 服务 DNS 名称 → Service 地址与端口 → 选中的端点 → 应用监听端口。可用 orders.shop.svc.cluster.local 表达常见默认集群域下的完整服务名,但集群域可以配置,必须以实际环境为准。同命名空间中的短名称通常更简洁,跨命名空间调用则应明确命名空间,避免调用到同名的另 1 个服务。
如果已有经批准的诊断 Pod,并且其中安装了所需工具,可以从接近真实调用方的位置发起测试。下面的 netcheck 是已有 Pod 的占位名称,/healthz 也要换成应用实际提供的只读检查路径。工具不存在时,不要把“命令找不到”解释为网络故障;应使用环境允许的诊断方式,并记录测试位置。
kubectl -n shop exec netcheck -- getent hosts orders.shop.svc.cluster.local
kubectl -n shop exec netcheck -- curl --connect-timeout 3 --max-time 5 -sv http://orders:80/healthz
kubectl -n shop logs deployment/orders --tail=50
服务名解析成功只能证明名称得到解析结果,不能证明 Service 后端可用。HTTP 检查成功能证明这个时间、这个来源、这个路径完成了交互,也不能代替全部业务验收。若要对照直接访问 Pod IP,应使用实际端点端口,并从同 1 个诊断位置测试;这种对照可以缩小范围,但绕过 Service 后成功并不能自动证明是 kube-proxy 故障,还要检查端口配置、端点更新和网络策略差异。

最后给图补上时间与来源:在什么时间、哪个命名空间、哪个 Pod 发起、目标名称是什么、连接结果是什么、应用是否记录到请求。应用若能输出请求标识,可把客户端观察与服务日志关联。日志里没有记录并不总等于请求未到达,可能是日志采样或记录时机不同;需要用入口日志、连接结果和应用状态交叉判断,形成能够复查的证据链。
5 网络策略与默认拒绝取舍
连通不等于所有连接都应该允许。订单 API 可能只需要接受入口组件和指定内部调用方的流量,数据库也只需接受订单等授权服务的连接。NetworkPolicy 用标签、命名空间和端口等条件描述 Pod 层面的允许范围。常规策略主要处理网络层与传输层访问,不会验证“这个用户能否查看这笔订单”;业务身份、应用鉴权和数据权限仍需要各自负责。
NetworkPolicy 是否生效,取决于集群网络实现是否支持并执行它。仅能创建策略对象,不能证明流量已经被限制。应在计划使用的来源和目标之间做允许、拒绝对照测试。原生 NetworkPolicy 通常也不直接提供按域名维护外部访问白名单的能力;实现扩展可能支持更多功能,但不能把某个环境的扩展当作所有 Kubernetes 集群都具备的标准行为。
在标准模型中,Pod 默认没有因为 NetworkPolicy 而被隔离;当某方向有策略选中它时,该方向才按策略进入隔离状态。入站和出站分别判断,多条适用策略的允许范围会合并。如果来源 Pod 的出站与目标 Pod 的入站都被隔离,连接需要同时满足两端的允许条件。增加 1 条更严格的策略,不一定能收回其他策略已经放开的路径,这是审查时很容易忽略的地方。
“默认拒绝”是先建立较小的可达面,再显式允许必要依赖。对订单服务,需要盘点入口到订单、订单到库存、订单到数据库,以及订单进行名称解析的 DNS 流量。若只允许业务目标而忘记 DNS,应用会在建立连接之前失败;若只看到 DNS 常用 UDP,就可能漏掉需要 TCP 的解析场景。具体解析服务的位置与标签,应根据集群实际部署确认。
默认拒绝的取舍是暴露面与依赖维护成本之间的取舍。规则范围较宽时,新依赖更容易连通,但误调用和横向访问的范围也更大;范围较窄时,依赖变更必须同步更新策略与验证。不能把策略条数直接当作安全分数。应从清楚的业务边界开始,例如先限制数据库入站,再逐步收紧应用出站,并为每次收紧准备允许测试、拒绝测试和恢复办法。
命名空间和 Pod 标签会影响策略选择,因此标签的修改权限也是边界的一部分。如果任意工作负载都能给自己贴上“受信调用方”标签,策略表达的信任就可能失真。对于共享集群,还需要配合合理的权限与命名空间管理。网络策略是重要的隔离手段,但不会代替节点安全、云网络边界或应用身份验证;方案应写清每层负责什么,避免把所有安全要求压给 1 个对象。
6 常见坑:把 ClusterIP 当跨集群地址
假设团队在另 1 个集群部署报表服务,想调用 shop 中的订单 API。有人复制了 orders 的 ClusterIP,发现地址格式与普通私网 IP 相似,就把它写进报表配置。这种做法混淆了地址形状和地址作用域。ClusterIP 是 Service 的集群内虚拟入口,默认不承诺被其他集群或外部网络路由到,外部客户端也通常没有本集群相应的转发上下文。
即使 2 个集群位于互通的 VPC 中,也不能直接推出 Service 网段互通。节点网段、Pod 网段、Service 网段是不同的规划对象,可能有不同的路由与转发机制。2 个集群还可能使用重叠地址,因此同 1 个数字地址在不同集群中可以指向不同对象。把“节点能互相 ping 通”作为“ClusterIP 可以跨集群调用”的证据,遗漏了真正需要验证的数据路径。
DNS 也有作用域。集群内部的服务域名通常由本集群 DNS 解析,外部客户端未必能解析;另 1 个集群解析相同名称,可能得到它自己环境中的服务。手动向外部 DNS 写入 ClusterIP 只改变了名称到地址的映射,并没有建立路由、转发、安全策略或故障切换。名称可解析、地址可达、服务可用应该分开验收,不能用其中 1 项代替其余各项。
跨集群连接需要明确设计入口。入门方案可以使用有受控访问范围的负载均衡或网关入口,再配置跨网络路由、访问限制、服务身份及加密。调用方使用这个入口对应的稳定名称,并接受合理的连接超时、重试和故障处理。更复杂的多集群服务发现和服务网络可以留到后续专题;本课的关键是不能靠复制 1 个内部地址,把跨边界连接所需的责任全部省略。

出现跨集群故障时,先问这个目标究竟是内部虚拟地址还是正式入口,然后从调用方检查解析、路由与访问限制,再检查入口和后端。不要首先重启所有网络组件,也不要为了快速验证就把所有网段全部放开。若必须临时放通,应明确来源、目标、端口与有效期,并保留变更前后的证据。诊断的目标是验证假设,过大的改动会同时改变多个条件,使原因更难确认。
7 案例:kube-proxy 模式切换中断会话
订单 API 使用 HTTP 长连接与库存服务通信。团队计划调整 kube-proxy 的实现模式,希望统一节点配置。测试只包含变更后的短请求,全部返回成功;上线期间却出现部分正在处理的连接中断。随后新建连接恢复正常。这里不能仅凭时间相近就宣布“某种模式一定会断连”,但可以提出假设:转发实现及其相关状态改变,影响了已有连接的连续性。
Service 地址保持不变,并不意味着已有会话必然连续。1 条连接可能依赖选定的后端、节点上的转发规则和连接状态;切换模式的操作还可能包含组件重启、旧规则清理与新规则生效。具体影响由实现、版本和操作步骤决定。某些切换也可能不被当前环境支持直接完成,因此应先核实支持范围,再讨论迁移方法,不能把配置字段可修改当作在线切换的安全保证。
调查时把“新建连接成功率”和“已有连接完成率”分开看。前者恢复,说明当前路径能接收新连接;后者下降,可能说明切换扰动了存量状态。再关联节点变更时间、客户端连接错误、入口日志、后端端点变化和应用重启记录。如果同一时段还发生 Pod 滚动发布或策略变更,就必须排除这些影响。证据不足时应记录为待验证假设,而不是给所有中断贴上 kube-proxy 标签。
改进方案应包含接近真实业务的预演:保持部分长连接,持续发送短请求,同时观察变更节点上的失败比例和恢复时间。先在受控范围验证,确认回退路径和停止条件,再按环境支持的方式推进。若平台支持逐节点操作,也需要确认流量如何避让以及避让能否覆盖已有连接;不能把“逐节点”本身当作不中断承诺。具体命令应跟随当前版本的操作文档,不在入门课里给出通用切换脚本。
应用也要面对网络中断。连接超时、读取超时和重试上限应有明确配置,避免故障时无限等待或同时猛烈重试。对创建订单这样的写操作,连接断开不代表服务端没有完成写入,直接重试可能产生重复订单。可以通过幂等键和结果查询降低风险。网络变更演练因此既要观察连接,也要核对业务结果:是否重复、是否漏单、用户能否得知最终状态。
8 把集群网络假设写进连通方案
连通方案不能只画“客户端 → Service → Pod”就结束。它需要把路径成立的条件写出来,例如调用方位于哪个集群和命名空间,集群 DNS 域是什么,网络实现是否执行 NetworkPolicy,外部入口由谁维护。图中的每条箭头都应对应来源、目标、协议、端口和访问目的。这样变更发生时,团队才能判断受到影响的是哪条依赖,而不是重新猜测全部网络。
先把订单场景整理成最小连接矩阵。顾客到入口使用 HTTPS,入口到订单服务使用已约定的后端协议,订单到库存和数据库分别填写真实端口,应用到 DNS 填写所需解析协议。每条连接还应注明身份如何确认:有的依靠 TLS 与应用令牌,有的还需要数据库账号。网络允许只是身份验证之前的可达条件,连接矩阵中应同时表达这 2 层责任。
地址规划至少记录节点、Pod、Service 所用范围,以及它们与现有网络和预期跨集群网络是否冲突。并非所有范围都要对外路由,但未来需要连接时,重叠地址可能显著增加迁移难度。方案也要说明哪些地址是临时位置,哪些名称是调用契约。业务配置优先使用约定名称;必须使用固定地址的外部系统,则应写明地址由谁分配、变更和通知。
验收要同时覆盖成功路径与应当失败的路径。允许的入口能访问订单健康检查,未经允许的 Pod 无法连接受保护数据库,这 2 类结果同样重要。再加入后端不可用、域名解析失败和已有连接遇到变更等场景,观察是否有足够信息定位。每项验收写明测试来源和预期结果,因为从管理员笔记本成功访问,不能代替真实业务 Pod 的出站验证。
运维约定应包含监测信号、负责人和变更窗口。入口关注请求量、错误与延迟,服务关注端点是否可用,网络组件关注运行状态,应用关注依赖调用结果。告警阈值根据业务基线制定,避免凭空规定“任何超时都必须报警”。同时明确网络策略、入口路由和转发实现的变更如何评审、验证和回退,使网络假设随着部署一起维护,而不是成为交付后失效的静态图片。
9 从K8s 网络走向K8s 存储(C31)
现在回看订单请求:顾客经过入口找到订单服务,Service 把连接交给可用 Pod,策略控制连接范围,应用执行请求。这里解决的是“谁能找到谁、数据如何送达”。当订单 Pod 被替换后,新 Pod 可以重新加入 Service,但如果订单数据只写在原容器的临时文件里,网络恢复也不能把丢失的数据找回来。可达性和持久性是不同的问题,需要分别设计。
数据库依赖把网络与存储连接起来。订单 API 能连上数据库,只说明建立通信的条件满足;写入是否持久、数据能否在故障后恢复、多个副本如何访问,都需要存储层的承诺。反过来,数据库磁盘正常也不能保证订单请求成功,DNS、连接上限、访问策略或入口配置都可能影响结果。因此业务验收应同时观察请求结果和数据状态,避免只看某 1 层的健康标志。
Pod 的生命周期短于业务数据的生命周期,是接下来学习存储的重要动机。网络用服务名称和 Service 把调用关系与 Pod 位置分开;存储也需要有机制,把应用需要的数据与某个临时容器分开。两者有相似的抽象思路,但实现和故障条件不同。不要因为 Service 会跟随后端变化,就推断挂载的数据也会自动复制到任何新节点。
进入 C31 时,继续保留本课的提问方式:资源属于谁,生命周期多长,谁负责提供能力,失败时怎样观察。下一课会用卷、持久卷声明等概念说明应用怎样申请持久存储,以及访问方式和放置条件如何约束部署。更深入的分布式存储复制与一致性留给后续专题。本课先确保能把请求路径画清,再把“请求产生的数据放在哪里”接到同 1 份方案里。
放进方案里
为订单 API 写连通方案时,先确定服务边界与调用范围。顾客通过受控的 HTTPS 入口访问订单路由,入口把请求交给 shop 命名空间中的 orders Service,再由可用端点承接。库存等内部调用方使用约定的服务名称,配置中不保存 Pod IP。文档注明集群 DNS 域、入口管理人和证书更新责任,使名称、路由与证书都有人维护。
将每条依赖列为来源、目标、协议、端口、身份与用途。记录订单到库存、数据库和 DNS 的必要连接,并说明 NetworkPolicy 是否由当前网络实现执行。收紧策略前先验证依赖,采用默认拒绝时保留明确允许规则,同时验证未经允许的访问确实失败。命名空间和标签的管理权限也纳入边界,避免规则依赖的身份被随意修改。
地址部分列出节点、Pod 与 Service 范围及冲突检查结果。明确 ClusterIP 的集群内作用域,跨集群调用使用正式管理的入口名称,补齐路由、加密和访问限制。入口终止 TLS 后,后端是否继续加密也要写清,不能仅凭外部使用 HTTPS 就宣称全程加密。
验收从真实调用位置检查解析、Service 端口、端点状态和应用响应,并保存时间及请求标识。补充后端摘除验收:将测试副本置为未就绪后,记录 EndpointSlice 状态变化,确认收敛后新建连接不再选中该副本;已有连接另行观察。策略验收保留允许来源与拒绝来源的标签、命名空间和连接结果,作为隔离生效的证据。监测入口错误、依赖超时和可用端点变化,明确各层负责人。网络实现变更要预演新连接与已有连接,设定停止条件和回退步骤;订单写入使用幂等处理,并核对中断后的最终结果。最后把数据库的持久性和恢复要求交给存储设计继续展开,使网络可达与数据可靠分别有证据支撑。
10 小结:下一步K8s 存储(C31)
K8s 网络把临时 Pod 位置、稳定服务入口、外部路由和访问边界分成不同责任。能解释 DNS、Service、端点与应用监听端口之间的关系,就有了入门排查的基础;能说明 ClusterIP 的范围和变更对已有连接的影响,才能把这条路径写成可交付的方案。
自测时尝试回答:Service 存在但没有可用端点,下一步检查什么?入口 HTTPS 成功,为何不能证明后端链路加密?跨集群为什么不能直接复制 ClusterIP?新连接成功而旧连接中断,应补充哪些证据?如果这些问题能够沿图解释,再进入 C31,学习 Pod 替换后如何保留并重新使用数据。