前言
容器运行时指的是Docker、containerd这样的容器引擎,而kubernetes是一个容器运行时编排工具,Kubernetes不仅可以编排Docker,还可以编排containerd。
本页文档介绍了4个容器运行时:containerd、CRI-O、Docker、mirantis.
转发IPV4并让iptables看到桥接流量
这个配置主要是配置net.bridge.bridge-nf-call-iptables为1。开启这个参数的目的是为了让bridge设备在做二层转发时也去调用iptables配置的三层规则。
在进一步解释这个参数前,先来看下service的访问流程。客户端->service clusterip->pod ip。如果不配置此参数的话,会导致同一个Node上的不同POD通过service访问时不通,因为k8s的service服务必须经过DNAT映射到真实的PODIP,但是经过DNAT到真实的POD IP后,在响应数据给客户端的时候发现目的端是同一个Node上的POD,则会直接在2层bridge设备上直接通信,没有经过三层的SNAT,也就是说去POD的数据和回来的数据走了不同的路,内核认为这两者的数据不是同一个连接,与是就不能互相通信导致数据传输失败。而配置net.bridge.bridge-nf-call-iptables意思就是即便二层bridge也会调用三层的iptables进行数据转发。service的具体实现是靠kube-proxy来做的,kube-proxy根据service的定义来创建路由条目。
cgroup控制组
cgroup控制组的作用主要是限制Linux的进程所能使用的资源阈值,比如一个进程最多能使用多少CPU,多少内存,多少硬盘IO等。kubelet功能就是根据从APISERVER获取到的容器资源限制参数来给容器所能使用的资源加以限制。在Linux上有两个cgroup控制组组件cgroupfs和systemd。
这里我想详细的说一下cgroups,因为这个知识点是容器实现技术的三大知识点中的其中之一。cgroups首先是Linux内核的一项功能,用于限制、记录和隔离一组进程的资源使用。cgroups功能的实现依赖于四个核心概念:子系统、控制组、层级树、任务。
- 控制组
cgroups和cgroup是两个东西,cgroups是内核的一个实现资源控制的组件。而cgroup是表示一组进程和一组带有参数的子系统的关联关系。比如一个进程使用了CPU子系统来限制CPU的使用时间,则这个进程和CPU子系统的关联关系称为cgroup控制组。 - 子系统
一个子系统代表一类资源控制器。例如内存子系统可以限制内存的使用量,CPU子系统可以限制CPU的使用时间。在/sys/fs/cgroup目录下可以看到内核支持的子系统类别。其中cpu是控制任务对CPU的使用,cpuacct是自动生成cgroup中任务对cpu资源使用情况的报告,cpuset可以为cgroup中的任务分配独立的cpu和内存,blkio是可以为块设备设定输入输出限制,devices可以开启或关闭cgroup中任务对设备的访问,freezer可以挂起或恢复cgroup中的任务,pids限制任务数量,memory可以设定cgroup中任务对内存使用量的限定并且生成使用报告,perf_event使用后可以是cgroup中的任务可以进行统一的性能测试。 - 层级树
由一系列控制组按照树状结构排列组成,形成带有父子结构的层级树。子控制组可以自动继承父控制组的资源限制。 - 任务
任务是一个进程,一个任务可以是多个cgroup的成员。
这里总结一下就是,使用不同的子系统来对控制组里的资源进行限制配置,然后将一个任务放进控制组中,那么这个任务就只能使用控制组中配置的资源值。多个任务可以形成层级树的结构,来简化任务的控制组分配工作量。
实际例子来使用cgroup
#!/bin/bash
while true;do
echo "1"
done
将以上4行内容保存为cgroup_test.sh,然后执行如下命令:
mkdir -p /sys/fs/cgroup/cpu/cgroup_test/
echo 50000 > /sys/fs/cgroup/cpu/cgroup_test/cpu.cfs_quota_us
执行完以上命令后使用bash cgroup_test.sh启动bash进程。然后ps -efww | grep bash查看bash的进程id。
echo 53742 > /sys/fs/cgroup/cpu/cgroup_test/cgroup.procs
使用top查看CPU的占用率是不是50%。
cgroupfs和systemd应该怎么选
当操作系统是使用systemd来初始化系统的时候,不推荐使用cgroupfs,因为systemd本身就有一个cgroup管理器,如果再启动一个cgroupfs,就会有两个cgroup管理器,资源的限制策略就会混乱,变的不稳定。docker配置使用systemd,是在/etc/docker/daemon.json文件中配置。kubelet配置使用systemd是在yaml中的配置项cgroupDriver配置.
从1.22开始,kubeadm默认使用systemd作为cgroup驱动。另外不要更改已经加入集群节点的cgroup驱动,而是先驱逐走所有的POD,然后更改节点cgroup驱动,然后再重新朝此节点调度POD。
容器运行时
- containerd
在centos7上安装containerd可以使用yum一键安装,如果提示没有containerd安装包的话,可以添加阿里云开源镜像站的docker仓库。在安装完containerd容器运行时候,需要在/etc/containerd/config.toml配置几个参数项:- 配置systemd cgroup驱动
[plugins.“io.containerd.grpc.v1.cri”.containerd.runtimes.runc.options]
SystemdCgroup = true - 启用CRI
disabled_plugins的CRI去掉 - 更改pause的镜像地址
sandbox_image = “registry.k8s.io/pause:3.2”
现在的阿里云、腾讯云的容器服务中,默认的容器运行时都是containerd了。所以docker已经是会被慢慢去掉了,尽早的研究和部署containerd。
- 配置systemd cgroup驱动
- CRI-O
CRI-O是一个轻量级的容器运行时,其安装、配置方式和containerd类似,这里不做重点解析了。 - Docker Engine
Docker在k8s 1.22版本后需要安装cri-dockerd组件来和kubernetes集成使用。Docker容器运行时,是使用比较多的一种容器运行时了。
从k8s1.24起,如果想让k8s继续管理docker容器,需要安装cri-dockerd组件,让k8s管理cri-dockerd,而让cri-dockerd去管理docker。因为1.24版本起,k8s移除了Dockershim模块,而Dockershim是docker容器的管理模块。 - mirantis
mirantis是一种商用容器运行时,mirantis公司收购了Docker的企业版,因此mirantis这个容器运行时是继承了docker ee的大部分功能和特点。