kubelet分析
kubelet是k8s中节点上运行的管理工具,它负责接受api-server发送的调度请求,在Node上创建管理pod,并且向api-server同步节点的状态.这篇文章主要讲讲kubelet组件如何使用docker的.
一.kubecontainer.Runtime
type Kubelet struct {
//....
containerRuntime kubecontainer.Runtime
//...
}
type Runtime interface {
//...
// Type returns the type of the container runtime.
Type() string
// Version returns the version information of the container runtime.
Version() (Version, error)
// Syncs the running pod into the desired pod.
SyncPod(pod *v1.Pod, apiPodStatus v1.PodStatus, podStatus *PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) PodSyncResult
KillPod(pod *v1.Pod, runningPod Pod, gracePeriodOverride *int64) error
GetPodStatus(uid types.UID, name, namespace string) (*PodStatus, error)
//...
}
在类Kubelet中定义了很多的组件和对象,其中containerRuntime就是负责和容器Runtime进行交互的,这里的容器Runtime可以理解为就是docker.我们可以看到, 这个containerRuntime是一个接口类型,这个接口中主要定义了一系列直接操作Pod的函数和获取Runtime信息的函数.其中最关键的函数是SyncPod, 它接受一个Pod的配置信息,启动一次同步,决定启动/更新/删除这个Pod. 目前Runtime接口只有一个实现类,kubeGenericRuntimeManager.
二.kubeGenericRuntimeManager
这个类是kubecontainer.Runtime的实现类,如上述所说,这个类对外暴露的接口是直接对Pod进行管理的.也就是说,这个类对使用者屏蔽了container的概念.对于一个创建Pod的请求,SyncPod函数负责进行处理.这个函数会首先创建一个sandbox,然后依次创建init containers和normal containers. 这里sandbox是用来提供pod层级的namespace隔离,具体细节不在本文的讨论范围之内.kubeGenericRuntimeManager中负责创建container的成员变量是runtimeService.
type kubeGenericRuntimeManager struct {
//...
// gRPC service clients
runtimeService internalapi.RuntimeService
//...
}
三.internalapi.RuntimeService
首先,我们观察一下这个接口的定义,这个接口聚合了好几个其它接口,每一个接口定义了一组操作.runtimeService的实例化函数是getRuntimeAndImageServices().这个函数做的事情稍有点复杂.在解析这个函数之前,首先解析下面这个代码片段,为了便于阅读,只列出了核心代码.
switch containerRuntime {
case kubetypes.DockerContainerRuntime:
//sentence 1
ds, err := dockershim.NewDockerService(kubeDeps.DockerClientConfig, crOptions.PodSandboxImage, streamingConfig,
&pluginSettings, runtimeCgroups, kubeCfg.CgroupDriver, crOptions.DockershimRootDirectory, !crOptions.RedirectContainerStreaming)
//sentence 2
server := dockerremote.NewDockerServer(remoteRuntimeEndpoint, ds)
server.Start()
}
// sentence 3
runtimeService, imageService, err := getRuntimeAndImageServices(remoteRuntimeEndpoint, remoteImageEndpoint, kubeCfg.RuntimeRequestTimeout)
A. sentence 1
这个函数调用的核心功能就是一句话:连接docker.
docker的守护进程会创建一个gPRC服务接口,本质上它是一个默认定义在/var/run/docker.sock的套接字.NewDockerService()函数首先会连接这个套接字,经过包装后,返回一个dockerService类的实例,该实例的client掌握了和docker守护进程的连接.
B. sentence 2
NewDockerServer函数有两个参数,一个是string类型的remoteRuntimeEndpoint,其默认值是/var/run/dockershim.sock.另一个就是NewDockerService函数构建的dockerService实例.在Start()函数中,首先启动dockerService,然后在endpoint(也就是/var/run/dockershim.sock)上启动一个gRPC服务.函数RegisterRuntimeServiceServer()将s.server上的请求映射到s.service上.
// NewDockerServer creates the dockershim grpc server.
func NewDockerServer(endpoint string, s dockershim.CRIService) *DockerServer {
return &DockerServer{
endpoint: endpoint,
service: s,
}
} // Start starts the dockershim grpc server.
func (s *DockerServer) Start() error {
// Start the internal service.
s.service.Start()
l, err := util.CreateListener(s.endpoint)// Create the grpc server and register runtime and image services.
s.server = grpc.NewServer(
grpc.MaxRecvMsgSize(maxMsgSize),
grpc.MaxSendMsgSize(maxMsgSize),
)
runtimeapi.RegisterRuntimeServiceServer(s.server, s.service)
runtimeapi.RegisterImageServiceServer(s.server, s.service)
go func() {
if err := s.server.Serve(l); err != nil {
glog.Fatalf("Failed to serve connections: %v", err)
}
}()
return nil
}
C. sentence 3
sentence 1建立了和docker的连接,sentence 2在/var/run/dockershim.sock上监听gRPC服务并且将收到的请求转发到sentence 1所构建的和docker的连接上.那么sentence 3所完成的事就很简单了,那就是建立到/var/run/dockershim.sock的连接.
四.小结
kubelet和docker的交互简单来说是通过两层gPRC服务来实现的,kubelet自己在/var/run/dockershim.sock启动一层gPRC服务,然后这个gPRC服务将请求转发给docker守护进程所创建的/var/run/docker.sock上.从而完成一次交互.那么kubelet为什么要再创建一层gPRC服务呢?原因是k8s为了兼容其他的container runtime,提出了CRI(container runtime interface)的概念,其理想的模型是kubelet->[x-runtime].sock.也就是说,所有runtime统一实现一个gPRC接口,kubelet直接调用这个接口,这样屏蔽了底层rutime的差异.而dockershim.sock只是这个CRI概念的docker化实现.
五. 其它container runtime
根据上文我们可以知道,CRI的存在是为了屏蔽container runtime的存在,从而使k8s可以更好的支持多种container runtime,例如rkt.那么其它的kubelet是如何管理其它的runtime呢.原来docker的CRI实现是以dockershim的形式存在于k8s的主线代码中了,其它的runtime需要自己实现类似于dockershim的一套gPRC服务给kubelet访问.
kubelet ----container-runtime-endpoint选项就是定义这个gPRC服务的地址的.
kubelet分析的更多相关文章
- kubelet分析-csi driver注册分析-Node Driver Registrar源码分析
kubernetes ceph-csi分析目录导航 Node Driver Registrar分析 node-driver-registrar是一个sidecar容器,通过Kubelet的插件注册机制 ...
- kubelet分析-csi driver注册源码分析
kubelet注册csi driver分析 kubelet注册csi driver的相关功能代码与kubelet的pluginManager有关,所以接下来对pluginManager进行分析.分析将 ...
- kubelet分析-pvc扩容源码分析
kubernetes ceph-csi分析目录导航 存储的扩容分为controller端操作与node端操作两大步骤,controller端操作由external-resizer来调用ceph完成,而 ...
- heapster源码分析——kubelet的api调用分析
一.heapster简介 什么是Heapster? Heapster是容器集群监控和性能分析工具,天然的支持Kubernetes和CoreOS.Kubernetes有个出名的监控agent---cAd ...
- kubelet源码分析(version: git tag 1.7.6)
一.概述 kubelet源码入口:cmd/kubelet/kubelet.go main() cmd/kubelet/app 包中的Run函数: 查看先参数,kubelet.KubeletDeps t ...
- 【原创】k8s源代码分析-----kubelet(1)主要流程
本人空间链接http://user.qzone.qq.com/29185807/blog/1460015727 源代码为k8s v1.1.1稳定版本号 kubelet代码比較复杂.主要是由于其担负的任 ...
- 【原创】k8s源代码分析-----kubelet(8)pod管理
本文QQ空间链接:http://user.qzone.qq.com/29185807/blog/1460540474 本文csdn博客链接:http://blog.csdn.net/screscent ...
- 11.深入k8s:kubelet工作原理及源码分析
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 源码版本是1.19 kubelet信息量是很大的,通过我这一篇文章肯定是讲不全的,大家可 ...
- kubelet之volume manager源码分析
kubernetes ceph-csi分析目录导航 基于tag v1.17.4 https://github.com/kubernetes/kubernetes/releases/tag/v1.17. ...
随机推荐
- Kuangbin带你飞 AC自动机
模板: struct Ac_Automation { int ch[MAXNNODE][SIGMA_SIZE]; int val[MAXNNODE]; int fail[MAXNNODE],last[ ...
- (七)计算G711语音的打包长度和RTP里timestamp的增长量
如何计算G711语音等的打包长度和RTP里timestamp的增长量 一般对于不同的语音有不同的打包周期,而不同的打包周期又对应着不同的timestamp in RTP 那么是如何计算的呢,我们通过G ...
- PL/SQL 02 声明变量 declare
语法:identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr] identifier:用于指定变量或常量的名称.CONSTANT:用于 ...
- Winform常用操作
>> c#操作cmd命令 using System.Diagnostics; private string RunCmd(string command) { //实例一个Process类, ...
- 【 Linux 】三大主流软件负载均衡器对比(LVS、Nginx、HAproxy)
三大主流软件负载均衡器对比(LVS.Nginx.HAproxy) (资料来自网络,做了部分的补充说明) LVS: 1. 抗负载能力强,性能高,能达到F5的60%,对内存和CPU资源消耗比较低 ...
- java设计模式之实现对象池模式示例分享
http://www.jb51.net/article/46941.htm 对象池模式经常用在频繁创建.销毁对象,且对象创建.销毁开销很大的场景,比如数据库连接池.线程池.任务队列池等.本代码简单,没 ...
- Android学习--探究服务(二)
服务的基本用法 定义服务: 我们需要先创建服务,我们要使用就的利用一个类去继承它,然后重写它的几个方法,具体的我们看下面的代码: 我们重写了下面三个方法: * onCreate() ...
- poj2155
poj2155 题意 二维区间更新,单点查询. 分析 二维线段树. 也可以用二维树状数组去做,维护矩阵前缀和. code #include<cstdio> using namespace ...
- 带WHERE子句的UPDATE语句
目前演示的几个UPDATE语句都是一次性更新所有行的数据,这无法满足只更新符合特定条件的行的需求,比如“将Tom 的年龄修改为12 岁”.要实现这样的功能只要使用WHERE 子句就可以了,在WHERE ...
- 【块状树】bzoj3720 Gty的妹子树
块状树.教程见:http://z55250825.blog.163.com/blog/static/1502308092014163413858/将树按一定大小分块,分成许多子树,在每个子树的根节点记 ...