【容器】k8s获取的节点oom事件并输出到node事件

news2024/11/25 20:45:23

在debug k8s node不可用过程中,有可能会看到:

System OOM encountered, victim process: xx

为了搞清楚oom事件是什么,以及如何产生的,我们做了一定探索,并输出了下面的信息。(本文关注oom事件是如何生成&传输的,具体cadvisor如何判定oom不在本片的讨论范围)

解析

主要代码文件:

1)pkg.kubelet.oom.oom_watcher_linux.go

oom_watcher主要描述了kubelet是如何接受并log系统产生的oom事件的

2)oom_watcher_linux.go:

NewWatcher方法会返回一个Watcher类型的对象,该对象包含recorder和oomStreamer。recorder用于记录,oomStreamer是一个OomParser(Cadvisor)类型的对象, 用于将OomInstance类型的对象写入outStream管道(channel)

package oom

import (
    "fmt"

    v1 "k8s.io/api/core/v1"
    "k8s.io/apimachinery/pkg/util/runtime"
    "k8s.io/client-go/tools/record"
    "k8s.io/klog/v2"

    "github.com/google/cadvisor/utils/oomparser"
)

// streamer 接口定义了一个 StreamOoms 函数,
// 它接收一个 oomparser.OomInstance 类型的 channel,存储OomInstance类型数据
type streamer interface {
    StreamOoms(chan<- *oomparser.OomInstance)
}

var _ streamer = &oomparser.OomParser{}

type realWatcher struct {
    recorder    record.EventRecorder
    oomStreamer streamer
}

var _ Watcher = &realWatcher{}

// NewWatcher creates and initializes a OOMWatcher backed by Cadvisor as
// the oom streamer.
// 启动一个新的OOM watcher, 参数是一个 EventRecorder
// EventRecorder 是一个能够存储event并记录到一个queue里的Interface
// 函数声明中前面的括号里面是函数形参列表;后面的括号里面是函数返回值列表。
func NewWatcher(recorder record.EventRecorder) (Watcher, error) {
// 生成一个oomStreamer,由cadvisor的oomparser创建
    oomStreamer, err := oomparser.New()
    if err != nil {
        return nil, err
    }
// 生成一个watcher,包含上面的两个对象: recorder 和 oomStreamer
    watcher := &realWatcher{
        recorder:    recorder,
        oomStreamer: oomStreamer,
    }

    return watcher, nil
}

// Start watches for system oom's and records an event for every system oom encountered.
func (ow *realWatcher) Start(ref *v1.ObjectReference) error {
// 这段代码用来创建一个outStream channel,它是一个由 oomparser.OomInstance 
// 类型指针元素的channel,并可以向channel中传输10个元素。接着就启动了一个goroutine,
// 该goroutine调用ow.oomStreamer.StreamOoms方法并将outStream作为参数传入。该方法会往outStream channel中不断地写数据(即oom instance对象)
    outStream := make(chan *oomparser.OomInstance, 10)
    go ow.oomStreamer.StreamOoms(outStream)

    go func() {
        defer runtime.HandleCrash()
// 从outStream 读取event,并根据判断条件做是否oom。并输出相应的log
        for event := range outStream {
            if event.VictimContainerName == recordEventContainerName {
                klog.V(1).InfoS("Got sys oom event", "event", event)
                eventMsg := "System OOM encountered"
                if event.ProcessName != "" && event.Pid != 0 {
                    eventMsg = fmt.Sprintf("%s, victim process: %s, pid: %d", eventMsg, event.ProcessName, event.Pid)
                }
                ow.recorder.Eventf(ref, v1.EventTypeWarning, systemOOMEvent, eventMsg)
            }
        }
        klog.ErrorS(nil, "Unexpectedly stopped receiving OOM notifications")
    }()
    return nil
}

再来看下kubelet.go中如何应用
kubelet.go:
创建oomWatcher

# 通过上面的NewWathcher方法创建一个新的oomWatcher
oomWatcher, err := oomwatcher.NewWatcher(kubeDeps.Recorder)
# 如果创建新的oomWatcher报错,则查看原因
if err != nil {
    if libcontaineruserns.RunningInUserNS() {
        if utilfeature.DefaultFeatureGate.Enabled(features.KubeletInUserNamespace) {
            // oomwatcher.NewWatcher returns "open /dev/kmsg: operation not permitted" error,
            // when running in a user namespace with sysctl value `kernel.dmesg_restrict=1`.
            klog.V(2).InfoS("Failed to create an oomWatcher (running in UserNS, ignoring)", "err", err)
            oomWatcher = nil
        } else {
            klog.ErrorS(err, "Failed to create an oomWatcher (running in UserNS, Hint: enable KubeletInUserNamespace feature flag to ignore the error)")
            return nil, err
        }
    } else {
        return nil, err
    }
}

