![Yikun Jiang](/assets/img/avatar_default.png)
1. Add computing offloading code 2. Add script.md 3. Add virsh_demo.xml Change-Id: Id9ef883e2f0eb727eb5448b9d1c47767f46b1021 Signed-off-by: Yikun Jiang <yikunkero@gmail.com>
166 lines
8.8 KiB
Markdown
166 lines
8.8 KiB
Markdown
|
||
# 容器管理面无感卸载部署指导
|
||
|
||
> ![](./public_sys-resources/icon-note.gif)**说明**:
|
||
>
|
||
> 本指导涉及对容器管理面组件的少量改动和rexec工具修改,这些修改基于指定版本,其他版本可基于实际执行环境做适配修改。文档中提供的patch仅供验证指导使用,不具备实际商用的条件。
|
||
|
||
> ![](./public_sys-resources/icon-note.gif)**说明**:
|
||
>
|
||
> 当前共享文件系统之间通信通过网络完成,可通过网络互连的两台物理机器或VM模拟验证。
|
||
>
|
||
> 建议用户验证前先搭建可正常使用的kubernetes集群和容器运行环境,针对其中单个节点的管理面进程进行卸载验证,卸载环境(DPU)可选择一台具备网络连接的物理机或VM。
|
||
|
||
## 简介
|
||
|
||
容器管理面,即kubernetes、dockerd、containerd、isulad等容器的管理工具,而容器管理面卸载,即是将容器管理面卸载到与容器所在机器(以下称为HOST)之外的另一台机器(当前场景下是指DPU,一个具备独立运行环境的硬件集合)上运行。
|
||
|
||
我们使用共享文件系统qtfs将HOST上与容器运行相关的目录挂载到DPU上,使得容器管理面工具(运行在DPU)可以访问到这些目录,并为容器(运行在HOST)准备运行所需要的环境,此处,因为需要挂载远端的proc和sys等特殊文件系统,所以,我们创建了一个专门的rootfs以作为kubernetes、dockerd的运行环境(以下称为`/another_rootfs`)。
|
||
|
||
并且通过rexec执行容器的拉起、删除等操作,使得可以将容器管理面和容器分离在不同的两台机器上,远程对容器进行管理。
|
||
|
||
## 相关组件补丁介绍
|
||
|
||
#### rexec介绍
|
||
|
||
rexec是一个用go语言开发的远程执行工具,基于docker/libchan下的[rexec](https://github.com/docker/libchan/tree/master/examples/rexec)示例工具改造而成,实现远程调用远端二进制的功能,为方便使用在rexec中增加了环境变量传递和监控原进程退出等能力。
|
||
|
||
rexec工具的具体使用方式为在服务器端用`CMD_NET_ADDR=tcp://0.0.0.0:<端口号> rexec_server`的方式拉起rexec服务进程,然后在客户端用`CMD_NET_ADDR=tcp://<服务端ip>:<端口号> rexec [要执行的指令] `的方式启动,便可以调用rexec_server执行需要执行的指令,并等待指令执行结果返回。
|
||
|
||
#### dockerd相关改动介绍
|
||
|
||
对dockerd的改动基于18.09版本。
|
||
|
||
在containerd中,暂时注释掉了通过hook调用libnetwork-setkey的部分,此处不影响容器的拉起。并且,为了docker load的正常使用,注释掉了在mounter_linux.go 中mount函数中一处错误的返回。
|
||
|
||
最后,因为在容器管理面的运行环境中,将`/proc`挂在了服务端的proc文件系统,而本地的proc文件系统则挂载在了`/local_proc`,所以,dockerd以及containerd中的对`/proc/self/xxx`或者`/proc/getpid()/xxx`或者相关的文件系统访问的部分,我们统统将`/proc`改为了`/local_proc`。
|
||
|
||
#### containerd相关改动介绍
|
||
|
||
对于containerd的改动基于containerd-1.2-rc.1版本。
|
||
|
||
在获取mountinfo时,因为`/proc/self/mountinfo`只能获取到dockerd本身在本地的mountinfo,而无法获取到服务端的mountinfo,所以,将其改为了`/proc/1/mountinfo`,使其通过获取服务端1号进程mountinfo的方式得到服务端的mountinfo。
|
||
|
||
在contaienrd-shim中,将与containerd通信的unix socket改为了用tcp通信,containerd通过`SHIM_HOST`环境变量获取containerd-shim所运行环境的ip,即服务端ip。用shim的哈希值计算出一个端口号,并以此作为通信的端口,来拉起containerd-shim.
|
||
|
||
并且,将原来的通过系统调用给contaienr-shim发信号的方式,改为了通过远程调用kill指令的方式向shim发信号,确保了docker杀死容器的行为可以正确的执行。
|
||
|
||
#### kubernetes相关改动介绍
|
||
|
||
kubelet暂不需要功能性改动,可能会遇到容器QoS管理器首次设置失败的错误,该错误不影响后续Pods拉起流程,暂时忽略该报错。
|
||
|
||
## 容器管理面卸载操作指南
|
||
|
||
在服务器端和客户端,都要拉起rexec_server。服务器端拉起rexec_server,主要是用于客户端创建容器时用rexec拉起containerd-shim,而客户端拉起rexec_server,则是为了执行containerd-shim对dockerd和containerd的调用。
|
||
|
||
#### 服务器端
|
||
|
||
创建容器管理面所需要的文件夹,然后插入qtfs_server.ko,并拉起engine进程。
|
||
|
||
此外在服务器端,还需要创建rexec脚本/usr/bin/dockerd.
|
||
|
||
``` shell
|
||
#!/bin/bash
|
||
CMD_NET_ADDR=tcp://<客户端ip>:<rexec端口号> rexec /usr/bin/dockerd $*
|
||
```
|
||
|
||
#### 客户端
|
||
|
||
需要准备一个rootfs,作为dockerd与containerd的运行环境,通过如下的脚本,将dockerd、containerd所需要的服务端目录挂载到客户端。并且,需要确保在以下脚本中被挂载的远程目录在服务端和客户端都存在。
|
||
|
||
``` shell
|
||
#!/bin/bash
|
||
mkdir -p /another_rootfs/var/run/docker/containerd
|
||
iptables -t nat -N DOCKER
|
||
echo "---------insmod qtfs ko----------"
|
||
insmod /YOUR/QTFS/PATH/qtfs.ko qtfs_server_ip=<服务端ip> qtfs_log_level=INFO
|
||
|
||
# chroot环境内的proc使用DPU的proc共享文件系统替换,需要将本机真实proc文件系统挂载到local_proc下使用
|
||
mount -t proc proc /another_rootfs/local_proc/
|
||
|
||
# 将chroot内环境与外部环境bind,方便进行配置和运行
|
||
mount --bind /var/run/ /another_rootfs/var/run/
|
||
mount --bind /var/lib/ /another_rootfs/var/lib/
|
||
mount --bind /etc /another_rootfs/etc
|
||
|
||
mkdir -p /another_rootfs/var/lib/isulad
|
||
|
||
# 在chroot环境内创建并挂载dev、sys和cgroup文件系统
|
||
mount -t devtmpfs devtmpfs /another_rootfs/dev/
|
||
mount -t sysfs sysfs /another_rootfs/sys
|
||
mkdir -p /another_rootfs/sys/fs/cgroup
|
||
mount -t tmpfs tmpfs /another_rootfs/sys/fs/cgroup
|
||
list="perf_event freezer files net_cls,net_prio hugetlb pids rdma cpu,cpuacct memory devices blkio cpuset"
|
||
for i in $list
|
||
do
|
||
echo $i
|
||
mkdir -p /another_rootfs/sys/fs/cgroup/$i
|
||
mount -t cgroup cgroup -o rw,nosuid,nodev,noexec,relatime,$i /another_rootfs/sys/fs/cgroup/$i
|
||
done
|
||
|
||
## common system dir
|
||
mount -t qtfs -o proc /proc /another_rootfs/proc
|
||
echo "proc"
|
||
mount -t qtfs /sys /another_rootfs/sys
|
||
echo "cgroup"
|
||
|
||
# 挂载容器管理面所需要的共享目录
|
||
mount -t qtfs /var/lib/docker/containers /another_rootfs/var/lib/docker/containers
|
||
mount -t qtfs /var/lib/docker/containerd /another_rootfs/var/lib/docker/containerd
|
||
mount -t qtfs /var/lib/docker/overlay2 /another_rootfs/var/lib/docker/overlay2
|
||
mount -t qtfs /var/lib/docker/image /another_rootfs/var/lib/docker/image
|
||
mount -t qtfs /var/lib/docker/tmp /another_rootfs/var/lib/docker/tmp
|
||
mkdir -p /another_rootfs/run/containerd/io.containerd.runtime.v1.linux/
|
||
mount -t qtfs /run/containerd/io.containerd.runtime.v1.linux/ /another_rootfs/run/containerd/io.containerd.runtime.v1.linux/
|
||
mkdir -p /another_rootfs/var/run/docker/containerd
|
||
mount -t qtfs /var/run/docker/containerd /another_rootfs/var/run/docker/containerd
|
||
mount -t qtfs /var/lib/kubelet/pods /another_rootfs/var/lib/kubelet/pods
|
||
```
|
||
|
||
在/another_rootfs中,需要创建以下脚本,用来支持部分跨主机操作。
|
||
|
||
* /another_rootfs/usr/local/bin/containerd-shim
|
||
|
||
``` shell
|
||
#!/bin/bash
|
||
CMD_NET_ADDR=tcp://<服务端ip>:<rexec端口号> /usr/bin/rexec /usr/bin/containerd-shim $*
|
||
```
|
||
|
||
* /another_rootfs/usr/local/bin/remote_kill
|
||
|
||
``` shell
|
||
#!/bin/bash
|
||
CMD_NET_ADDR=tcp://<服务端ip>:<rexec端口号> /usr/bin/rexec /usr/bin/kill $*
|
||
```
|
||
|
||
* /another_rootfs/usr/sbin/modprobe
|
||
``` shell
|
||
#!/bin/bash
|
||
CMD_NET_ADDR=tcp://<服务端ip>:<rexec端口号> /usr/bin/rexec /usr/sbin/modprobe $*
|
||
```
|
||
|
||
在chroot到dockerd和containerd运行所需的rootfs后,用如下的命令拉起dockerd和containerd
|
||
|
||
* containerd
|
||
``` shell
|
||
#!/bin/bash
|
||
SHIM_HOST=<服务端ip> containerd --config /var/run/docker/containerd/containerd.toml --address /var/run/containerd/containerd.sock
|
||
```
|
||
|
||
* dockerd
|
||
``` shell
|
||
#!/bin/bash
|
||
SHIM_HOST=<服务端ip> CMD_NET_ADDR=tcp://<服务端ip>:<rexec端口号> /usr/bin/dockerd --containerd /var/run/containerd/containerd.sock
|
||
```
|
||
|
||
* kubelet
|
||
|
||
在chroot环境内使用原参数拉起kubelet即可。
|
||
|
||
因为我们已经将/var/run/和/another_rootfs/var/run/绑定在了一起,所以可以在正常的rootfs下,通过docker来访问docker.sock接口进行容器管理。
|
||
|
||
至此,完成容器管理面卸载到DPU,可以通过docker相关操作进行容器创建、删除等操作,也可以通过kubectl在当前节点进行pods调度和销毁,且实际容器业务进程运行在HOST侧。
|
||
|
||
> ![](./public_sys-resources/icon-note.gif)**说明**:
|
||
>
|
||
> 本指导所述操作只涉及容器管理面进程卸载,不包含容器网络和数据卷volume等卸载,如有相关需求,需要通过额外的网络或存储卸载能力支持。本指导支持不带网络和存储的容器跨节点拉起。 |