Deptool: Khi tôi tự xây dựng công cụ triển khai "trong mơ" thay vì dùng Ansible

Phần mềm06 tháng 5, 2026·11 phút đọc

Mệt mỏi với sự phức tạp và tốc độ chậm của các công cụ hiện nay như Ansible, kỹ sư Ruuda đã tự xây dựng một công cụ riêng gọi là Deptool. Với triết lý tập trung vào tốc độ, tính dự đoán và an toàn, Deptool cho phép triển khai cấu hình trong chưa đến một giây và hỗ trợ tự động hoàn nguyên, giải quyết triệt để các vấn đề của hạ tầng cá nhân.

Đã 00:43 đêm. Tôi nhìn vào kế hoạch và nhấn phím y. “s4.ruuda.nl: đang kết nối…” Tôi nín thở. Cụm từ “Applying” (đang áp dụng) chớp nhoáng trên cửa sổ terminal trước khi hiện lên dòng chữ “done” (hoàn tất). Nó hoạt động rồi. Bây giờ công việc thực sự mới có thể bắt đầu. Quay lại stack frame. Mình đang làm gì nhỉ?

Những người từng làm việc với tôi một thời gian có thể sẽ buộc tội tôi mắc phải hội chứng “không phải do mình tạo ra” (not-invented-here syndrome). Tôi thích gọi đó là “có tiêu chuẩn cao hơn”. Tại sao phải tự chịu sự frustrate vô tận mà những công cụ tầm thường gây ra cho bạn, khi bạn có thể tự xây dựng công cụ riêng của mình thực sự dễ sử dụng? Nhưng dù sao thì, mình đang làm gì nhỉ?

À, tôi muốn viết một bài blog về chủ quyền kỹ thuật số của châu Âu. Việc đăng bài đó lên một blog được lưu trữ tại Mỹ, với một nhà cung cấp dịch vụ đám mây khổng lồ do Mỹ kiểm soát, là điều đầy mâu thuẫn. Vậy hãy chuyển nó sang châu Âu, điều đó khá dễ dàng. Quay lại stack frame. Tạo một máy ảo (VM) mới, trỏ bản ghi DNS về… à, đúng rồi, DNS. Tôi dùng Cloudflare cho việc này. Một thực thể khác mà Trump có thể ra lệnh ngừng cung cấp dịch vụ khi mọi chuyện trở nên tồi tệ. Có lẽ tôi nên tự lưu trữ các máy chủ DNS của mình. Quay lại stack frame.

Máy chủ web của tôi là một máy ảo nhỏ chạy Nginx, cùng với Lego để gia hạn chứng chỉ. Cấu hình Nginx đã trở nên khá phức tạp theo năm tháng, nhưng tôi tạo nó bằng Nix nên vẫn ổn, chỉ có hai file cấu hình. Tôi đã viết một script Python nhỏ để sao chép các file đó lên máy chủ và khởi động lại Nginx. Script này đã phục vụ tôi tốt trong vài năm qua, nhưng giờ tôi muốn bắt đầu chạy các máy chủ DNS. Tôi cần ít nhất hai máy chủ. Và nhiều systemd unit, file cấu hình, zonefile hơn… Script này không còn đủ khả năng nữa, tôi cần một công cụ quản lý cấu hình cluster chuyên nghiệp. Quay lại stack frame.

“NixOS,” tôi nghe giọng Arian thì thầm trong đầu. “Chỉ cần dùng NixOS thôi. Chỉ mất một dòng để cấu hình, services.nsd.enable = true.” Đương nhiên là ông ấy đúng. Tôi đã dùng Nix để dựng các image EROFS tối thiểu cho Nginx và Lego. Đó là cách tôi chạy chúng trên Flatcar. Nhưng tôi thích ý tưởng về một hệ điều hành cơ bản tối thiểu, và chạy các dịch vụ của mình từ các chroot chỉ đọc với ít binary nhất có thể. “Đừng để vấn đề bị lan man (scope-creep) thành việc chuyển distro ngay bây giờ,” tôi tự nhủ. “Hãy xây dựng một công cụ triển khai mới thay thế.”

Deptool trông như thế nào

Và giờ, một tháng sau, Deptool đã ra đời. Đây là lúc tôi đang cập nhật các bản ghi DNS của mình:

$ deptool deploy
s4.ruuda.nl
  update nsd
    ~ zones/ruuda.nl.zone
    restart unit nsd.service
s5.ruuda.nl
  update nsd
    ~ zones/ruuda.nl.zone
    restart unit nsd.service
Auto-rollback if deploy fails.
Apply to 2 hosts in cluster 'prod'? [y/N/d] y
s4.ruuda.nl: done
s5.ruuda.nl: done
Changes deployed successfully to 2 hosts in 0.99s.

