Kubernetes 之从容器运行时到 CRI
容器运行时
1. 什么是 Container Runtime?
Container Runtime 提供容器运行环境,是负责运行容器的软件。通俗地讲就是:容器从拉取镜像创建、启动、运行管理、销毁的一个完整生命周期。
以 Docker 为例,作为一个整体容器运行时实现,主要提供的功能如下:
- 制定容器镜像格式
- 构建容器镜像
- 运行容器
2. 低层运行时和高层运行时
目前较为流行说法根据不同的功能实现将容器运行时分成了低层运行时(low-level)和高层运行时(high-level)两类。
- 低层运行时(low-level container runtime):通常只关注如 Namespace、Cgroups、镜像拆包等基础的容器运行时实现。
- 高层运行时(high-level container runtime):支持更多高级功能(如镜像管理和 CRI 实现)的运行时。
3. 运行时其他分类
基于 hypervisor 的运行时
代表技术:KVM(Kernel-based Virtual Machine)、Kata Containers 等。
原理:利用 hypervisor 在物理主机上创建多个虚拟机,每个虚拟机都有自己独立的操作系统和资源隔离环境,将容器运行在虚拟机内部,以实现更强大的隔离性。
特点:
- 优点:
- 提供了硬件级别的强隔离,不同虚拟机之间的资源相互隔离,安全性高,一个容器的故障或攻击很难影响到其他容器或主机系统。
- 可以方便地进行资源分配和限制,能根据不同容器的需求灵活分配 CPU、内存、存储等资源。
- 缺点:
- 由于需要模拟完整的硬件环境和运行独立的操作系统,启动时间相对较长,资源占用较大,性能开销相对较高。
基于 Linux 容器的运行时
代表技术:Docker、runc、containerd 等。
原理:利用 Linux 内核的命名空间(Namespace)、控制组(Cgroup)等技术来实现容器的隔离和资源限制。命名空间用于隔离进程、网络、文件系统等资源,Cgroup 用于限制容器对 CPU、内存等资源的使用。
特点:
- 优点:
- 启动速度快,因为不需要像虚拟机那样加载完整的操作系统,只需启动容器内的应用程序。
- 资源利用率高,多个容器可以共享主机的操作系统内核,减少了资源的浪费。
- 轻量化,容器镜像体积通常较小,便于部署和分发。
- 缺点:
- 隔离性相对较弱,虽然命名空间和 Cgroup 提供了一定的隔离,但在某些情况下,如内核漏洞利用,可能会导致容器之间的隔离被突破。
- 对一些特殊硬件的支持可能不如虚拟机完善。
基于其他技术的运行时
代表技术:Wasm(WebAssembly)运行时等。
原理:Wasm 是一种为在 Web 浏览器和其他环境中运行而设计的字节码格式,它提供了一个安全、轻量级的执行环境。基于 Wasm 的容器运行时将应用程序编译为 Wasm 字节码,然后在 Wasm 运行时中执行,实现应用的隔离和运行。
特点:
- 优点:
- 具有极高的安全性,Wasm 的沙盒机制可以防止应用程序访问未经授权的资源。
- 启动速度极快,加载和初始化 Wasm 模块通常非常迅速。
- 可移植性强,Wasm 字节码可以在不同的平台和环境中运行。
- 缺点:
- 目前 Wasm 的生态系统相对较小,对一些复杂的应用场景和系统功能的支持还不够完善,例如对某些系统调用的支持有限,可能无法满足一些传统应用的需求。
4. 安全容器运行时 Kata
尽管容器有许多技术优势,然而传统以 runc 为代表基于共享内核技术进行的软隔离还是存在一定的风险性。如果某个恶意程序利用系统缺陷从容器中逃逸,就会对宿主机造成严重威胁,尤其是公有云环境,安全威胁很可能会波及到其他用户的数据和业务。
将虚拟机的安全优势与容器的高速及可管理性相结合,为用户提供标准化、安全、高性能的容器解决方案,这就是 Kata Containers 出现的背景。
Kata Containers 安全容器的诞生解决了许多普通容器场景无法解决的问题,例如多租户安全保障、不同 SLO 混部容器混合部署、可信/不可信容器混合部署等等。在这些优势的基础上,Kata Containers 也在虚拟化上也追求极致的轻薄,从而让整体资源消耗和弹性能力接近 runc 容器方案,以此达到 Secure as VM、Fast as Container 的技术目标。
Kata Containers 的特点包括:
- 容器和虚拟机二合一:Kata Containers 结合了容器和虚拟机的优点,既具有高性能和高效管理的特点,又拥有独立隔离性和安全性。
- 安全性:Kata Containers 使用轻量级虚拟化技术,为每个容器创建一个轻量级虚拟机,可以实现容器级别的隔离和安全。
- 可扩展性:Kata Containers 支持与多种容器管理工具,如 Docker 和 Kubernetes 集成,可以与现有的容器环境无缝集成。
- 兼容性:Kata Containers 能够支持 OCI(Open Container Initiative)规范,与现有的容器镜像和工具兼容。
CRI in Kubernetes
Kubernetes 从 1.5 版本开始,在遵循 OCI 基础上,将容器操作抽象为一个接口,该接口作为 Kubelet 与运行时实现对接的桥梁,Kubelet 通过发送接口请求对容器进行启动和管理,各个容器运行时只要实现这个接口就可以接入 Kubernetes。
这个接口就是 Kubernetes 容器运行时接口:CRI(Container Runtime Interface)。
CRI 主要组件
CRI 是一套通过 Protocol Buffer 定义的 API,如下图:
CRI 主要有 gRPC client、gRPC Server 和具体容器运行时实现三个组件。
其中 Kubelet 作为 gRPC Client 调用 CRI 接口,CRI shim 作为 gRPC Server 来响应 CRI 请求,并负责将 CRI 请求内容转换为具体的运行时管理操作。
对于 Kubernetes,需要在集群内每个 Node 节点上安装一个容器运行时以使 Pod 可以运行在上面。
Protocol Buffers API
包含两个 gRPC 服务:ImageService 和 RuntimeService。
- ImageService:提供了从仓库拉取镜像、查看和移除镜像的功能。
- RuntimeService:负责 Pod 和容器的生命周期管理,以及与容器的交互(exec/attach/port-forward)。
rkt 和 Docker 这样的容器运行时可以使用一个 Socket 同时提供两个服务,在 kubelet 中可以用 --container-runtime-endpoint
和 --image-service-endpoint
参数设置这个 Socket。
创建容器的流程
- 调度选择节点:Kubernetes 调度器根据资源需求和策略,选择一个合适的节点来运行 Pod。
- Kubelet 接收请求:选定节点的 Kubelet 接收 Pod 创建请求,准备启动 Pod。
- CRI 请求处理:Kubelet 通过容器运行时接口(CRI)向容器运行时发起创建 Pod 的请求。CRI 适配层(CRI shim)将标准化的 CRI 请求转换为具体容器运行时的指令。
- Pod Sandbox 创建:容器运行时根据指令创建 Pod Sandbox,提供共享运行环境。Sandbox 隔离网络和文件系统,确保 Pod 内容器独立运行。Linux 环境下,Sandbox 可能是一个命名空间;Hypervisor 环境下,则为虚拟机。
- Container Runtime 管理:容器运行时负责 Pod Sandbox 的生命周期管理,包括创建、启动和停止。提供资源隔离和进程管理,确保 Pod 正常运行。
- 结果反馈:容器运行时将处理结果返回给 Kubelet,完成 Pod 创建流程。
总结
- CRI 的优势:通过在容器级别实现通用特性,CRI 加速了容器运行时的开发,确保与 Kubelet 的兼容性。
- Kubelet 的责任:保持容器应用的实际状态与声明状态一致,确保 Pod 正常运行。