惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
N
Netflix TechBlog - Medium
P
Proofpoint News Feed
D
Docker
J
Java Code Geeks
L
LangChain Blog
Microsoft Security Blog
Microsoft Security Blog
The GitHub Blog
The GitHub Blog
I
InfoQ
Stack Overflow Blog
Stack Overflow Blog
云风的 BLOG
云风的 BLOG
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
月光博客
月光博客
T
Tailwind CSS Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
Google DeepMind News
Google DeepMind News
腾讯CDC
罗磊的独立博客
U
Unit 42
爱范儿
爱范儿
Vercel News
Vercel News
MyScale Blog
MyScale Blog

蛮荆

如何获取更多的免费服务器 Kubernetes 调度器队列 - 设计与实现 Kubernetes 调度器 - 核心流程 Kubernetes Networking Model & CNI Kubernetes 控制器管理总结 Kubernetes CronJob 设计与实现 Kubernetes Job 设计与实现 Kubernetes HPA 设计与实现 Kubernetes Deployment 滚动更新实现原理 Kubernetes GC 设计与实现 Kubernetes Pod 驱逐 - 设计与实现 Kubernetes Daemonset 设计与实现 Kubernetes ReplicaSet 设计与实现 Kubernetes EndPoint 设计与实现 Kubernetes Informer 设计与实现 降本增效之应用优化 (三) 日志存储与检索 Kubernetes Pod 设计与实现 - 创建流程 Kubernetes 探针设计与实现 Unix 编程艺术名句摘录 Golang 编译速度为什么这么快? Kubernetes Pod 设计与实现 - Pause 容器 Kubernetes - kube-proxy 代理模式工程优化 Kubernetes 应用最佳实践 - 优雅关闭长连接 Kubernetes Service 类型和会话亲和性 Kubernetes 为什么需要 Ingress Kubernetes 架构 - 控制平面和数据平面 降本增效之应用优化 (二) 大报表 Go 语言如何获取 CPU 利用率 降本增效之应用优化 (一) Redis 业务规则引擎演变过程简述
Kubernetes - CRI 概述
2023-11-07 · via 蛮荆

2023-11-07 Cloud Native Kubernetes 读代码

概述

CRI(Container Runtime Interface, 容器运行时接口)是 Kubernetes 用于管理容器运行时和容器镜像的 gRPC 协议接口集合,kubelet 可以通过 CRI 来使用不同的容器运行时,而无需重新编译集群组件。

为了保证 CRI 可以正常工作,Kubernetes 集群中的每个节点都需要有一个实现了 CRI 的具体容器运行时 (例如 containerd),这样 kubelet 可以直接对 Pod 及其内部容器进行操作。

下面以 containerd 为例进行说明,containerd 是来自 Docker 的高级容器运行时,实现了 CRI 规范

containerd 实现了 CRI

宏观接口模型

因为 Pod 是 Kubernetes 中应用运行的最小单位,此外容器运行时除了运行、重启、停止 Pod 操作外,还有容器对应的镜像拉取、删除等操作, 结合两者,我们可以给出一个粗糙的 CRI 模型示例图:

CRI 模型

然后就可以直接将上述接口模型转化成伪代码 (Go 语言实现):

type CRI interface {
	PullImage(name string)   // 拉取容器镜像
	RemoveImage(name string) // 删除容器镜像

	StartPod(name string)  // 启动 Pod
	StopPod(name string)   // 停止 Pod
	RemovePod(name string) // 删除 Pod

	StartContainer(name string)  // 启动 Pod
	StopContainer(name string)   // 停止 Pod
	RemoveContainer(name string) // 删除 Pod
}

// Containerd (模拟) 实现了 CRI 接口
type Containerd struct {
}

func (c *Containerd) PullImage(name string)       {}
func (c *Containerd) RemoveImage(name string)     {}
func (c *Containerd) StartPod(name string)        {}
...
func (c *Containerd) RemoveContainer(name string) {}

// Rktlet (模拟) 实现了 CRI 接口
type Rktlet struct {
}

