首页 > 其他分享 >记一次 CGroup 小实验

记一次 CGroup 小实验

时间:2022-09-03 00:11:27浏览次数:70  
标签:一次 CGroup cgexec libcgroup cgroup test 实验 pod name

前言

之前遇到一个需求:解决 cephfs 的 csi-node 插件,在 csi-node 重启以后,ceph-fuse 进程也随之终止,导致已挂在的目录挂载点丢失。

最终通过 cgexec 命令,在执行 ceph-fuse 命令时,修改了 ceph-use 进程的 cgroup,避免了 pod 重启之后随着 pod 之前的 cgroup 被删除而终止。

近期,遇到了类似的问题,又重新回顾并模拟了主要操作,并在本文中做了记录。

实验原因

kubelet 有一个参数:cgroups-per-qos(布尔类型),启用后会为每个 pod 以及 pod 对应的 Qos 创建 cgroups 层级树,默认启用。

启用后,pod 退出时,会清理 cgroup 下所有进程,详情参考:https://github.com/kubernetes/kubernetes/blob/release-1.22/pkg/kubelet/cm/pod_container_manager_linux.go#L144

// Scan through the whole cgroup directory and kill all processes either
// attached to the pod cgroup or to a container cgroup under the pod cgroup
func (m *podContainerManagerImpl) tryKillingCgroupProcesses(podCgroup CgroupName) error {
    pidsToKill := m.cgroupManager.Pids(podCgroup)
    // No pids charged to the terminated pod cgroup return
    if len(pidsToKill) == 0 {
        return nil
    }

    var errlist []error
    // os.Kill often errors out,
    // We try killing all the pids multiple times
    removed := map[int]bool{}
    for i := 0; i < 5; i++ {
        if i != 0 {
            klog.V(3).InfoS("Attempt failed to kill all unwanted process from cgroup, retrying", "attempt", i, "cgroupName", podCgroup)
        }
        errlist = []error{}
        for _, pid := range pidsToKill {
            if _, ok := removed[pid]; ok {
                continue
            }
            klog.V(3).InfoS("Attempting to kill process from cgroup", "pid", pid, "cgroupName", podCgroup)
            if err := m.killOnePid(pid); err != nil {
                klog.V(3).InfoS("Failed to kill process from cgroup", "pid", pid, "cgroupName", podCgroup, "err", err)
                errlist = append(errlist, err)
            } else {
                removed[pid] = true
            }
        }
        if len(errlist) == 0 {
            klog.V(3).InfoS("Successfully killed all unwanted processes from cgroup", "cgroupName", podCgroup)
            return nil
        }
    }
    return utilerrors.NewAggregate(errlist)
}

 

由此,我们也受到启发,如果能把进程从 pod 自身的 cgroup 移出,是不是就可以实现 ceph-fuse 进程不会再 pod 终止时随之被清理。

主要操作

首先,在一个 linux 测试机上,启动一个单节点的 kubernetes 测试集群。

向集群提交如下 pod 准备测试:

apiVersion: v1
kind: Pod
metadata:
  name: my-centos
  labels:
    app: centos
spec:
  hostPID: true
  hostNetwork: true
  containers:
  - name: my-centos
    image: centos:7
    imagePullPolicy: IfNotPresent
    command: ["top","-b"]
    volumeMounts:
    - mountPath: /sys
      name: host-sys
    securityContext:
      privileged: true
  volumes:
  - hostPath:
      path: /sys
      type: ""
    name: host-sys

 

注意上述 pod 共享了 /sys 目录,启用了特权容器,和宿主机共享了 PID。

执行:kubectl exec -it my-centos bash,进入容器内部,并执行:cd ~,回到用户目录。

执行如下命令,创建一个脚本:

cat << EOF > test-cgroup.sh
#!/bin/bash
sleep 1234s
EOF

chmod +x test-cgroup.sh

 

执行:./test-cgroup.sh &,启动这个脚本,然后再新开一个连接宿主机的窗口,通过执行:ps aux | grep test-cgroup | grep -v test-cgroup,查看 PID:

 

 

 然后执行:pstree -ps ${PID},查看进程的依赖关系。

接下来,我们删除之前创建的 Pod,再查看进程是否存在:

 

 

 很明显,子进程随着 Pod 被删除而被清理。

接下来,我们试一下 cgexec 工具,重新提交一下上述的 my-centos 的 pod,并进入容器。

默认 centos 镜像没有 cgexec 命令,我们执行:yum install -y wget gcc-c++ byacc flex pam-devel gcc automake autoconf libtool make,先安装依赖。

安装一下默认的 libcgroup:yum install libcgroup libcgroup-tools -y。

 

 

 

 

 

 

 回到用户目录,再次创建脚本:

cd ~

cat << EOF > test-cgroup.sh
#!/bin/bash
sleep 1234s
EOF

chmod +x test-cgroup.sh

 

执行:cgexec -g *:/ ./test-cgroup.sh &(cgexec 的作用在于在指定子系统的 cgroup 执行命令,* 表示所有子系统),然后再另一个窗口查看进程 PID,以及该进程所在各个 cgroup(cat /proc/${PID}/cgroup):

 

 

 我们发现,默认的 cgexec 命令,没有办法修改 name=systemd 子系统的 cgroup,其余的子系统的 cgroup 都改为了 root cgroup。

然后我们尝试删除 my-centos 的 pod,由于无法更改 name=systemd 的子系统的 cgroup,果不其然,子进程随 pod 删除而被回收:

 

 

 我们看下 libcgroup 源码的一段说明:https://github.com/libcgroup/libcgroup/blob/v0.41/README_systemd

