Kubelet 探针如何选择 IP:status.PodIP 溯源与“同 Pod 两个 IP“现象解析

背景与现象

同一个 Pod 的 readiness 和 liveness 探针日志显示连接的 IP 不一致(例如 10.10.6.10:999910.10.6.32:9999)。本文从 kubelet 源码入手,解释探针目标 IP 的来源、为何会出现两个不同 IP,并给出建议与验证方法。

在如下探针配置下:

readinessProbe:initialDelaySeconds: 5periodSeconds: 10tcpSocket:port: 9999timeoutSeconds: 1
livenessProbe:initialDelaySeconds: 60periodSeconds: 15tcpSocket:port: 9999timeoutSeconds: 1

结论摘要

  • tcpSocket.host 未显式设置时,kubelet 探针使用“当下缓存”的 status.PodIP 作为目标主机。

  • readiness 与 liveness 是两个独立的 worker,按各自的周期、初始延迟读取 kubelet 的状态缓存。如果 Pod 在两次读取之间被重建(sandbox 重建、CNI 重新分配 IP),两者可能各自命中旧/新 IP,因此日志出现两个不同 IP。

源码调用链(关键片段)

  • 探针(TCP)如何选择主机:若 TCPSocket.Host 为空,使用 status.PodIP

if p.TCPSocket != nil {port, err := extractPort(p.TCPSocket.Port, container)if err != nil {return probe.Unknown, "", err}host := p.TCPSocket.Hostif host == "" {host = status.PodIP}klog.V(4).InfoS("TCP-Probe Host", "host", host, "port", port, "timeout", timeout)return pb.tcp.Probe(host, port, timeout)
}
  • 探针在每次执行前从 status manager 读取“当下缓存”的 v1.PodStatus

status, ok := w.probeManager.statusManager.GetPodStatus(w.pod.UID)
if !ok {// Either the pod has not been created yet, or it was already deleted.klog.V(3).InfoS("No status for pod", "pod", klog.KObj(w.pod))return true
}
  • status manager 的读取接口(返回缓存的 v1.PodStatus):

func (m *manager) GetPodStatus(uid types.UID) (v1.PodStatus, bool) {m.podStatusesLock.RLock()defer m.podStatusesLock.RUnlock()status, ok := m.podStatuses[types.UID(m.podManager.TranslatePodUID(uid))]return status.status, ok
}
  • kubelet 如何生成 PodIPs/PodIP 并写入 v1.PodStatus(先排序,再取首个作为 PodIP):

podIPs = kl.sortPodIPs(podIPs)
for _, ip := range podIPs {apiPodStatus.PodIPs = append(apiPodStatus.PodIPs, v1.PodIP{IP: ip})
}
if len(apiPodStatus.PodIPs) > 0 {apiPodStatus.PodIP = apiPodStatus.PodIPs[0].IP
}
  • Pod 的 IP 列表来自 CRI 报告的 sandbox 网络状态:

func (m *kubeGenericRuntimeManager) determinePodSandboxIPs(podNamespace, podName string, podSandbox *runtimeapi.PodSandboxStatus) []string {podIPs := make([]string, 0)if podSandbox.Network == nil {klog.InfoS("Pod Sandbox status doesn't have network information, cannot report IPs", "pod", klog.KRef(podNamespace, podName))return podIPs}if len(podSandbox.Network.Ip) != 0 {if net.ParseIP(podSandbox.Network.Ip) == nil {klog.InfoS("Pod Sandbox reported an unparseable primary IP", "pod", klog.KRef(podNamespace, podName), "IP", podSandbox.Network.Ip)return nil}podIPs = append(podIPs, podSandbox.Network.Ip)}for _, podIP := range podSandbox.Network.AdditionalIps {if nil == net.ParseIP(podIP.Ip) {klog.InfoS("Pod Sandbox reported an unparseable additional IP", "pod", klog.KRef(podNamespace, podName), "IP", podIP.Ip)return nil}podIPs = append(podIPs, podIP.Ip)}return podIPs
}
  • 当 sandbox 变化时,kubelet 会覆盖当前的 podIPs