Trong bài viết này, chúng ta sẽ đi sâu vào cách thức hoạt động của nó, nhưng đừng vội vượt trước. Tôi đã đến được đây như thế nào?

Danh sách mong muốn

Nếu tôi định xây dựng công cụ cho riêng mình… thì một công cụ quản lý cấu hình thực sự tốt sẽ trông như thế nào? Chúng ta có thể nhìn vào Ansible để làm hướng dẫn: nó đã phạm phải mọi sai lầm để người khác có thể học hỏi từ đó. Tôi muốn công cụ của mình phải:

  • Nhanh: Việc cập nhật cấu hình nên mất dưới một giây. Không có lý do cơ bản nào để nó chậm hơn thế, kể cả ping xuyên Đại Tây Dương cũng chỉ mất 100ms.
  • Dự đoán được: Công cụ nên cho tôi biết nó sẽ làm gì, sau đó làm đúng những điều đó. Giống như OpenTofu, với các giai đoạn lập kế hoạch (plan) và áp dụng (apply) tách biệt. Không giống như Ansible, nơi chế độ kiểm tra vô dụng vì mọi bước mệnh lệnh có thể kích hoạt một chuỗi thay đổi chỉ được biết sau khi thực hiện bước đó.
  • An toàn: Nếu tôi làm hỏng cấu hình Nginx, tôi không muốn máy chủ web của mình bị down trong vài phút trong khi tôi hoảng hốt cố gắng sửa chữa. Không, tôi muốn công cụ tự động hoàn nguyên (rollback) cho mình. Trong tích tắc.
  • Đơn giản: Tôi chỉ cần sao chép các file cấu hình từ laptop lên máy chủ và khởi động lại vài systemd unit. Tôi không cần giải quyết mọi vấn đề triển khai cho tất cả mọi người; tôi không cần luồng điều khiển hoặc thực thi mã tùy ý.
  • Khảo báo (Declarative): Nếu tôi xóa một file hoặc ứng dụng khỏi cấu hình, nó nên bị xóa khỏi máy chủ. Tôi không muốn phải thêm các bước dọn dẹp rõ ràng.
  • Cài đặt bằng không (Zero-setup): Tôi muốn dùng công cụ này để quản lý máy chủ ngay sau khi cung cấp (provisioning). Tôi không muốn cài đặt thủ công các tác nhân, daemon hoặc dependencies.

Tách biệt phân phối

Ý tưởng cốt lõi có vẻ hiển nhiên khi nhìn lại, có lẽ vì nó cứ xuất hiện khắp nơi. Ở công ty, David gần đây đã xây dựng Unsible, một công cụ lấy các playbook của Ansible, nhưng thay vì thực thi chúng từng bước, nó tự dựng một tarball cục bộ và chuyển nó đến máy chủ, nơi hầu như chỉ cần đặt các file vào vị trí. Tôi thích ý tưởng tách biệt việc tạo cấu hình khỏi việc phân phối này. Đó là cách script deploy đơn giản của tôi hoạt động: dựng cấu hình bên ngoài, và script về cơ bản là một công cụ sao chép file “ngu ngốc”.

Deptool hoạt động như thế nào:

  1. Tạo trước (Pre-render) file cấu hình cho toàn bộ cluster. Lưu chúng vào một thư mục trên đĩa. Cây thư mục này có hai cấp độ: một thư mục cho mỗi máy chủ đích ở cấp độ cao nhất, một thư mục cho mỗi ứng dụng bên dưới đó.
  2. Đặt thứ đó vào một kho lưu trữ Git. Bây giờ chúng ta có thể diff một phiên bản với phiên bản khác và xem những gì đã thay đổi trên toàn bộ cluster. Từ diffstat, chúng ta có thể thấy máy chủ nào bị ảnh hưởng và ứng dụng nào thay đổi ở đó.
  3. Materialize các file trong một thư mục bị cô lập trên máy chủ. Chúng ta đặt mọi thứ trong /var/lib/deptool nơi nó không can thiệp vào bất cứ thứ gì. Ở đó chúng ta tạo một thư mục được đặt tên theo commit cần triển khai. Bây giờ nhiều phiên bản có thể cùng tồn tại trên đĩa.
  4. Theo dõi những gì được triển khai với các remote-tracking refs. Trên laptop của người vận hành, chúng ta theo dõi commit mà chúng ta đã triển khai cho mỗi máy chủ. Đây là thuộc tính trên mỗi máy chủ thay vì thuộc tính toàn cluster.
  5. Triển khai: Đầu tiên thử lấy một khóa (lock) tại máy chủ đích. Nếu chúng ta lấy được khóa, kế hoạch của chúng ta hợp lệ và không có gì khác có thể được triển khai trên máy chủ đó cho đến khi chúng ta giải phóng khóa.
  6. Khởi động lại systemd units. Tôi chạy tất cả các dịch vụ của mình như các systemd unit. Sau khi cấu hình của một ứng dụng thay đổi, chúng ta khởi động lại các systemd unit bị ảnh hưởng. Nếu unit không khởi động được, chúng ta có thể trỏ symlink trở lại phiên bản tốt đã biết trước đó và khởi động lại. Tự động rollback trong tích tắc.

