Docker Swarm là gì

Khi một cụm các máy (cluster) cùng chạy Docker Engine tập hợp lại kết nối với nhau nó hình thành nên một Docker Swarm, mỗi máy này có thể là một máy vật lý thật, VPS hay là máy ảo tự tạo.

Biến cụm máy thành một Swarm trải qua các bước như sau:

  • Một máy trong cụm máy ra lệnh chuyển nó chạy ở chế độ Swarm (swarm mode), lập tức nó trở thành một nút node trong swarm, do máy này khởi tạo đầu tiên trên swarm nên nó nắm quyền kiểm soát toàn bộ swarm và nó gọi là manager, vì là manager nên chỉ có nó mới có quyền khởi tạo các dịch vụ (ứng dụng) chạy trên swarm, quyền xóa một nút khác ra khỏi swarm.
  • Các máy chạy Docker Engine khác gia nhập vào swarm nhờ một lệnh xin ra nhập, và khi trở thành một node của swarm nó gọi là các worker node, nó chỉ có khả năng cung cấp khả năng chạy các dịch vụ chứ không có quyền quản lý, các dịch vụ chạy trên node này do node manager ra lệnh và quản lý.
  • Khi sử dụng swarm, chủ yếu làm việc ở node manager để tạo và chạy các dịch vụ (ứng dụng), các dịch vụ khởi tạo từ node manager sẽ tạo ra nhiều container ở nhiều node worker (kể cả chạy ở node manager) khác nhau.

Thực hành tạo Docker Swarm

Tạo các máy ảo Docker Machine

Để tạo swarm cần có các máy trên đó có chạy Docker (Docker Deamon), sẽ nhiều người chưa có vài 3 server (hay VPS) thực thụ từ các DataCenter để thực hành, nên sẽ tạo ra máy ảo Docker Machine. (Trước tiên xem phần Docker Machine)

Tiến hành tạo 3 máy ảo Docker Machine đặt tên là vps1, vps2, vps3 (các máy ảo này dùng công cụ Virtualbox để tạo máy áo, trong các máy ảo Docker Machine thì Docker Daemon đã có sẵn)

docker-machine create --driver virtualbox vps1
docker-machine create --driver virtualbox vps2
docker-machine create --driver virtualbox vps3

Sau khi tạo nó có địa chỉ IP tương ứng là 192.168.99.117 (vps1), 192.168.99.120 (vps2), 192.168.99.119 (vps3), có thể xem bằng lệnh liệt kê máy ảo:

docker-machine ls 
NAME   ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER     ERRORS
vps1   -        virtualbox   Running   tcp://192.168.99.117:2376           v19.03.0
vps2   -        virtualbox   Running   tcp://192.168.99.120:2376           v19.03.0
vps3   -        virtualbox   Running   tcp://192.168.99.119:2376           v19.03.0

Các IP này có thể là khác trên hệ thống của bạn, nên hãy lưu ý áp dụng đúng IP tương ứng với từng máy vps1, vps2, vps3

Tạo Swarm với 3 node - vps1, vps2, vps3

vps1 ấn định là node manager, nên tại VPS1 (vào bằng lệnh docker-machine ssh vps1) gõ lệnh sau để tạo swarm

docker swarm init --advertise-addr=192.168.99.117

Chú ý địa chỉ IP chính là IP của vps1, sau lệnh này nó có thông báo:

Swarm initialized: current node (sfysjr8wstldv2wrmgqcrpozt) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-5xv7z2ijle1dhivalkl5cnwhoadp6h8ae0p7bs5tmanvkpbi3l-5ib6sjrd3w0wdhfsnt8ga7ybd 192.168.99.117:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Đoạn mã:
docker swarm join --token SWMTKN-1-5xv7z2ijle1dhivalkl5cnwhoadp6h8ae0p7bs5tmanvkpbi3l-5ib6sjrd3w0wdhfsnt8ga7ybd 192.168.99.111:2377
được dùng để ở một máy chạy docker khác xin ra nhập vào swarm!

Như vậy hiện giờ đang có swarm, với node quản trị là ở máy VPS1. Giờ nếu liệt kê xem swarm có các node nào (có các máy nào tham gia) thì dùng lệnh (đang trong vps1):

docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
sfysjr8wstldv2wrmgqcrpozt *   vps1                Ready               Active              Leader              18.09.5

Thấy có một node, với quền manager (Leader).

Bây giờ hãy ssh vào vps2 và vps3 gõ lệnh sau để ra nhập swarm! lệnh docker swarm join kèm mã token do node manager cung cấp ở trên.

docker swarm join --token SWMTKN-1-5xv7z2ijle1dhivalkl5cnwhoadp6h8ae0p7bs5tmanvkpbi3l-5ib6sjrd3w0wdhfsnt8ga7ybd 192.168.99.117:2377

Sau đó ssh vào vps1 gõ kiểm tra

docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
sfysjr8wstldv2wrmgqcrpozt *   vps1                Ready               Active              Leader              18.09.5
z4i90rojpknedxn52aa764k38     vps2                Ready               Active                                  18.09.5
7vdibj6lfdma874qc05tiuhr3     vps3                Ready               Active                                  18.09.5

Giờ thì trong swarm đã có 3 node (3 máy) kết nối với nhau, dưới sự quản lý của node ở máy VPS1.

Thực hành chạy dịch vụ Docker Swarm

Các dịch vụ chạy trên Swarm thì nó sẽ tạo ra các container từ các Image, ở đây có xây dựng sẵn các ứng dụng đạng lưu ở Hub Docker, đó là các ứng dụng chạy bằng Node, DotNet, PHP với tên Image tương ứng trên Hub Docker là ichte/swarmtest:node, ichte/swarmtest:dotnet, ichte/swarmtest:php (swarmtest). Xây dựng sẵn để các Node trong Swarm có thể pull về khí nó cần.

Chạy dịch vụ đầu tiên:

docker service create --replicas 5 -p 8085:8085 --name testservice ichte/swarmtest:node

Lệnh trên tạo ra một dịch vụ đặt tên là testservcie --name testservice, nó tạo 5 container trên swarm cho dịch vụ này --replicas 5, các container tạo từ Image ichte/swarmtest:node, có ánh xạ cổng qua tham số -p

Một số lệnh quản lý, cập nhật, scale dịch vụ (lệnh thi hành trên node manager)

# Liệt kê các service trên swarm
docker service ls

# Liệt kê các container cho dịch vụ có tên testservice
docker service ps testservice

# Kiểm tra log cho dịch vụ testservice
docker service logs testservice

# Scale - thay đổi số container cho dịch vụ testservice đang chạy thành n (1, 2, 3 ...) container
docker service scale testservice=n

# Cập nhật thiết lập cho dịch vụ testservice đang chạy
# - Thay đổi Image
docker service update --image=ichte/swarmtest:php testservice
# - Thay đổi tài nguyên CPU, MEM
docker service update --limit-cpu="0.5"  --limit-memory=150MB testservice
# - Các cập nhật khác update service

# Xóa dịch vụ testservice
docker service rm servicename

Lệnh docker stack

Lệnh docker stack để quản lý các dịch vụ chạy trên swarm, các thành phần của dịch vụ đó được mô tả trong file docker-compose.yml

Mạng Overlay trên Docker Swarm

Mạng mà các container chạy trên swarm kết nối vào là loại mạng overlay, mạng này kết nối các docker host lại với nhau, xem chi tiết video sau:

Các ổ đĩa - volume trên swarm

Để chia sẻ dữ liệu giữa các container chạy trên node khác nhau cần dùng đến các loại ổ đĩa mạng bằng các giao thức như nfs, smb, ssh ..., xem chi tiết video sau:

Đọc thêm - Tạo Registry riêng sử dụng bởi Swarm

B1) Chuẩn bị một image để kiểm tra

Mục đích để khởi chạy dịch vụ (sinh ra các container) từ image này. Image này sẽ tạo ra từ image cơ sở httpd:latest, khi chạy gọi đến cổng 8888 nó hiện thị hostname của container. Trước tiên tạo ra thư mục máy host /mycode/swarm (thư mục này phải chia sẻ quyền truy cập cho Docker - File Sharing) để chứa dữ liệu chuẩn bị. Trong này tạo ra các file sau:

Chạy lệnh sau để trích xuất httpd.conf của httpd ra thư mục trên để chỉnh sửa:

docker run --rm -v /mycode/swarm/:/home/ httpd:latest cp /usr/local/apache2/conf/httpd.conf /home/httpd.conf

Mở file httpd.conf (code /mycode/swarm/httpd.conf) trích xuất được chỉnh sửa các mục sau:

#kích hoạt CGI để chạy script sh bằng HTTPD

LoadModule cgid_module modules/mod_cgid.so
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
    Options Indexes FollowSymLinks ExecCGI
    AddHandler cgi-script .cgi .pl
    AllowOverride None
    Require all granted
</Directory>

Tiếp theo tạo một file test.pl (code /mycode/swarm/test.pl) có nội dung :

#!/usr/bin/env sh
echo "Content-type: text/plain"
echo ""

cat /proc/sys/kernel/hostname

File này là một script sh (bash) sẽ copy vào /usr/local/apache2/htdocs của Apache HTTPD, khi Apache gọi nó, nó trả về tên hostname của container (Hostname Linux). Vì hostname này là khác nhau ở các container khác nhau, điều này sau này giúp nhận biết được container nào chạy! Bạn sẽ phát hiện ra một dịch vụ được đảm nhận bởi nhiều container chạy trên swarm

Tạo file Dockerfile (code /mycode/swarm/Dockerfile) để xây dựng Image (Image để khởi chạy các container cho dịch vụ trên swarm) với nội dung như sau:

FROM httpd:latest
Add ./httpd.conf /usr/local/apache2/conf/httpd.conf
Add ./test.pl /usr/local/apache2/htdocs/test.pl
RUN chmod +x /usr/local/apache2/htdocs/test.pl

B2) Tạo registry kho chứa Image riêng dùng cho vps1, vps2, vps3

Sẽ chạy một Registry riêng ở máy vps1, kho này sẽ có địa chỉ 192.168.99.117:5000 (Trên hệ thống của bạn áp dụng theo đúng IP của VPS1)

Vào trong vps1 bằng lệnh:

docker-machine ssh vps1

Tạo và chạy kho chứa riêng Registry:

docker run -d -p 5000:5000 --name registry --restart always registry:2.7

Sau đó biên tập file /etc/docker/daemon.json

sudo vi /etc/docker/daemon.json

Trong file này có nội dung sau:

{
    "insecure-registries" : ["192.168.99.117:5000"]
}

Lưu lại, exit ra khỏi vps1 và gõ lệnh sau để khởi động lại máy ảo vps1

docker-machine restart vps1

Bạn cũng ssh vào vps2, vps3 rồi biên tập /etc/docker/daemon.json trong 2 máy này với nội dung như trên, sau đó khởi động lại vps2, vps3

Tạo image có tên 192.168.99.117:5000/httpdtest:latest từ Dockerfile ở trên

Lưu ý đặt tên (Tag) image

Để đảm bảo Image được Push (đẩy lên) đúng kho chứa (Registry) riêng cần lưu ý về cách thiết lập tên (tag) cho Image như sau:

Tên image theo cấu trúc: [HOSTNAME]/[PROJECT-ID]/[IMAGE]

  • [HOSTNAME] địa chỉ HOST của kho lưu trữ (gồm cả port nếu cần). Ví dụ 192.168.99.117:5000 hoặc myregistry.com:5000, nếu tên không có thành phần này coi như mặc định Registry là tại https://hub.docker.com (kho này bạn chỉ tạo được một Image riêng, còn lại phải public trừ khi bỏ tiền mua thêm).
  • [PROJECT-ID] bạn có thể đặt một tên dự án ví dụ dự án myproject để tập hợp các Image thuộc về dự án này. Thành phần này có thể không cần thiết
  • [IMAGE] tên của Image, theo nguyên tắc gồm dịnh-danh:tag ví dụ httpdtest:latest

Với nguyên tắc trên, một image có tên đầy đủ: 192.168.99.111:5000/httpdtest:latest thì khi push nó đấy lên địa chỉ 192.168.99.111:5000, tương tự pull nó cũng tìm từ địa chỉ 192.168.99.111:5000

Đầu tiên copy các file trong /mycode/swarm vào thư mục /home/data của vps1

docker-machine scp -r /mycode/swarm/ vps1:/home/data/

Sau đó vào vps1 tiến hành tạo Image từ Dockerfile

docker-machine ssh vps1
cd /home/data/
docker build -f Dockerfile . -t 192.168.99.117:5000/httpdtest:latest

Sau khi image được tạo, đẩy nó lên Registry

docker push 192.168.99.117:5000/httpdtest:latest

B3) Chạy thử dịch vụ trong swarm

Tại node manager (VPS1) chạy dịch vụ từ image 192.168.99.117:5000/httpdtest:latest có ánh xạ cổng 8888 vào 80 của các container, nó là máy chủ apache httpd, khi chạy truy cập script test.pl sẽ trả về hostname của container.

docker service create --replicas 5 -p 8888:80 --name website 192.168.99.117:5000/httpdtest:latest
curl http://192.168.99.117:8888/test.pl?[1-5000]s

Trước khi chạy bạn có thể dùng lệnh sau trong vps1, docker service logs website -f để quan sát xem container nào đạng phục vụ cho truy vấn hiện tại

Swarm có nhiều Node Manager

Ở trên bạn đã tạo ra một Swarm với 1 node vài trò manager (vps1) và 2 node worker (vps3, vps2). Trong tình huống này, nếu node manager bị lỗi dẫn tới toàn bộ swarm không hoạt động. Trong tình huống đề phòng, bạn có thể đề xuất vps2, vps3 cũng có vai trò Manager, nếu node manager chính (vps1) chết, hệ thống tự động kích hoạt vps2 là node manager ...

Để làm điều đó, bạn chỉ việc thực hiện lệnh tại node manager đang hoạt động, lệnh này là đề xuất vps2 sẽ là node manager nếu vps1 die.

Tại vps1 bạn gõ lệnh

docker node promote NODEID

Trong đó NODEID là ID của Node cần đề xuất trở thành Manager, giả sử vps2 có ID là 8gh99fdy6vup0yjyaz9m5ucr5, (lấy được từ lệnh docker node ls), thì bạn gõ

docker node promote 8gh99fdy6vup0yjyaz9m5ucr5

Từ giờ thì node vps2 cũng có vai trò Manager, nó sẽ thay thế cho vps1 nếu vps1 không còn hoạt động ...


Đăng ký nhận bài viết mới