Kubelet CRI-RemoteImageService

文摘   科技   2021-08-20 09:09  

微信公众号:朱慧君 大龄yaml工程师瞎逼逼 关注容器技术、关注Kubernetes。问题或建议,请公众号留言。

ImageMangerService

ImageManagerService 类型为 interface,该接口定义了容器就像管理需要实现的方法,方法包括:

staging/src/k8s.io/cri-api/pkg/apis/services.go:108

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, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error)
// RemoveImage removes the image. 用于移除指定镜像。
RemoveImage(image *runtimeapi.ImageSpec) error
// ImageFsInfo returns information of the filesystem that is used to store images.
// 用于返回 container runtime 所在存储设备,已经使用多少空间来存储镜像。
ImageFsInfo() ([]*runtimeapi.FilesystemUsage, error)
}

remoteImageService

remoteImageService 实现了上述 ImageMangerService 接口,具体结构体为:

// remoteImageService is a gRPC implementation of internalapi.ImageManagerService.
type remoteImageService struct {
// timeout 用于配置远程连接超时时间,此处默认为 kubeconf 中 runtime request timeout 时间
timeout time.Duration
// imageClient 用于创建远程调用 grpc client
imageClient runtimeapi.ImageServiceClient
}

NewRemoteImageService

NewRemoteImageService 该方法用于初始化 ImageManagerService 接口,需要传入远程镜像入口地址、连接超时时间:

// NewRemoteImageService creates a new internalapi.ImageManagerService.
func NewRemoteImageService(endpoint string, connectionTimeout time.Duration) (internalapi.ImageManagerService, error) {
klog.V(3).InfoS("Connecting to image service", "endpoint", endpoint)
// 此处主要用于从 endpoint 中解析出远程地址和连接器函数
addr, dialer, err := util.GetAddressAndDialer(endpoint)
if err != nil {
return nil, err
}

// 创建带超时的 context
ctx, cancel := context.WithTimeout(context.Background(), connectionTimeout)
defer cancel()

// 创建 grpc 客户端
conn, err := grpc.DialContext(ctx, addr, grpc.WithInsecure(), grpc.WithContextDialer(dialer), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxMsgSize)))
if err != nil {
klog.ErrorS(err, "Connect remote image service failed", "address", addr)
return nil, err
}

// 初始化 remoteImageService
return &remoteImageService{
timeout: connectionTimeout,
imageClient: runtimeapi.NewImageServiceClient(conn),
}, nil
}

GetAddressAndDialer

传入 endpoint 字符串中,kubelet 默认获取当前环境的操作系统类型,目前支持 Linux 和 Windows 两种,具体值如下:

remoteRuntimeEndpoint := ""
if runtime.GOOS == "linux" {
remoteRuntimeEndpoint = "unix:///var/run/dockershim.sock"
} else if runtime.GOOS == "windows" {
remoteRuntimeEndpoint = "npipe:////./pipe/dockershim"
}

ListImages

rpc方法入参功能说明
/runtime.v1alpha2.ImageService/ListImages*runtimeapi.ImageFilter
此处 filter 中可以传入 image 名称和 annotation。
如果 filter 为 nil 则获取所有镜像列表。
用于获取镜像列表

该方法会有以下几处进行调用:

ImageGCManager.Start(),该方法主要用于清理宿主机镜像,清理之后需要重建镜像信息缓冲,此时会调用本方法。kubeGenericRuntimeManager.ImageStats,该方法用于统计当前镜像总存储量,此处需要先 list 所有镜像,然后遍历求存储总和。

ImageStatus

rpc方法入参功能说明
/runtime.v1alpha2.ImageService/ImageStatus*runtimeapi.ImageSpec
此处 filter 中可以传入 image 名称和 annotation。
用于获取镜像状态

该方法会有以下几处进行调用:

ImageGCManager.Start(),该方法主要用于清理宿主机镜像,清理之后需要重建镜像信息缓冲,此时会调用本方法。kubeGenericRuntimeManager.ImageStats,该方法用于统计当前镜像总存储量,此处需要先 list 所有镜像,然后遍历求存储总和。

Image Info

