2052 kubernetes runtime部署及维护

01.介绍

kubernetes runtime一般是指容器生命周期的管理, 早起kubelet在创建容器的时候直接调用docker daemon, docker daemon调用自己的libcontainer就可以把容器启动起来, 但是随着后续rkt的加入出现了很多兼容性的问题, Container Runtime Interface(CRI)即程序运行时接口就这样出生了, 后续接入的runtime按照CRI的接口实现就可以了, 启动容器的过程中需要根据Open Container Initiative(OCI)即开放容器标准中的有关规定进行启动, 目前比较稳定的还是Docker并且Dockershim 核心代码依然保留在 kubelet 内部是最稳定和特性支持最好的运行时

目前官方文档中支持的如下:

OCI

OCI的runtime spec标准中对于容器的状态描述,以及对于容器的创建、删除、查看等操作进行了定义。 目前包括两个标准容器运行时标准和容器镜像标准, 简单的来说就是创建镜像的标准和运行容器的标准,

  • 容器镜像标准

    文件系统: 以layer保存的文件系统,每个layer保存了和上层之间变化的部分,layer应该保存哪些文件,怎么表示增加、修改和删除的文件等

    config文件: 保存了文件系统的层级信息(每个层级的hash值,以及历史信息)以及容器运行时需要的一些信息(比如环境变量、工作目录、命令参数、mount 列表)

    manifest文件: 镜像的config文件索引,有哪些layer,额外的annotation信息,manifest文件中保存了很多和当前平台有关的信息

    index文件: 可选的文件,指向不同平台的manifest文件,这个文件能保证一个镜像可以跨平台使用,每个平台拥有不同的manifest文件,使用index作为索引

  • 容器运行时标准

    ociVersion: OCI版本

    id: 容器的ID,在宿主机唯一

    status: 容器运行时状态,生命周期

    • creating: 使用 create 命令创建容器,这个过程称为创建中,创建包括文件系统、namespaces、cgroups、用户权限在内的各项内容

    • created: 容器创建出来,但是还没有运行,表示镜像和配置没有错误,容器能够运行在当前平台

    • running: 容器的运行状态,里面的进程处于up状态,正在执行用户设定的任务

    • stopped: 容器运行完成,或者运行出错或者stop命令之后,容器处于暂停状态,这个状态,容器还有很多信息保存在平台中,并没有完全被删除

    pid: 容器进程在宿主机的进程ID

    bundle: 容器文件目录,存放容器rootfs及相应配置的目录

    annotations: 与容器相关的注释

CRI

容器运行时插件(Container Runtime Interface,简称 CRI)容器运行时接口, 其中包括容器运行时和镜像的管理两个grpc接口, Kubelet 作为 CRI 的客户端,而容器运行时则需要实现 CRI 的服务端(即 gRPC server,通常称为 CRI shim)。容器运行时在启动 gRPC server 时需要监听在本地的 Unix Socket, 具体请看下图:

简单的来说就是容器的编排API调用CRI, CRI调用OCI启动容器

02.使用docker作为k8s runtime 时的启动流程

当kubelet要创建一个容器时,需要以下几步:

  • Kubelet 通过 CRI 接口(gRPC)调用 dockershim,请求创建一个容器。CRI 即容器运行时接口(Container Runtime Interface),这一步中,Kubelet 可以视作一个简单的 CRI Client,而 dockershim 就是接收请求的 Server。目前 dockershim 的代码其实是内嵌在 Kubelet 中的,所以接收调用的凑巧就是 Kubelet 进程;

  • dockershim 收到请求后,转化成 Docker Daemon 能听懂的请求,发到 Docker Daemon 上请求创建一个容器。

  • Docker Daemon 请求 containerd 创建一个容器;

  • containerd 收到请求后,并不会自己直接去操作容器,而是创建一个叫做 containerd-shim 的进程,让 containerd-shim 去操作容器。这是因为容器进程需要一个父进程来做诸如收集状态,维持 stdin 等 fd 打开等工作。而假如这个父进程就是 containerd,那每次 containerd 挂掉或升级,整个宿主机上所有的容器都得退出了。而引入了 containerd-shim 就规避了这个问题(containerd 和 shim 并不是父子进程关系);

  • containerd-shim 在这一步需要调用 runC 这个命令行工具,来启动容器;

  • runC 启动完容器后本身会直接退出,containerd-shim 则会成为容器进程的父进程,负责收集容器进程的状态,上报给 containerd,并在容器中 pid 为 1 的进程退出后接管容器中的子进程进行清理,确保不会出现僵尸进程。

03.Docker 安装

卸载旧版本docker

$ yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine
$ rm -rf /var/lib/docker #删除旧版本数据

安装依赖包

$ yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2yum

添加源,使用了阿里云镜像

$ yum-config-manager \
    --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
$ yum makecache fast  #配置元数据缓存

安装最新稳定版docker

$ yum install -y docker-ce

04.配置docker使用flannel网络

修改docker的配置文件/usr/lib/systemd/system/docker.service,增加如下几条环境变量配置:

EnvironmentFile=-/run/docker_opts.env
EnvironmentFile=-/run/flannel/subnet.env

systemd 维护

$ systemctl daemon-reload
$ systemctl start docker #启动docker引擎
$ systemctl enable docker #设置开机启动

番外篇配置加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["http://hub-mirror.c.163.com"]
}
EOF

05.Q&A

Q: 没有配置flannel之前启动了docker, 已经默认分配了网络, docker0使用bip分配的地址

"Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address"

A: 查看/lib/systemd/system/docker.service文件发现启动命令没有调用/run/docker_opts.env中的${DOCKER_OPTS}, 需要将启动命令从

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

修改为

/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock  $DOCKER_OPTS

Q: 修改docker的默认网段

A: 编辑/etc/docker/daemon.json添加如下内容

{
 "bip": "172.26.0.1/16"
}

重启docker服务

systemctl restart docker.service

参考

最后更新于