- เขียนงานอัตโนมัติสำหรับเซิร์ฟเวอร์ด้วย โค้ด Python และรันแบบขนานผ่าน SSH เพื่อสั่งงานอย่างมีคุณสมบัติ idempotent โดยไม่ต้องใช้เอเจนต์
- pyinfra ชูจุดเด่นว่า เร็วกว่า Ansible 6 เท่า ในเวิร์กโหลดเดียวกัน โดยใช้การรันพร้อมกันบนพื้นฐานของ gevent และ SSH
- ใช้ตัวเลือก
--dryเพื่อตรวจสอบ diff ของการเปลี่ยนแปลงแยกตามโฮสต์ก่อนนำไปใช้จริง และเมื่อรันจริงผลลัพธ์จะถูกส่งกลับมาแบบ parallel streaming - โฮสต์ปลายทางต้องมีเพียง shell และ SSH เท่านั้น โดยไม่มี daemon, state file หรือ control plane
- เน้นแนวทาง configuration ที่ยึดโค้ดเป็นศูนย์กลาง โดยไม่เข้ารหัส control flow ลงใน YAML แต่ใช้ลูปและเงื่อนไขของ Python ได้ตรง ๆ
ฟีเจอร์หลักและลำดับการทำงาน
-
ทำงานอัตโนมัติกับเซิร์ฟเวอร์นับพันเครื่อง
- pyinfra เป็นเครื่องมืออัตโนมัติแบบ Python-native และ agentless ที่รันคำสั่งผ่าน SSH
- การรันคำสั่งเน้นเรื่อง concurrency, idempotency และความเร็ว โดยชูว่า เร็วกว่า Ansible 6 เท่า ในเวิร์กโหลดเดียวกัน
- คำสั่งติดตั้งคือ
$ uv tool install pyinfra - คุณสมบัติพื้นฐานที่ระบุไว้คือ MIT license, Python 3.10 ขึ้นไป, no agents และ zero config
-
ตัวอย่างโค้ดสำหรับดีพลอย
- ใช้งาน
apt,files,systemdผ่านโค้ด Python เพื่อทำการติดตั้งแพ็กเกจ วางเทมเพลต และรีโหลดบริการ - โค้ดตัวอย่างติดตั้งแพ็กเกจ
nginxและcertbotแล้ววางtemplates/nginx.conf.j2ไปที่/etc/nginx/sites-enabled/api - ขั้นตอนสุดท้ายรีโหลดบริการ
nginxด้วยsystemd.service("nginx", reloaded=True)
from pyinfra.operations import apt, files, systemd apt.packages( packages=["nginx", "certbot"], update=True, ) files.template( src="templates/nginx.conf.j2", dest="/etc/nginx/sites-enabled/api", ) systemd.service("nginx", reloaded=True) - ใช้งาน
-
อินเวนทอรีและผลลัพธ์การรัน
- ตัวอย่างอินเวนทอรีประกอบด้วยโฮสต์เว็บตั้งแต่
web-01.prodถึงweb-23.prodและโฮสต์ฐานข้อมูลdb-01.prod,db-02.prod - คำสั่ง
$ pyinfra inventory.py deploy.py --limit webจะจำกัดการรันเฉพาะกลุ่มเป้าหมายweb - เอาต์พุตการรันทำงานตามลำดับคือโหลดอินเวนทอรี เก็บ fact พร้อมกัน รัน
deploy.pyแล้วสรุปผล - ตัวอย่างสรุประบุว่ามีโฮสต์สำเร็จ 23 เครื่อง เปลี่ยนแปลง 18 เครื่อง ล้มเหลว 0 เครื่อง ใช้เวลารวม 2.1 วินาที
- ตัวอย่างอินเวนทอรีประกอบด้วยโฮสต์เว็บตั้งแต่
-
ตรวจสอบก่อนเปลี่ยนแปลง
--dryช่วยให้ตรวจสอบ diff แยกตามโฮสต์ ของทุกงานที่ pyinfra จะทำได้ล่วงหน้า- เมื่อรันจริง ผลลัพธ์จะถูกสตรีมกลับมาแบบขนาน พร้อมแสดงจำนวนการเปลี่ยนแปลงและเวลาที่ใช้ของแต่ละโฮสต์
- ตัวอย่างการรันบันทึกว่าใน 24 โฮสต์ มี 18 โฮสต์ที่เปลี่ยนแปลง 6 โฮสต์ไม่เปลี่ยนแปลง ล้มเหลว 0 โฮสต์ และใช้เวลารวม 2.1 วินาที
คุณลักษณะ การเปรียบเทียบกับ Ansible และหลักการ
-
เหตุผลหกข้อที่ควรเลือก pyinfra
- Just Python: เขียน control flow จริงด้วย Python โดยไม่ใช้ YAML และ Jinja-in-YAML
- Concurrent SSH: รันพร้อมกันบนพื้นฐานของ gevent และ SSH และเร็วกว่า Ansible 6 เท่าในเวิร์กโหลดเดียวกัน
- Diff before apply: ใช้
--dryเพื่อดูทุกการเปลี่ยนแปลงล่วงหน้า และงานแบบ idempotent จะกลายเป็น no-op เมื่อนำไปรันซ้ำ - 0 agents: โฮสต์ต้องมีเพียง shell และ SSH เท่านั้น โดยไม่มี daemon, state file หรือ control plane
- Scale-ready: ทำงานได้ตั้งแต่ 1 โฮสต์จนถึง 10,000 โฮสต์ รองรับการรันแบบขนานและเอาต์พุตสตรีมมิงแบบเรียลไทม์
- Hackable: สร้างงานแบบกำหนดเองได้ใน 10 บรรทัด และเชื่อมต่อกับ docker, lxc, k8s ที่สื่อสารผ่าน shell ได้
-
เปรียบเทียบโค้ดระหว่าง Ansible กับ pyinfra
- ตัวอย่าง Ansible ใช้
playbook.yml16 บรรทัดเพื่อติดตั้งnginx, เรนเดอร์เทมเพลต และรีโหลดบริการผ่าน handler - ตัวอย่าง pyinfra ใช้
deploy.py8 บรรทัดเพื่อเขียนลำดับงานเดียวกันด้วยโค้ด Python - ตัวอย่าง pyinfra จะรัน
systemd.service("nginx", reloaded=True)เฉพาะเมื่อcfg.will_changeของผลลัพธ์จากfiles.templateเป็นจริงเท่านั้น
from pyinfra.operations import apt, files, systemd apt.packages(["nginx"], update=True) cfg = files.template( src="nginx.conf.j2", dest="/etc/nginx/sites-enabled/api", ) if cfg.will_change: systemd.service("nginx", reloaded=True) - ตัวอย่าง Ansible ใช้
-
ถ้อยแถลงหลัก
- Code > config: ลูปก็คือลูป ไม่เข้ารหัส control flow ลงใน YAML
- Show, then do: ดู diff ก่อน แล้วค่อยนำไปใช้เพื่อลดการเปลี่ยนแปลงที่ไม่คาดคิด
- Stay out of the way: รันผ่าน SSH ได้โดยตรงโดยไม่มีเอเจนต์ state file หรือ control plane
- Read like english: งานสามารถอ่านได้เหมือนคำนามและคำกริยา เช่น
apt.packages,files.template,systemd.service
-
คำสั่งเริ่มต้น
- คำสั่งติดตั้งคือ
$ uv tool install pyinfra - มีคำแนะนำให้อ่าน quickstart 5 นาทีแล้วดีพลอยโฮสต์เครื่องแรก
- คำสั่งติดตั้งคือ
1 ความคิดเห็น
ความคิดเห็นจาก Lobste.rs
pyinfra ให้ความรู้สึกเหมือน Ansible ในแบบที่มันควรจะเป็นมาตั้งแต่แรก แทนที่จะเอา YAML ที่ปนเทมเพลตมาพอกด้วย control flow คุณสามารถเขียนงานอัตโนมัติเป็น Python ได้โดยตรง
พอใช้ Ansible มานานแล้วก็รู้สึกสดใหม่ดี ไม่ได้อยู่ฝั่งที่เกลียด Ansible เป็นพิเศษด้วย
น่าจะดีกว่าถ้ามีแบบไฮบริดที่ใช้ Python บนเซิร์ฟเวอร์ปลายทางด้วย เพราะจะลดนรกเรื่องเครื่องหมายอัญประกาศเวลาแก้ไฟล์ และหลีกเลี่ยงข้อจำกัดของ regex ใน
sedได้ชอบ pyinfra และอยากให้ถูกใช้อย่างแพร่หลายกว่านี้
ทุกบริษัทที่เคยทำงานมาล้วนใช้ Ansible ไม่ว่าจะใช้ Terraform ควบคู่กันหรือไม่ก็ตาม และไม่มีที่ไหนที่ทีมพร้อมจะเขียนระบบอัตโนมัติเดิมทั้งหมดใหม่ด้วยเครื่องมือที่พนักงานยังไม่มีประสบการณ์
pyinfra ต้องการให้ SysOps รู้ Python ซึ่งส่วนตัวมองว่า SysOps ควรรู้ภาษา scripting สักภาษาอยู่แล้ว โดยเฉพาะใน Ansible เอง ถ้าเขียนโมดูลด้วย Python ก็ช่วยลดความรกของ YAML ได้ แต่ดูเหมือนอย่างน้อยในฝรั่งเศสจะไม่ใช่ความคิดที่แพร่หลายนัก
อาจไม่ใช่ประเด็นที่ถกเถียงกันดุเดือดขนาดนั้นก็ได้
เคยใช้ Ansible ใน homelab แล้วเริ่มอึดอัดขึ้นเรื่อย ๆ การตั้งค่าด้วย YAML แย่มาก ทุกอย่างให้ความรู้สึกเหมือนเป็นการแฮ็ก และยังช้ามากด้วย ไม่เข้าใจเหมือนกันว่าการจะรันคำสั่งเชลล์ไม่กี่คำสั่งทำไมเซิร์ฟเวอร์ต้องมี
python3รู้จัก
pyinfraจาก Google AI Mode และในช่วงที่ลองใช้มาเกือบเดือน มันสดชื่นกว่ามาก ข้อดีคือเร็วกว่า Ansible มาก เขียนลูปและเงื่อนไขด้วย Python ได้ และไม่ต้องมี roles หรือไดเรกทอรีซ้อนกัน โดยฝั่งเซิร์ฟเวอร์แค่มีเชลล์ก็พอ มันจะสร้างแผนจากสถานะปัจจุบันก่อนรัน และถ้าไม่ใส่-yก็จะถามยืนยันก่อนข้อเสียคือชุดงานพื้นฐานยังมีแค่บางส่วนเล็ก ๆ เมื่อเทียบกับโมดูลของ Ansible โค้ดก็กลายเป็นสปาเกตตีได้เร็ว และวิธีอย่าง
if 'web_server' in hosts.groupsก็ไม่ได้ดีนัก ไม่แน่ใจว่าoperation(..., filter_group='web_server')จะดีกว่าหรือเปล่าสิ่งที่แย่ที่สุดคือการ เขียน custom connector นั้นทรมานมาก ดูเหมือนต้องมี
pyproject.tomlที่ใส่ entry point เฉพาะของpyinfraและถึงจะใช้uvการพัฒนา connector ภายในบริษัทก็ยังเหมือนฝันร้าย มันควรจะทำเป็นไฟล์ Python ปกติในโปรเจกต์ได้กำลังลองใช้ pyinfra เป็นเครื่องมือ deploy ใน homelab มาหลายวันแล้ว และเมื่อเทียบกับ Ansible สิ่งที่ชอบที่สุดจนถึงตอนนี้ไม่ใช่ syntax ของ Python แต่เป็น ความเร็ว
Ansible ให้ความรู้สึกว่าช้าจนทนไม่ไหวอยู่เสมอ
อยากใช้แทนการใช้ Ansible และ Salt ในหลาย ๆ ที่
น่าสนใจดีที่ infrastructure as code วนกลับมาครบรอบ จากสคริปต์ไปเป็น YAML แล้วก็ย้อนกลับมาเป็นสคริปต์ที่ซับซ้อนขึ้นอีก
แต่ละแนวทางมีจุดที่เหมาะของมัน และจากมุมมองของผู้ใช้ Ansible แล้ว pyinfra ก็ดูดีทีเดียว
เหตุผลสำคัญที่ทำให้เลือกใช้ Ansible คือ โหมด dry run และการดู diff เพราะมันทำให้มั่นใจได้ว่าจะไม่ไปทำอะไรที่ไม่คาดคิด
แต่ดูเหมือนว่า CLI ของ pyinfra จะไม่มีตัวเลือกแบบนั้น อาจเป็นไปได้ว่าผมหาไม่เจอเพราะไม่เจอเอกสารอ้างอิงที่รวมออปชันทั้งหมดเรียงตามตัวอักษร
—dryและโชว์อยู่ในหน้าแรกของ pyinfra เลยสำหรับคนที่สนใจ ผมก็มีโปรเจกต์ที่คล้ายกันของตัวเองซึ่งทำมาแล้ว 14 ปี: https://github.com/sebastien/cuisine/tree/main
มันเป็นแบบ agentless ใช้แค่ SSH และมี API สไตล์ Python ครอบอยู่บนความสามารถจัดการหลัก ๆ แต่ไม่รองรับ dry mode
เราใช้ Ansible สำหรับ provision resource บน OpenStack และใช้ pyinfra จัดการส่วนที่เหลือ ซึ่งตลอดหลายปีที่ผ่านมาก็ทำงานได้ค่อนข้างดี
ข้อเสียใหญ่สุดคือชุมชนยังเล็ก เลยต้องเขียนทางแก้เอง เช่น เราเก็บ shared secret ที่ใช้ในการ deploy ไว้บนดิสก์ด้วย keyring + privy และเขียนโค้ดไม่กี่บรรทัดเองเพื่อแปลง inventory ของ OpenStack compute ให้เป็นข้อมูล hosts