Trang chủTác giảLiên hệ

[Docker swarm - P2] Tìm hiểu Docker swarm qua các ví dụ đơn giản

By Nguyễn Thanh Sơn
Published in Docker
June 09, 2021
6 min read

Bài viết này yêu cầu bạn cần nắm được các khái niệm cơ bản về Docker swarm trước. Các khái niệm đó mình đã viết ở phần 1.

Trong bài viết này, mình sẽ hướng dẫn các bạn cách để tạo 1 docker swarm, làm thế nào để add node vào swarm cũng như deploy service lên các node đó.

Setup môi trường

Trong bài viết này mình sẽ sử dụng 3 instance EC2 để làm docker host tương ứng với 3 node trong swarm. Nếu máy local đủ khỏe, có thể dùng docker-machine để tạo máy ảo 3 máy ảo để thao tác ở local luôn cũng được.

Role in SwarmPublic IPPrivate IP
Manager54.251.177.177172.31.27.110
Worker113.229.130.20172.31.30.109
Worker252.221.190.233172.31.20.119

Tất cả các node đều cần phải cài đặt docker engine. Nếu dùng docker-machine tạo máy ảo thì mặc định docker engine đã được cài đặt sẵn.

Đảm bảo các port sau được mở trên tất cả các node

TCP/UDPPortMục đính
TCP2377Quản lý cluster
TCP & UDP7946Giao tiếp giữa các node
UDP4789Overlay network

Khái niệm Overlay network có thể hiểu đơn giản một network có tên ingress, được tạo đồng thời khi khởi tạo swarm, các container hoặc service trong swarm sẽ sử dụng overlay network để giao tiếp với nhau.

Tạo swarm

Run command docker swarm init trên docker host bạn muộn chọn làm manager node để tạo swarm, ở đây mình chọn host có private IP là 172.31.27.110:

Output của command sẽ trả về một command khác dùng để join swarm với role là worker.

Nếu như bạn để ý sẽ thấy IP address của manager node trong join command chính là private IP. Điều này có nghĩa với command join trên, ta chỉ có thể add với các node trong cùng mạng LAN vào swarm. Tuy nhiên nếu manager node cho phép public access, ta hoàn toàn có thể add một node ở ngoài mạng LAN vào swarm bằng cách dùng public IP thay cho private IP

Thêm node vào swarm

Để add một node vào swarm với role là worker, run command từ output của docker swarm init trên docker host bạn muốn add vào swarm

Nếu như bạn không lưu lại output của command init swarm, bạn hoàn toàn có thể lấy lại bằng cách run comman docker swram join-token worker trên manager node

Để lấy token join swarm với role là manager, run command sau trên manager node:

Để list danh sách các node trong swarm, run command docker node ls trên manager node. Đây là output của mình sau khi add 2 node Worker1Worker2 vào swarm

Output bao gồm một số thông tin như trạng thái của từng node, phân biệt manager và worker, Docker engine version của từng node

Deploy service lên swarm

Như đã nói ở bài viết trước, tất cả các thao tác liên quan đến quản lý service hoàn toàn được thực hiện trên manager node, ta không cần thao tác trực tiếp trên các worker node.

Trước tiên ta sẽ tạo một replicated services đơn giản:

Command bao gồm một số thành phần sau:

  • docker service create đây chính là command khỏi tạo 1 service
  • Flag --replicas chỉ định số replicas hay còn gọi là số task của service sẽ được deploy, ở đây mình set là 1
  • Flag --name dùng để set tên cho service, ở đây là helloworld
  • alpine ping docker.com là tham số định nghĩa cho service sẽ tạo container từ image alpine và run command ping docker.com bên trong container đó

Run command docker service ls để list danh sách các service hiện có của swarm:

Kiểm tra thông tin một service trong swarm

Để show thông tin chi tiết về một service, run command docker service inspect <SERVICE-ID | SERVICE-NAME>

Flag --pretty để set output với format dễ đọc hơn. Nếu ko có flag này, output sẽ trả về dưới dạng json

Các thông tin cần chú ý ở đây đó là Service ModeContainerSpec

  • Service Mode: Thông tin về deploy model của service. Như đã nói ở bài trước, ta có thể deploy service với 2 model đó là ReplicatedGlobal
  • ContainerSpec: Thông tin liên quan tới image và command được config khi tạo service

Các thông tin về UpdateConfigRollbackConfig mình sẽ giải thích ở phần sau

Để kiểm tra danh sách task của một service, run command sau:

Scale service

Sau khi tạo service, chúng ta hoàn toàn có thể thay đổi số lượng container (hay còn gọi là task) của một service. Như ban đầu mình đã tạo service helloworld với duy nhất 1 container.

Bây giờ hãy kiểm tra số lượng task của service để xem thay đổi ra sao.

Có thể thấy đã có thêm 4 task mới được add vào service, các task này được phân chia cho toàn bộ các node trong swarm chứ không chỉ deploy lên 1 node duy nhất.

Delete service

Ta có thể kiểm tra lại list service trong swarm

Kết quả là service helloworld đã bị xóa khỏi swarm. Tuy service đã bị xóa nhưng các task (container) của service vẫn cần một vài giây để có thể xóa hoàn toàn. Nếu run docker ps ngay sau khi xóa service, ta vẫn có thể thấy các container của service đã bị xóa trong danh sách.

Rolling update service

