ความยุ่งยากของ Nix กับการติดตามที่มาแพ็กเกจ: เมื่อแหล่งที่มาของซอฟต์แวร์ซับซ้อนเกินคาด

ทีมชุมชน BigGo
ความยุ่งยากของ Nix กับการติดตามที่มาแพ็กเกจ: เมื่อแหล่งที่มาของซอฟต์แวร์ซับซ้อนเกินคาด

ในโลกของการจัดการแพ็กเกจ Nix ได้รับการยกย่องมานานสำหรับการสร้างที่ทำซ้ำได้และแนวทางแบบประกาศ (declarative) อย่างไรก็ตาม การสำรวจล่าสุดเกี่ยวกับการทำงานภายในของ Nix ได้เผยให้เห็นพฤติกรรมบางอย่างที่น่าประหลาดใจ ซึ่งท้าทายความเข้าใจของแม้แต่ผู้ใช้ที่มีประสบการณ์เกี่ยวกับการที่ระบบติดตามแหล่งที่มาของแพ็กเกจ ชุมชนกำลังอภิปรายอย่างกระตือรือร้นถึงสิ่งที่นักพัฒนาคนหนึ่งเรียกว่า ความบ้าคลั่งของอนุพันธ์ (derivation madness) – สถานการณ์ที่ความสัมพันธ์ระหว่างแหล่งที่มาของแพ็กเกจและผลลัพธ์ของพวกมันกลับมีความซับซ้อนอย่างไม่คาดคิด

คดีลึกลับของการหายไปของอนุพันธ์

ปัญหาหลักอยู่ที่สิ่งที่เกิดขึ้นเมื่อผู้ใช้พยายามย้อนรอยแพ็กเกจกลับไปยังอนุพันธ์ต้นทาง (source derivation) ซึ่งเป็นคำอธิบายอย่างเป็นทางการเกี่ยวกับวิธีการสร้างมัน ผู้ใช้ค้นพบว่าเมื่อสอบถามหาอนุพันธ์สำหรับแพ็กเกจทั่วไปอย่างเช่น Ruby Nix จะรายงานเส้นทางที่ simply ไม่มีอยู่บนระบบของพวกเขา ที่สับสนยิ่งกว่านั้นคือ ความพยายามในการดึงอนุพันธ์ที่หายไปเหล่านี้จากแคชไบนารีของ Nix ล้มเหลว แม้ว่าแพ็กเกจเองจะพร้อมใช้งานอย่างง่ายดาย

นี่ไม่ใช่แค่บั๊กธรรมดาหรือปัญหาข้อมูลเสีย ฐานข้อมูลของระบบเองชี้ไปยังเส้นทางอนุพันธ์ที่ไม่สามารถดึงกลับมาได้อย่างสม่ำเสมอ ดังที่นักพัฒนาคนหนึ่งที่กำลังสืบสวนปัญหานี้ระบุ different commands จะรายงานเส้นทางอนุพันธ์ที่แตกต่างกันโดยสิ้นเชิงสำหรับผลลัพธ์แพ็กเกจเดียวกัน สร้างสถานการณ์ที่สับสนซึ่งอนุพันธ์หลายตัวสามารถให้ผลลัพธ์ที่เหมือนกันทุกประการได้

Fixed-Output Derivations: รากเหง้าของความซับซ้อน

คำอธิบายอยู่ในวิธีการจัดการ Fixed-Output Derivations (FODs) ของ Nix สิ่งเหล่านี้คือนิยามแพ็กเกจพิเศษที่ทราบแฮชของผลลัพธ์ล่วงหน้า มักใช้สำหรับการดาวน์โหลดซอร์สโค้ดหรือเนื้อหาอื่นที่ไม่ควรเปลี่ยนแปลง ข้อคิดสำคัญคือ การเปลี่ยนแปลงคำนิยามของ fixed-output derivation ไม่ได้เปลี่ยนเส้นทางผลลัพธ์ของมัน ตราบใดที่เนื้อหาจริงยังคงเหมือนเดิม

สิ่งนี้สร้างความสัมพันธ์แบบ many-to-one: ไฟล์อนุพันธ์ที่แตกต่างกันหลายไฟล์สามารถสร้างผลลัพธ์ที่เหมือนกันทุกประการได้ เมื่อนักพัฒนาต้นน้ำ (upstream) แก้ไขอนุพันธ์เหล่านี้โดยไม่เปลี่ยนเนื้อหาจริง เส้นทางอนุพันธ์ใหม่ก็จะถูกสร้างขึ้น ในขณะที่เส้นทางผลลัพธ์ยังคงเหมือนเดิม อนุพันธ์ดั้งเดิมที่สร้างผลลัพธ์เหล่านี้ในตอนแรกอาจหายไปจากแคชเมื่อเวลาผ่านไป สร้างปรากฏการณ์อนุพันธ์หายไปที่ทำให้ผู้ใช้สับสน

ฟิลด์ deriver ใน Nix เป็นคุณลักษณะที่ผิดพลาดมาโดยตลอด มันถูกออกแบบมาเพื่อให้สามารถติดตามย้อนกลับไปยัง Nix expression ที่ใช้สร้างอนุพันธ์ได้ แต่มันไม่ได้ทำอย่างนั้นจริงๆ

