Kubelet运行时介绍

kubernetes的核心竞争力是对各种workload的抽象和编排,在与计算、存储和网络对接中,分别对应衍生了其对接的事实标准CRI、CNI和CSI。今天我们来重点分析CRI,另外二者在接下来的文章中再做详细的介绍。

部署架构

先从部署架构上来认识一下CRI,下面这张图展现了CRI客户端与服务端、以及服务端与底层服务是如何协调工作的。

  • 客户端
    和服务端之间基于unix socket套接字/run/dockershim.sock,通过gRPC来通信。

  • 服务端
    在kubelet源码中,整个服务端的代码都位于dockershim包中。它实现了对container、image、checkpoint、logs以及sandbox的操作,其本质都是调用docker和CNI plugin来实现的。

    这里值得特殊提到的是:若只想kubelet启动CRI server,而不启动kubelet其他功能,可以在启动参数中指定--experimental-dockershim参数的值为true

客户端

  • crictl
    我们知道,如今安装kubeadm的时候,都会安装对应依赖包,比如kubeletcrictl等。这里的crictl就是一个独立的客户端工具,当kubelet启动之后,可以基于它来调试CRI server。

    为了便于理解cri的各功能,我将crictl的命令提示列出来,后面是对每个命令操作的描述。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    [root@vm ~]# crictl --help
    NAME:
    crictl - client for CRI

    USAGE:
    crictl [global options] command [command options] [arguments...]

    VERSION:
    v1.12.0

    COMMANDS:
    attach Attach to a running container
    create Create a new container
    exec Run a command in a running container
    version Display runtime version information
    images List images
    inspect Display the status of one or more containers
    inspecti Return the status of one or more images
    inspectp Display the status of one or more pods
    logs Fetch the logs of a container
    port-forward Forward local port to a pod
    ps List containers
    pull Pull an image from a registry
    runp Run a new pod
    rm Remove one or more containers
    rmi Remove one or more images
    rmp Remove one or more pods
    pods List pods
    start Start one or more created containers
    info Display information of the container runtime
    stop Stop one or more running containers
    stopp Stop one or more running pods
    update Update one or more running containers
    config Get and set crictl options
    stats List container(s) resource usage statistics
    completion Output bash shell completion code
    help, h Shows a list of commands or help for one command
  • kubelet
    在阅读kubelet源码的时候,有经常看到kubeGenericRuntimeManager这个类。它在kubelet初始化的时候被创建,是整个kubelet的runtime;一旦kubelet需要容器底层操作资源时,就会调动这个接口方法来处理。

这两个客户端都是通过gRPC来访问CRI server的,所以当使用crictl的时候,需要保障其版本与kubelet的版本一致性,否则可能protobuf定义的报文格式有差异,导致无法正常访问。

服务端

服务端是通过dockershim包中的dockerService来实现的。它实现了CRI的所有接口(pod对容器运行时的需求),在这些接口的handler中包含了抽象的业务逻辑,包括网络、日志、流式读写、镜像管理等。

在这些抽象之下,最终依然是调用容器和CNI接口实现的功能。

  • 使用dockerlib库,基于/run/docker.sock来访问docker engine;
  • /etc/cni/*下查询pod所使用的CNI网络类型,然后调用/opt/cni/*下的CNI插件来为pod添加、卸载网络。

源码分析

kubelet中,对容器运行时的源码主要包含以下几块(结合下图来分析):

  • 服务端(dockershim包中)
    dockershim.NewDockerService创建出dockerService类,它实现了CRI的所有接口,对应代码在action指定的文件中实现。同时,该类的属性包含了CNI、streamServicer、containerManager、checkPointHandler等,分别为CRI接口提供各个方面的功能。

  • 启动服务端(kubelet中)
    图中上半部分是kubelet启动的时候,指定了--experimental-dockershim=true参数后,只启动CRI server的流程;而下半部分是完整的kubelet启动后的流程。

  • protobuf接口定义(api)
    也就是定义CRI的方法和消息结构的定义了,主要位于kubernetes项目的/pkg/kubelet/apis/cri/目录下。

  • 客户端
    kubelet的客户端代码其实就是调用gRPC的接口了,主要位于GenericRuntimeManager中。在上图中可以看到,kubelet会通过klet.runtime调用操作pod各种资源的方法。

0%