Đầu tiên, tạo một service mới trước

Command tạo một service với các setting như sau:

  • Service name: redis
  • Số replica (task): 3
  • Set thời gian delay --update-delay: thời gian delay giữa mỗi lần update 1 hoặc 1 set các task, trong trường hợp này là 10 giây
  • Service sử dụng image redis với tag là 3.0.6

Ở section UpdateConfig, có 2 param còn chú ý

  • Parallelism: Giới hạn số lượng task update đồng thời, default là 1. Để update tất cả các task trong service đồng thời, set giá trị cho tham số này bằng 0 với flag --update-parallelism
  • Delay: chính là thời gian giữa các lần update task được set bởi flag --update-delay
  • On failure: Action nếu như gặp lỗi trong quá trình update
    • pause (default): Dừng việc update
    • continue: Tiếp tục update
  • Update order: Trình tự khi update service:
    • stop-first (default): Stop task cũ trước rồi thực hiện start task mới
    • start-first: Start task mới trước rồi thực hiện stop task cũ

Tiếp theo ta sẽ update image của service lên redis:3.0.7

Khi chạy thực tế, bạn sẽ thấy có 1 khoảng thời gian delay giữa mỗi lần deploy task.

Với command docker service ps, ta có thể xem lịch sử update của từng task

Rollback service

Ở vị dụ trước ta đã update image của service từ redis:3.0.6 lên redis:3.0.7. với command rollback, ta có thể revert service về trạng thái thước đó.

Ý nghĩa của các param trong RollbackConfig cũng có ý nghĩa tương tự như của UpdateConfig nên mình sẽ không nói thêm ở đây nữa. Đây là lịch sử các task của service redis sau khi rollback

Drain a node

Để đỡ rối thì mình sẽ xóa service redis hiện và tạo lại với config tương tự trong ví dụ trên.

Trước tiên hãy kiểm tra lại tình trạng các node trong swarm

Ở đây có 1 cột ta cần chú ý đó là AVAILABILITY. Cột này thể hiện tình trạng sẵn sàng nhận task từ manager hay không.

Mặc định khi add node vào swarm, node sẽ run với trạng thái availability là Active. Điều đó có nghĩa manager có thế assgin task cho node.

Để ngăn node có thể nhận task từ swarm manager, ta có thể set availability của node về Drain.

Trước khi drain 1 node, cùng kiểm tra lại các task trong swarm để thấy sự khác biệt giữa trước và sau khi drain node

Tiếp theo mình sẽ drain node Worker1

Trạng thái AVAILABILITY của node Worker1 đã thay đổi tử Active sang Drain

Tiếp theo chúng ta sẽ kiểm tra đến tình trạng các task trong swarm

Ta có thể thấy, ngoài việc set lại trạng thái AVAILABILITY của node, swarm manager còn stop các task đã được assign cho node đó và assign sang cho một Active node khác trong swarm.

Routing mesh

Docker nói chung và Docker Swarm nói riêng đều cho phép publish port cho các service để có thể access được từ bên ngoài swarm.

Với routing mesh, tất cả các node đều có thể accept connect trên các port được publish ngay cả khi không có task nào assign cho node đó. Routing mesh sẽ forward request tới node có container chịu trách nhiệm xử lý request trên port được publish.

Để dễ hình dung, mình sẽ tạo 1 service run image nginx với 2 replica trên swarm có 3 node. Như vậy sẽ chỉ có 2 node được assign task.

Ở command trên, ngoài việc tạo service run nginx, nó còn thực hiện publish port 8080 và map với port 80 của container. Các bạn có thể tìm đọc về port mapping của docker để hiểu rõ hơn.

Task được assign cho 2 node ManagerWorker2. Bây giờ hãy thử access Worker1 bằng public IP qua port 8080 trên web browser. ![alt text](/uploads/c740/2cbb/Screen Shot 2020-05-11 at 17.57.30.png)

Có thể thấy, mặc dù không hề có task nào được assign cho Worker1, nhưng ta vân có thể access web server thông qua địa chỉ IP của nó.

Tạo global service

Trước khi tạo global service, mình sẽ remove Worker1 ra khỏi swarm.

Mặc định service sẽ run với mode Replicated. Để tạo Global service, ta cần set giá trị cho flag --mode trong command create service

Trong swarm manager sẽ tạo số task bằng với số active node ở trong swarm, mỗi task sẽ được assign cho 1 node.

Sau đó mình sẽ add lại Worker1 vào swarm

Kiểm tra lại danh sách task của service

Ta thấy swarm manager sẽ tự động tạo và assign task mới cho node mới join vào swarm.

Kết

Hy vọng thông qua các ví dụ đơn giản trên, các bạn có thể nắm được cách thức hoạt động của Docker swarm.

Trong thực tế, một application sẽ được cấu thành từ nhiều service khác nhau hay còn gọi là một stack các service. Ví dụ như một web application sẽ có các service như web server, database, caching system, …

Trong phần tiếp theo, mình sẽ hướng dẫn các bạn các để deploy một stack lên Docker swarm. Hẹn gặp lại các bạn trong bài viết tiếp theo.


Nguyễn Thanh Sơn

Developer

Related Posts

Docker
[Docker swarm - P3] Deploy một stack lên docker swarm
June 09, 2021
3 min
© 2021, All Rights Reserved.

Quick Links

Liên hệ quảng cáoThông tinLiên hệ

Social Media