แนวคิดหลักของ Nix Derivation:

  • Derivation: คำอธิบายการ build ที่ระบุวิธีการสร้าง package output
  • Fixed-Output Derivation (FOD): derivation ที่ทราบค่า hash ของ output ล่วงหน้า
  • Content-Addressed Derivation: แนวทางใหม่ที่ derivation ถูกระบุด้วย content hash
  • Store Path: path เฉพาะใน /nix/store ที่เก็บ package outputs

เส้นทางสู่การติดตามที่มาที่ดีขึ้น

ชุมชน Nix ยอมรับว่านี่คือความท้าทายด้านการออกแบบพื้นฐานมากกว่าที่จะเป็นบั๊กง่ายๆ ดังที่นักพัฒนาหลักคนหนึ่งอธิบาย derivers ไม่ได้ถูกกำหนดอย่างมีเอกลักษณ์ในกรณีที่มี fixed-output derivations ซึ่งเป็นไปโดยการออกแบบ การตระหนักรู้นี้ได้จุดประกายการอภิปรายเกี่ยวกับแนวทางที่ดีกว่าสำหรับการติดตามที่มาของแพ็กเกจ

มีหลายวิธีแก้ปัญหาที่กำลังถูกสำรวจ รวมถึงระบบ build trace ที่เสนอ ซึ่งจะจัดการกับธรรมชาติที่ไม่ซ้ำกันของอนุพันธ์ได้อย่างเหมาะสม อีกแนวทางหนึ่งเกี่ยวข้องกับ content-addressed derivations (CA derivations) ซึ่งมีเป้าหมายเพื่อทำให้สถานการณ์เหล่านี้เป็นกรณีที่คาดหวังและจัดการได้อย่างเหมาะสม แทนที่จะเป็นกรณีขอบ (edge cases) ที่น่าประหลาดใจ

การอภิปรายนี้เน้นย้ำถึงความตึงเครียดระหว่างต้นกำเนิดจากการวิจัยของ Nix และการนำไปใช้จริง ดังที่ผู้แสดงความคิดเห็นคนหนึ่งระบุ Nix เป็นโครงการวิจัยที่ยอดเยี่ยม ตอนนี้คือเวลาที่จะเขียนมันใหม่ตั้งแต่ต้น อย่างไรก็ตาม บางคนชี้ไปยังงานที่กำลังดำเนินอยู่ซึ่งพยายามปรับปรุงระบบทีละขั้นตอนในขณะที่ยังคงความเข้ากันได้

แนวทางแก้ไขที่เสนอ:

  • สร้างระบบ trace เพื่อการติดตามแหล่งที่มาที่ดีขึ้น
  • derivations แบบ content-addressed (CA derivations)
  • การเซ็นชื่อด้วยวิธีการเข้ารหัสลับของ build traces
  • การจัดการ metadata แยกต่างหากสำหรับชั้น evaluation และ store

ผลกระทบต่อความปลอดภัยและความสามารถในการทำซ้ำ

ความซับซ้อนของอนุพันธ์เหล่านี้มีผลกระทบอย่างมีนัยสำคัญต่อความปลอดภัยของซัพพลายเชนซอฟต์แวร์และความสามารถในการทำซ้ำของการสร้าง (build reproducibility) การที่ไม่สามารถย้อนรอยผลลัพธ์แพ็กเกจกลับไปยังแหล่งที่มาได้อย่างน่าเชื่อถือ ทำให้การตรวจสอบและความรับผิดชอบซับซ้อนขึ้น ดังที่นักพัฒนาคนหนึ่งระบุ สิ่งนี้ส่งผลต่อทั้งการสร้าง SBOM (Software Bill of Materials) และฟีเจอร์ประสบการณ์ผู้ใช้ต่างๆ

ชุมชนกำลังทำงานอย่างแข็งขันเพื่อหาวิธีแก้ไขที่จะให้การลงนามทางคริปโตกราฟี (cryptographic signing) ของ build trace ที่เหมาะสมและการจัดการเมตาดาต้าที่ดีขึ้น ข้อเสนอบางอย่างแนะนำให้เก็บข้อมูลเฉพาะของ flake ไว้ในเครื่อง (locally) เพื่อรับประกันว่ามันตรงกับวิธีที่ผู้ใช้ได้รับแพ็กเกจ แทนที่จะเป็นวิธีที่ผู้สร้าง (builders) ผลิตพวกมัน

สถานการณ์นี้แสดงให้เห็นว่าแม้แต่ระบบที่ได้รับการยอมรับอย่างดีเช่น Nix ยังคงพัฒนาต่อไปเพื่อตอบสนองต่อรูปแบบการใช้งานในโลกจริง เมื่อภูมิทัศน์ของการจัดการแพ็กเกจมีความซับซ้อนมากขึ้น การทำความเข้าใจและปรับปรุงกลไกพื้นฐานเหล่านี้จึงมีความสำคัญมากขึ้นเรื่อยๆ สำหรับระบบนิเวศซอฟต์แวร์ทั้งหมด

อ้างอิง: Nix derivation madness