Thay Kubernetes bằng systemd (2024)
(blog.yaakov.online)- Trên máy chủ cá nhân và VPS cỡ nhỏ, khả năng tự động hóa khai báo của Kubernetes rất hấp dẫn, nhưng gánh nặng CPU·bộ nhớ và độ phức tạp vận hành có thể vượt quá lợi ích thực tế
- Kubernetes tự động hóa các tác vụ như điều chỉnh Pod và gia hạn chứng chỉ TLS bằng cách liên tục đưa hệ thống về trạng thái mong muốn, nhưng để làm vậy nó phải luôn duy trì một runtime khá lớn
- Trong các thử nghiệm với Azure Kubernetes Service, Microk8s, K3S và Raspberry Pi, mức sử dụng tài nguyên khi nhàn rỗi cùng nhiệt độ·tiếng ồn quạt liên tục là vấn đề lặp đi lặp lại
- Podman có thể biến container thành dịch vụ systemd và dùng
io.containers.autoupdatecùngpodman auto-updateđể phát hiện rồi thay thế bằng image mới - Kết hợp Podman, systemd và user lingering cung cấp hầu hết khả năng tự động hóa từng mong muốn ở Kubernetes theo cách đơn giản hơn, nhưng phần tích hợp với systemd đang chuyển dần sang hướng Quadlet
Vì sao tự động hóa của Kubernetes lại quá nặng cho máy chủ cá nhân
- Kubernetes gồm nhiều thành phần, dịch vụ web, sidecar và webhook, nhưng hoạt động cốt lõi gần như là một vòng lặp liên tục so sánh trạng thái hiện tại với trạng thái mong muốn rồi áp dụng phần chênh lệch
- Nếu cần có Pod mà chưa có thì tạo ra
- Nếu cần 3 replica mà đang có 4 thì xóa bớt một
- Mô hình này đặc biệt hữu ích với các phần mở rộng như cert-manager
- Khai báo rằng cần có chứng chỉ TLS hợp lệ cho một tên miền nhất định
- Khi đã chỉ định cách yêu cầu chứng chỉ, hệ thống sẽ lấy chứng chỉ mới và cài vào máy chủ web nếu chưa có hoặc sắp hết hạn
- Với mục đích thử nghiệm cá nhân thì nó thú vị và có giá trị học tập, nhưng cho mục tiêu vận hành thực tế thì gần như là công cụ quá mức cần thiết
- Gánh nặng tài nguyên lặp lại ở nhiều môi trường
- Trên NUC, máy tính chạy liên tục, nóng lên và phát ra tiếng quạt khiến khó ngủ
- Trên Azure Kubernetes Service, phần triển khai Kubernetes chiếm nhiều RAM và dùng khoảng 7~10% CPU nhàn rỗi trên worker node
- Một instance Microk8s đơn lẻ trên VPS x86_64 2 vCPU có mức CPU nhàn rỗi khoảng 12%
- K3S trên máy Ampere A1 2 vCPU, dù được biết đến là nhẹ hơn, vẫn dùng khoảng 6% CPU thường trực
- Ngay cả trên Raspberry Pi cũng không tìm được triển khai nào vừa tránh được vấn đề nhiệt·quạt vừa để lại đủ CPU cho workload
Cách tự động hóa được thay thế bằng Podman và systemd
- Lý do lớn nhất khiến tiếp tục dùng Kubernetes là tự động hóa triển khai
- Dùng GitOps và Flux giúp thao tác thay đổi dễ dàng
- Với tự động hóa image container và webhook của Flux v2, khi push image mới thì máy chủ sẽ kéo image mới trong vài giây và chạy ứng dụng production
- Các lựa chọn thay thế truyền thống bên ngoài Kubernetes đều không thật sự thỏa đáng
- Cách tạo lại container bằng cách phải nhớ toàn bộ tham số dòng lệnh ban đầu gây gánh nặng quản lý lớn
- Cũng không thích các công cụ đòi toàn quyền kiểm soát
docker.sock
- Podman auto-updating là thứ gần nhất với chức năng cần có
- Podman có thể xem là một lựa chọn thay thế cho Docker CLI
- Sau khi tạo container, có thể sinh tệp dịch vụ systemd
- Khi khởi động dịch vụ, nó sẽ tạo hoặc thay thế container; khi dừng dịch vụ, nó sẽ xóa container
- Tự động cập nhật hoạt động bằng nhãn
io.containers.autoupdate- Có thể chạy bằng timer mỗi ngày một lần hoặc chạy trực tiếp
podman auto-update - Nếu có image mới, container sẽ được tạo lại bằng image đó
- Có thể chạy bằng timer mỗi ngày một lần hoặc chạy trực tiếp
- Bài Auto-updating Podman containers with systemd của Fedora Magazine cung cấp phần lớn cách triển khai, và cần thêm hai cấu hình nữa
systemctl --user enable mycontainer.serviceđể container tự khởi động khi đăng nhậploginctl enable-lingerđể phiên người dùng hoạt động ngay khi máy chủ khởi động
- Kết hợp Podman, systemd và user lingering mang lại khoảng 99% lợi ích từng có từ Kubernetes nhưng với độ phức tạp cùng gánh nặng CPU·bộ nhớ thấp hơn nhiều
- Toàn bộ dịch vụ đã được chuyển từ VPS cũ sang VPS mới có số vCPU và RAM chỉ bằng một nửa, và sau vài giờ chạy thử, hệ thống nhẹ hơn, nhanh hơn và chi phí tính toán cũng thấp hơn
- Tuy vậy, phần tích hợp systemd của Podman dường như đã bị ngừng hỗ trợ, và định nghĩa container đang được thảo luận theo hướng dùng tệp Quadlet
1 bình luận
Ý kiến trên Hacker News
Hoàn toàn đồng cảm với cảm xúc của tác giả bài gốc. Ở chỗ làm, chúng tôi quản lý khá dễ dàng nhiều cụm Kubernetes chạy hàng chục microservice, nhưng với các dự án sở thích không tạo doanh thu thì ngân sách nhỏ đến mức dù muốn cũng không dùng Kubernetes được
Trên một VPS $10/tháng với 1 vCPU dùng chung và 2GB RAM, Kubernetes quá nặng. Thay vì Deployment, tôi chạy thủ công
docker compose up/downqua SSH; thay vì Ingress, tôi dựa vào tính năng khám phá container của Traefik; và vì không dùng được CronJobs nên còn tự viết cả một script nhỏ để quản lý crontab theo cách idempotentThứ tôi thật sự muốn là một lựa chọn thay thế nhẹ, cung cấp API tương thích Kubernetes và chạy tốt cả trên VPS giá rẻ. Khoảng cách giữa điều phối container cấp enterprise và hosting giá rẻ cho sở thích vẫn còn quá lớn
docker composedùng manifest KubernetesCũng có thể dùng cùng các unit systemd như cách được mô tả trong bài. Podman cũng hỗ trợ phần lớn hoặc toàn bộ Docker API, nên
docker composecũng chạy được, và bạn cũng có thể kết nối tới socket từ xa qua SSH để thao táchttps://docs.podman.io/en/latest/markdown/podman-kube-play.1...
https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
Miễn phí 4 lõi ARM64 và 24GB RAM, có thể chia thành 1–4 node tùy cách bạn muốn
https://www.oracle.com/cloud/free/
docker composebản mạnh hơnDùng Traefik cùng label để tổng quát hóa reverse proxy và chứng chỉ TLS, rồi gắn Authelia làm nhà cung cấp xác thực đơn giản là xong. Trên GitHub cũng có nhiều dự án mẫu, và nếu bỏ ra khoảng một cuối tuần để cấu hình thì sẽ có một hệ thống khá dễ quản lý
systemd bị chửi rất nhiều, nhưng nó thật sự giải quyết được rất nhiều vấn đề nên không nên dễ dàng xem nhẹ. Khi nó bắt đầu được đưa vào mặc định trong các distro, phần lớn là vì mọi người ghét việc phải thay đổi
Có container,
machinectl,nspawnnhư một chroot mạnh hơn,vmspawndùng khi cần ảo hóa đầy đủ,importctlđể tải xuống, nhập và xuất machine,homed/homectlgiúp dễ mã hóa thư mục home và kiểm soát quyền, v.v.Nó xử lý mount như unit thay vì
fstab, kiểm soát thứ tự boot và việc start/stop service, đồng thời cũng cung cấp timer mạnh hơncron. Ví dụ có thể biết các job đã không chạy được vì máy bị tắt, hoặc trì hoãn chạy sau khi boot trong một số điều kiện nhất địnhService unit cho phép kiểm soát tác vụ chi tiết và giới hạn quyền, còn
systemctl editcho phép tạo cấu hình override mà không đụng tới cấu hình gốc. Học lúc đầu hơi phiền, nhưng nếu muốn làm việc phức tạp thì dù sao cũng chẳng có công cụ nào không cần đọc tài liệu cảVấn đề là thái độ của maintainer. Họ thản nhiên làm hỏng những thứ đang hoạt động tốt mà không đưa ra cách sửa phù hợp. Nếu bạn không cảm thấy đau khổ vì systemd, có thể là bạn tham gia muộn, hoặc nhu cầu của bạn tình cờ trùng với nhu cầu của các maintainer cốt lõi
execchính nó tại chỗHoàn toàn có thể có một chương trình nhỏ hơn nhiều, làm chính xác 100% những việc PID 1 phải làm và không làm gì ngoài những việc đó. Nếu chạy systemd trên đó, thì dù systemd gặp vấn đề gì cũng không lập tức dẫn tới kernel panic
Nguồn: https://ewontfix.com/14/
cronđi. Nó đã hoạt động tốt suốt 50 năm, vậy mà đột nhiên lại thành thứ rất sai trái và đương nhiên phải bị thay bằng systemdfstabvà dùng mount của systemd, các quy tắc automount phức tạp và dù làm khớp 1:1 với tài liệu thì đôi khi vẫn đơn giản là không chạy, khiến filesystem có thể không được mount đúng lúcVới distro hoặc upstream, nó khiến cuộc sống dễ dàng hơn rất nhiều, nhưng cái giá là thêm vào tầng thấp nhất của hệ thống một độ phức tạp ngày càng lớn. Tùy góc nhìn, những thứ như
journalctl,timedatectl, phụ thuộc vào dbus hoặc thay thế nó có thể bị xem là không hợp với triết lý UnixNếu mục đích chỉ là phối hợp các process, chạy chúng theo đúng thứ tự và đảm bảo tự động kích hoạt, tôi thấy đây là công cụ ở mức phù hợp hơn k8s hay Docker
Tôi đã vận hành homelab một thời gian bằng podman-systemd, tức Quadlet, và mỗi lần xem qua một biến thể k8s mới thì đều thấy không đáng để chịu thêm phiền phức. Chỉ cần playbook Ansible cũ tải sẵn image và đặt các unit file vào đúng chỗ là đủ
Tôi cũng chạy toàn bộ stack máy in 3D Voron bằng podman-systemd để có thể cập nhật và rollback mọi thành phần cùng lúc. Tuy vậy, giờ tôi cũng đang cân nhắc cách cập nhật/rollback nguyên disk image một lần bằng
mkosivàsystemd-sysupdateVấn đề chính là mọi người thường chỉ phân phối file
docker-compose, nên phải chuyển chúng sang systemd unit; và một số Docker image có những phức tạp không cần thiết với Podman trong thiết lập user/quyền. Đặc biệt khi container từ chối chạy bằng root hoặc chuyển sang user khác, đôi khi cần mapping IDusernskhá phiềnDù vậy, nhìn chung nó ít phức tạp hơn rất nhiều so với bất kỳ thiết lập k8s hay biến thể k8s nào. Việc được tích hợp cả với systemd lẫn journald, không bị chia làm hai nơi, cũng rất hay
Chỉ cần đặt unit vào là xong, nên rất ổn định và đơn giản
composesang file Quadlet, có thể dùngpodlet: https://github.com/containers/podletNhưng nó không thay thế được phần trừu tượng hóa điều phối và lập lịch trên nhiều node mà k8s cung cấp. Nó thiếu phần “đây là các máy có thể chạy file Podman-systemd, đây là đặc tả tôi muốn chạy, hãy tự bố trí giúp tôi”
podman runđể chạy thử container, xác nhận nó hoạt động đúng, rồi dùngpodlettạo file container cơ bản, sau đó chỉnh file container bằng cách tách volume và network sang các file Quadlet khác là xongDự án
podman-composecó vẻ vẫn được duy trì tích cực và có thể là một lựa chọn thay thế tốt chodocker-compose. Nhưng sự tích hợp giữa Podman và systemd thật sự rất thỏa mãnBước tiếp theo để đơn giản hóa việc này hơn nữa là quản lý container bằng Quadlet bên trong systemd. Chi tiết có ở https://www.redhat.com/en/blog/quadlet-podman
docker composesang rootless Podman Quadlet; quá trình chuyển đổi vất vả, nhưng tôi rất hài lòng với kết quảTôi đã tạo skate: https://github.com/skateco/skate. Về cơ bản nó phục vụ mục đích này, nhưng hỗ trợ nhiều host và cả manifest k8s. Bên trong dùng Podman và systemd
Tuy vậy, tôi cho rằng k8s có API và trải nghiệm người dùng rất tệ. Đặc tả Docker Compose thân thiện với người dùng hơn nhiều, nên hiện tôi đang thử nghiệm
docker-composecho nhiều host: https://github.com/psviderski/uncloudTôi đã quay lại cách đóng gói thành deb package và chạy trực tiếp bằng systemd trên instance EC2, không dùng container nữa. Các instance được đặt trong Auto Scaling Group gắn với ALB, và khi khởi động thì một
ansible-pullđơn giản sẽ cài debCách này khá thô sơ, nhưng tôi đã mệt với HCL chứa YAML chứa JSON vô tận. Giờ tôi chỉ muốn xử lý cỡ YAML của Ansible thôi
apt full-upgraderồi restart các process đang chạy là được bảo vệKhông cần build lại thứ gì, cũng không cần tìm cách cập nhật một thư viện bị chôn sâu trong container mà có thể do mình tạo hoặc cũng có thể không
Nhờ hỗ trợ cgroup, việc chạy nhiều service trên một VPS cũng ổn
Vì bài viết đã hơn 1 năm, hiện giờ còn có cả ParticleOS, một bản phân phối OS hỗ trợ chính thức cho workflow bất biến của systemd
https://github.com/systemd/particleos
https://news.ycombinator.com/item?id=43649088
systemd-kernel, thế là hoàn tấtĐọc qua thì có vẻ toàn bộ những thứ này có thể được thay bằng lệnh
docker composevà một thứ như Caddy để tự động lấy chứng chỉChỉ cần có
compose.yamlthì về cơ bản một dòngdocker compose up -d --pull alwayslà đủ. Cấu hình CI cũng chỉ cầnscp compose.yaml user@remote-host:~/rồissh user@remote-host 'docker compose up -d --pull always'là đủƯu điểm là đơn giản và chạy được cả trên máy dev. Tất nhiên, nếu mục tiêu phụ là thử làm và học những thứ thú vị thì Quadlet, k8s, systemd cũng là lựa chọn tốt
docker context create --docker 'host=ssh://user@remote-host' remote-hostSau đó dùng
docker -c remote-host compose -f compose.yaml up -d --pull alwaysthì không cần sao chép file nữa. Ngoài ra, nếu thiết lập thông tin người dùng trong~/.ssh/configthì khi gọi SSH không cần viếtuser@, giúp cả nhóm dễ sao chép tài liệu hoặc lệnh để dùng hơnDOCKER_HOSTlà được. Tuy nhiên cần lưu ý rằng phép nội suy trong filecomposesẽ dùng biến môi trường cục bộVì nghĩ rằng việc triển khai lên một server đơn lẻ không nên phức tạp đến mức này, tôi đã tạo một công cụ triển khai theo cách mình muốn: https://harbormaster.readthedocs.io/
Harbormaster tìm các repository bằng file YAML, định kỳ clone/cập nhật chúng, rồi chạy file Docker Compose bên trong. Mọi trạng thái cũng được lưu trong một thư mục duy nhất nên dễ backup
Nếu chỉ cần một server đơn lẻ, đây là công cụ điều phối container dễ và tốt nhất tôi từng thấy. Tôi thích việc toàn bộ cấu hình được khai báo trong repository, mọi trạng thái nằm trong một thư mục, và mọi thứ đơn giản chỉ là file Compose
Đọc các bình luận ở đây khiến tôi thấy mình già đi. Tự hỏi giờ không còn ai chỉ dùng ssh và nginx nữa sao
Nhét tất cả vào một máy, backup máy đó thật quyết liệt là xong. Dùng ở nhà thì thật sự không cần đến mức quản lý microservice