启动oomWatcher

    // Start out of memory watcher.
    if kl.oomWatcher != nil {
        if err := kl.oomWatcher.Start(kl.nodeRef); err != nil {
            return fmt.Errorf("failed to start OOM watcher: %w", err)
        }
    }

图示

在这里插入图片描述

上面的代码体现的就是如下流程,下图较完整描述了oom事件是如何被cAdvisor读取最终输出到node的事件的。

图片参考:启动oomWatcher

参考

1)https://www.jianshu.com/p/ef524b0b0119

2)启动oomWatcher

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

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

相关文章

LeetCode-1463. 摘樱桃 II【数组 动态规划 矩阵】

LeetCode-1463. 摘樱桃 II【数组 动态规划 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;动态规划一般有自顶向下和自底向上两种编写方式&#xff0c;其中自顶向下也被称为「记忆化搜索」。解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一…

HBase 读写流程

HBase 读写流程 1. 读流程 Client先访问zookeeper&#xff0c;从zookeeper获取meta region的位置从meta region中读取meta表中的数据&#xff0c;meta中存储了用户表的region信息&#xff1b;根据namespace、表名和rowkey在meta表中找到对应的region信息&#xff1b;找到这个r…

深入剖析Spring框架:推断构造方法与@Bean注解的内部机制

你好&#xff0c;我是柳岸花开。 Spring框架作为Java开发中广泛使用的基础架构&#xff0c;其设计精巧、功能强大&#xff0c;尤其是其依赖注入&#xff08;DI&#xff09;和控制反转&#xff08;IoC&#xff09;特性&#xff0c;极大地提高了代码的可维护性和可测试性。本文将…

9. Django Admin后台系统

9. Admin后台系统 Admin后台系统也称为网站后台管理系统, 主要对网站的信息进行管理, 如文字, 图片, 影音和其他日常使用的文件的发布, 更新, 删除等操作, 也包括功能信息的统计和管理, 如用户信息, 订单信息和访客信息等. 简单来说, 它是对网站数据库和文件进行快速操作和管…

SpringBoot项目部署到阿里云服务器

部署步骤 步骤分以下&#xff1a; 将SpringBoot项目打包Linux上准备好Java环境、可用的MySql数据库项目上传到服务器启动项目停止项目 1.SpringBoot项目打包 数据库的链接&#xff0c;账户和密码需要和Linux上一致。 如上图打包即可。 2.Linux上准备好Java环境以及Mysql环境…

【数据结构】二叉树知识点详解

树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合有一个特殊的结点&#xff0c;称为根结点&#xff0c;根节点没有前驱结点除根节点外&#xff0c;其余结点被分成M(M>0)个互不相交的集合T1、T2、…

【busybox记录】【shell指令】expand

目录 内容来源&#xff1a; 【GUN】【expand】指令介绍 【busybox】【expand】指令介绍 【linux】【expand】指令介绍 使用示例&#xff1a; 把制表符转化为空格 - 默认输出 把制表符转化为空格 - 修改制表符转空格的个数 把制表符转化为空格 - 修改制表符转空格的个数…

git bash各分支修改内容不同但合并后不显示冲突问题

在跟着廖雪峰老师的git学习时&#xff0c;按部就班的执行明后&#xff0c;发现 而不是出现原文的结果 解决方法&#xff1a; 切换位feature分支&#xff0c;再合并 git switch feature1 git merge master 此时我们发现&#xff1a; 后面再跟着原文敲就可以了

CSS学习笔记之基础教程(二)

上节内容CSS学习笔记之基础教程&#xff08;一&#xff09; 6、边距 6.1 外边距&#xff1a;margin 6.1.1 外边距 marginmargin-topmargin-leftmargin-bottommargin-right <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8…

python-scrapy框架示例

