Como criar cgroups de usuários com o systemd

14

Eu uso lxc contentores não privilegiados em Arch Linux . Aqui estão as informações básicas do 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

É um kernel personalizado / compilado com 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 

Infelizmente, systemd não joga bem com lxc atualmente. Especialmente configurar cgroups para um usuário não-root parece não estar funcionando bem ou não estou muito familiarizado com isso. lxc só iniciará um contêiner no modo não privilegiado quando puder criar os cgroups necessários em /sys/fs/cgroup/XXX/* . No entanto, isso não é possível para lxc porque systemd monta a hierarquia root cgroup em /sys/fs/cgroup/* . Uma solução parece ser fazer o seguinte:

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

Esse código cria os diretórios cgroup correspondentes na hierarquia cgroup para um usuário não privilegiado. No entanto, algo que não entendo acontece. Antes de executar o acima mencionado, verei isto:

[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

Depois de executar o código mencionado, vejo no shell que o corri:

[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

Mas em qualquer outro shell eu ainda vejo:

[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

Portanto, posso iniciar meu contêiner lxc sem privilégios no shell que executei o código mencionado acima, mas não em nenhum outro.

  1. Alguém pode explicar esse comportamento?

  2. Alguém encontrou uma maneira melhor de configurar o cgroups necessário com uma versão atual de systemd ( >= 217 )?

por lord.garbage 02.12.2014 / 10:53

3 respostas

12

Uma solução melhor e mais segura é instalar cgmanager e executá-lo com systemctl start cgmanager (em uma distribuição systemd -based). Você pode ter seu usuário root ou, se tiver sudo direitos no host, criar cgroups para seu usuário não privilegiado em todos os controladores com:

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

Uma vez que eles foram criados para o seu usuário não privilegiado, ele pode mover processos aos quais ele tem acesso em seu cgroup para cada controlador usando:

cgm movepid all $USER $PPID

Mais seguro, mais rápido e mais confiável do que o script de shell que postei.

Solução 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

Eu ignorava o que estava acontecendo exatamente quando escrevi esse script, mas li este e experimentar um pouco me ajudou a entender o que está acontecendo. O que eu estou basicamente fazendo neste script é criar uma nova sessão cgroup para o atual user , que é o que eu já disse acima. Quando executo esses comandos no shell atual ou os executo em um script e o faço para que ele seja avaliado no atual shell e não em um subshell (via . script O . é importante para isso funciona!) é que eu não apenas abro uma nova sessão para user , mas adiciono o shell atual como um processo que é executado neste novo cgroup. Posso obter o mesmo efeito executando o script em um subshell e, em seguida, descendo até a cgroup hierarchy no chb subcgroup e use echo $$ > tasks para adicionar o shell atual a todos os membros do chb cgroup hierarchy .

Portanto, quando eu executar lxc no shell atual, meu contêiner também se tornará membro de todos os chb subcgroup s dos quais o shell atual é membro. Isso significa que meu container herda o status cgroup do meu shell . Isso também explica por que ele não funciona em nenhum outro shell que não faça parte do atual chb subcgroup s.

Eu ainda passo em 2. . Provavelmente precisaremos esperar por um systemd update ou mais Kernel desenvolvimentos para fazer com que systemd adote um comportamento consistente, mas prefiro a configuração manual de qualquer maneira, pois isso obriga a entender o que você está fazendo.

    
por 04.12.2014 / 15:20
0

Na verdade, no archlinux, isso não funcionará com, por exemplo, um usuário sem privilégios (recomendado ao usar contêineres lxc unpriv). ou seja, esse usuário não tem sudo:)

Em vez disso, defina group no /etc/cgconfig.conf, ative cgconfig, cgrules (libcgroup no AUR), adicione também cgrules, feito .. univ. O usuário também terá os mesmos direitos.

No systemd 218 (não sei quando, mas parece que é necessário adicionar mais duas condições, pois elas não são definidas quando criadas a partir do modo 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/

Supondo que o namespace é compilado no kernel.

Este é um modelo, o cpus pode estar de acordo com quantos núcleos você possui, mem pode ser configurado para algum valor real, etc etc.

EDIT 2: Finalmente, no systemd, se você quiser usar o auto-start com um usuário tão sem privilégios, você pode fazer:

cp /usr/lib/systemd/system/lxc{,admin}\@.service, em seguida, adicione User = lxcadmin

e habilite-o para o container do lxcadmin chamado lolz systemctl enable lxcadmin @ lolz.

    
por 28.01.2015 / 23:15
0

Então eu tive o mesmo problema ao tentar fazer com que os contêineres não-autorizados do LXC trabalhassem no CentOS 7. Eu não queria usar cgmanager porque eu não gosto de introduzir nenhum serviço adicional se não for absolutamente necessário. O que eu acabei fazendo, em vez disso, é remendar o systemd usando alguns patches do pacote ubuntu e um patch customizado para expandir a lista de controllers do cgroup. Eu tenho as fontes necessárias para criar um RPM na minha conta do GitHub no link . Eu também tenho versões corrigidas de shadow-utils (para subuids e subgids) e pam (para loginuid). Depois que eu instalar esses RPMs e configurar um usuário para executar contêineres não-privilegiados (atribuir subuids e subgids, alocar pares veth em lxc-usernet, criar .config / lxc / default.conf, etc) eu posso executar contêineres não privilegiados do LXC muito bem. / p>

EDIT: Outra razão que eu não queria usar o cgmanager é porque eu não queria que meus usuários regulares tivessem que usar o sudo. Usuários regulares devem poder fazer login e tudo deve "simplesmente funcionar" imediatamente.

    
por 04.02.2016 / 19:49