Compilation
===========
As stated in [2], libcgroup should not interact with the 'name=systemd'
hierarchy. Compile libcgroup with the --enable-opaque-hierarchy configure option
to do so:

./configure --enable-opaque-hierarchy=name=systemd

Consequently, the 'name=systemd' hierarchy will not be visible to libcgroup and
all of its tools. For example, the lscgroup command will not list systemd
cgroups and the cgclear command will not remove them.

Start-up and services
====================

 

大意是,libcgroup 的工具默认不会操作 name=systemd 的层级,默认情况也是如此。

既然是开源的代码,我们就可以自己编译一个 cgexec 命令。

再次,启动测试的 pod,进入容器内部,回到用户目录。

执行:yum install -y wget gcc-c++ byacc flex pam-devel gcc automake autoconf libtool make,安装依赖。

执行:wget https://github.com/libcgroup/libcgroup/releases/download/v0.41/libcgroup-0.41.tar.gz,下载源码(使用 0.41 版是对应上文,默认依赖的 libcgroup 版本)。

执行:tar -zxvf libcgroup-0.41.tar.gz && cd libcgroup-0.41,解压并进入代码目录。

执行:./configure --enable-opaque-hierarchy=none && make && make install,编译并安装 cgexec,这次,我们没有采用默认方式,将参数设为 --enable-opaque-hierarchy=none。

再次创建脚本:

cd ~

cat << EOF > test-cgroup.sh
#!/bin/bash
sleep 1234s
EOF

chmod +x test-cgroup.sh

 

执行:cgexec -g *:/ ./test-cgroup.sh &,然后再另一个窗口查看进程 PID,以及该进程所在各个 cgroup(cat /proc/${PID}/cgroup):

 

 

 

 

 此时,我们发现,所有子系统的 cgroup 都被修改为了 root cgroup。

我们再次删除测试 pod,再观察子进程:

 

 成功了,子进程成功“越狱”!符合了预期。

不过这种方式并不是一个安全的方式,需要根据需求使用。

简单汇总一下,我们在容器内安装 cgexec 的命令:

cd ~

yum install -y wget gcc-c++ byacc flex pam-devel gcc automake autoconf libtool make

wget https://github.com/libcgroup/libcgroup/releases/download/v0.41/libcgroup-0.41.tar.gz

tar -zxvf libcgroup-0.41.tar.gz

cd libcgroup-0.41

./configure --enable-opaque-hierarchy=name=systemd

make

make install

 

标签:一次,CGroup,cgexec,libcgroup,cgroup,test,实验,pod,name
From: https://www.cnblogs.com/wangao1236/p/16644994.html

相关文章

  • 记一次被非托管代码支配的恐惧「C#对接企微会话存档SDK问题修复」
    序这个问题是我目前在做企微服务商开发以来周期最长、最折磨人的一个问题了;从3月开始着手排查问题(其实在开发之初就发现了该问题,迫于进度,就暂时搁置了),其中断断续续去尝试......
  • 2022年java第一次随堂测试
    //源代码importjava.util.Scanner;publicclassRoomManagement{ publicstaticvoidmain(String[]args){ Scannersc=newScanner(System.in); RoomInformati......
  • 提交按钮:用户点击多次,只有一次有效(多次提交只有一次有效)
    <el-buttonv-if="showBtn!=='no'"v-preventReClickstyle="width:120px;backgroundColor:#007c84;color:#fff;marginLeft:80px;"......
  • 记一次No Buffee Space Availble
           这几天新生报到,很多学生修改上网密码,所以这几天都有发生没同步到Ldap的情况,一半处理下ok。但是今天自己处理下没用。看日志,报错了。运行了一两年......
  • RAID1实验
    实验任务添加两块硬盘,将两块硬盘组建成RAID1.并测试删除一块硬盘后会不会对数据有影响  实验环境一台添加了两块硬盘的Cento7  实验步骤1.添加两块新硬盘......
  • git rebase详解(图解+最简单示例,一次就懂)
    引言网上有太多讲rebase和merge的文章,但大多都是复制粘贴没有自己的理解,而且很多博客的例子写的过于复杂,让人没兴趣看下去。本文举最简洁的例子,大白话几句就让你快速掌握......
  • 记一次给win10客户电脑上装上tomcat程序后,启动出问题的情况
    情景描述本来是给一个客户安装我们公司的bs程序,以前也给其他公司安装过,问题都不大,这次客户因为在国外,使用向日葵进行远程操作,网络极度不稳地,超级卡,过程相当崩溃。不论是数......
  • git rebase详解(图解+最简单示例,一次就懂)
    引言网上有太多讲rebase和merge的文章,但大多都是复制粘贴没有自己的理解,而且很多博客的例子写的过于复杂,让人没兴趣看下去。本文举最简洁的例子,大白话几句就让你快速掌握re......
  • HCIA综合实验 鸽了的原因
    原计划周日出的综合实验,可惜人近三十,事情太多,搬家,医院,疫情,实在是力不从心,没得办法。我的实验其实早就写了,本来我是准备做一个稍微超纲HCIA综合实验的,但是和某兔的老哥聊天......
  • 实验产品:Project Tye
    实验产品:ProjectTye南非朋友,https://martech.org/optimizely-buys-experiment-engine-optimization-tools/今天,它是微软已经试验性启动并继续作为开源开发的项目。......