参考&#xff1a;https://blog.csdn.net/qq_44907926/article/details/119531324 创建项目步骤&#xff1a; 1.目标网站:www.itcast.cn 2.安装虚拟环境 pip install virtualenv3.创建虚拟环境 virtualenv --always-copy --system-site-packages venv4.激活虚拟环境 venv\sc…

OCR文本识别模型CRNN

CRNN网络结构 论文地址&#xff1a;https://arxiv.org/pdf/1507.05717 参考&#xff1a;https://blog.csdn.net/xiaosongshine/article/details/112198145 git:https://github.com/shuyeah2356/crnn.pytorch CRNN文本识别实现端到端的不定长文本识别。 CRNN网络把包含三部分&…

推荐5个免费的国内平替版GPT

提起AI&#xff0c;大家第一个想到的就是GPT。 虽然它确实很厉害&#xff0c;但奈何于我们水土不服&#xff0c;使用门槛有些高。 不过随着GPT的爆火&#xff0c;现在AI智能工具已经遍布到各行各业了&#xff0c;随着时间的推移&#xff0c;国内的AI工具也已经“百花盛放”了…

简单了解泛型

基本数据类型和对应的包装类 在Java中, 基本数据类型不是继承自Object, 为了在泛型代码中可以支持基本类型, Java给每个基本类型都对应了一个包装类型. 简单来说就是让基本数据类型也能面向对象.基本数据类型可以使用很多方法, 这就必须让它变成类. 基本数据类型对定的包装类…

Istio 流量管理(请求路由、流量转移、请求重试、流量镜像、故障注入、熔断等)介绍及使用

一、Istio 流量管理 Istio是一个开源的服务网格&#xff0c;它为分布式微服务架构提供了网络层的抽象。它使得服务之间的通信变得更为可靠、安全&#xff0c;并且提供了细粒度的流量管理、监控和策略实施功能。Istio通过在服务之间插入一个透明的代理&#xff08;Envoy&#x…

Unreal游戏GPU参数详解,游戏性能优化再升级

UWA GOT Online For Unreal GPU模式近期全新发布&#xff0c;方便开发者从渲染和带宽的角度进行GPU分析。同时&#xff0c;此次更新中UWA也增加了丰富的GPU参数&#xff0c;涵盖了GPU SoC和GPU Counter模块。这些新增的参数不仅能够帮助Unreal开发者从宏观层面监控GPU的压力状况…

QT-TCP通信

网上的资料太过于书面化&#xff0c;所以看起来有的让人云里雾里&#xff0c;看不懂C-tcpsockt和S-tcpsocket的关系 所以我稍微画了一下草图帮助大家理解两个套接字之间的关系。字迹有的飘逸勉强看看 下面是代码 服务端&#xff1a; MainWindow::MainWindow(QWidget *parent) …

Jira Server 不维护了,如何将 Jira 平滑迁移到阿里云云效

作者&#xff1a;天彤 Atlassian 在 2020 年官方发布公告&#xff0c;从 2021 年起停止 Jira Server 产品的销售&#xff0c;并且在 2024 年彻底停止 Server 端产品的服务支持&#xff0c;这对于国内使用 Jira 产品的企业和研发团队造成了不小的影响。而此时国内很多 DevOps 产…

本地主机访问服务器的Redis -- 配置 ssh 端口转发

前言 在进行Java开发时&#xff0c;高度的依赖 Windows 上的开发软件 idea &#xff0c;那么我们想访问位于服务器上的 redis 怎么办呢&#xff1f;在平时我们想访问位于服务器上的程序&#xff0c;只需要开放它的端口即可&#xff0c;比如我们创建的网站&#xff0c;比如 tomc…

【拆位法 决策包容性 位运算】2871. 将数组分割成最多数目的子数组

本文涉及知识点 拆位法 贪心 位运算 决策包容性 位运算、状态压缩、子集状态压缩汇总 LeetCode2871. 将数组分割成最多数目的子数组 给你一个只包含 非负 整数的数组 nums 。 我们定义满足 l < r 的子数组 nums[l…r] 的分数为 nums[l] AND nums[l 1] AND … AND nums[r…

使用图网络和视频嵌入预测物理场

文章目录 一、说明二、为什么要预测&#xff1f;三、流体动力学模拟的可视化四、DeepMind神经网络建模五、图形编码六、图形处理器七、图形解码器八、具有不同弹簧常数的轨迹可视化九、预测的物理编码和推出轨迹 一、说明 这是一篇国外流体力学专家在可视化流体物理属性的设计…