cAdvisor_Advisor

cAdvisor_Advisor一.cadvisor和k8s的耦合cadvisor是一个谷歌开发的容器监控工具,它被内嵌到k8s中作为k8s的监控组件。现在将k8s中的cadvisor实现分析一下。k8s中和cadvisor的

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一. cadvisor和k8s的耦合

cadvisor是一个谷歌开发的容器监控工具,它被内嵌到k8s中作为k8s的监控组件。现在将k8s中的cadvisor实现分析一下。

k8s中和cadvisor的代码主要在./pkg/kubelet/cadvisor目录下。在当前k8s版本(v1.13)中,kubelet主要调用的cadvisor方法如下:

MachineInfo
RootFsInfo
VersionInfo
GetDirFsInfo

GetFsInfo

—————————————
ContainerInfoV2
SubcontainerInfo
ContainerInfo
WatchEvents

分割线之上的方法和cadvisor本身耦合较松,分割线之下的方法则和cadvisor耦合紧密。怎么样理解这里的耦合度呢?举例来说,对于分割线

之上的方法,例如MachineInfo,它的操作只是简单的读取本地文件以获取主机的信息。比如通过读取/proc/cpuinfo文件读取本地主机的cpu信息。

对于这种方法,我们可以非常轻松的移植他们。

而分割线之下的方法则很难从cadvisor中单独剥离出来,它们的实现是依赖于整个cadvisor的体系。下面分析一下cadvisor具体的实现

 

二. 事件监听层

cadvisor的架构简单来说就是一个event机制。它基本上可以分为两层,事件监听层和事件处理层。事件监听层负责监听linux系统发生的事件,而事件处理层

负责对这些事件进行处理。

首先说说事件监听层。事件监听层主要包含两个监听者,ContainerAdd事件和OOM事件。其对应的函数是watchForNewContainers, watchForNewOoms。

watchForNewContainers完成的事情是启动每一个watcher。代码如下,可以看到和watcher交互的是eventsChannel。目前cadvisor中包含两种wathcer, 一个是rawWatcher,另一个是rktWatcher。

    for _, watcher := range self.containerWatchers {
        err := watcher.Start(self.eventsChannel)
        if err != nil {
            return err
        }
    }

rawWatcher直接监控系统的cgroup根目录,而rktWatcher似乎是与rkt的client进行交互,由于rkt不是主流的技术,因此我们目前主要研究rawWatcher。这个watcher的代码在./manager/watcher/raw目录下。

稍作分析就可以看出这个watcher是调用了github.com/sigma/go-inotify库,这个库简单来说就是利用linux的inotify机制对cgroup根目录进行监听,如果根目录创建了新的目录,那么它就会触发一个ContainerAdd的事件。

然后将事件发送到上面代码中的self.eventsChannel中。注意linux的inotify机制会监听目录的增删改。而这里rawWatcher只对目录的增删感兴趣。也就是说它只对容器的创建和删除感兴趣,对容器本身状态的变化不感兴趣。

对函数rawContainerWatcher.watchDirectory的代码稍作分析不难发现,它是一个递归调用的结构。如果用户请求对任何目录进行监听,它会一并监听这个目录下的所有子目录。

 

watchForNewOoms是为了监控OOM事件,它的执行流程与container watcher类似,只不过调用的库是github.com/euank/go-kmsg-parser/,这个库的原理是读取linux系统的/dev/kmsg字符串设备。这个字符串设备的大概

意思是将系统的事件报告出来。其核心代码如下。

    outStream := make(chan *oomparser.OomInstance, 10)
    oomLog, err := oomparser.New()
    if err != nil {
        return err
    }
    go oomLog.StreamOoms(outStream)

    go func() {
        for oomInstance := range outStream {
            // Surface OOM and OOM kill events.
            newEvent := &info.Event{
                ContainerName: oomInstance.ContainerName,
                Timestamp:     oomInstance.TimeOfDeath,
                EventType:     info.EventOom,
            }
            err := self.eventHandler.AddEvent(newEvent)
            if err != nil {
                klog.Errorf("failed to add OOM event for %q: %v", oomInstance.ContainerName, err)
            }

 

三 事件处理层

事件监听层将event发送到self.eventsChannel上,这些event包含了,ContainerAdd, ContainerDelete,EventOomKill三种。这三种事件分两类进行处理,对于ContainerAdd和ContainerDelete, Manager分别

调用CreateContainer和ContainerDestroy方法,然后调用self.eventHandler.AddEvent(event)方法。而EventOomkill事件则只调用self.eventHandler.AddEvent(event)方法,没有其他特殊的处理。

那么这个eventHandler是干啥的呢。这个东西实际上就是一个缓冲区,我们看一下这个evnetHandler的数据结构。它的核心数据结构就是events.watchers,它维护了一组watch,每一个watch存储了一个channel和一个

request。这个request其所在的watch想要监听的事件特性。evnetsHandler每当接收到新的事件的时候,它会根据这个事件的类型分发给各个watch。

 

// events provides an implementation for the EventManager interface.
type events struct {
    // eventStore holds the events by event type.
    eventStore map[info.EventType]*utils.TimedStore
    // map of registered watchers keyed by watch id.
    watchers map[int]*watch
    // lock guarding the eventStore.
    eventsLock sync.RWMutex
    // lock guarding watchers.
    watcherLock sync.RWMutex
    // last allocated watch id.
    lastId int
    // Event storage policy.
    storagePolicy StoragePolicy
}

// initialized by a call to WatchEvents(), a watch struct will then be added
// to the events slice of *watch objects. When AddEvent() finds an event that
// satisfies the request parameter of a watch object in events.watchers,
// it will send that event out over the watch object's channel. The caller that
// called WatchEvents will receive the event over the channel provided to
// WatchEvents
type watch struct {
    // request parameters passed in by the caller of WatchEvents()
    request *Request
    // a channel used to send event back to the caller.
    eventChannel *EventChannel
}

// Request holds a set of parameters by which Event objects may be screened.
// The caller may want events that occurred within a specific timeframe
// or of a certain type, which may be specified in the *Request object
// they pass to an EventManager function
type Request struct {
    // events falling before StartTime do not satisfy the request. StartTime
    // must be left blank in calls to WatchEvents
    StartTime time.Time
    // events falling after EndTime do not satisfy the request. EndTime
    // must be left blank in calls to WatchEvents
    EndTime time.Time
    // EventType is a map that specifies the type(s) of events wanted
    EventType map[info.EventType]bool
    // allows the caller to put a limit on how many
    // events to receive. If there are more events than MaxEventsReturned
    // then the most chronologically recent events in the time period
    // specified are returned. Must be >= 1
    MaxEventsReturned int
    // the absolute container name for which the event occurred
    ContainerName string
    // if IncludeSubcontainers is false, only events occurring in the specific
    // container, and not the subcontainers, will be returned
    IncludeSubcontainers bool
}

 

 

剩下的事就很简单了,对于任何ContainerAdd事件,manager维护了一组工厂类,每一个类对应一种container类型。这些工厂类定义在./container中。manager分析ContainerAdd事件中的相关信息,将它传递

给对应的工厂类,工厂类为container生成一个对应的handler并且存储起来,handler执行具体的监控任务。具体来说就是定期读取container对应的cgroup文件。从中获取信息。handler将读取到的数据存储到自己的缓存memoryCache中。

handler的包装类型是containerData

 

四. k8s中用到的几个关键函数

GetContainerV2(),直接获取它想要的container对应的handler,然后读取其中memoryCache的状态数据

WatchEvents(),这个函数主要是OOMWatcher在调用,它暴露出一个channel给OOMWatcher用以监听系统的OOMWatcher事件

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/166472.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • python和c++哪个好_run pycharm community edition

    python和c++哪个好_run pycharm community edition在pycharm中使用django命令的过程中经常会用到pythonmanage.py相关的命令,每次都输入pythonmanage.py会比较麻烦,可以利用pycharm提供的tools来省去pythonmanage.py的重复输入。具体实现过程如下:先进入settings完成如下操作随后可勾选Tools中的Runmanage.pyTask完成后即可以直接输入manag…

  • TP传输的两种模式

    TP传输的两种模式

  • python lambda表达式 if_Python学习-lambda表达式

    python lambda表达式 if_Python学习-lambda表达式lambda只是一个表达式,函数体比def简单很多。lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。lambda表达式是起到一个函数速写的作用。允许在代码内嵌入一个函数的定义。#求三个数的和1f=lambdax,y,z:x+y+x2print(f(1,2,3))#434f=lambdax,y,z:x+y+z5print(…

    2022年10月18日
  • word文件都变成了白色的图标了,该怎么处理?-ZOL问答_word图标变成白底docx

    word文件都变成了白色的图标了,该怎么处理?-ZOL问答_word图标变成白底docxwin10word图标变白了怎么办?在win10操作系统中当我们需要使用一些办公软件office,当我们在win10系统中安装了office之后,桌面上出现了excel、word以及PowerPoint等图标,这些图标上竟然都显示不正常,在图标上面有一个白色的图标,变白的现象该怎么办呢?针对这样的现象一般是缓存文件引起的,下面给大家介绍下win10word图标变成白底的解决方法。word图标…

    2022年10月19日
  • iPhone 各屏幕尺寸及解析[通俗易懂]

    一.iPhone各屏幕尺寸表手机型号屏幕物理尺寸屏幕密度开发尺寸像素尺寸倍图4/4s3.5inch326ppi320*480pt640*960px@2×5/5S/5c/SE4.0inch326ppi320*568pt640*1136px@2×6/6S/7/84.7inch326ppi375*667pt75…

  • Oracle 时间戳转Date

    Oracle 时间戳转Date当前系统时间向前推一个月selectto_char(add_months(sysdate,-1),’yyyy-mm-ddhh24:mi:ss’)fromdual根据13位毫秒向前推一个月,转换为dateselectto_char(add_months(TO_DATE(TO_CHAR(1564588800000/(1000*60*60*24)+…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号