在Kubrnetes的最底层是容器运行时(Container Runtime),他们负责启动、暂停容器。最有名的容器运行时就是Docker了,后面又支持rkt。在kubernetes 1.5版本,kubernetes引入了CRI,即Container Runtime Interface。
每一种容器运行时,都有自己的有点,kubernetes的许多用户都要求kubernetes引入新的运行时。因为在kubernetes 1.5中引入了CRI。有了CRI,kubrentes不需要重新编译,就可以支持多种容器运行时。CRI本质上只是一种抽象的软件协议,它定义了kubrentes与容器运行时之间的接口。
为什么要提出这一接口协议呢?在此之前,kubernetes支持docker和rkt两种容器运行时,这两种容器运行时的代码与kubelet源码镶嵌在一起。这样就导致了许多问题,首先假如容器运行时接口发生了变化,也必然导致,其他容器运行时代码需要改动,这样会给维护带来很大的问题,其次,假如用户想要增加一类新的容器运行时代码,那必须十分了解Kubelet的源码结构,不利于扩展。因此kuberntes推出了CRI这一接口,使的容器运行时,就像网络、存储一样,是一个可以插拔的软件
CRI规定了kubelet与容器运行时之间的接口,kubelet通过unix套接字与容器运行时进行通信,为了高性能,通信必须使用grpc协议。因此kubelet是作为客户端,而CRI则作为服务器端接受请求。CRI包括了CRI shim和容器运行时,CRI shim就是接受请求的服务器端,cri shim接受到请求后,再去调用容器运行时创建容器。如下图所示
grpc使用protocol buffers进行序列化。CRI主要规定了两类接口,即ImageService和RuntimeService,ImageService提供Pull、查看、删除镜像的RPC接口。而RuntimeSerivce主要包括容器和Pod生命周期管理的RPC接口
ImageService接口
type ImageManagerService interface {
// ListImages lists the existing images.
ListImages(filter *runtimeapi.ImageFilter) ([]*runtimeapi.Image, error)
// ImageStatus returns the status of the image.
ImageStatus(image *runtimeapi.ImageSpec) (*runtimeapi.Image, error)
// PullImage pulls an image with the authentication config.
PullImage(image *runtimeapi.ImageSpec, auth *runtimeapi.AuthConfig) (string, error)
// RemoveImage removes the image.
RemoveImage(image *runtimeapi.ImageSpec) error
// ImageFsInfo returns information of the filesystem that is used to store images.
ImageFsInfo(req *runtimeapi.ImageFsInfoRequest) (*runtimeapi.ImageFsInfoResponse, error)
}
RuntimeService接口。RuntiemService接口主要可以分为两类,即PodSandboxManager和ContainerManager,其中PodSandboxManager主要给Pod提供隔离用的,假如容器运行时是Docker,则是一个名为Pod的容器,Pod为该Pod内的所有容器提供Network、IPC环境,假如容器运行时是基于Hypervisor,如hyper,则Pod代表一个虚拟机。ContainerManager则负责创建具体的容器
type RuntimeService interface {
RuntimeVersioner
ContainerManager
PodSandboxManager
ContainerStatsManager
// UpdateRuntimeConfig updates runtime configuration if specified
UpdateRuntimeConfig(runtimeConfig *runtimeapi.RuntimeConfig) error
// Status returns the status of the runtime.
Status() (*runtimeapi.RuntimeStatus, error)
}
type RuntimeVersioner interface {
// Version returns the runtime name, runtime version and runtime API version
Version(apiVersion string) (*runtimeapi.VersionResponse, error)
}
type ContainerManager interface {
// CreateContainer creates a new container in specified PodSandbox.
CreateContainer(podSandboxID string, config *runtimeapi.ContainerConfig, sandboxConfig *runtimeapi.PodSandboxConfig) (string, error)
// StartContainer starts the container.
StartContainer(containerID string) error
// StopContainer stops a running container with a grace period (i.e., timeout).
StopContainer(containerID string, timeout int64) error
// RemoveContainer removes the container.
RemoveContainer(containerID string) error
// ListContainers lists all containers by filters.
ListContainers(filter *runtimeapi.ContainerFilter) ([]*runtimeapi.Container, error)
// ContainerStatus returns the status of the container.
ContainerStatus(containerID string) (*runtimeapi.ContainerStatus, error)
// ExecSync executes a command in the container, and returns the stdout output.
// If command exits with a non-zero exit code, an error is returned.
ExecSync(containerID string, cmd []string, timeout time.Duration) (stdout []byte, stderr []byte, err error)
// Exec prepares a streaming endpoint to execute a command in the container, and returns the address.
Exec(*runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error)
// Attach prepares a streaming endpoint to attach to a running container, and returns the address.
Attach(req *runtimeapi.AttachRequest) (*runtimeapi.AttachResponse, error)
}
type PodSandboxManager interface {
// RunPodSandbox creates and starts a pod-level sandbox. Runtimes should ensure
// the sandbox is in ready state.
RunPodSandbox(config *runtimeapi.PodSandboxConfig) (string, error)
// StopPodSandbox stops the sandbox. If there are any running containers in the
// sandbox, they should be force terminated.
StopPodSandbox(podSandboxID string) error
// RemovePodSandbox removes the sandbox. If there are running containers in the
// sandbox, they should be forcibly removed.
RemovePodSandbox(podSandboxID string) error
// PodSandboxStatus returns the Status of the PodSandbox.
PodSandboxStatus(podSandboxID string) (*runtimeapi.PodSandboxStatus, error)
// ListPodSandbox returns a list of Sandbox.
ListPodSandbox(filter *runtimeapi.PodSandboxFilter) ([]*runtimeapi.PodSandbox, error)
// PortForward prepares a streaming endpoint to forward ports from a PodSandbox, and returns the address.
PortForward(*runtimeapi.PortForwardRequest) (*runtimeapi.PortForwardResponse, error)
}
type ContainerStatsManager interface {
// ContainerStats returns stats of the container. If the container does not
// exist, the call returns an error.
ContainerStats(req *runtimeapi.ContainerStatsRequest) (*runtimeapi.ContainerStatsResponse, error)
// ListContainerStats returns stats of all running containers.
ListContainerStats(req *runtimeapi.ListContainerStatsRequest) (*runtimeapi.ListContainerStatsResponse, error)
}
目前kubernetes源码里面包括了dockershim这个CRI运行时,该运行时是自动嵌入kubelet源码中的,因此只要适当的配置参数就可以运行。此外kubernetes还支持如下CRI运行时
要开启CRI接口,kubelet主要需要配置两个参数,即–container-runtime-endpoint和–image-service-endpoint。
假如你不是使用的dockershim,则你需要自己启动CRI服务器端
文章转自:http://licyhust.com/%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF/2017/11/03/cri/