k8s CRI
CRI(container runtime interface)
在1.5以前的版本中,k8s依赖于dokcer,为了与docker解耦并支持更多的容器运行时,比如rkt、containerd,kubelet从1.5开始加入了CRI,作为k8s和容器运行时通信的标准,CRI是一组rpc接口,也就是说只要是实现了这组接口都可以作为kubelet的运行时,另外在k8s内部将之前的Pod抽象为一种更为通用的SandBox。
接口定义
接口实现
提出了CRI标准以后,意味着在新的版本里需要使用新的连接方式与docker通信,也就是说docker端需要按CRI的标准实现一个rpc的服务端,所以为了兼容以前的版本,不改变用户习惯,k8s提供了针对docker的CRI实现,也就是k8s源码中kubelet包下的dockershim包,dockershim是一个rpc服务,监听一个端口供kubelet连接,dockershim收到kubelet的请求后,将其转化为REST API请求,发送给物理机上的docker daemon,以下是创建和启动dockershim的代码(k8s v1.11版本):
pkg/kubelet/kubelet.go:NewMainKubelet():617
// 创建dockershim
ds, err := dockershim.NewDockerService(kubeDeps.DockerClientConfig, crOptions.PodSandboxImage, streamingConfig,
...
// 启动rpc服务
if err := server.Start(); err != nil {
创建Docker客户端的逻辑是在创建dockershim的过程中,关键代码:
pkg/kubelet/dockershim/libdocker/client.go:100
:
client, err := getDockerClient(dockerEndpoint)
client对象就是docker的客户端,包含了我们常用的docker run
,docker images
等所有操作,其中dockerEndpoint
变量就是kubelet启动参数--container-runtime-endpoint
选项的值,默认是unix:///var/run/docker.sock
。
k8s调用容器运行时过程如下:
kubelet -> remote -> CRI -> dockershim -> docker_client -> docker_daemon
在Github上阅读完整的源码:
- CRI客户端实现(remote包): pkg/kubelet/remote,与容器相关的逻辑主要在remote_runtime.go文件中。
- CRI服务端实现(dockershim包): pkg/kubelet/dockershim,与容器相关的逻辑主要在docker_container.go文件中。
- dockershim调用Docker的逻辑: pkg/kubelet/dockershim/libdocker
kubelet相关参数
//指定资源管理驱动
--runtime-cgroups cgroupfs
//指定容器运行时
--container-runtime docker
//指定docker daemon的地址
--docker-endpoint unix:///var/run/docker.sock
//创建dockershim服务,供kubelet连接
--container-runtime-endpoint unix:///var/run/dockershim.sock
--image-service-endpoint unix:///var/run/dockershim.sock