2 điểm bởi GN⁺ 2025-05-06 | 1 bình luận | Chia sẻ qua WhatsApp
  • 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.autoupdate cùng podman 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 đó
  • 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ập
    • loginctl 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

 
GN⁺ 2025-05-06
Ý 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/down qua 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 idempotent
    Thứ 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

    • Tùy phạm vi Kube API cần dùng, Podman có thể đảm nhận vai trò đó. Nó có thể tạo container và pod từ manifest Kubernetes, nên hoạt động giống như docker compose dùng manifest Kubernetes
      Cũ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 compose cũng chạy được, và bạn cũng có thể kết nối tới socket từ xa qua SSH để thao tác
      https://docs.podman.io/en/latest/markdown/podman-kube-play.1...
      https://docs.podman.io/en/latest/markdown/podman-systemd.uni...
    • Không biết bạn đã xem k0s hay k3s chưa. Có khá nhiều trường hợp dùng chúng tốt ở quy mô nhỏ: https://news.ycombinator.com/item?id=43593269
    • Tôi không muốn nghe như đang quảng bá cho Oracle, nhưng Oracle Cloud Free Tier hào phóng vượt trội. Bạn có thể chạy khá nhiều thứ, kể cả một cụm k8s nhỏ, và dịch vụ control plane của k8s cũng miễn phí
      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/
    • Cứ dùng kiểu cũ như Ansible là được. Tôi quản lý hoàn toàn vài máy chủ dedicated bằng Ansible, và có thể dùng nó như một dạng docker compose bản mạnh hơn
      Dù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ý
    • Bạn đã nói chi phí dùng Kubernetes quá cao rồi, nên tùy đo hiệu quả theo trục nào, giải pháp tự làm có khi lại hiệu quả hơn
  • 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, nspawn như một chroot mạnh hơn, vmspawn dùng khi cần ảo hóa đầy đủ, importctl để tải xuống, nhập và xuất machine, homed/homectl giú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ơn cron. 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 định
    Service unit cho phép kiểm soát tác vụ chi tiết và giới hạn quyền, còn systemctl edit cho 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ả

    • Việc systemd bị chửi trong vài năm đầu, có lẽ gần 10 năm, không phải vì bản thân dự án tệ. Ngược lại, nó đủ tốt để thành công bất chấp nhiều vấn đề
      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
    • Điều duy nhất tôi không thích ở systemd là một binary sinh ra từ codebase lớn đến mức không đếm xuể lại đảm nhận vai trò PID 1, và khi nâng cấp còn có hành vi phức tạp hơn khi cố exec chí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/
    • Tôi khó chấp nhận chuyện bảo hãy quên 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 systemd
    • Nếu quên fstab và 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úc
    • systemd rất tuyệt cho Linux desktop hoặc server hiện đại, hoặc các mục đích tương tự. Nhưng nếu bạn cố làm điều gì nằm ngoài cách mà dự án giả định, bạn sẽ gặp sự chế giễu và phản kháng. Cứ hỏi nhóm musl là biết
      Vớ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ý Unix
      Nế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 mkosisystemd-sysupdate
    Vấ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 ID userns khá phiền
    Dù 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

    • Tôi đã dùng một cách tiếp cận tương tự trong vài năm: https://github.com/Mati365/hetzner-podman-bunjs-deploy. Dựa trên Podman và systemd, và suốt thời gian đó chưa có gì bị hỏng
      Chỉ cần đặt unit vào là xong, nên rất ổn định và đơn giản
    • Khi chuyển file compose sang file Quadlet, có thể dùng podlet: https://github.com/containers/podlet
    • Rốt cuộc có lẽ đây chỉ là một node đơn lẻ, hoặc một cụm các node độc lập. Podman/systemd/Quadlet có thể là chi tiết triển khai của việc một node k8s chạy container, kiểu như CRI
      Như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”
    • Tôi cũng có trải nghiệm tương tự. Quy trình là dùng lệnh podman run để chạy thử container, xác nhận nó hoạt động đúng, rồi dùng podlet tạ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à xong
      Dự án podman-compose có vẻ vẫn được duy trì tích cực và có thể là một lựa chọn thay thế tốt cho docker-compose. Nhưng sự tích hợp giữa Podman và systemd thật sự rất thỏa mãn
  • Bướ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

    • Quadlet chính là con đường đó. Đây là một cách chạy container thật sự tốt, kiểu cấu hình xong rồi có thể quên nó đi. Trên Fedora hoặc Rocky Linux thì ít nhất cũng không cần cài thêm package nào
    • Phần cuối bài có đề cập, nhưng tác giả khi đó vẫn chưa xem xét. Tích hợp systemd của Podman trông như đã deprecated, và giờ lại có câu chuyện định nghĩa container bằng file “Quadlet”, nên họ để đó như một thứ cần học sau
    • Lý do tôi vào xem bình luận là để kiểm tra xem có ai nhắc đến Quadlet không. Tuần trước tôi đã chuyển home server từ docker compose sang 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ả
    • Bài này cũng giúp ích rất nhiều cho việc chuyển homelab sang Quadlet một cách trơn tru: https://news.ycombinator.com/item?id=43456934
  • 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

    • Tôi rất thích cách tiếp cận này. Thật sự bực mình khi không có cách đơn giản để chạy Docker/Podman trên nhiều host. Docker Swarm thì đáng tiếc là gần như bị bỏ mặc từ sau năm 2019
      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-compose cho nhiều host: https://github.com/psviderski/uncloud
  • Tô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 deb
    Cá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

    • Điểm hay của cách tiếp cận này là khi có lỗi trong thư viện dùng chung, chỉ cần chạy apt full-upgrade rồ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
    • Tôi đã chọn cùng con đường này cho một ứng dụng rất đơn giản. systemd bất ngờ là khá dễ chịu, và việc chạy service với quyền tối thiểu bằng tài khoản user do hệ thống cấp phát cũng khá tốt
      Nhờ hỗ trợ cgroup, việc chạy nhiều service trên một VPS cũng ổn
    • Nghĩ đến lượng đời người đã bị lãng phí vào lĩnh vực vấn đề “quản lý YAML quy mô lớn” mà thấy choáng
  • 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

    • Bước hợp lý tiếp theo chắc sẽ là thay Linux kernel bằng 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 compose và một thứ như Caddy để tự động lấy chứng chỉ
    Chỉ cần có compose.yaml thì về cơ bản một dòng docker compose up -d --pull always là đủ. Cấu hình CI cũng chỉ cần scp compose.yaml user@remote-host:~/ rồi ssh 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

    • Chỉ cần chạy một lần docker context create --docker 'host=ssh://user@remote-host' remote-host
      Sau đó dùng docker -c remote-host compose -f compose.yaml up -d --pull always thì 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/config thì khi gọi SSH không cần viết user@, giúp cả nhóm dễ sao chép tài liệu hoặc lệnh để dùng hơn
    • Làm theo cách của bình luận anh em, hoặc đặt biến môi trường DOCKER_HOST là được. Tuy nhiên cần lưu ý rằng phép nội suy trong file compose sẽ 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

    • Tôi chỉ dùng nginx và vài service tùy chỉnh, nhưng làm được vì yêu cầu rất nhỏ. Khi phức tạp hơn một chút hoặc cần chạy nhiều node để có tính dư thừa, container bắt đầu trở nên cực kỳ hợp lý