วิธีการสร้างกลุ่มผู้ใช้ด้วย systemd


14

ฉันใช้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ปัจจุบัน โดยเฉพาะอย่างยิ่งการตั้งค่าcgroupsสำหรับผู้ใช้ที่ไม่ใช่รูทดูเหมือนจะทำงานได้ไม่ดีหรือฉันก็ไม่คุ้นเคยกับวิธีการทำเช่นนี้ lxcจะเริ่มต้นภาชนะในโหมดด้อยโอกาสเมื่อมันสามารถสร้าง cgroups /sys/fs/cgroup/XXX/*จำเป็น อย่างไรก็ตามเรื่องนี้เป็นไปไม่ได้lxcเพราะsystemdม้าrootลำดับชั้น cgroup /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

รหัสนี้สร้างcgroupไดเรกทอรีที่สอดคล้องกันในcgroupลำดับชั้นสำหรับผู้ใช้ที่ไม่มีสิทธิ์ อย่างไรก็ตามสิ่งที่ฉันไม่เข้าใจเกิดขึ้น ก่อนดำเนินการตามที่กล่าวมาฉันจะเห็นสิ่งนี้:

[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ภาชนะunprivileged ของฉันในเปลือกฉันเรียกใช้รหัสที่กล่าวถึงข้างต้น แต่ไม่ได้อยู่ในอื่น ๆ

  1. มีคนอธิบายพฤติกรรมนี้ได้ไหม

  2. มีคนพบวิธีที่ดีกว่าในการตั้งค่าสิ่งที่จำเป็นcgroupsด้วยsystemd( >= 217) รุ่นปัจจุบันหรือไม่?

คำตอบ:


13

ทางออกที่ดีกว่าและปลอดภัยกว่าคือการติดตั้งcgmanagerและเรียกใช้งานด้วยsystemctl start cgmanager(ในฐานsystemddistro) คุณสามารถมีrootผู้ใช้ของคุณหรือถ้าคุณมีsudoสิทธิ์ในโฮสต์ที่สร้างขึ้นcgroupsสำหรับผู้ใช้ที่ไม่มีสิทธิ์ของคุณในตัวควบคุมทั้งหมดด้วย:

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เซสชันใหม่สำหรับปัจจุบันuserซึ่งเป็นสิ่งที่ฉันระบุไว้ข้างต้น เมื่อฉันเรียกใช้คำสั่งเหล่านี้ในปัจจุบันshellหรือเรียกใช้พวกเขาในสคริปต์และทำให้มันได้รับการประเมินในปัจจุบันshellและไม่ได้อยู่ในsubshell(ผ่าน. scriptThe .เป็นสิ่งสำคัญสำหรับการทำงาน!) คือฉันไม่เพียงแค่เปิดเซสชันใหม่สำหรับuserแต่เพิ่มเชลล์ปัจจุบันเป็นกระบวนการที่ทำงานใน cgroup ใหม่นี้ ฉันสามารถบรรลุผลเดียวกันโดยใช้สคริปต์ใน subshell แล้วลงไปในcgroupลำดับชั้นในchb subcgroupและใช้echo $$ > taskschb cgroup hierarchyเพื่อเพิ่มเปลือกปัจจุบันสมาชิกของทุก

ดังนั้นเมื่อฉันเรียกใช้lxcในเชลล์ปัจจุบันนั้นคอนเทนเนอร์ของฉันจะกลายเป็นสมาชิกของchb subcgroups ทั้งหมดที่ปัจจุบันshellเป็นสมาชิกอยู่ นั่นคือจะบอกว่าฉันcontainerสืบทอดสถานะของฉันcgroup shellนอกจากนี้ยังอธิบายว่าทำไมมันไม่ทำงานในเชลล์อื่น ๆ ที่ไม่ได้เป็นส่วนหนึ่งของchb subcgroups ปัจจุบัน

2.ฉันยังคงผ่านที่ เราอาจต้องรอการsystemdอัปเดตหรือการKernelพัฒนาเพิ่มเติมเพื่อให้systemdมีพฤติกรรมที่สอดคล้องกัน แต่ฉันชอบการตั้งค่าด้วยตนเองเนื่องจากมันบังคับให้คุณเข้าใจสิ่งที่คุณทำ


คุณไม่สามารถเพียงแค่ติด cgroups dir ที่อื่น(คำถามเที่ยงตรง) ? มีการถกเถียงกันอย่างมากเกี่ยวกับ cgroups ของ linux และ systemd เมื่อปีที่แล้วเมื่อผู้ดูแลกลุ่ม cgroups ตัดสินใจที่จะให้ชื่อระบบและชื่อแอพอื่น ๆ ที่คล้ายกันมากกว่า cgroups ที่จัดการใน userspace ไม่แน่ใจว่ามันจะเปิดออกทั้งหมด แต่ฉันรู้ว่ามันสวยขึ้นไปในอากาศว่าผู้ใช้สามารถทำสิ่งนี้ได้ตลอดปีที่ผ่านมา
mikeserv

ฉันอาจจะทำเช่นนั้น แต่ฉันจะต้องป้องกัน systemd จากการติดตั้งไดเรกทอรีราก cgroup ในสถานที่แรก เมื่อใดก็ตามที่ฉันเข้าสู่ระบบ machined ของฉันจะเมานต์ลำดับชั้นของรูต cgroup ภายใต้ / sys / fs / cgroup และเพิ่มผู้ใช้ cgroup ภายใต้ส่วน systemd ของรูต cgroup (คุณสามารถดูได้ด้านบน) ความแตกต่างระหว่าง distros ตาม systemd และไม่ใช่ distros ตาม systemd ก่อนที่จะสลับนั่นคือเช่นใน Ubuntu cgroup การจัดการไม่ได้อยู่ในมือของ daemon init
lord.garbage

มันถูกจัดการแทนโดยโปรแกรมเช่น cgmanager หรือคุณสามารถทำได้ด้วยตนเองตามที่แนะนำในลิงค์ไปยัง kernel.org ฉันโพสต์ข้างต้น ขณะนี้ฉันยังไม่มีความเข้าใจที่ลึกซึ้งพอที่จะจัดการกับ systemg cgroup ให้ซอลึกลงไปกว่านี้ แต่หวังว่าจะมีการเปลี่ยนแปลงในไม่ช้า
lord.garbage

1
จริงฉันจำคุณได้ว่าในความคิดเห็นต่อคำตอบที่ฉันให้มานานแล้ว ฉันจะสอบถาม ...
lord.garbage

1
sudo systemctl start cgmanager && sudo cgm create all $USER && sudo cgm chown all $USER $(id -u) $(id -g) && sudo cgm movepid all $USER $PPIDเคล็ดลับโดยทั่วไปคือ คำสั่งสุดท้ายจะต้องมีการทำงานในเปลือกปัจจุบันเพื่อที่จะเพิ่มไปยัง cgroup $USERใหม่สำหรับ
lord.garbage

0

ที่จริงแล้วใน archlinux สิ่งนี้จะไม่ทำงานเช่นผู้ใช้ที่ไม่มีสิทธิพิเศษ (แนะนำเมื่อใช้ unpriv. lxc container) เช่นผู้ใช้นั้นไม่มี sudo :)

ให้กำหนดกลุ่มใน /etc/cgconfig.conf เปิดใช้งาน cgconfig, cgrules (libcgroup ใน AUR) เพิ่ม 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/

สมมติว่ามีการรวบรวม namespace ในเคอร์เนล

นี่คือเทมเพลตซีพียูสามารถเป็นไปตามจำนวนแกนที่คุณมี mem สามารถตั้งค่าเป็นค่าจริง ฯลฯ

แก้ไข 2: ในที่สุดใน systemd หากคุณต้องการใช้การเริ่มอัตโนมัติกับผู้ใช้ที่ไม่มีสิทธิเช่นคุณสามารถทำได้:

cp /usr/lib/systemd/system/lxc{,admin}\@.service จากนั้นเพิ่มผู้ใช้ = lxcadmin

และเปิดใช้งานสำหรับคอนเทนเนอร์ของ lxcadmin ชื่อ lolz systemctl enable lxcadmin @ lolz


ขอบคุณ @Athon ฉันไม่เคยได้รับการจัดรูปแบบรหัสที่ถูกต้องในเว็บไซต์เหล่านี้ x
Malina Salina

ขอขอบคุณ. ขออภัยสำหรับการตอบกลับปลาย. จุดแรกของคุณ "ที่จริงแล้วใน archlinux สิ่งนี้จะไม่สามารถใช้ได้กับผู้ใช้ที่ไม่ได้รับสิทธิพิเศษ (แนะนำเมื่อใช้ unpriv. lxc container) นั่นคือผู้ใช้นั้นไม่มี sudo :)" ไม่สามารถทำได้เพราะคุณต้องการเพียงrootผู้ดูแลระบบของคุณสร้างและchownคุณเป็นcgroupตัวควบคุมทั้งหมด นี่คือที่ดีอย่างสมบูรณ์และปลอดภัย movepidสามารถทำได้โดยไม่มีrootสิทธิ์ ผู้ใช้ไม่ต้องการsudoสิทธิ์ใด ๆ (Btw libcgroupไม่ควรใช้อีกต่อไป RHEL และอื่น ๆ เลิกใช้แล้ว)
lord.garbage

@Brauner คุณเริ่มต้นโดยอัตโนมัติเมื่อบูตคอนเทนเนอร์ของผู้ใช้ที่ไม่มีสิทธิพิเศษแล้วอย่างไร? ที่จริงแล้วโซลูชันของคุณในรายการใช้งานได้เท่านั้น (และโดยนัย) ผู้ใช้ sudo ฉันไม่ได้ คุณถามว่าจะแก้ไขอย่างไร อย่างไรก็ตามเพิ่งมีการอัปเดตและตอนนี้ cgconfig ไม่สามารถเริ่มต้นได้เนื่องจาก user.slices ถูกเพิ่มโดยอัตโนมัติก่อนการตั้งค่า cgconfig ที่ปรากฏ สิ่งเหล่านี้ขาดการอนุญาตจากผู้ใช้ (อาจเป็นข้อผิดพลาดในการถดถอยกำลังมองหาอยู่ตอนนี้) ฉันไม่ได้บอกว่ามันเป็นทางออกที่ดีที่สุด มันเป็น/ aทางออกสำหรับคำถามของคุณ :) แต่คอนเทนเนอร์ของฉันไม่ได้เริ่มตอนบูตตอนนี้ grrr
Malina Salina

เหตุผลที่ฉันแสดงรายการ systemctl เปิดใช้งาน lxcadmin @ container คือรากเพื่อให้สามารถตัดสินใจที่จะเรียกใช้คอนเทนเนอร์ unpriv ในการบูต หากผู้ใช้เองใช้ใน --user (ฝั่ง) ผู้ใช้จะบูตเมื่อเขาล็อกอินเท่านั้นซึ่งไม่มีประโยชน์สำหรับเซิร์ฟเวอร์ และหมายเหตุเกี่ยวกับความคิดเห็นของคุณ ฉันเชื่อว่าผู้ใช้เป็นผู้ควบคุมทั้งหมดอนุญาตให้ผู้ใช้นั้นเริ่มเคลื่อนย้าย pid ไปสู่พื้นที่โฮสต์ฉันเชื่อว่าซึ่งค่อนข้างเสี่ยงต่อความปลอดภัย
Malina Salina

เอ่อที่ดูเหมือนจะเป็นสิ่งที่คุณกำลังทำอยู่กับวิธีการของคุณที่ระบุไว้ในตอนแรกผมคิดว่า แต่ดูที่นี้ถึงแม้ว่ามันจะเป็นอูบุนตู systemd แพคเกจbugs.launchpad.net/ubuntu/+source/systemd/+bug/1413927แต่สิ่งที่ได้รับการปรับปรุงใน วันที่ผ่านมาเปลี่ยนตรรกะ .. ฉันพยายามติดตามมัน
Malina Salina

0

ดังนั้นฉันจึงพบปัญหาเดียวกันเมื่อพยายามให้ตู้คอนเทนเนอร์ที่ไม่ได้รับสิทธิ LXC ทำงานบน CentOS 7 ฉันไม่ต้องการใช้cgmanagerเพราะฉันไม่ต้องการแนะนำบริการเพิ่มเติมใด ๆ หากไม่จำเป็นจริงๆ สิ่งที่ฉันทำแทนการ patching systemd โดยใช้ patch บางตัวจากแพ็คเกจ ubuntu และ patch ที่กำหนดเองหนึ่งอันเพื่อขยายรายการของ cgroup controllers ฉันมีแหล่งที่มาที่จำเป็นในการสร้าง RPM ในบัญชีของฉันที่ GitHub https://github.com/CtrlC-Root/rpmdist ฉันยังมีรุ่น shadow-utils ที่แพตช์ (สำหรับ subuids และ subgids) และ pam (สำหรับ loginuid) หลังจากที่ฉันติดตั้ง RPMs เหล่านี้และกำหนดค่าผู้ใช้ให้เรียกใช้คอนเทนเนอร์ที่ไม่ได้รับสิทธิพิเศษ (กำหนด subuids & subgids จัดสรรคู่ veth ใน lxc-usernet สร้าง. config / lxc / default.conf ฯลฯ ) ฉันสามารถเรียกใช้ LXC unprivileged container ได้ดี

แก้ไข: อีกเหตุผลที่ฉันไม่ต้องการใช้ cgmanager ก็เพราะฉันไม่ต้องการให้ผู้ใช้ทั่วไปต้องใช้ sudo เลย ผู้ใช้ทั่วไปควรจะสามารถเข้าสู่ระบบและทุกอย่างควร "เพิ่งทำงาน" นอกกรอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.