if !kubecontainer.IsHostNetworkPod(pod) {// Overwrite the podIPs passed in the pod status, since we just started the pod sandbox.podIPs = m.determinePodSandboxIPs(pod.Namespace, pod.Name, podSandboxStatus)klog.V(4).InfoS("Determined the ip for pod after sandbox changed", "IPs", podIPs, "pod", klog.KObj(pod))
}
  • 仅从“最新且 READY 的” sandbox 读取 IP:

// Only get pod IP from latest sandbox
if idx == 0 && podSandboxStatus.State == runtimeapi.PodSandboxState_SANDBOX_READY {podIPs = m.determinePodSandboxIPs(namespace, name, podSandboxStatus)
}
  • TCP 探针最终发起连接的位置:

func (pr tcpProber) Probe(host string, port int, timeout time.Duration) (probe.Result, string, error) {return DoTCPProbe(net.JoinHostPort(host, strconv.Itoa(port)), timeout)
}
  • hostNetwork 场景:若 PodIP 为空,用节点 IP 初始化 PodIP/PodIPs

s.HostIP = hostIPs[0].String()
if kubecontainer.IsHostNetworkPod(pod) && s.PodIP == "" {s.PodIP = hostIPs[0].String()s.PodIPs = []v1.PodIP{{IP: s.PodIP}}if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) && len(hostIPs) == 2 {s.PodIPs = append(s.PodIPs, v1.PodIP{IP: hostIPs[1].String()})}
}

流程图

为什么会出现两个不同的 IP

  • readiness 与 liveness 的 worker 独立运行、定时时间不同;每次探测都“就地读取”缓存中的 v1.PodStatus

  • 若该 Pod 在两次读取之间 sandbox 重建(IP 变化),一个 worker 可能还读到旧 IP,另一个已经读到新 IP,于是日志显示不同地址。

  • 双栈时,sortPodIPs 会按节点 IP 家族偏好排序,导致 PodIP(主 IP)在不同条件下选择不同家族的地址,也会引起切换。

  • timeoutSeconds=1 对 TCP 探针较苛刻,网络抖动时更易出现超时和重试导致的时序差异。

配置与排查建议

  • 合理的时序参数:为 TCP 探针设置更宽松的 timeoutSecondsfailureThreshold,降低瞬时抖动影响。

  • 显式 host(可选):在明确网络拓扑的前提下设置 tcpSocket.host,避免依赖 status.PodIP 切换窗口。

  • 关注 hostNetwork 与双栈:hostNetwork 以节点 IP 为准;双栈可能改变主 IP 选择。

  • 对齐重建时间线:结合 CNI/runtime 与 kubelet 日志,确认 IP 切换是否由 sandbox 重建触发。

FAQ

  • status.PodIP 存在哪里?

    • 在 kubelet 的内存缓存(status manager)中,以 UID -> versionedPodStatus 记录,探针通过 GetPodStatus 读取。

  • 探针为什么不使用“同一时刻”的统一状态?

    • readiness/liveness 分属不同 goroutine,按各自周期读取缓存的快照,没有全局“同一时刻”的合并视图。

  • 非 hostNetwork Pod 的 PodIP 从何而来?

    • 来自 CRI 的 sandbox 网络状态(primary + additional IPs),经 kubelet 排序、选主后写入。

参考文件清单

官方源码https://github.com/kubernetes/kubernetes/tree/release-1.22

  • pkg/kubelet/prober/prober.go

  • pkg/kubelet/prober/worker.go

  • pkg/kubelet/status/status_manager.go

  • pkg/kubelet/kubelet_pods.go

  • pkg/kubelet/kuberuntime/kuberuntime_manager.go

  • pkg/kubelet/kuberuntime/kuberuntime_sandbox.go

  • pkg/probe/tcp/tcp.go

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92386.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92386.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Arm Development Studio 安全通告:CVE-2025-7427

