CRI概述
节点的底层由一个叫做“容器运行时”的软件进行支撑,它负责比如启停容器这样的事情。最广为人知的容器运行时当属Docker,但它不是唯一的。事实上,容器运行时这个领域发展迅速。为了使Kubernetes的扩展变得更容易,我们一直在打磨支持容器运行时的K8s插件API:容器运行时接口(Container Runtime Interface, CRI)。
从1.5版本引入CRI接口规范,通过插件接口模式,k8s无需重新编译就可以使用更多的容器运行。CRI包括Protocol Buffers、gRPC API、运行库支持及开发中的标准规范和工具。Docker的CRI实现在K8S 1.6中被更新为Beta版本,并在kubelet启动时默认启动。
CRI的主要组件
kubelet是客户端,CRI代理(shim)是服务端。
Protocol Buffers API包含两个gRPC服务:ImageService 和 RuntimeService
ImageService 提供从仓库拉取镜像、查看和移除镜像功能。
RuntimeService负责Pod和容器的生命周期管理,以及与容器的交互(exec/attach/port-forward)。rkt和Docker运行时可以使用一个Socket同时提供两个服务,在kubelet中可以用--container-runtime-endpoint和--image-service-endpoint参数设置这个Socket.
Pod和容器的生命周期管理
Pod由一组应用容器组成,其中包含共有的环境和资源约束。在CRI里称为“PodSandbox”。Kubernetes有意为容器运行时留下一些发挥空间, 它们可以根据自己的内部实现来解释PodSandbox。对于Hypervisor类的运行时, PodSandbox会具体化为一个虚拟机。 其他例如Docker, 会是一个Linux命名空间。 在v1alpha1 API中, kubelet会创建Pod级别的cgroup传递给容器运行时, 并以此运行所有进程来满足PodSandbox对Pod的资源保障。
在启动Pod之前, kubelet调用RuntimeService.RunPodSandbox来创建环境。 这一过程包括为Pod设置网络资源(分配IP等操作) 。PodSandbox被激活之后, 就可以独立地创建、 启动、 停止和删除不同的容器了。 kubelet会在停止和删除PodSandbox之前首先停止和删除其中的容器。kubelet的职责在于通过RPC管理容器的生命周期, 实现容器生命周期的钩子, 存活和健康监测, 以及执行Pod的重启策略等。
service RuntimeService {
// Sandbox operations.
rpc RunPodSandbox(RunPodSandboxRequest) returns (RunPodSandboxResponse) {}
rpc StopPodSandbox(StopPodSandboxRequest) returns (StopPodSandboxResponse) {}
rpc RemovePodSandbox(RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {}
rpc PodSandboxStatus(PodSandboxStatusRequest) returns (PodSandboxStatusResponse) {}
rpc ListPodSandbox(ListPodSandboxRequest) returns (ListPodSandboxResponse) {}
// Container operations.
rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse) {}
rpc StartContainer(StartContainerRequest) returns (StartContainerResponse) {}
rpc StopContainer(StopContainerRequest) returns (StopContainerResponse) {}
rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse) {}
rpc ListContainers(ListContainersRequest) returns (ListContainersResponse) {}
rpc ContainerStatus(ContainerStatusRequest) returns (ContainerStatusResponse) {}
…
}
尝试使用新的Docker-CRI来创建容器
要尝试新的Kubelet-CRI-Docker集成, 只需为kubelet启动参数加上--enable-cri=true开关来启动CRI。 这个选项从Kubernetes 1.6开始已经作为kubelet的默认选项了。 如果不希望使用CRI, 则可以设置--enablecri=false来关闭这个功能。
查看kubelet的日志, 可以看到启用CRI和创建gRPC Server的日志:
创建一个Deployment:
查看Pod的详细信息, 可以看到将会创建沙箱(Sandbox) 的Event:
这表明kubelet使用了CRI接口来创建容器。