systemd를 사용하여 사용자 cgroup을 만드는 방법

systemd를 사용하여 사용자 cgroup을 만드는 방법

나는 lxc입니다 Arch Linux. 기본 시스템 정보는 다음과 같습니다.

[chb@conventiont ~]$ uname -a
Linux conventiont 3.17.4-Chb #1 SMP PREEMPT Fri Nov 28 12:39:54 UTC 2014 x86_64 GNU/Linux

다음을 갖춘 사용자 정의/컴파일된 커널입니다 user namespace enabled.

[chb@conventiont ~]$ lxc-checkconfig 
--- Namespaces ---
Namespaces: enabled
Utsname namespace: enabled
Ipc namespace: enabled
Pid namespace: enabled
User namespace: enabled
Network namespace: enabled
Multiple /dev/pts instances: enabled

--- Control groups ---
Cgroup: enabled
Cgroup clone_children flag: enabled
Cgroup device: enabled
Cgroup sched: enabled
Cgroup cpu account: enabled
Cgroup memory controller: enabled
Cgroup cpuset: enabled

--- Misc ---
Veth pair device: enabled
Macvlan: enabled
Vlan: enabled
File capabilities: enabled

Note : Before booting a new kernel, you can check its configuration
usage : CONFIG=/path/to/config /usr/bin/lxc-checkconfig

[chb@conventiont ~]$ systemctl --version
systemd 217
+PAM -AUDIT -SELINUX -IMA -APPARMOR +SMACK -SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID -ELFUTILS +KMOD +IDN 

