Cómo crear grupos de usuarios con systemd


14

Yo uso lxccontenedores sin privilegios en Arch Linux. Aquí están las informaciones básicas del sistema:

[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 un kernel personalizado / compilado con 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 

Lamentablemente, systemdno juega bien con la lxcactualidad. cgroupsParece que la configuración especial para un usuario no root no funciona bien o no estoy familiarizado con cómo hacerlo. lxcsolo iniciará un contenedor en modo no privilegiado cuando pueda crear los grupos c necesarios /sys/fs/cgroup/XXX/*. Sin embargo, esto no es posible lxcporque systemdmonta la rootjerarquía de cgroup en /sys/fs/cgroup/*. Una solución alternativa parece ser hacer lo siguiente:

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

Este código crea los cgroupdirectorios correspondientes en la cgroupjerarquía para un usuario sin privilegios. Sin embargo, sucede algo que no entiendo. Antes de ejecutar lo anterior veré esto:

[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

Después de ejecutar el código antes mencionado que veo en el shell, lo ejecuté:

[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

Pero en cualquier otro caparazón todavía veo:

[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

Por lo tanto, puedo iniciar mi lxccontenedor sin privilegios en el shell. Ejecuté el código mencionado anteriormente pero no en ningún otro.

  1. ¿Alguien puede explicar este comportamiento?

  2. ¿Alguien ha encontrado una mejor manera de configurar lo requerido cgroupscon una versión actual de systemd( >= 217)?

Respuestas:


13

Una solución mejor y más segura es instalarlo cgmanagery ejecutarlo con systemctl start cgmanager(en una systemddistribución basada en). Puede hacer que su rootusuario, o si tiene sudoderechos sobre el host, cree cgroupspara su usuario no privilegiado en todos los controladores con:

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

Una vez que se han creado para su usuario no privilegiado, él / ella puede mover los procesos a los que tiene acceso al suyo cgrouppara cada controlador mediante:

cgm movepid all $USER $PPID

Más seguro, más rápido, más confiable que el script de shell que publiqué.

Solución manual:

Para responder 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

Yo ignoraba lo que estaba sucediendo exactamente cuando escribí ese guión, pero leer esto y experimentar un poco me ayudó a comprender lo que estaba sucediendo. Lo que básicamente estoy haciendo en este script es crear una nueva cgroupsesión para el actual, userque es lo que ya dije anteriormente. Cuando corro estos comandos en la corriente shello ejecutarlos en un guión y hacerlo de modo que se evalúa en la corriente shelly no en un subshell(a través de . scriptla .es importante para que esto funcione!) Es que no acaba de abrir una nueva sesión de userpero agregue el shell actual como un proceso que se ejecuta en este nuevo cgroup. Puedo lograr el mismo efecto ejecutando el script en una subshell y luego descender a la cgroupjerarquía en el chb subcgroupy usarecho $$ > taskspara agregar el shell actual a cada miembro de chb cgroup hierarchy.

Por lo tanto, cuando ejecuto lxcen ese shell actual, mi contenedor también se convertirá en un miembro de todos los chb subcgroupcorreos electrónicos de los que shelles miembro el actual . Es decir, mi containerhereda el cgroupestado de mi shell. Esto también explica por qué no funciona en ningún otro shell que no sea parte del chb subcgroups actual .

Todavía paso a las 2.. Probablemente tendremos que esperar una systemdactualización o más Kerneldesarrollos para systemdadoptar un comportamiento coherente, pero prefiero la configuración manual de todos modos, ya que te obliga a entender lo que estás haciendo.


¿no puedes simplemente montar el directorio cgroups en otro lugar (pregunta honesta) ? hubo una gran controversia sobre Linux cgroups y systemd el año pasado cuando el responsable de cgroups aparentemente decidió dar systemd por nombre y otros aplicaciones similares no autorizadas autoridad sobre el manejo de cgroups en el espacio de usuario. No estoy seguro de cómo resultó todo, pero sé que estaba bastante en el aire si un usuario podía hacer esto hace un año.
mikeserv

Probablemente podría hacer eso, pero tendría que evitar que systemd monte el directorio raíz de cgroup en primer lugar. Cada vez que inicio sesión en mi máquina, systemd montará la jerarquía raíz de cgroup raíz en / sys / fs / cgroup y agregará un cgroup de usuario solo debajo de la parte systemd del cgroup raíz (puede ver esto más arriba). La diferencia entre las distribuciones basadas en systemd y las distribuciones no basadas en systemd antes de que cambien es que, por ejemplo, en Ubuntu la administración de grupos no está en manos del demonio init.
lord.garbage

En cambio, es manejado por un programa como, por ejemplo, cgmanager. O puede hacerlo a mano como se sugiere en el enlace a kernel.org que publiqué anteriormente. Actualmente no tengo una comprensión lo suficientemente profunda de la administración de cgroup de systemd como para tocarla más profundamente que ahora. Pero espero que esto cambie pronto.
lord.garbage

1
Es cierto, recuerdo que dijiste eso en un comentario a una respuesta que di hace mucho tiempo. Preguntaré ...
lord.garbage

1
El truco es básicamente: sudo systemctl start cgmanager && sudo cgm create all $USER && sudo cgm chown all $USER $(id -u) $(id -g) && sudo cgm movepid all $USER $PPID. El último comando debe ejecutarse en el shell actual para agregarlo al nuevo cgroup para $USER.
lord.garbage

0

En realidad, en archlinux, esto no funcionará, por ejemplo, con un usuario sin privilegios (recomendado cuando se usan contenedores no privados .xxc). es decir, ese usuario no tiene sudo :)

En su lugar, defina el grupo en /etc/cgconfig.conf, active cgconfig, cgrules (libcgroup en AUR), agregue cgrules también, listo ... sin privilegios. El usuario también tendrá los mismos derechos.

En systemd 218 (no sé cuándo, pero parece que uno tiene que agregar dos condiciones más, ya que no se establecen cuando se crean de la manera 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/

Suponiendo que el espacio de nombres se compila en el núcleo.

Esta es una plantilla, cpus puede estar de acuerdo con la cantidad de núcleos que tenga, mem puede establecerse en algún valor real, etc.

EDITAR 2: Finalmente, en systemd, si desea utilizar el inicio automático con un usuario sin privilegios, puede hacer lo siguiente:

cp /usr/lib/systemd/system/lxc{,admin}\@.service, luego agregue User = lxcadmin

y habilítelo para el contenedor de lxcadmin llamado lolz systemctl enable lxcadmin @ lolz.


Gracias @Anthon, nunca puedo obtener el formato de código correcto en estos sitios web, x
Malina Salina

Gracias. Lo siento por la respuesta tardía. Su primer punto, "En realidad en archlinux, esto no funcionará con, por ejemplo, un usuario no privilegiado (recomendado cuando se usan contenedores no privados. Lxc). Es decir, ese usuario no tiene sudo :)" no es válido ya que solo necesita su rootadministrador para crear y chownusted en todos los cgroupcontroladores. Esto está perfectamente bien y seguro. movepidse puede hacer sin rootderechos y, por lo tanto, sin privacidad. El usuario no necesita ningún sudoderecho. (Por cierto, libcgroupse supone que ya no se debe usar. RHEL y otros lo han desaprobado.)
lord.garbage

@Brauner. ¿Cómo se inicia automáticamente en el arranque, los contenedores de sus usuarios no privilegiados entonces? En realidad, sus soluciones enumeradas solo funcionaron (e implicaron) un usuario de sudo. La mía no. Me preguntaste cómo solucionarlo. De todos modos, solo ha habido una actualización, y cgconfig ahora no puede iniciarse, ya que user.slices se agregan automáticamente, por delante de la configuración de cgconfig que parece. Estos carecen de permisos de usuario (posiblemente un error de regresión, lo estoy investigando ahora). No dije que era la mejor solución. Fue la / una solución a su consulta. :) Pero mis contenedores no están comenzando en el arranque ahora, grrr.
Malina Salina

La razón por la que enumeré systemctl enable lxcadmin @ container fue para que root pudiera decidir ejecutar un contenedor no privado en el arranque. Si el usuario lo usa en --user (land), solo se iniciará cuando inicie sesión, lo que no es muy útil para un servidor. Y una nota sobre tu comentario. Al incluir a un usuario en todos los controladores, ese usuario puede comenzar a mover los pid al espacio del host, creo, lo cual es un gran riesgo de seguridad.
Malina Salina

Erm, eso aparentemente es lo que estabas haciendo con tu método inicialmente listado, supongo, pero mira esto, incluso si es ubuntu systemd package bugs.launchpad.net/ubuntu/+source/systemd/+bug/1413927 Pero algo se actualizó en días pasados ​​cambiando la lógica ... Estoy tratando de localizarlo.
Malina Salina

0

Así que me encontré con el mismo problema al intentar hacer que los contenedores no privilegiados de LXC funcionaran en CentOS 7. No quería usarlo cgmanagerporque no me gusta introducir ningún servicio adicional si no es absolutamente necesario. Lo que terminé haciendo es parchear systemd usando algunos parches del paquete ubuntu y un parche personalizado para expandir la lista de controladores de cgroup. Tengo las fuentes necesarias para crear un RPM en mi cuenta de GitHub en https://github.com/CtrlC-Root/rpmdist . También tengo versiones parcheadas de shadow-utils (para subuids y subgids) y pam (para loginuid). Después de instalar estos RPM y configurar un usuario para ejecutar contenedores no privilegiados (asignar subuids y subgids, asignar veth pares en lxc-usernet, crear .config / lxc / default.conf, etc.) puedo ejecutar LXC contenedores no privilegiados muy bien.

EDITAR: Otra razón por la que no quería usar cgmanager es porque no quería que mis usuarios habituales tuvieran que usar sudo en absoluto. Los usuarios habituales deberían poder iniciar sesión y todo debería "funcionar" de inmediato.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.