func (r *Rktlet) PullImage(name string)       {}
func (r *Rktlet) RemoveImage(name string)     {}
func (r *Rktlet) StartPod(name string)        {}
...
func (d *Rktlet) RemoveContainer(name string) {}

// CRI-O 实现了 CRI 接口
type CRI-O struct {
}

func (c *CRI-O) PullImage(name string)       {}
func (c *CRI-O) RemoveImage(name string)     {}
func (c *CRI-O) StartPod(name string)        {}
...
func (c *CRI-O) RemoveContainer(name string) {}

通过上面的伪代码,我们可以对 CRI 有一个基础的认识,下面我们一起看看 Kubernetes 中 CRI 的代码,学习一下成熟的方案和设计思路。


Kubernetes 中的 CRI

Kubernetes 中的 CRI 功能对应的源代码位于 Kubernetes 项目的 staging/src/k8s.io/cri-api 目录,本文以 Kubernetes v1.28 版本源代码进行分析。

CRI 定义和实现使用的是 gRPC 协议,在对应的 gRPC 定义文件中,可以看到两个 Service:

  1. RuntimeService: 定义了容器运行时的相关操作 API
  2. ImageService: 定义了容器镜像管理的相关操作 API
// cri-api/pkg/apis/runtime/v1/api.proto

service RuntimeService {
    rpc Version(VersionRequest) returns (VersionResponse) {}
	
    rpc RunPodSandbox(RunPodSandboxRequest) returns (RunPodSandboxResponse) {}
    rpc StopPodSandbox(StopPodSandboxRequest) returns (StopPodSandboxResponse) {}
    rpc RemovePodSandbox(RemovePodSandboxRequest) returns (RemovePodSandboxResponse) {}
	
	...
}

service ImageService {
    rpc ListImages(ListImagesRequest) returns (ListImagesResponse) {}
    rpc PullImage(PullImageRequest) returns (PullImageResponse) {}
	
	...
}

上面的 Service 对应的 Go 代码如下:

// cri-api/pkg/apis/services.go

type RuntimeVersioner interface {
	Version(ctx context.Context, apiVersion string) (*runtimeapi.VersionResponse, error)
}

// 容器管理接口
type ContainerManager interface {
	CreateContainer(ctx context.Context, podSandboxID string, ...) (string, error)
	StartContainer(ctx context.Context, containerID string) error
	StopContainer(ctx context.Context, containerID string, timeout int64) error
	RemoveContainer(ctx context.Context, containerID string) error
	ListContainers(ctx context.Context, filter *runtimeapi.ContainerFilter) ([]*runtimeapi.Container, error)
    ...
}

// Pod 管理接口
type PodSandboxManager interface {
	RunPodSandbox(ctx context.Context, ...) (string, error)
	StopPodSandbox(pctx context.Context, odSandboxID string) error
	RemovePodSandbox(ctx context.Context, podSandboxID string) error
    ...
}

// 通过内嵌上述几个接口,形成一个 CRI 主要接口
type RuntimeService interface {
	RuntimeVersioner
	ContainerManager
	PodSandboxManager

	UpdateRuntimeConfig(ctx context.Context, runtimeConfig *runtimeapi.RuntimeConfig) error
	Status(ctx context.Context, verbose bool) (*runtimeapi.StatusResponse, error)
	RuntimeConfig(ctx context.Context) (*runtimeapi.RuntimeConfigResponse, error)
}

// 镜像管理接口
type ImageManagerService interface {
	PullImage(ctx context.Context, image *runtimeapi.ImageSpec, ...) (string, error)
	RemoveImage(ctx context.Context, image *runtimeapi.ImageSpec) error
	...
}

containerd

containerd, Docker 和 CRI 交互

这里以 containerd 为例,看看其内部关于 CRI 接口的具体代码结构,时间所限,这里只留下相关代码骨架截图,具体的源代码不再进行分析。

remote_image.go 实现了容器镜像相关操作

remote_runtime.go 实现了容器运行时相关操作

Reference

扩展阅读