ฉันกำลังทดสอบคุณสมบัติการดีบัก k8s รวมถึงพ็อดดีบั๊กและคอนเทนเนอร์ชั่วคราว และฉันไม่สามารถหาวิธีแมปพ็อด "เป้าหมาย" ได้อย่างถูกต้อง ระบบไฟล์ ลงในคอนเทนเนอร์การดีบัก
ฉันต้องการ เชื่อมโยงเนมสเปซเมานต์ disjoint สองอันด้วยการเมานต์การผูกแบบเรียกซ้ำ* ดังนั้นคอนเทนเนอร์ A จึงเห็นรูทของคอนเทนเนอร์ B เป็น /คอนเทนเนอร์ข
หรือในทางกลับกัน รวมถึงวอลุ่มทั้งหมดและการเมานต์อื่นๆ
เป้าหมาย: เข้าถึงทั้งระบบไฟล์ดีบักและคอนเทนเนอร์เป้าหมายพร้อมกัน
เป้าหมายคือการมีฝักเป้าหมาย โครงสร้างระบบไฟล์แบบเต็ม รวมถึงวอลุ่มและการเมานต์อื่นๆ แมปกับส่วนย่อยของคอนเทนเนอร์ดีบั๊กเช่น /วิ่ง/เป้าหมาย
. หากคอนเทนเนอร์เป้าหมายเมาต์ไดรฟ์ข้อมูลถาวร ควรแมปจุดเชื่อมต่อเหล่านั้น เช่น หากคอนเทนเนอร์เป้าหมายมี /ข้อมูล
จากนั้นควรติดตั้งดีบักคอนเทนเนอร์ /รัน/เป้าหมาย/ข้อมูล
.
อีกทางหนึ่ง จะเป็นการดีที่จะ "แทรก" โครงสร้างระบบไฟล์คอนเทนเนอร์ดีบักลงในคอนเทนเนอร์เป้าหมาย ดังนั้นจึงมีเช่น ก /รัน/ดีบั๊ก
ที่แสดงการดีบักคอนเทนเนอร์รูทที่พร้อมใช้งานเมื่อ เซนเตอร์
ใช้งานดีบักคอนเทนเนอร์ รวมถึงตัวยึดเช่น procfs ดังนั้นมันจึงทำงานได้อย่างสมบูรณ์
ฉันต้องการที่จะสามารถเช่น gdb -p $target_pid
ที่ไหน จีดีบี
มีให้โดยคอนเทนเนอร์การดีบัก จีดีบี
จะต้องสามารถค้นหากระบวนการที่เรียกใช้งานได้จาก คอนเทนเนอร์เป้าหมาย สำหรับสิ่งนี้.
ฉันได้สำรวจแนวทางแก้ไขปัญหาบางอย่างแล้ว แต่สิ่งที่ฉัน จริงๆ ที่อยากทำคือ เมานต์ --rbind
ต้นไม้ FS ของคอนเทนเนอร์เป้าหมายไปยังแขกหรือในทางกลับกัน รับคอนเทนเนอร์ดีบักสิทธิพิเศษที่สร้างขึ้นเอง เช่น:
api เวอร์ชัน: v1
ชนิด: ฝัก
ข้อมูลเมตา:
ชื่อ: debugcontainer
เนมสเปซ: ค่าเริ่มต้น
ข้อมูลจำเพาะ:
ชื่อโหนด: TARGET_NODE_NAME_HERE
enableServiceLinks: จริง
hostIPC: จริง
โฮสต์เครือข่าย: จริง
hostPID: จริง
นโยบายรีสตาร์ท: ไม่เคย
ตู้คอนเทนเนอร์:
- รูปภาพ: DIAG_CONTAINER_IMAGE_HERE # คุณสามารถทดลองใช้บางอย่างเช่น Ubuntu:20.04
ชื่อ: ดีบักเกอร์
stdin: จริง
tty: จริง
ปริมาณการติดตั้ง:
- mountPath: /เป้าหมาย
ชื่อ: เป้าหมาย
#- เส้นทางภูเขา: /host
# mountการขยายพันธุ์: ไม่มี
# ชื่อ: โฮสต์รูท
บริบทความปลอดภัย:
สิทธิพิเศษ: จริง
เรียกใช้ AsGroup: 0
เรียกใช้ AsUser: 0
ปริมาณ:
- ว่างDir: {}
ชื่อ: เป้าหมาย
#- เส้นทางโฮสต์:
# เส้นทาง: "/"
# พิมพ์: ""
# ชื่อ: โฮสต์รูท
ที่เปิดตัวคอนเทนเนอร์การแก้ไขข้อบกพร่องใน โหนดเดียวกัน ในฐานะคอนเทนเนอร์เป้าหมาย ฉันสามารถ:
- ดูกระบวนการคอนเทนเนอร์เป้าหมายใน
ปล
- แนบไปกับกระบวนการด้วย
สเตรส
, จีดีบี
ฯลฯ เนื่องจากคอนเทนเนอร์การดีบักที่มีสิทธิพิเศษมี CAP_SYS_PTRACE
nsenter -t $some_target_container_pid --ทั้งหมด
เพื่อ "กลายเป็น" proc ในคอนเทนเนอร์เป้าหมายราวกับว่าฉันทำเสร็จแล้ว ผู้บริหาร kubectl
. ฉันไม่สามารถ "ดู" หรือเข้าถึงไฟล์/เครื่องมือดีบักคอนเทนเนอร์ได้อีกต่อไป
nsenter -t $some_target_container_pid -m --root=/ --wd=/
เพื่อป้อนเนมสเปซเมานต์ของ proc เป้าหมาย แต่คงไว้ซึ่ง privs ของคอนเทนเนอร์ดีบั๊ก ฉันไม่สามารถ "ดู" หรือเข้าถึงไฟล์/เครื่องมือดีบักคอนเทนเนอร์ได้อีกต่อไป
แต่ฉันไม่สามารถ:
- ดูไฟล์ในคอนเทนเนอร์เป้าหมายพร้อมกับเข้าถึงเครื่องมือในคอนเทนเนอร์แก้ไขข้อบกพร่อง เช่น
จีดีบี
ไม่พบไฟล์เรียกทำงานที่ถูกดีบั๊ก
- ดูเนื้อหาของวอลุ่มในคอนเทนเนอร์เป้าหมายและใช้เครื่องมือดีบักคอนเทนเนอร์กับพวกเขา
มีวิธีการใดที่รู้จักในการทำเช่นนี้หรือไม่?
มันไม่ได้เจาะจง k8 ทั้งหมด: ปัญหาเดียวกันนี้ใช้กับ Docker, containerd, วิ่ง
ฯลฯ
คุณอาจคาดหวังว่าสิ่งนี้จะเป็นไปได้โดยใช้ เมานต์ --rbind
เพื่อ "ฉีด" คอนเทนเนอร์ดีบั๊กลงในคอนเทนเนอร์เป้าหมายผ่านเนมสเปซคอนเทนเนอร์โฮสต์โดยใช้ไฟล์ เส้นทางโฮสต์
ปริมาณ
กับ การขยายพันธุ์: แบบสองทิศทาง
. แต่ ตู้คอนเทนเนอร์
เมานต์อิมเมจรูทของคอนเทนเนอร์ ตั้งค่าการเผยแพร่เมานต์เป็นแบบส่วนตัว จากนั้นติดตั้งไดรฟ์ข้อมูลภายใน ดังนั้นเนมสเปซการเมานต์ของโฮสต์จึงไม่เห็นการเมานต์ที่สร้างขึ้นภายในอิมเมจรูทของคอนเทนเนอร์และ procs ในคอนเทนเนอร์จะไม่เห็นการเมานต์ใหม่ที่โฮสต์เพิ่มหลังจากกระบวนการแรกของคอนเทนเนอร์เริ่มต้น ดู https://man7.org/linux/man-pages/man7/mount_namespaces.7.html สำหรับรายละเอียด
ฉันได้ลองใช้ เซนเตอร์
เพื่อ "ข้าม" เมานต์เนมสเปซ แต่ฉันไม่สามารถเมานต์ผูกให้ทำงานได้ เช่น. ในคอนเทนเนอร์ดีบักฉันทำได้
nsenter -t $some_target_container_pid --root=/ -m /bin/bash
ซึ่งทำให้ฉันมีเปลือกที่ .
(CWD) เป็น rootfs ของคอนเทนเนอร์ดีบัก และ /
คือ คอนเทนเนอร์เป้าหมาย ราก แต่ฉันไม่สามารถผูกมัดพวกเขาได้:
$ mkdir /รัน/ดีบัก
$ เมาท์ --rbind . /รัน/ดีบั๊ก
mount: /run/debug: ประเภท fs ผิด, ตัวเลือกไม่ดี, superblock เสียบน ., ไม่มีหน้ารหัสหรือโปรแกรมตัวช่วย หรือข้อผิดพลาดอื่นๆ
สิ่งเดียวกันนี้จะเกิดขึ้นหากฉันใช้ nsenter --wd=/
ปราศจาก --ราก
และพยายามที่จะ เมานต์ --rbind / ./run/debug
.
ฉันได้ลองใช้ ยกเลิกการแบ่งปัน -m
เพื่อสร้างเนมสเปซเมานต์ภายในใหม่ก่อน และฉันได้พยายาม เมานต์ --make-rprivate /
บนแผนผังคอนเทนเนอร์การดีบักก่อนการเมานต์การผูก ข้อตกลงเดียวกัน
ฉันไม่สามารถหาสาเหตุได้: ไม่มีอะไรใน dmesg และข้อผิดพลาดนั้นธรรมดามาก ฉันเดาว่าเป็นเพราะรากที่แยกจากกันและ/หรือเนมสเปซเมานต์ที่แยกจากกัน ดูเหมือนจะไม่ได้เกิดจากการป้องกันของเคอร์เนลต่อการผูกเป็นวงกลม และฉันใช้การผูกแบบเรียกซ้ำ ดังนั้นจึงไม่ควรเกิดจากการป้องกันการเมานต์ทรีเอสเคปในเนมสเปซผู้ใช้ linux
ทางเลือกในการ --rbind
การใช้ทรี FS จะเป็นถ้าฉันมีวิธี เมานต์-ผูก
โดย รหัสเมานต์ ตามที่ปรากฏใน /proc/$target_pid/mountinfo
. จากนั้นฉันสามารถโคลนการเมานต์ทั้งหมดจาก pid เป้าหมายไปยังเนมสเปซเมานต์ของคอนเทนเนอร์ดีบั๊ก แต่ฉันทำไม่ได้ เมานต์-ผูก
ใช้พาธสัมบูรณ์ปกติ เนื่องจากเนมสเปซการเมาต์ของคอนเทนเนอร์เป้าหมายและดีบักนั้นแยกจากกัน และทั้งคู่มีทรีย่อยของการเมาต์ที่มีการเผยแพร่ส่วนตัว
ฉันได้ลองใช้กระบวนการเป้าหมายแล้ว /proc/$pid/ns/mnt
เมานต์เนมสเปซตามที่ฉันเห็นการอ้างอิงถึงการผูกมัดโดยใช้มัน แต่ในเคอร์เนลของฉัน 5.16 มันเป็นต้นไม้ของ symlinks ปลอมไม่ใช่ต้นไม้ fs:
$ readlink /proc/self/ns/mnt
นาที:[4026531840]
$ ls /proc/self/ns/mnt/
ls: ไม่สามารถเข้าถึง '/proc/self/ns/mnt/': ไม่ใช่ไดเรกทอรี
สิ่งที่ใกล้เคียงที่สุดที่ฉันต้องแก้ไขในขณะนี้คือ เซนเตอร์
แฮ็คกับไดเร็กทอรีการทำงาน ซึ่งให้การใส่เครื่องมือที่จำกัดมากในคอนเทนเนอร์เป้าหมาย โดยที่ pid 1055 เป็น pid ในคอนเทนเนอร์เป้าหมาย:
# nsenter -t 1055 -p -m --wd=/ /bin/bash
shell-init: เกิดข้อผิดพลาดในการเรียกไดเร็กทอรีปัจจุบัน: getcwd: ไม่สามารถเข้าถึงไดเร็กทอรีพาเรนต์: ไม่มีไฟล์หรือไดเร็กทอรีดังกล่าว
# ล /
...กำหนดเป้าหมายเนื้อหา rootfs ของคอนเทนเนอร์ที่นี่...
#ล .
...debug rootfs ของคอนเทนเนอร์ที่นี่...
#ล ..
...debug คอนเทนเนอร์ rootfs ที่นี่เช่นกันเพราะ . เป็นราก...
# pwd
pwd: ข้อผิดพลาดในการเรียกไดเรกทอรีปัจจุบัน: getcwd: ไม่สามารถเข้าถึงไดเรกทอรีหลัก: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
# ls usr/bin/gdb
usr/bin/gdb
# ls /usr/bin/gdb
ls: ไม่สามารถเข้าถึง '/usr/bin/gdb': ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
แต่ฉันไม่สามารถผูกเมานต์ได้อย่างที่ฉันต้องการจากภายในเซสชัน nsenter เดียวกัน:
# mkdir /รัน/ดีบัก
# mount --rbind . /รัน/ดีบั๊ก
mount: /run/debug: ประเภท fs ผิด, ตัวเลือกไม่ดี, superblock เสียบน ., ไม่มีหน้ารหัสหรือโปรแกรมตัวช่วย หรือข้อผิดพลาดอื่นๆ
คำใบ้?
ลิงค์อ้างอิง: