So erstellen Sie Benutzergruppen mit systemd

14

Ich benutze nichtprivilegierte lxcContainer in Arch Linux. Hier sind die grundlegenden Systeminfos:

[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

Es ist ein angepasster / kompilierter Kernel mit 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 

Leider systemdspielt das lxcmomentan nicht gut mit . Insbesondere das Einrichten cgroupsfür einen Nicht-Root-Benutzer scheint nicht gut zu funktionieren, oder ich bin einfach zu ungewohnt, wie dies zu tun ist. lxcstartet einen Container nur im nichtprivilegierten Modus, wenn er die erforderlichen Gruppen erstellen kann /sys/fs/cgroup/XXX/*. Dies ist jedoch nicht möglich, lxcda systemddie rootcgroup-Hierarchie darin eingebunden ist /sys/fs/cgroup/*. Eine Problemumgehung scheint darin zu bestehen, Folgendes zu tun:

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

Dieser Code erstellt die entsprechenden cgroupVerzeichnisse in der cgroupHierarchie für einen nicht privilegierten Benutzer. Es passiert jedoch etwas, was ich nicht verstehe. Vor dem Ausführen des oben genannten werde ich Folgendes sehen:

[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

Nachdem ich den oben genannten Code ausgeführt habe, sehe ich in der Shell, in der ich ihn ausgeführt habe:

[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

Aber in jeder anderen Hülle sehe ich noch:

[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

Daher kann ich meinen nichtprivilegierten lxcContainer in der Shell starten , in der ich den oben genannten Code ausgeführt habe, aber in keiner anderen.

  1. Kann jemand dieses Verhalten erklären?

  2. Hat jemand eine bessere Möglichkeit gefunden, die cgroupsmit einer aktuellen Version von systemd( >= 217) benötigten einzurichten ?

lord.garbage
quelle

Antworten:

13

Eine bessere und sicherere Lösung ist die Installation cgmanagerund Ausführung mit systemctl start cgmanager(auf einer systemdbasierten Distribution). Sie können dann Ihren rootBenutzer oder, wenn Sie sudoRechte auf dem Host haben, cgroupsfür Ihren nichtprivilegierten Benutzer in allen Controllern erstellen lassen mit:

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

Sobald sie für Ihren nichtprivilegierten Benutzer erstellt wurden, kann er / sie Prozesse, auf die er Zugriff hat, cgroupfür jeden Controller in seine verschieben , indem er / sie Folgendes verwendet:

cgm movepid all $USER $PPID

Sicherer, schneller, zuverlässiger als das von mir gepostete Shell-Skript.

Manuelle Lösung:

Um zu antworten 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

Ich war unwissend darüber , was genau los war , als ich das Drehbuch geschrieben , aber das Lesen dieser und Experimentieren ein wenig half mir zu verstehen , was los ist. Was ich im Grunde in diesem Skript tue, ist, eine neue cgroupSitzung für den aktuellen zu erstellen, userwas ich bereits oben angegeben habe. Wenn ich diese Befehle im aktuellen shelloder in einem Skript ausführe und es so mache, dass es im aktuellen ausgewertet wird shellund nicht in einem subshell(via . scriptDas .ist wichtig, damit das funktioniert!) Ist, dass ich nicht nur eine neue Sitzung für öffne userFügen Sie jedoch die aktuelle Shell als einen Prozess hinzu, der in dieser neuen cgroup ausgeführt wird. Ich kann den gleichen Effekt erzielen, indem ich das Skript in einer Subshell ausführe und dann in die cgroupHierarchie in the chb subcgroupand use absteigereecho $$ > tasksum die aktuelle Shell zu jedem Mitglied der chb cgroup hierarchy.

Wenn ich also lxcin dieser aktuellen Shell laufe , wird mein Container auch zu einem Mitglied aller chb subcgroups, zu denen der aktuelle shellgehört. Das heißt, mein containererbt den cgroupStatus von meinem shell. Dies erklärt auch, warum es in keiner anderen Shell funktioniert, die nicht Teil des aktuellen chb subcgroups ist.

Ich gehe immer noch vorbei 2.. Wir werden wahrscheinlich entweder auf ein systemdUpdate oder auf weitere KernelEntwicklungen warten müssen , systemdum ein konsistentes Verhalten zu erreichen, aber ich bevorzuge die manuelle Einrichtung, da sie Sie dazu zwingt, zu verstehen, was Sie tun.

lord.garbage
quelle
kannst du die cgroups nicht einfach woanders einhängen (ehrliche frage) ? Letztes Jahr gab es eine große Kontroverse über Linux-cgroups und systemd, als der cgroups-Betreuer anscheinend entschied, systemd namentlich und anderen ähnlichen unbenannten Apps die Autorität über die Behandlung von cgroups im Userspace zu geben. Ich bin mir nicht sicher, wie das alles ausgegangen ist, aber ich weiß, dass es ziemlich unklar war, ob ein Benutzer dies vor einem Jahr überhaupt tun konnte.
mikeserv
Ich könnte das wahrscheinlich tun, aber ich müsste verhindern, dass systemd das cgroup-Stammverzeichnis an erster Stelle einbindet. Jedes Mal, wenn ich mich auf meinem Computer anmelde, hängt systemd die Root-Cgroup-Hierarchie unter / sys / fs / cgroup ein und fügt eine Benutzer-Cgroup nur unter dem systemd-Teil der Root-Cgroup hinzu (siehe oben). Der Unterschied zwischen systemd-basierten Distributionen und nicht systemd-basierten Distributionen vor dem Wechsel besteht darin, dass z. B. in Ubuntu die Gruppenverwaltung nicht in den Händen des init-Daemons liegt.
lord.garbage
Es wird stattdessen von einem Programm wie zB cgmanager gehandhabt. Oder Sie können es von Hand tun, wie in dem Link zu kernel.org, den ich oben gepostet habe, vorgeschlagen. Derzeit verstehe ich das systemd cgroup management nicht so gut, dass ich mich tiefer damit beschäftigen könnte als jetzt. Aber hoffentlich wird sich das bald ändern.
lord.garbage
1
Es stimmt, ich erinnere mich, dass Sie das in einem Kommentar zu einer Antwort gesagt haben, die ich vor langer Zeit gegeben habe. Ich werde nachfragen ...
lord.garbage
1
Der Trick ist im Grunde: sudo systemctl start cgmanager && sudo cgm create all $USER && sudo cgm chown all $USER $(id -u) $(id -g) && sudo cgm movepid all $USER $PPID. Der letzte Befehl muss in der aktuellen Shell ausgeführt werden, um ihn der neuen cgroup für hinzuzufügen $USER.
lord.garbage
0

Tatsächlich funktioniert dies in Archlinux nicht mit einem nicht privilegierten Benutzer (empfohlen, wenn unpriv. Lxc-Container verwendet werden). dh dieser Benutzer hat kein sudo :)

Definieren Sie stattdessen group in /etc/cgconfig.conf, aktivieren Sie cgconfig, cgrules (libcgroup in AUR), fügen Sie auch cgrules hinzu, done .. unpriv. Benutzer haben auch die gleichen Rechte.

In systemd 218 (ich weiß nicht wann, aber es scheint, als müsste man zwei weitere Bedingungen hinzufügen, da diese bei der Erstellung mit cgconfig nicht festgelegt werden):

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/

Vorausgesetzt, der Namespace ist im Kernel kompiliert.

Dies ist eine Vorlage, die CPU kann abhängig von der Anzahl der Kerne sein, die Sie haben, Mem kann auf einen tatsächlichen Wert gesetzt werden, usw. usw.

BEARBEITEN 2: Schließlich können Sie in systemd Folgendes tun, wenn Sie den automatischen Start für einen solchen nicht privilegierten Benutzer verwenden möchten:

cp /usr/lib/systemd/system/lxc{,admin}\@.service, dann fügen Sie User = lxcadmin hinzu

und aktivieren Sie es für den lxcadmin-Container mit dem Namen lolz systemctl enable lxcadmin @ lolz.

Malina Salina
quelle
Vielen Dank @Anthon, ich kann den Code auf diesen Websites nie richtig formatieren. X
Malina Salina
Vielen Dank. Entschuldigung für die späte Antwort. Ihr erster Punkt "Eigentlich funktioniert dies in Archlinux nicht mit einem unprivilegierten Benutzer (empfohlen bei Verwendung von unpriv. Lxc-Containern), dh dieser Benutzer hat kein sudo :)" steht nicht, da Sie nur Ihren rootAdministrator benötigen erstellen und chownSie in alle cgroupController. Das ist vollkommen in Ordnung und sicher. movepidkann ohne rootRechte und damit die unpriv getan werden. Benutzer benötigt keine sudoRechte. (Übrigens, sollte libcgroupnicht mehr verwendet werden. RHEL und andere haben es abgelehnt.)
lord.garbage
@ Brauner. Wie können Sie beim Booten automatisch starten, also bei den Containern Ihres nicht privilegierten Benutzers? Tatsächlich haben Ihre aufgeführten Lösungen nur einen sudo-Benutzer bearbeitet (und impliziert). Meins nicht. Sie haben gefragt, wie Sie das Problem beheben können. Wie auch immer, es wurde gerade ein Update durchgeführt, und cgconfig kann jetzt nicht gestartet werden, da user.slices automatisch vor den cgconfig-Einstellungen hinzugefügt werden. Diesen fehlen Benutzerberechtigungen (möglicherweise ein Regressionsfehler, der derzeit untersucht wird). Ich habe nicht gesagt, dass es die beste Lösung ist. Es war die / eine Lösung für Ihre Anfrage. :) Aber meine Container starten jetzt nicht beim Booten, grrr.
Malina Salina am
Der Grund, warum ich systemctl enable lxcadmin @ container aufführte, war, dass root entscheiden konnte, beim Booten einen unpriv-Container auszuführen. Wenn der Benutzer es selbst in --user (land) verwendet, wird es nur gestartet, wenn er sich anmeldet, was für einen Server nicht sehr nützlich ist. Und eine Anmerkung zu Ihrem Kommentar. Wenn Sie einen Benutzer in alle Controller einbinden, kann dieser Benutzer PIDs in den Host-Bereich verschieben, was meines Erachtens ein ziemliches Sicherheitsrisiko darstellt.
Malina Salina
Erm, die scheinbar ist , was Sie mit Ihrer Methode zu tun zunächst aufgelistet Ich denke, aber Blick auf diese, auch wenn es ubuntu Paket Systemd bugs.launchpad.net/ubuntu/+source/systemd/+bug/1413927 Aber war etwas aktualisiert in Die letzten Tage haben die Logik geändert. Ich versuche, sie aufzuspüren.
Malina Salina am
0

Daher trat das gleiche Problem auf, als ich versuchte, unprivilegierte LXC-Container unter CentOS 7 zum Laufen zu bringen. Ich wollte sie nicht verwenden, cgmanagerweil ich keine zusätzlichen Dienste einführen möchte, wenn sie nicht unbedingt benötigt werden. Stattdessen habe ich systemd mit einigen Patches aus dem Ubuntu-Paket und einem benutzerdefinierten Patch gepatcht, um die Liste der Gruppencontroller zu erweitern. Ich habe die Quellen, die zum Erstellen eines RPM auf meinem GitHub-Konto unter https://github.com/CtrlC-Root/rpmdist benötigt werden . Ich habe auch Versionen von shadow-utils (für subuids und subgids) und pam (für loginuid) gepatcht. Nachdem ich diese RPMs installiert und einen Benutzer so konfiguriert habe, dass unprivilegierte Container ausgeführt werden (Zuweisen von Sub-Uids und Sub-Gids, Zuweisen von Veth-Paaren in lxc-usernet, Erstellen von .config / lxc / default.conf usw.), kann ich unprivilegierte LXC-Container problemlos ausführen.

BEARBEITEN: Ein weiterer Grund, warum ich cgmanager nicht verwenden wollte, ist, dass meine regulären Benutzer Sudo überhaupt nicht verwenden sollten. Normale Benutzer sollten sich anmelden können und alles sollte sofort funktionieren.

ctrlc-root
quelle