Đồng thời lạc quan

Việc triển khai Deptool có các yếu tố của sự đồng thời lạc quan (optimistic concurrency). Chúng ta giả định rằng chúng ta biết trạng thái hiện tại của cluster và lập kế hoạch dựa trên điều đó. Nếu giả định đó sai, chúng ta phải thử lại. Điều này có nghĩa là nó rất nhanh khi không có tranh chấp (tôi là người duy nhất triển khai, luôn từ cùng một laptop), cái giá phải trả là hoạt động rất tệ dưới sự tranh chấp (một đội ngũ người đều cố gắng triển khai liên tục).

Đây là cùng một mô hình với git push. Nó sẽ không mở rộng lên hàng trăm người hay hàng ngàn máy chủ, nhưng điều đó ổn. Tôi là người duy nhất quản lý hạ tầng cá nhân của mình, và tôi không có hàng ngàn máy chủ. Điều tuyệt vời khi xây dựng công cụ của riêng bạn là bạn có thể tối ưu hóa chúng chính xác cho trường hợp sử dụng của mình!

Xây dựng tác nhân (Agent)

Chúng ta có thiết kế, chúng ta biết ở cấp độ cao cần làm gì. Làm thế nào để biến nó thành hiện thực trên một máy chủ được quản lý? Máy chủ web của tôi chạy Flatcar Linux, một hệ điều hành dựa trên image với không gian người dùng rất tối thiểu. Nó có coreutils và Bash, nhưng không có trình quản lý gói và không có Python. Điều này tuyệt vời để giảm bề mặt tấn công. Nó không tốt lắm để cài đặt các thứ khác.

Vì vậy, chúng ta cần quản lý máy chủ mới từ bên ngoài. Tôi có thể SSH vào nó và sử dụng passwordless sudo ở đó. Có lẽ chúng ta có thể chỉ thực thi các lệnh qua SSH? Nếu bạn từng thử tự động hóa bất cứ điều gì phi tầm thường theo cách đó, bạn sẽ sớm nhận ra theo cách khó khăn rằng việc bắt tay (handshake) không chỉ chậm — argv cũng không vượt qua biên SSH một cách nguyên vẹn. Tôi muốn một công cụ nhanh và tôi không muốn đối phó với những tinh tế của việc tách từ và thoát shell-qua-SSH.

Vì vậy, chúng ta xây dựng một binary tĩnh. Không có giả định về những gì có sẵn ngoại trừ kernel, và không có trình thông dịch phải phân tích qua hàng megabyte code trước khi nó có thể bắt đầu làm điều gì đó hữu ích. Chúng ta đặt nó tại một vị trí được đặt tên theo commit nó được dựng từ đó. Điều này đảm bảo cả hai đầu của kết nối chạy cùng một phiên bản.

Kết luận

Tôi đã dùng Deptool để quản lý hạ tầng cá nhân trong tháng qua và tôi rất hài lòng với nó. Thật tuyệt vời khi nhìn thấy ngay lập tức một kế hoạch chính xác trước khi kết nối, và có tính năng tự động hoàn nguyên, nhưng việc deploy dưới một giây mới thực sự là bước thay đổi cuộc chơi. Khi cách đúng đắn để triển khai mất hàng phút, tôi luôn bị cám dỗ để chỉnh sửa file trực tiếp trên máy chủ để rút ngắn vòng lặp phản hồi. Với Deptool, việc chỉnh sửa cục bộ và deploy nhanh hơn nhiều so với việc SSH vào máy chủ và mở trình chỉnh sửa ở đó.

Cách đúng đắn là cách có ma sát ít nhất. Mọi chỉnh sửa được áp dụng đều được ghi lại trong lịch sử Git, và nếu tôi làm hỏng cái gì đó, Deptool sẽ hoàn nguyên trước khi tôi kịp nhận ra nó bị hỏng. Thật sảng khoái khi sử dụng một công cụ biết lùi lại, thay vì một công cụ mà tôi sợ phải chạy.

Tôi đã xây dựng Deptool cho chính mình, để giải quyết chính xác vấn đề của tôi. Việc nó không cố gắng giải quyết mọi vấn đề triển khai cho tất cả mọi người cũng chính là điều khiến nó tỏa sáng cho trường hợp sử dụng của tôi. Deptool hiện có sẵn từ Codeberg và GitHub, và nó có một hướng dẫn sử dụng (manual) đầy đủ.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