아쉽게도 현재는 systemd잘 재생되지 않습니다 lxc. 특히 루트가 아닌 사용자를 위해 설정하는 것은 cgroups잘 작동하지 않는 것 같거나, 어떻게 해야 하는지 너무 익숙하지 않습니다. lxc컨테이너가 에 있을 수 있는 경우에만 가능합니다 . 그러나 cgroup 계층 구조가 에 마운트되어 있으므로 /sys/fs/cgroup/XXX/*이는 불가능합니다 . 해결 방법은 다음과 같습니다.lxcsystemdroot/sys/fs/cgroup/*

for d in /sys/fs/cgroup/*; do
        f=$(basename $d)
        echo "looking at $f"
        if [ "$f" = "cpuset" ]; then
                echo 1 | sudo tee -a $d/cgroup.clone_children;
        elif [ "$f" = "memory" ]; then
                echo 1 | sudo tee -a $d/memory.use_hierarchy;
        fi
        sudo mkdir -p $d/$USER
        sudo chown -R $USER $d/$USER
        echo $$ > $d/$USER/tasks
done

이 코드는 권한이 없는 사용자를 위해 계층 구조에 적절한 디렉터리를 만듭니다 cgroup. cgroup그런데 이해할 수 없는 일이 일어났습니다. 위의 작업을 수행하기 전에 다음을 확인합니다.

[chb@conventiont ~]$ cat /proc/self/cgroup 
8:blkio:/
7:net_cls:/
6:freezer:/
5:devices:/
4:memory:/
3:cpu,cpuacct:/
2:cpuset:/
1:name=systemd:/user.slice/user-1000.slice/session-c1.scope

위의 코드를 실행한 후 실행한 셸에서 다음을 볼 수 있습니다.

[chb@conventiont ~]$ cat /proc/self/cgroup 
8:blkio:/chb
7:net_cls:/chb
6:freezer:/chb
5:devices:/chb
4:memory:/chb
3:cpu,cpuacct:/chb
2:cpuset:/chb
1:name=systemd:/chb

그러나 다른 쉘에서는 여전히 다음을 볼 수 있습니다.

[chb@conventiont ~]$ cat /proc/self/cgroup 
8:blkio:/
7:net_cls:/
6:freezer:/
5:devices:/
4:memory:/
3:cpu,cpuacct:/
2:cpuset:/
1:name=systemd:/user.slice/user-1000.slice/session-c1.scope

따라서 lxc위 코드를 실행하는 셸에서 권한 없는 컨테이너를 시작할 수 있지만 다른 컨테이너에서는 시작할 수 없습니다.

  1. 누군가 이 동작을 설명할 수 있나요?

  2. cgroups현재 버전 systemd( )에 필요한 사항을 설정하는 더 좋은 방법을 찾은 사람이 있습니까 >= 217?

답변1

더 좋고 더 안전한 솔루션은 cgmanager이를 설치하고 실행하는 것입니다 systemctl start cgmanager( systemd기반 배포판에서). 그런 다음 사용자를 만들 거나 호스트에 대한 권한이 root있는 경우 모든 컨트롤러에서 권한 없는 사용자에 대해 만들 수 있습니다.sudocgroups

sudo cgm create all $USER
sudo cgm chown all $USER $(id -u $USER) $(id -g $USER)

권한이 없는 사용자를 위해 이러한 프로세스가 생성되면 해당 사용자는 다음을 cgroup사용하여 액세스 권한이 있는 프로세스를 각 컨트롤러의 프로세스로 이동할 수 있습니다.

cgm movepid all $USER $PPID

제가 게시한 쉘 스크립트보다 더 안전하고 빠르며 안정적입니다.

수동 솔루션:

1에 답합니다.

for d in /sys/fs/cgroup/*; do
        f=$(basename $d)
        echo "looking at $f"
        if [ "$f" = "cpuset" ]; then
                echo 1 | sudo tee -a $d/cgroup.clone_children;
        elif [ "$f" = "memory" ]; then
                echo 1 | sudo tee -a $d/memory.use_hierarchy;
        fi
        sudo mkdir -p $d/$USER
        sudo chown -R $USER $d/$USER
        echo $$ > $d/$USER/tasks
done

그 대본을 썼을 때는 정확히 무슨 일이 일어나고 있는지 몰랐지만, 읽어보니cgroup 문서몇 가지 실험은 무슨 일이 일어나고 있는지 이해하는 데 도움이 되었습니다. 이 스크립트에서 내가 하는 일은 기본적으로 cgroup현재 세션에 대한 새 세션을 생성하는 것인데 user, 이는 위에서 이미 말한 것입니다. 이 명령을 현재에서 실행 shell하거나 스크립트에서 실행하고 shellin 대신 현재에서 평가하도록 하면 subshell( . script이것이 .작동하는 데 중요합니다!) 새 세션을 여는 것이 아니라 user현재 쉘을 다음과 같이 추가합니다. 이 프로세스는 새 cgroup에서 실행됩니다. 하위 셸에서 스크립트를 실행한 다음 cgroup계층 구조 로 드릴다운 chb subcgroup하고 echo $$ > tasks각 멤버를 사용하여 현재 셸을 chb cgroup hierarchy.

따라서 lxc현재 셸에서 실행하면 내 컨테이너도 chb subcgroup현재 셸이 shell속한 모든 의 멤버가 됩니다. 즉, 나의 ​​지위를 container물려받은 것입니다 . 이는 또한 현재 s의 일부가 아닌 다른 쉘에서는 작동 하지 않는 이유를 설명합니다 .cgroupshellchb subcgroup

나는 아직도 통과했다 2.. 일관된 동작을 채택하려면 systemd업데이트나 추가 Kernel개발을 기다려야 할 수도 있지만 systemd, 그럼에도 불구하고 나는 수행 중인 작업을 사용자가 알 수 있도록 수동 설정을 선호합니다.

답변2

실제로 Archlinux에서는 권한이 없는 사용자에게는 작동하지 않습니다(unpriv.lxc 컨테이너를 사용할 때 권장됨). 즉, 이 사용자에게는 sudo가 없습니다 :)

대신 /etc/cgconfig.conf에서 그룹을 정의하고, cgconfig, cgrules(AUR의 libcgroup)를 활성화하고, cgrules를 추가하고, unpriv를 완료합니다. 사용자도 동일한 권리를 갖습니다.

systemd 218에서(언제인지는 모르겠지만 cgconfig 모드에서 생성할 때 설정되지 않았기 때문에 두 조건을 모두 추가해야 했던 것 같습니다):

cat /etc/cgconfig.conf

group lxcadmin {
perm {
    task {
        uid = lxcadmin;
        gid = lxcadmin;
    }
    admin {
        uid = lxcadmin;
        gid = lxcadmin;
    }
}
cpu { }
memory { memory.use_hierarchy = 1; }  
blkio { }
cpuacct { }
cpuset { 
    cgroup.clone_children = 1;
    cpuset.mems = 0;
    cpuset.cpus = 0-3; 
}
devices { }
freezer { }
hugetlb { }
net_cls { }
}

cat /etc/cgrules.conf
lxcadmin        *       lxcadmin/

네임스페이스는 커널에서 컴파일된다고 가정합니다.

이것은 템플릿이며, CPU는 보유한 코어 수에 따라 설정될 수 있고, mem은 일부 실제 값으로 설정될 수 있습니다.

편집 2: 마지막으로 systemd에서 이와 같이 권한이 없는 사용자에 대해 자동 시작을 사용하려면 다음을 수행할 수 있습니다.

cp /usr/lib/systemd/system/lxc{,admin}\@.service 그런 다음 User=lxcadmin을 추가합니다.

그리고 lxcadmin의 컨테이너인 Lolz systemctl 활성화 lxcadmin@lolz에 대해 활성화합니다.

답변3

그래서 CentOS 7에서 LXC 비특권 컨테이너를 실행하려고 시도했을 때 동일한 문제가 발생했습니다. cgmanager꼭 필요한 것이 아니라면 추가 서비스를 도입하는 것을 좋아하지 않기 때문에 사용하고 싶지 않습니다 . 내가 한 일은 ubuntu 패키지의 일부 패치와 cgroup 컨트롤러 목록을 확장하는 사용자 정의 패치를 사용하여 systemd를 패치하는 것이었습니다. RPM을 구축하는 데 필요한 리소스는 내 GitHub 계정에서 사용할 수 있습니다.https://github.com/CtrlC-Root/rpmdist. 또한 Shadow-utils(subuid 및 subgids용) 및 pam(loginuid용) 버전도 패치했습니다. 이러한 RPM을 설치하고 권한이 없는 컨테이너를 실행하도록 사용자를 구성한 후(subuid 및 subgid 할당, lxc-usernet에 veth 쌍 할당, .config/lxc/default.conf 생성 등), LXC 권한이 없는 컨테이너를 제대로 실행할 수 있습니다.

편집: cgmanager를 사용하고 싶지 않은 또 다른 이유는 일반 사용자가 sudo를 사용해야 하는 것을 원하지 않기 때문입니다. 일반 사용자는 로그인할 수 있어야 하며 모든 것이 즉시 작동해야 합니다.

관련 정보