Jak tworzyć grupy użytkowników za pomocą systemd

14

Używam nieuprzywilejowanych lxcpojemników w Arch Linux. Oto podstawowe informacje o systemie:

[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

Jest to niestandardowe / skompilowane jądro z 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 

Niestety systemdobecnie nie gra dobrze lxc. Zwłaszcza konfigurowanie cgroupsdla użytkownika innego niż root wydaje się nie działać dobrze lub po prostu jestem zbyt obeznany z tym, jak to zrobić. lxcuruchomi kontener w trybie nieuprzywilejowanym tylko wtedy, gdy będzie mógł utworzyć niezbędne grupy /sys/fs/cgroup/XXX/*. Nie jest to jednak możliwe, lxcponieważ systemdmontuje roothierarchię grupy /sys/fs/cgroup/*. Obejściem wydaje się być wykonanie następujących czynności:

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

Ten kod tworzy odpowiednie cgroupkatalogi w cgrouphierarchii dla nieuprzywilejowanego użytkownika. Jednak dzieje się coś, czego nie rozumiem. Przed wykonaniem powyższego zobaczę to:

[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

Po wykonaniu wyżej wymienionego kodu widzę go w powłoce, w której go uruchomiłem:

[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

Ale w każdej innej powłoce nadal widzę:

[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

Dlatego mogę uruchomić mój nieuprzywilejowany lxckontener w powłoce, którą wykonałem wyżej wymieniony kod, ale nie w żadnym innym.

  1. Czy ktoś może wyjaśnić to zachowanie?

  2. Czy ktoś znalazł lepszy sposób na skonfigurowanie wymaganej cgroupswersji w bieżącej wersji systemd( >= 217)?

lord.garbage
źródło

Odpowiedzi:

13

Lepszym i bezpieczniejszym rozwiązaniem jest instalacja cgmanageri uruchamianie go systemctl start cgmanager(w systemddystrybucji opartej na systemie ). Możesz wtedy mieć swojego rootużytkownika lub jeśli masz sudouprawnienia do hosta, utworzyć cgroupsdla swojego nieuprzywilejowanego użytkownika na wszystkich kontrolerach z:

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

Po utworzeniu dla nieuprzywilejowanego użytkownika może on / ona przenosić procesy, do których ma dostęp, cgroupdla każdego kontrolera, używając:

cgm movepid all $USER $PPID

Bezpieczniejszy, szybszy, bardziej niezawodny niż skrypt powłoki, który opublikowałem.

Rozwiązanie ręczne:

Aby odpowiedzieć 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

Nie wiedziałem, co się dokładnie dzieje, kiedy napisałem ten scenariusz, ale przeczytanie go i eksperymentowanie pomogło mi zrozumieć, co się dzieje. W zasadzie robię w tym skrypcie, aby utworzyć nową cgroupsesję dla prądu, userco już powiedziałem powyżej. Kiedy uruchamiam te polecenia w bieżącym shelllub uruchamiam je w skrypcie i robię to, aby był oceniany w bieżącym, shella nie w subshell(przez . scriptThe .jest ważne, aby to działało!), To że nie tylko otwieram nową sesję dla userale dodaj bieżącą powłokę jako proces działający w tej nowej grupie. Ten sam efekt mogę osiągnąć, uruchamiając skrypt w podpowłoce, a następnie schodząc do cgrouphierarchii w chb subcgroupi używajecho $$ > tasksaby dodać bieżącą powłokę do każdego członka chb cgroup hierarchy.

Dlatego gdy uruchomię lxctę bieżącą powłokę, mój kontener stanie się również członkiem wszystkich chb subcgroups, których obecny shelljest członek. To znaczy, że mój containerdziedziczy cgroupstatus mojego shell. To wyjaśnia również, dlaczego nie działa w żadnej innej powłoce, która nie jest częścią obecnych chb subcgroups.

Nadal przechodzę o 2.. Prawdopodobnie będziemy musieli poczekać na systemdaktualizację lub dalsze Kernelzmiany, aby systemdzastosować spójne zachowanie, ale i tak wolę ręczną konfigurację, ponieważ zmusza cię to do zrozumienia, co robisz.

lord.garbage
źródło
czy nie możesz po prostu zamontować cgroups w innym miejscu (szczere pytanie) ? w zeszłym roku pojawiło się wiele kontrowersji dotyczących grup linuksowych i systemd, kiedy opiekun grup cg najwyraźniej postanowił nadać systemd według nazwy i innych podobnych nienazwanych aplikacji uprawnień nad obsługą grup w przestrzeni użytkownika. nie jestem pewien, jak to wszystko się potoczyło, ale wiem, że było całkiem w powietrzu, czy użytkownik może to zrobić rok temu.
mikeserv
Prawdopodobnie mógłbym to zrobić, ale najpierw musiałbym uniemożliwić systemdowi zamontowanie katalogu głównego cgroup. Za każdym razem, gdy loguję się na moim komputerze, systemd zamontuje hierarchię katalogu głównego root w grupie / sys / fs / cgroup i doda grupę użytkownika tylko w części systemowej root grupy (możesz to zobaczyć powyżej.). Różnica między dystrybucjami systemowymi a dystrybucjami systemowymi przed ich przełączeniem polega na tym, że np. W Ubuntu zarządzanie grupami nie jest w rękach demona init.
lord.garbage
Zamiast tego jest obsługiwany przez program taki jak np. Cgmanager. Lub możesz to zrobić ręcznie, zgodnie z sugestią zamieszczoną powyżej w linku do kernel.org. Obecnie nie mam wystarczającej wiedzy na temat systemowego zarządzania grupami, aby manipulować nim głębiej niż teraz. Ale mam nadzieję, że wkrótce to się zmieni.
lord.garbage
1
To prawda, pamiętam, jak powiedziałeś to w komentarzu do odpowiedzi, którą dawno dawno temu.
Zapytam
1
Sztuką jest zasadniczo: sudo systemctl start cgmanager && sudo cgm create all $USER && sudo cgm chown all $USER $(id -u) $(id -g) && sudo cgm movepid all $USER $PPID. Ostatnie polecenie należy uruchomić w bieżącej powłoce, aby dodać je do nowej grupy cgroup $USER.
lord.garbage
0

Właściwie w archlinuxie nie będzie to działać np. Z nieuprzywilejowanym użytkownikiem (zalecane przy korzystaniu z kontenerów unpriv. Lxc). tzn. ten użytkownik nie ma sudo :)

Zamiast tego zdefiniuj grupę w /etc/cgconfig.conf, aktywuj cgconfig, cgrules (libcgroup w AUR), dodaj również cgrules, gotowe .. unpriv. użytkownik będzie miał te same prawa.

W systemd 218 (nie wiem kiedy, ale wydaje się, że trzeba dodać dwa dodatkowe warunki, ponieważ nie są one ustawione, gdy są tworzone z 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/

Zakładając, że przestrzeń nazw jest kompilowana w jądrze.

Jest to szablon, procesor może być zgodny z liczbą posiadanych rdzeni, pamięcią można ustawić rzeczywistą wartość itp.

EDYCJA 2: Wreszcie, w systemie, jeśli chcesz korzystać z automatycznego uruchamiania z tak nieuprzywilejowanym użytkownikiem, możesz:

cp /usr/lib/systemd/system/lxc{,admin}\@.service, a następnie dodaj User = lxcadmin

i włącz go dla kontenera lxcadmin o nazwie lolz systemctl enable lxcadmin @ lolz.

Malina Salina
źródło
Dziękuję @Anthon, nigdy nie mogę uzyskać formatowania kodu bezpośrednio na tych stronach, x
Malina Salina
Dziękuję Ci. Przepraszam za późną odpowiedź. Twój pierwszy punkt: „Właściwie w Archlinuxie, to nie zadziała np. Z nieuprzywilejowanym użytkownikiem (zalecane przy korzystaniu z unpriv. Kontenerów LXC). Tzn. Że ten użytkownik nie ma sudo :)” nie ma znaczenia, ponieważ potrzebujesz jedynie rootadministratora, aby stwórz i chownty do wszystkich cgroupkontrolerów. Jest to całkowicie w porządku i bezpieczne. movepidmożna tego dokonać bez rootpraw, a tym samym bez przywilejów. użytkownik nie potrzebuje żadnych sudopraw. (Btw, libcgroupnie należy go już używać. RHEL i inni przestali go
używać
@Brauner. Jak więc automatycznie uruchamiasz się przy starcie, kiedy Twoje nieuprzywilejowane kontenery są używane? W rzeczywistości wymienione rozwiązania działały tylko (i sugerowały) użytkownika sudo. Mój nie. Zapytałeś, jak to naprawić. W każdym razie właśnie została zaktualizowana i cgconfig nie uruchamia się teraz, ponieważ użytkownik.slices są dodawane automatycznie, przed ustawieniami cgconfig. Brakuje im jakichkolwiek uprawnień użytkownika (prawdopodobnie błąd regresji, teraz go szukam). Nie powiedziałem, że to najlepsze rozwiązanie. To było / a rozwiązanie twojego zapytania. :) Ale moje pojemniki nie zaczynają się teraz przy starcie, grrr.
Malina Salina
Powodem, dla którego wymieniłem systemctl enable lxcadmin @ container, było to, że root mógł zdecydować o uruchomieniu kontenera unpriv podczas uruchamiania. Jeśli sam użytkownik użyje go w --user (land), uruchomi się tylko po zalogowaniu, co nie jest bardzo przydatne dla serwera. I uwaga na twój komentarz. wprowadzenie użytkownika do wszystkich kontrolerów pozwala temu użytkownikowi rozpocząć przenoszenie pidów do przestrzeni hosta, co moim zdaniem stanowi poważne zagrożenie bezpieczeństwa.
Malina Salina
Erm, to wydaje się, że to, co robiłeś z metodą początkowo wymienioną, chyba, ale spójrz na to, nawet jeśli jest to pakiet systemowy ubuntu bugs.launchpad.net/ubuntu/+source/systemd/+bug/1413927 Ale coś zostało zaktualizowane w ostatnie dni zmieniają logikę. Próbuję to wyśledzić.
Malina Salina
0

Zetknąłem się z tym samym problemem, próbując uzyskać nieuprzywilejowane kontenery LXC działające na CentOS 7. Nie chciałem z tego korzystać, cgmanagerponieważ nie lubię wprowadzać żadnych dodatkowych usług, jeśli nie jest to absolutnie wymagane. Skończyło się na tym, że załatałem systemd przy użyciu kilku łat z pakietu ubuntu i jednej niestandardowej łatki, aby rozwinąć listę kontrolerów cgroup. Mam źródła potrzebne do zbudowania RPM na moim koncie GitHub na https://github.com/CtrlC-Root/rpmdist . Mam również załatane wersje narzędzi-cieni (dla subuidów i subgidów) i pam (dla loginuid). Po zainstalowaniu tych RPM i skonfigurowaniu użytkownika do uruchamiania nieuprzywilejowanych kontenerów (przypisywanie podrzędnych i podrzędnych, przydzielanie par veth w lxc-usernet, tworzenie .config / lxc / default.conf itp.) Mogę dobrze uruchomić nieuprzywilejowane kontenery LXC.

EDYCJA: Innym powodem, dla którego nie chciałem używać cgmanager, jest to, że nie chciałem, aby moi zwykli użytkownicy w ogóle musieli używać sudo. Zwykli użytkownicy powinni móc się zalogować i wszystko powinno „po prostu działać” od razu po wyjęciu z pudełka.

ctrlc-root
źródło