长期支持版本

    社区创新版本

      1 容器管理面无感卸载

      1.1 简介

      容器管理面,即dockerd、containerd、isulad等容器的管理工具,而容器管理面卸载,即是将容器管理面卸载到与容器所在机器(以下称为HOST)之外的另一台机器(以下称为DPU)上运行。

      我们使用qtfs将HOST上一些与容器运行相关的目录挂载到DPU上,使得容器管理面工具可以访问到这些目录,为容器准备运行所需要的环境。此外,因为需要挂载远端的proc和sys文件系统,为避免对当前系统运行造成影响,可以创建一个专门的rootfs以作为dockerd、contianerd的运行环境(以下称为/another_rootfs)。

      通过rexec执行容器的拉起、删除等操作,可以将容器管理面和容器分离在不同的两台机器上,对容器进行远程管理。无感卸载的验证可以使用下述两种模式。

      1.1.1 测试模式

      需准备2台物理机(或虚拟机),两台机器之间网络互通。

      其中一台作为DPU模拟,另一台作为HOST模拟。在本文档中用DPU和HOST指代这两台服务器。

      说明: 测试模式因为会暴露网络端口且不做连接认证,存在网络安全风险,仅能用于内部测试验证,不要用于实际生产环境。 实际生产环境中应使用封闭通信方式,以防止外界连接风险,如下述vsock通信模式。

      1.1.2 vsock模式

      需要DPU和HOST通过virtio提供vsock通信方式。

      文档当前仅描述基于测试模式的方法,下面的内容依然默认使用测试模式。如果验证环境支持vsock通信(虚拟化环境或支持vsock的DPU-HOST环境),下述测试步骤仍适用,只需要将测试中的IP网络地址修改为vsock cid即可(相关二进制编译过程也无需使用TEST_MODE)。

      2 环境搭建

      2.1 qtfs文件系统部署

      可参考qtfs主页

      说明: 如果使用测试模式,需要在qtfs客户端及服务端ko编译时指定qtfs_TEST_MODE=1,vsock模式无需指定。

      qtfs建联需要关闭DPU和HOST侧的防火墙,或在防火墙中开放相关网络端口号。

      2.2 UDSPROXYD服务部署

      2.2.1 简介

      udsproxyd是一个跨主机的unix domain socket代理服务,需要分别部署在HOST和DPU上,在HOST和DPU上的udsproxyd组件是对等的关系,可以实现分布在HOST与DPU上的2个进程之间使用标准uds进行通信,通信进程是无感的,即如果这两个进程在同一主机内通过uds正常通信的功能,拉远到HOST和DPU之间也可以,不需要做代码适配。udsproxyd作为一个跨主机的unix socket服务,可以用LD_PRELOAD=libudsproxy.so动态库截获的方式对接使用,也可以通过提前进行udsconnect白名单配置无感应用,白名单配置具体有两种方式,将在后面详述。

      2.2.2 部署方式

      首先,在dpu-utilities工程内编译udsproxyd:

      cd qtfs/ipc
      
      make -j UDS_TEST_MODE=1 && make install
      

      说明: 如果使用vsock模式,编译时不需要设置UDS_TEST_MODE

      当前最新版本下,qtfs server侧的engine服务已经整合了udsproxyd的能力,所以server侧需要再额外启动udsproxyd。client侧则单独拉起udsproxyd服务:

      nohup /usr/bin/udsproxyd <thread num> <addr> <port> <peer addr> <peer port> 2>&1 &
      

      参数解释:

      thread num: 线程数量,目前只支持单线程,填1
      
      addr: 本机使用的ip,如果使用vsock通信模式则为cid
      
      port:本机占用的port
      
      peer addr: udsproxyd对端的ip,如果使用vsock模式则为cid
      
      peer port: 对端port
      

      示例:

      nohup /usr/bin/udsproxyd 1 192.168.10.10 12121 192.168.10.11 12121 2>&1 &
      

      如果未拉起qtfs的engine服务,想单独测试udsproxyd,则在server端也对等拉起udsproxyd即可:

      nohup /usr/bin/udsproxyd 1 192.168.10.11 12121 192.168.10.10 12121 2>&1 &
      

      2.2.3 应用方式

      2.2.3.1 独立使用udsproxyd服务

      需要在使用uds服务的unix socket应用程序的client端进程启动时添加LD_PRELOAD=libudsproxy.so环境变量,以接管glibc的connect api进行uds对接,或者通过qtcfg增加udsconnect白名单的方式指定系统接管特定目录下的uds连接。

      2.2.3.2 无感使用udsproxyd服务

      首先为qtfs配置uds服务的白名单,这里说的白名单是unix socket的server端bind的sock文件地址,提供两种方式供选择:

      • 通过配置工具qtcfg加载,进入qtfs/qtinfo目录编译工具:

      在qtfs的client端执行

      make role=client 
      make install
      

      在qtfs的server端执行

      make role=server
      make install
      

      配置工具将会自动安装,然后使用qtcfg命令配置白名单,假设需要增加的白名单为"/var/lib/docker",输入:

      qtcfg -w udsconnect -x /var/lib/docker
      

      查询白名单为:

      qtcfg -w udsconnect -z
      

      删除白名单为:

      qtcfg -w udsconnect -y 0
      

      删除白名单时,参数为查询白名单时列出来的index序号。

      • 通过配置文件增加,这需要在qtfs或qtfs_server内核模块加载前配置,通过内核模块初始化时读取该文件进行白名单配置。

      在/etc/qtfs/whitelist文件中增加如下字段:

      [Udsconnect]
      /var/lib/docker
      

      说明: 白名单是为了防止不相干的unix socket链接也进行远程连接产生错误,或者浪费不必要的资源,所以白名单尽量设置得精确一些,比如本文中针对容器场景设置为/var/lib/docker比较好,而直接将/var/lib/或/var/或直接将根目录加入的做法是有较大风险和系统影响的。

      2.3 REXEC服务部署

      2.3.1 简介

      rexec是一个用c语言开发的远程执行组件,分为rexec client和rexec server。server端为一个常驻服务进程,client端为一个二进制文件,client端被执行后会基于udsproxyd服务与server端建立uds连接,并由server常驻进程在server端拉起指定程序。在容器管理面卸载中,dockerd卸载到DPU上,当它需要在HOST拉起容器业务进程时调用rexec client进行远程拉起。

      2.3.2 部署方法

      2.3.2.1 配置环境变量与白名单

      在HOST侧配置rexec server的白名单,将文件whitelist放置在/etc/rexec/目录下并修改权限为只读:

      chmod 400 /etc/rexec/whitelist
      

      下载dpu-utilities代码后,进入qtfs/rexec主目录下,执行:make && make install即可安装rexec所需全部二进制到/usr/bin目录下,包括了:rexec、rexec_server两个二进制可执行文件。

      在server端启动rexec_server服务之前,检查是否存在/var/run/rexec目录,没有则创建:

      mkdir /var/run/rexec
      

      rexec服务运行时底层通信使用unix socket,因此跨主机的rexec和rexec_server通信依赖上述udsproxyd服务,并且需要在udsproxy中添加相关白名单:

      qtcfg -w udsconnect -x /var/run/rexec
      

      2.3.2.2 服务方式

      server端可以通过两种方式拉起rexec_server服务。

      • 方式1: 配置systemd服务

      在/usr/lib/systemd/system/下增加rexec.service文件,内容如下:

      rexec.service

      然后通过systemctl管理rexec服务。

      首次配置服务时:

      systemctl daemon-reload
      systemctl enable --now rexec
      

      后续重启新启动服务:

      systemctl stop rexec
      systemctl start rexec
      
      • 方式2: 手动后台拉起
      nohup /usr/bin/rexec_server 2>&1 &
      

      3 管理面组件改动

      3.1 dockerd相关改动介绍

      对dockerd的改动是基于18.09版本的。

      在docker中,暂时绕过了网络部分,管理面卸载依赖容器网络组件做针对性适配,本测试方案暂不涉及。

      对docker的改动可以参考该目录下的patch文件。

      3.2 containerd相关改动介绍

      对于containerd的改动是基于containerd-1.2-rc.1版本的。

      对containerd的改动可以参考该目录下的patch文件。

      4 容器管理面卸载操作指南

      说明:

      1. 在HOST端和DPU端,都要拉起rexec_server;
      2. HOST端拉起rexec_server,主要是用于DPU创建容器时用rexec拉起containerd-shim;
      3. DPU拉起rexec_server,则是为了执行containerd-shim对dockerd和containerd的调用。

      4.1 准备dockerd和containerd运行的rootfs

      注:本步骤仅需在DPU上执行的。

      在下面的文档中,我们将这个rootfs称为/another_rootfs(具体的目录名称,可以根据自己的需求进行调整)。

      4.1.1 使用openEuler官方qcow2镜像构造rootfs

      建议用openEuler官方提供的qcow2镜像,来准备一个新的rootfs:

      4.1.1.1 工具安装

      需要用yum安装xz、kpartx、qemu-img

      yum install xz kpartx qemu-img
      

      4.1.1.2 下载qcow2镜像

      在openEuler官网获取22.03版本openEuler-x86虚拟机镜像(X86架构),或者22.03版本openEuler-arm64虚拟机镜像(ARM架构)。

      4.1.1.3 解压qcow2镜像

      使用xz -d解压为openEuler-22.03-LTS-.qcow2文件, 以x86镜像为例

      xz -d openEuler-22.03-LTS-x86_64.qcow2.xz
      

      4.1.1.4 挂载qcow2镜像并拷贝文件

      1. 使用modprobe nbd maxpart=<任意数字>来加载nbd模块
      2. qemu-nbd -c /dev/nbd0 <虚拟机镜像的路径>
      3. 创建任意文件夹/random_dir
      4. 执行挂载mount /dev/nbd0p2 /random_dir
      5. 拷贝文件
      mkdir /another_rootfs
      cp -r /random_dir/* /another_rootfs/
      

      此时,虚拟机镜像遍已经挂载到当前文件夹中了。

      4.1.1.5 qcow2卸载

      在准备好rootfs后,需要卸载qcow2文件,此时,需要执行如下指令:

      umount /random_dir
      qemu-nbd -d /dev/nbd0
      

      4.1.2 向another_rootfs中安装软件

      1. 将根目录中的/etc/resolv.conf拷贝到/another_rootfs/etc/resolv.conf
      2. 清空/another_rootfs/etc/yum.repos.d中的文件,并将/etc/yum.repos.d/中的文件拷贝到/another_rootfs/etc/yum.repos.d
      3. 使用yum install <软件包> --installroot=/another_rootfs来安装软件包
      yum install --installroot=/another_rootfs iptables
      

      4.2 在Host侧拉起qtfs_server

      需要将rexec、containerd-shim、runc、engine拷贝到/usr/bin下面,这里要注意权限问题,rexec、engine已提供,docker相关二进制根据上述第三章相关patch编译生成。

      4.2.1 插入qtfs_server驱动

      创建容器管理面所需要的文件夹,然后插入qtfs_server.ko,并拉起engine进程。

      可以使用这个脚本来执行此操作,如果执行错误,可能需要dos2unix来将此脚本的格式转换(如下所有脚本皆同理)。

      注意,使用实际qtfs路径替换脚本中的模块及二进制路径。

      此外在HOST端,还需要创建执行rexec指令的脚本/usr/bin/dockerd以及/usr/bin/containerd

      /usr/bin/dockerd:

      #!/bin/bash
      rexec /usr/bin/dockerd $*
      

      /usr/bin/containerd:

      #!/bin/bash
      exec /usr/bin/containerd $*
      

      在创建完成后,需要用chmod为这两个脚本赋予执行权限

      chmod +x /usr/bin/containerd
      chmod +x /usr/bin/dockerd
      

      4.3 挂载Host上依赖目录至DPU

      4.3.1 安装软件包

      4.3.2.1 在根目录的安装

      DPU根目录中(another_rootfs之外):安装iptables和libtool、libcgroup、tar,可以通过yum直接直接安装。

      yum install iptables libtool libcgroup tar
      

      也可以下载其所有的依赖包之后,用rpm指令安装,iptables以及libtool的包及依赖包链接如下:iptables, libtool, emacs, autoconf, automake, libtool-ltdl, m4tar, libcgroup

      在下载上述软件包之后,执行命令

      rpm -ivh iptables-1.8.7-5.oe2203.x86_64.rpm libtool-2.4.6-34.oe2203.x86_64.rpm emacs-27.2-3.oe2203.x86_64.rpm autoconf-2.71-2.oe2203.noarch.rpm automake-1.16.5-3.oe2203.noarch.rpm libtool-ltdl-2.4.6-34.oe2203.x86_64.rpm m4-1.4.19-2.oe2203.x86_64.rpm tar-1.34-1.oe2203.x86_64.rpm libcgroup-0.42.2-1.oe2203.x86_64.rpm
      

      4.3.2.2 another_rootfs环境配置

      1. /another_rootfs中,需要安装iptables,这个是dockerd启动所必须的依赖

      使用yum install <软件包> --installroot=/another_rootfs来安装软件包

      1. 并需要将rexec拷贝到/another_rootfs/usr/bin下面,并对其添加可执行权限
      cp rexec /another_rootfs/usr/bin
      chmod +x /another_rootfs/usr/bin/rexec
      
      1. 另外,将根据社区docker源码与前述patch编译出来的containerd和dockerd拷贝到/another_rootfs/usr/bin下面, 将docker拷贝到/usr/bin
      cp {YOUR_PATH}/dockerd /another_rootfs/usr/bin
      cp {YOUR_PATH}/containerd /another_rootfs/usr/bin
      cp {YOUR_PATH}/docker /usr/bin
      
      1. /another_rootfs中删除/another_rootfs/usr/sbin/modprobe
      rm -f /another_rootfs/usr/sbin/modprobe
      
      1. /another_rootfs中创建如下三个脚本

      containerd-shim创建路径:/another_rootfs/usr/local/bin/containerd-shim

      #!/bin/bash
      /usr/bin/rexec /usr/bin/containerd-shim $*
      

      remote_kill创建路径:/another_rootfs/usr/bin/remote_kill

      #!/bin/bash
      /usr/bin/rexec /usr/bin/kill $*
      

      modprobe创建路径:/another_rootfs/usr/sbin/modprobe

      #!/bin/bash
      /usr/bin/rexec /usr/sbin/modprobe $*
      

      在创建完成后,为其赋予执行权限

      chmod +x /another_rootfs/usr/local/bin/containerd-shim
      chmod +x /another_rootfs/usr/bin/remote_kill
      chmod +x /another_rootfs/usr/sbin/modprobe
      

      4.3.2.3 目录挂载

      在DPU上执行此脚本prepare.sh ,将dockerd、containerd所需要的HOST目录挂载到DPU。

      并且,需要确保在该脚本被挂载的远程目录在HOST和DPU都存在。

      4.4 拉起dockerd和containerd

      在DPU上,打开两个窗口,并且都chroot到dockerd和containerd运行所需的/another_rootfs。

      chroot /another_rootfs
      

      在两个窗口中用如下的命令先拉起containerd,后拉起dockerd。

      containerd

      #!/bin/bash
      SHIM_HOST=${YOUR_SERVER_IP} containerd --config /var/run/docker/containerd/containerd.toml --address /var/run/containerd/containerd.sock
      

      dockerd

      #!/bin/bash
      # this need to be done once
      /usr/bin/rexec mount -t qtfs /var/lib/docker/overlay2 /another_rootfs/var/lib/docker/overlay2/
      SHIM_HOST=${YOUR_SERVER_IP} /usr/bin/dockerd --containerd /var/run/containerd/containerd.sock -s overlay2 --iptables=false --debug 2>&1 | tee docker.log
      

      因为我们已经将/var/run//another_rootfs/var/run/绑定在一起,可以在正常的rootfs下,通过docker来访问docker.sock接口,从而管理容器。

      5 环境恢复

      如果需要卸载相关的目录,需要先删除已有容器,再关掉containerd、dockerd,并执行如下指令:

      for i in `lsof | grep v1.linux | awk '{print $2}'`
      do
              kill -9 $i
      done
      mount | grep qtfs | awk '{print $3}' | xargs umount
      mount | grep another_rootfs | awk '{print $3}' | xargs umount
      
      sleep 1
      
      umount /another_rootfs/etc
      umount /another_rootfs/sys
      pkill udsproxyd
      rmmod qtfs
      

      文档捉虫

      “有虫”文档片段

      问题描述

      提交类型 issue

      有点复杂...

      找人问问吧。

      PR

      小问题,全程线上修改...

      一键搞定!

      问题类型
      规范和低错类

      ● 错别字或拼写错误;标点符号使用错误;

      ● 链接错误、空单元格、格式错误;

      ● 英文中包含中文字符;

      ● 界面和描述不一致,但不影响操作;

      ● 表述不通顺,但不影响理解;

      ● 版本号不匹配:如软件包名称、界面版本号;

      易用性

      ● 关键步骤错误或缺失,无法指导用户完成任务;

      ● 缺少必要的前提条件、注意事项等;

      ● 图形、表格、文字等晦涩难懂;

      ● 逻辑不清晰,该分类、分项、分步骤的没有给出;

      正确性

      ● 技术原理、功能、规格等描述和软件不一致,存在错误;

      ● 原理图、架构图等存在错误;

      ● 命令、命令参数等错误;

      ● 代码片段错误;

      ● 命令无法完成对应功能;

      ● 界面错误,无法指导操作;

      风险提示

      ● 对重要数据或系统存在风险的操作,缺少安全提示;

      内容合规

      ● 违反法律法规,涉及政治、领土主权等敏感词;

      ● 内容侵权;

      您对文档的总体满意度

      非常不满意
      非常满意
      提交
      根据您的反馈,会自动生成issue模板。您只需点击按钮,创建issue即可。
      文档捉虫
      编组 3备份