// 容器镜像的基本信息
type Image struct {
// 镜像 ID
Id string
// 镜像 tag 列表
RepoTags []string
// 镜像 digests sha256 id
RepoDigests []string
// 镜像大小
Size_ uint64
// UID 为创建容器时的默认用户,UID和以下 Username 为互斥选项
Uid *Int64Value
// 指定容器执行命令的用户,与上面 UID 互斥
Username string
// spec 包括镜像名称和 annotation
Spec *ImageSpec
}
# docker images fedora --digests --no-trunc
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
fedora latest sha256:aa889c59fc048b597dcfab40898ee3fcaad9ed61caf12bcfef44493ee670e9df sha256:b3048463dcefbe4920ef2ae1af43171c9695e2077f315b2bc12ed0f6f67c86c7 8 months ago 175MB
fedora 30 sha256:3a0c8c86d8ac2d1bbcfd08d40d3b757337f7916fb14f40efcb1d1137a4edef45 sha256:177d5adf0c6c2627a752e168479395d2a530a090deab65b47716405075bd2107 17 months ago 238MB
fedora 26 sha256:7f1cf1e2baaa65da0763ceec36202b5f5e49ba18069ab2950503ffe3b22f8fbf sha256:f36d549d2474f7689939a24aedf9690d7dcdc8010250cb98482fe7d2a24cf4d4 2 years ago 232MB
fedora 24 sha256:0c1580c63e623ecfa0ef2d4a548d73a655e8072725bcca01bc6f2e446914a7bc sha256:971e0f0a8b7138a4f8eccd0e402e4cca958fd2c622c5c8308f16b183d0d15d06 3 years ago 204MB
fedora 20 sha256:5d5a02b873d298da9bca4b84440c5cd698b0832560c850d92cf389cef58bc549 sha256:ba74bddb630e4dc18b3c97241f7e7fc5fb4babfd0d79e10b73f5d85b52db46ae 4 years ago 291MB
fedora 21 sha256:a268e5e12257c7770eb44c24041baf5e728fba2eed1a84f007b81845ded0a485 sha256:ba6369d667d15c1f4f7d7aaa1bded5389e68eaafd57a86a4459a52b5b7457d9f 4 years ago 241MB

PullImage

rpc方法入参功能说明
/runtime.v1alpha2.ImageService/PullImage*runtimeapi.ImageSpec,此处 filter 中可以传入 image 名称和 annotation。
*runtimeapi.AuthConfig,此处传入远端 registry 认证信息
*runtimeapi.PodSandboxConfig,此处传入
用于拉取镜像

该方法会有以下几处进行调用:

kubeGenericRuntimeManager.PullImage(),该方法主要实现通过网络从远程拉取镜像到本地,将遍历提供的所有 registry 证书信息,尝试拉取镜像,只要成功一次即返回成功。

RemoveImage

rpc方法入参功能说明
/runtime.v1alpha2.ImageService/RemoveImage*runtimeapi.ImageSpec,此处 filter 中可以传入 image 名称和 annotation。用于从本地删除镜像

该方法会有以下几处进行调用:

kubeGenericRuntimeManager.RemoveImage(),该方法主要用于删除指定镜像,主要在本地镜像进行 gc 时会使用该方法。

上述方法又会被 realImageGCManager.freeSpace() 调用,该方法主要返回当前镜像存储占用量,同时完成镜像的清理工作。


freeSpace

该方法主要用于释放宿主机镜像存储空间,主要实现如下:

1.首先需要将 sandboxImage 跳过,该镜像用于组建 pod local network 不能被删除。2.获取宿主机上的 镜像列表 images、pod列表 pods,通过 pod 列表获取正在使用中的镜像列表 imagesInUse3.遍历 images 列表记录当前探测镜像列表 currentImages4.遍历 images 列表,新建镜像记录列表 imageRecords ,如果当前镜像正在被使用,则需要将该镜像 imageRecords[id].lastUsed 字段更新为当前时间,同时记录该镜像大小、第一次探测时间。5.通过比较 imageRecords 和 currentImages 来清理已经不存在的镜像。

ImageFsInfo

rpc方法返回功能说明
/runtime.v1alpha2.ImageService/ImageFsInfo[]*runtimeapi.FilesystemUsage用于统计 runtime 所在文件系统存储使用情况

runtimeapi.FilesystemUsage

// FilesystemUsage 记录文件系统资源消耗信息
type FilesystemUsage struct {
// Timestamp 信息采集的时间,纳秒级别的时间戳, 必须 > 0
Timestamp int64
// 文件系统唯一标识
FsId *FilesystemIdentifier
// UsedBytes 用于记录文件系统中镜像占用字节大小
// 该值可能不等于 CapacityBytes - AvailableBytes
// 因为当前文件系统不会只被 cri 组件使用,也不会只用于存储镜像
UsedBytes *UInt64Value
// InodesUsed 用于记录被镜像使用的 inodes 数量
// 该值可能不等于 InodesCapacity - InodesAvailable
// 因为当前文件系统不会只被 cri 组件使用,也不会只用于存储镜像
InodesUsed *UInt64Value
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_sizecache int32 `json:"-"`
}

该方法会有以下几处进行调用:

criStatsProvider.ImageFsStats(),该方法主要用于获取返回存储镜像文件系统详情,返回包括时间、当前可用大小、总大小、镜像占用大小、inode空闲值、inode总数、inode使用数。

realImageGCManager.GarbageCollect(),该方法用于镜像回收操作,会调用上述方法获取当前文件系统资源使用情况。


朱慧君
大龄yaml工程师逼逼叨