安全之安全(security)博客目录导读 目录 一、概述 二、CVE 详情 三、受影响产品 四、建议 五、致谢 六、版本历史 一、概述 ARM已知悉一个影响 Arm Development Studio 的安全漏洞,该漏洞可能允许攻击者执行 DLL 劫持攻击(DLL hijacking attack&…

C#异步编程双利器:异步Lambda与BackgroundWorker实战解析

**摘要:**深入剖析两种异步编程范式,解决GUI线程阻塞难题 一、异步Lambda表达式:事件处理的轻量化利器 核心价值:简化事件响应中的异步操作,避免UI线程阻塞 ✅ 典型应用场景(WPF示例)&#xff1…

yolo world (1): 论文解读

YOLO 系列检测器以其高效性和实用性而闻名。然而,它们依赖于预定义和训练的目标类别,这限制了其在开放场景中的适用性。为了解决这一限制,我们提出了 YOLO-World,这是一种创新的方法,通过视觉-语言建模和大规模数据集预训练,增强了 YOLO 的开放词汇检测能力。具体来说,我…

【JVM】深入解析Java虚拟机

目录 1. 区分JDK,JRE 和 JVM 1.1 JVM 1.2 JRE 1.3 JDK 1.4 关系总结 2. 跨平台性 3. JVM中的内存划分 4. JVM的类加载机制 5. 双亲委派模型 6. 垃圾回收机制(GC) 6.1 识别垃圾 6.1.1 单个引用 6.1.2 多个引用 6.2 释放垃圾 6.…

98-基于Python的网上厨房美食推荐系统

基于Python的网上厨房美食推荐系统 - 技术分享博客 📋 目录 项目概述技术栈系统架构核心功能实现数据库设计推荐算法数据可视化部署与优化项目特色总结与展望 🎯 项目概述 项目背景 随着生活节奏的加快,越来越多的人开始关注美食制作&…

创建MyBatis-Plus版的后端查询项目

记得编码和maven库的检测&#xff01;&#xff01;&#xff01; 1、maven库导入包<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupI…

开发板RK3568和stm32的异同:

RK3568 和 STM32 是两类不同定位的处理器 / 微控制器&#xff0c;在架构、性能、应用场景等方面差异显著&#xff0c;但也存在部分共性。以下从核心特性、异同点及典型场景进行对比&#xff1a;一、核心差异维度RK3568&#xff08;瑞芯微&#xff09;STM32&#xff08;意法半导…

C# 使用iText获取PDF的trailer数据

文章目录C# 使用iText获取PDF的trailer数据iText 核心概念C# 代码示例步骤 1: 确保已安装 iText步骤 2: C# 代码程序运行效果解读 Trailer 的输出总结C# 使用iText获取PDF的trailer数据 开发程序debug的时候&#xff0c;看到了PDF有个trailer数据&#xff0c;挺有意思&#xf…

京东流量资产基于湖仓架构的落地实践

在当今数字化商业浪潮中&#xff0c;数据无疑是企业的核心资产&#xff0c;而流量数据更是电商巨头京东业务运转的关键驱动力。它广泛应用于搜索推荐、广告投放等多个核心业务场景&#xff0c;直接影响着用户体验和商业效益。但随着业务规模的不断膨胀&#xff0c;传统架构在处…

​​​​​​​【Datawhale AI夏令营】多模态RAG财报问答挑战赛:学习笔记与上分思考

一、 初识赛题——从迷茫到清晰刚看到赛题时&#xff0c;坦白说有些不知所措。“多模态”、“RAG”、“图文混排PDF”&#xff0c;这些词汇组合在一起&#xff0c;听起来就像一个庞大而复杂的工程。但当我强迫自己静下心来&#xff0c;从“终点”&#xff08;提交格式和评审规则…

数据挖掘2.6 Perceptron Modeling 感知器建模

Perceptron Modeling 感知器建模Linear Discriminants 线性判别式Loss Function 损失函数misclassification 误分类0-1 Loss/Error function 0-1损失函数Hinge Loss Function 铰链损失函数Optimization 优化算法Linear Discriminants 线性判别式 线性判别式公式 f(x;w)w1x(1)w…

使用qemu运行与GDB调试内核

目录 一、前期准备 二、内核编译 三、QEMU与GDB 1、QEMU调试参数 2、gdb vmlinux 一、前期准备 内核镜像&#xff1a;bzimage gdb&#xff1a;x86_64 QEMU&#xff1a;qemu-system-x86_64 前置知识&#xff1a; &#xff08;1&#xff09;内核编译 &#xff08;2&#x…

欧盟 Radio Equipment Directive (RED)

欧盟 Radio Equipment Directive (RED) ——从 2014/53/EU 原文到 2025-08-01 强制生效的网络安全新规&#xff0c;一次看懂全部关键点。1. 法规身份与适用范围要素内容指令全称Directive 2014/53/EU on radio equipment取代指令1999/5/EC (R&TTE)适用产品所有“有意发射/接…

【FastExcel】解决ReadSheet在Map中获取对象不准确问题(已提交PR并合并到开源社区)

解决问题&#xff1a;源码ReadSheet在同一个Map中获取对象不准确问题 PR&#xff1a;Fixed the issue where different ReadSheet objects could not get the correct value when comparing them. 一&#xff1a;问题场景 ReadSheet在同一个Map中获取对象不准确(如Map<…

【网络安全入门基础教程】TCP/IP协议深入解析(非常详细)零基础入门到精通,收藏这一篇就够了

前言 这是小编给粉丝盆友们整理的网络安全入门到精通系列第三章计算机网络中TCP/IP协议的解析&#xff0c;喜欢的朋友们&#xff0c;记得给大白点赞支持和收藏一下&#xff0c;关注我&#xff0c;学习黑客技术。TCP/IP协议包含了一系列的协议&#xff0c;也叫TCP/IP协议族&…

Latex中公式部分输入正体的字母\mathrm{c}

Latex中公式部分输入正体的字母\mathrm{c}“\mathrm{c}”如何在Word中输入\mathrm{c}“\mathrm{c}” 在 LaTeX 中&#xff0c;“\mathrm{c}” 用于在数学模式中排版“c”这个字母为罗马体&#xff08;正体&#xff09;。“\mathrm” 是罗马字体命令&#xff0c;它告诉LaTeX以罗…

Document Picture-in-Picture API拥抱全新浮窗体验[参考:window.open]

在前端开发中&#xff0c;我们经常会遇到这样的需求&#xff1a;弹出一个浮动窗口来显示一些实时信息、工具栏或视频内容。过去我们会用 window.open()&#xff0c;后来越来越多的开发者倾向于使用 Modal。但现在&#xff0c;一个更现代的 API 出现了——Document Picture-in-P…

【指南版】网络与信息安全岗位系列(三):安全运维工程师

一、安全运维工程师到底做什么&#xff1f;—— 用校园场景帮你理解简单说&#xff0c;安全运维工程师就像 “网络世界的安保队长 系统管家”&#xff1a;既要实时监控网络和系统的 “异常动静”&#xff08;类似学校保安巡逻查隐患&#xff09;&#xff0c;又要负责日常的安全…

matlab——simulink学习(5向NXP库中添加新模块)

向NXP库中添加新的函数模块一、环境二、库添加模块1.打开文件夹2.创建文件3.添加S-Function三、浏览器添加模块一、环境 Windows10、MATLAB R2022b、安装NXP的S32K1XX系列工具包 二、库添加模块 1.打开文件夹 在文件系统中找到安装工具包的位置&#xff0c;用文件资源管理器…