容器 31:指标如何归属到一次真实请求
监控面板中一条“容器 CPU 高”曲线,只要没绑定到同一个26 的 Pod UID/容器 ID/PID,就未必能解释这一次 /ready 延迟。最小可迁移做法是从业务请求返回时间追到当时进程,再读该进程所属 cgroup 的 CPU、内存和 I/O 计数器,而不是把不同采样窗口的曲线拼在一起。 最容易出错的是先找一张“看起来同时变高”的监控图,再往上套一个慢请求的故事。应用 200 的耗时包含连接建立、服务接收、进程排队与响应传输;cpu.stat 里的节流次数是某个 cgroup 的累积量。两者测量对象、时间窗口和统计单位不同。即使图上时间线重合,没有请求身份与 cgroup 路径的映射,因果链也不成立。本篇用共用 probe-app 与 bounded_load 构造可限定范围的对照,但不把还未运行的 YAML 当成 CPU 节流实测。 建立时间和身份的双重坐标 固定一份 bounded_load 的输入规模、持续时间与并发,在请求侧保留开始/结束时间、HTTP 状态与总耗时;在应用侧保留日志、PID 和真实服务延迟;在节点侧同一时间窗读取 cpu.sta...
容器 30:PV/PVC 与 CSI 怎样到达进程的目录
16已经表明容器内同一路径可能属于可写层、bind、volume 或 tmpfs;Kubernetes 加上声明、绑定与节点挂载流程,才使 Pod 能看到一份外部存储。PV/PVC、StorageClass、CSI 的对象关系见存储体系;这里专看“这次写入究竟落到了哪一个挂载对象”。 把 kubectl get pvc 的 Bound 当作数据已经落盘,会混淆至少三个时间点:控制面决定使用哪个卷、节点让哪个挂载可见、进程成功写入并在下一次启动后重新读到同样的字节。本篇沿着一个固定 PVC 和同一份 probe-app,从声明到应用路径逐项取证;先不假定本机 kind 附带的默认 StorageClass 是 CSI,也不把单节点路径假装成跨节点持久存储。 声明成功不等于目录可写 PVC 指明容量/访问模式等需求,通过绑定/动态供给关联 PV;具体 CSI 驱动与节点组件按存储类型准备卷,把它挂载进 Pod;进程最终看到的是自己的 mount namespace 中某个路径。不同驱动对动态供给、重挂载、跨节点恢复、备份一致性的承诺不同。即使 Pod Running,卷的所有者、只读...
容器 29:Pod IP 与 Service 后端如何关联
28 的 Ready影响谁有资格接请求,24 的 CNI ADD使 Pod 获得网络地址。用户却通常请求一个 Service 名称而非 Pod IP:DNS 返回什么地址、Service 怎样挑后端、数据包经哪种转发实现、谁能被 NetworkPolicy 放行,是四个不同的问题。把它们笼统写成“Service 代理访问 Pod”,很难解释“直连 Pod 有回应但 Service 超时”或“策略对象存在但仍能访问”的分歧。本篇从一条客户端 HTTP 请求出发,先在两个实际后端上找到身份,再逐层检查入口和策略。 四份对象信息各管哪一段 Pod status 的 IP 表示运行时/CNI 所配置网络视图里的地址;单机 veth/bridge 机制已在 22–24 讨论。它不证明另一台节点能路由到此 IP,也不保证上层进程在正确接口和端口监听。Service spec 给客户端一个稳定的入口和端口映射;ClusterIP 通常是虚拟服务地址而不是运行着 probe-app 的第三台机器。EndpointSlice 存放 Service 当前的后端地址/端口与条件,控制器据 select...
容器 28:Running 之后服务为什么还不能用
普通进程00 的 /health=200、/ready=503已说明“活着”与“就绪”不同。移到 Kubernetes 后又多了几道门:Pod phase、容器当前状态、探针结果、Pod Ready condition、EndpointSlice 后端集合,以及一次真正的 Service 请求。kubectl get pods 显示 Running 时,有时应用还在加载;显示 Ready 时,业务查询也可能失败。真正的问题不是“该把 readiness 调短多少”,而是要能在同一份时间线上指出请求被允许进入后端的条件和失败发生在哪个环节。 Running 是一个阶段,不是一个端到端结果 Kubernetes 的 Pod phase 是对象状态的粗粒度概览。Pending 可包含等待调度、下载镜像或启动 init 容器;Running 表示 Pod 已绑定节点、容器已创建,至少有一个容器正在运行、启动或重启中,并不承诺所有容器对请求负责。CrashLoopBackOff 通常是某个容器处于重启退避的等待原因,不是第六种 Pod phase;不...
容器 27:requests 与 limits 怎样走到节点的 cgroup
26 的 Pod UID解决“到哪台节点、找哪只进程”,06和07解释 cgroup 控制器。现在同一份 Pod 清单写下 `requests.cpu` 和 `limits.memory`,究竟发生了什么?“Pod 因 CPU 不足等不到节点”“进程运行很慢”“容器因内存退出”“节点驱逐 Pod”分别发生在调度、进程 cgroup、内存回收和 kubelet 节点压力处理这几层;把它们统称资源不够,既找不到应读的证据,也容易把修复动作施加在错误对象上。 先分清资源声明的作用时刻 一个容器的 CPU/memory request 表示调度与资源分配要考虑的需求,不是给进程预存一块永远闲置的物理内存。调度器从节点 allocatable 和已承诺的 request 等信息判断新 Pod 是否能安排;计算取决于 Pod 内所有容器、init 容器以及适用的 Pod overhead 等版本/配置细节,不等同于 free 命令看到的实时空闲量。同一节点此刻 CPU 很空闲,也可能因为已承诺的请求量而拒绝新 Pod;相反安排成功以后,实际使用也可能远低于 request。只拿一个瞬时 CP...
容器 26:Pod 到达节点后变成哪些对象
Pod 已经分配给一台节点,怎样找到真正接收请求的那个进程?17 的 OCI runtime从执行配置走到进程,18 的 containerd 对象把内容与运行分开,24 的 CNI解释网络配置;然而 Kubernetes 的 Pod UID 并不是这三个系统共同使用的进程号。需要在每一道边界找到上一层交给下一层的稳定标识,再验证请求确实被该对象处理。已有Kubernetes 核心概念介绍词汇,本篇聚焦节点的身份链,不重述控制面全集。 “已分配节点”只解决了哪个问题 调度器为一个尚未指定节点的 Pod 选择 spec.nodeName,这表明控制面希望某台节点承担它,不表明该节点已拉取镜像、配置网络,更不表明探针可用。kubelet 按本机应处理的 Pod 做协调,所需镜像可能尚未拉下,Pod sandbox 可能失败,应用也可能启动后立即退出。kubectl get pod -o wide 能给出节点与当前 IP,却不能通过显示的 Running 推断某一次业务请求已经落到哪只进程。下一篇讨论资源约束,28 讨论 Ready 与业务成功;本篇先解决“这是什么对象”的问题。 选一...
容器 25:跨主机路径为什么会出现小包通大包失败
24在一台节点内创建接口与地址;两台宿主是否互通还取决于 underlay 路由和封装路径。把 Pod IP “看着在同一个网段”当成两台物理宿主共享一个二层网络的证据,容易在 MTU 边界上失败。VXLAN 等 overlay 会增加外层头部,同样的应用报文占用更多 underlay 字节,但具体开销依 IP 家族与报文头选项而变,不能在未抓包时抄一个固定减数。 两端都要记录 直路由路径要使两端宿主知道对端 Pod 子网经哪个下一跳到达;封装路径则由 overlay 端点把内层包封装为外层 UDP/IP,并靠 underlay 递送到另一端。无论哪种,先在两台独立 VM 固定 IP、路由表、接口 MTU 和过滤规则,双端抓包,再逐次提高自建探针请求负载的报文大小。若小包成功、大包失败,比较内层 DF/分片、外层包长、ICMP Packet Too Big 和 PMTU 发现,不能只说“网络不稳定”。 正常例应验证小包与不超过路径 MTU 的大包均到达;边界例将受控 overlay 接口 MTU 配错,使请求在确定阈值附近失败,再调整仅属于实验的配置并复核双端结果。计时与丢包只报...
容器 24:CNI 接口由谁调用,失败怎样回收
手工执行22 的 ip 命令可以构造连通路径,但节点运行时还要重复地给新进程挂接网络,并在失败时回收地址、设备与路由。CNI 规范定义调用方与插件之间的配置、输入环境、输出和操作接口,不是一个指定必须使用 bridge 或 VXLAN 的数据面。 把意图、调用、对象串起来 调用方给插件网络配置、容器 ID、netns 路径和接口名,执行 ADD;插件/链式配置可能交给 IPAM 分配地址并创建 veth、bridge 连接、路由,再返回地址和接口信息。CHECK 用于适用版本的状态核对;DEL 释放自己创建的网络资源。命令成功也不能单独证明业务连通,应该把输出配置的 IP 对应到 namespace inode、内核网络对象及一次真实请求。各操作的幂等、失败恢复前提需要对选定插件的固定版本源码再验证,不对所有插件宣称绝对原子。 正常实验必须在专用 VM 固定 CNI spec、插件和 IPAM 版本,先建两个自有 netns,逐个执行 ADD/CHECK/DEL,前后读取 veth、地址租约、路由;异常例故意使第二步失败,再调用 DEL 并确认设备与 IP 真正释放,二次执行结果...
容器 23:bridge、端口发布和 DNS 各在哪一跳
22 的 veth只是一段二层链路;把几段 veth 的宿主侧接进 bridge 才可能形成一个二层转发域。外部从宿主端口进入、容器把名字解析成地址、应用真正监听到这个地址,又是不同的链路步骤。不能看到 `docker -p` 就把 DNS、路由、NAT 都说成“bridge 干的”。 两条访问路径要分开画 对同一 bridge 子网中两个端点,发送方按照目标 IP/路由挑下一跳,经 veth 到宿主 bridge,再依据二层目的 MAC 转发。对宿主公开端口,请求的原始目标是宿主 IP:端口;具体实现可通过 NAT/代理把流量送入容器 IP:端口,需要核对当时的规则和 conntrack 元组,不能把容器 IP:端口的直连记录冒充端口发布记录。DNS 把名字变成地址,解析成功后仍可能因服务只在 loopback 监听、规则丢包或目标端口未打开而失败。 专用 VM 正例应给同一个 probe-app 分别测试“容器 IP 直连”“宿主发布端口”“名字解析后访问”,记录请求前后源/目的元组、路由、conntrack 与 DNS 结果。三个反例依次让探针只监听 127.0.0.1、让...
容器 22:两个隔离进程怎样通过 veth 通信
02中的 UTS 变更使一侧看到另一主机名。网络 namespace 则把设备、路由、地址与端口状态分隔开:单有独立 netns 并不能让两个进程通信。两端的报文必须经过明确建立的连接与正确配置的地址、路由;veth 是一对虚拟二层端点,不会自动给另一端分配 IP。 从内核对象推导路径 让进程 A、B 分别进入两个 netns:每一侧起初可只看到自己的 loopback 设备;需先把 lo 置 up,建立 veth 对,把两个端点分别放入 netns,给接口分配互通地址与路由,确认 ARP/邻居条目及链路状态,再用同一 probe_app.py 的 /health 观测端到端访问。对同一网段的直连流量,veth 负责把一端送出的二层帧交给另一端;想连第三个网段需路由/网关,不是再加一个 curl 就能自动到达。IP 地址和监听地址各有作用:只监听 127.0.0.1 的服务不会因 veth 配通而自动变得可从另一 netns 访问。 本云端可以安全调用 unshare -Ur -n;原始记录显示新 netns inode net:[4026532574] 与原来 net:[402...











