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。特に、root以外のユーザーのために設定するのは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

このコードは、権限のないユーザーの階層に適切なディレクトリを作成しますcgroupcgroupところが理解できないことが起こりました。上記の作業を行う前に、次の点を確認してください。

[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 cgmanagersystemdベースのディストリビューションから)。その後、ユーザーを作成するか、ホストに対する権限が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か、スクリプトで実行し、inのshell代わりに現在で評価するようにした場合subshell. scriptこれが.機能するために重要です!)、新しいセッションを開くのではなく、現在のuserシェルを次のように追加します。このプロセスは新しいcgroupで実行されます。サブシェルでスクリプトを実行し、階層にドリルダウンし、cgroupchb 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を使用したくないもう1つの理由は、一般ユーザーがsudoを使用する必要がないことです。一般ユーザーはログインできる必要があり、すべてがすぐに機能する必要があります。

関連情報