Docker Swarm: Kiến Trúc Cluster và Raft
Tới giờ ta chạy container trên một máy. Nhưng hệ thống thật cần nhiều máy: để chịu tải lớn hơn, và để một máy chết thì hệ thống vẫn sống. Điều phối container trên nhiều máy gọi là orchestration, và Docker có sẵn một công cụ cho việc đó: Docker Swarm. Bốn bài cuối series dành cho Swarm, bắt đầu từ kiến trúc.
Swarm là gì
Theo tài liệu Docker, "một swarm gồm nhiều Docker host chạy ở chế độ swarm, đóng vai trò manager (quản lý thành viên và phân việc) và worker (chạy các service)". Nói cách khác, Swarm gom nhiều máy chạy Docker thành một cụm logic, rồi bạn ra lệnh cho cả cụm thay vì từng máy.
Mỗi máy trong cụm là một node — một thể hiện Docker engine tham gia swarm. Có hai vai trò:
- Manager node: nhận lệnh từ bạn, ra quyết định điều phối (đặt container nào lên máy nào), và duy trì trạng thái cụm. Manager cũng có thể chạy task.
- Worker node: nhận và chạy task do manager giao. Worker không ra quyết định điều phối.
bạn ra lệnh
│
┌──────────▼───────────┐
│ Manager nodes │ ── điều phối + giữ trạng thái (Raft)
│ [m1*] [m2] [m3] │ (* = leader)
└─────┬────────┬───────┘
│ giao task
┌─────────▼──┐ ┌──▼─────────┐ ┌────────────┐
│ Worker w1 │ │ Worker w2 │ │ Worker w3 │ ── chạy container
│ [task][task]│ │ [task] │ │ [task][task]│
└────────────┘ └───────────┘ └────────────┘
Mô hình desired-state: bạn khai báo, Swarm lo
Đây là thay đổi tư duy quan trọng nhất khi chuyển từ docker run sang Swarm. Với docker run, bạn ra lệnh mệnh lệnh: "chạy container này". Với Swarm, bạn khai báo trạng thái mong muốn (desired state): "tôi muốn luôn có 5 bản của ứng dụng này chạy".
Manager liên tục so sánh trạng thái thực tế với trạng thái mong muốn và tự điều chỉnh. Một worker chết, 2 bản trên đó mất? Manager thấy "đang có 3, cần 5" và tự khởi động 2 bản mới trên node khác. Bạn không phải can thiệp. Khả năng tự phục hồi này là lý do chính người ta dùng orchestration.
Raft: vì sao manager phải đồng thuận
Nếu chỉ có một manager, nó chết là cả cụm mất não. Nên thường có nhiều manager. Nhưng nhiều manager thì phải đảm bảo chúng nhất quán với nhau về trạng thái cụm — không thể mỗi manager nghĩ một kiểu. Swarm giải quyết bằng thuật toán đồng thuận Raft.
Theo tài liệu Docker, Raft dùng để "đảm bảo tất cả các manager node phụ trách quản lý và phân việc đều lưu cùng một trạng thái nhất quán". Cơ chế cốt lõi:
- Các manager bầu ra một leader; leader điều phối, các manager khác sao chép trạng thái.
- Mọi thay đổi trạng thái phải được đa số (quorum) manager đồng ý mới có hiệu lực. Quorum là
(N/2)+1trên tổng N manager. - Nhờ vậy cụm chịu được tối đa
(N-1)/2manager hỏng mà vẫn hoạt động.
Tài liệu nêu ví dụ: cụm 5 manager, nếu 3 manager không khả dụng thì "hệ thống không thể xử lý thêm yêu cầu phân việc" (vì mất quorum). Các task đang chạy vẫn chạy, nhưng không điều phối thêm được.
Vì sao nên dùng số manager lẻ
Đây là hệ quả trực tiếp của công thức quorum. So sánh:
N manager quorum (N/2)+1 chịu hỏng tối đa (N-1)/2
─────────────────────────────────────────────────────
1 1 0
3 2 1
4 3 1 ← tốn hơn mà không hơn 3
5 3 2
7 4 3
Để ý: 4 manager chịu hỏng được đúng 1 — bằng với 3 manager, nhưng tốn thêm một máy. Số chẵn không tăng khả năng chịu lỗi mà còn dễ kẹt quorum. Vì vậy luôn dùng số manager lẻ: thường là 3 (cho cụm nhỏ/vừa) hoặc 5 (cho cụm lớn). Nhiều hơn 7 manager hiếm khi cần và làm Raft chậm đi vì phải đồng bộ nhiều bản.
Worker thì không tham gia Raft, nên thêm bao nhiêu worker cũng được, không ảnh hưởng quorum.
Khởi tạo một swarm
Biến máy hiện tại thành manager đầu tiên:
docker swarm init
Swarm initialized: current node (s48p4l0i2md2...) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-4tvv... 192.168.65.3:2377
Lệnh trả về sẵn câu lệnh để node khác tham gia làm worker, kèm một token và địa chỉ manager (cổng 2377 là cổng quản lý cụm). Trên một máy worker, bạn chỉ việc chạy đúng câu docker swarm join --token ... <manager-ip>:2377 đó.
Xem các node trong cụm:
docker node ls
HOSTNAME STATUS MANAGER STATUS
docker-desktop Ready Leader
Hiện chỉ một node, vừa là manager vừa là leader. Lấy lại token khi cần:
docker swarm join-token worker # token cho worker
docker swarm join-token manager # token cho manager (thêm manager)
Kiểm tra trạng thái swarm:
docker info | grep -A4 Swarm
Swarm: active
Is Manager: true
Managers: 1
Nodes: 1
Làm sao học multi-node khi chỉ có một máy
Phần lớn lệnh Swarm (Bài 11–13) chạy được trên cụm một node — bạn vẫn tạo service, scale, deploy stack được. Nhưng để thấy rõ điều phối giữa nhiều máy (task chia ra node, manager thay node chết), bạn cần nhiều node. Vài cách không tốn server thật:
- play-with-docker.com: môi trường Docker nhiều node chạy thẳng trên trình duyệt, miễn phí, không cài gì. Cách nhanh nhất để nghịch multi-node thật.
- Máy ảo nhẹ: dùng Multipass hoặc VirtualBox dựng vài VM Linux, cài Docker, rồi
swarm join. - VPS giá rẻ: 2–3 máy nhỏ ở nhà cung cấp cloud, thực tế nhất nhưng tốn tiền.
Các bài sau mình demo trên cụm một node (chạy được trên máy bạn) và chú thích phần nào cần nhiều node để thấy rõ.
🧹 Lưu ý dọn dẹp
Ta sẽ giữ swarm hoạt động xuyên suốt Bài 11–13 để thực hành. Phần dọn dẹp tổng (rời swarm) nằm ở cuối Bài 13. Nếu muốn thoát swarm ngay bây giờ:
docker swarm leave --force
(--force cần vì đây là node manager cuối cùng.)
Tổng kết
Docker Swarm gom nhiều node thành một cụm gồm manager (điều phối, giữ trạng thái qua Raft) và worker (chạy task). Bạn khai báo desired state, manager tự giữ cho thực tế khớp với nó — đó là nền của tự phục hồi. Raft đòi hỏi quorum (N/2)+1, nên số manager nên lẻ (3 hoặc 5). docker swarm init tạo manager đầu tiên và cho sẵn token để các node khác tham gia.
Bài 11 ta dùng cụm này để triển khai service: chạy nhiều bản của một ứng dụng, scale lên xuống, và cập nhật phiên bản không gián đoạn.