Deploy web app với Traefik và Docker Swarm
Bài đăng này đã không được cập nhật trong 2 năm
Giới thiệu chung
Tiếp tục với chủ đề Traefik, hôm nay mình sẽ làm một bài demo nho nhỏ deploy Traefik trong Swarm mode. Nếu bạn chưa biết Traefik là gì, hãy đọc bài viết Tổng quan về Traefik của mình trước nhé. Bài viết hôm nay sẽ sử dụng các kiến thức sau:
- Cơ bản về traefik + docker
- Docker Swarm cơ bản
- Docker Machine + Virtualbox
Bài viết này sử dụng Ubuntu làm hệ điều hành, các bạn đọc bài này nếu thực hiện trên môi trường khác lưu ý giúp mình nhé. Nội dung tổng quan bài viết mình sẽ đi vào giới thiệu qua về Docker Swarm, Docker Machine. Sau đó mình bắt tay vào thực hành infrastructure với Docker, Traefik và Swarm mode. Giúp bạn scale service web.
- Dựng các VPS ảo trên máy local với Docker Machine
- Thiết lập Swarm mode cho các VPS ở trên
- Deploy Traefik + web service trong swarm mode
Docker Swarm là gì?
Chúng ta sẽ giả thuyết rằng ta có 3 con VPS mỗi còn này có một IP address của riêng nó. Tất cả các VPS sẽ hỗ trợ load balancer cho nhau và cùng phục vụ một cho chung một hệ thống web. Chúng ta chỉ cần thực hiện các lệnh deploy với docker trên một con VPS chính (tạm gọi là manager), nó sẽ quản lý những con VPS còn lại (gọi nó là worker). Vậy làm sao để làm được như vậy? Chúng ta sẽ cần nhờ tới sự trợ giúp đắc lực của Docker Swarm. Khi bật Swarm mode, chúng ta có thể gom nhóm các VPS lại các cụm máy chủ, mình gọi là clusters hay swarm clusters - bao gồm một server manager và các workers đi kèm.
Nếu chỉ có một VPS, chúng ta vẫn có thể chạy docker ở Swarm mode được. Manager lúc này sẽ đảm nhiệm mọi thứ. (worker = 0)
Như vậy, Docker Swarm sẽ giúp mình nhóm các máy chủ lại và thực hiện lệnh chỉ trên server manager, những server worker cũng sẽ thay đổi theo. Nó quá hữu ích khi ta muốn scale hệ thống khi bạn muốn tăng thêm hay giảm đi số lượng container của một service.
Không chỉ vậy, Docker Swarm còn giúp bạn thực hiện load balancing. Tất các các cluster đều được đặt trong một network gọi là ingress network. Routing mesh của swarm như hình trên, sẽ đưa tất cả các request sẽ đi qua ingress network tới Swarm Loadbalancer, bộ balancer này sẽ phân bổ request tới các container của các service ở các server (cả manager + worker) cùng chung một mạng swarm.
Các khái niệm trong Swarm
Trong Swarm có một số khái niệm mà bạn cần nắm được gồm:
- Container: Cái này bạn biết khi tìm hiểu docker rồi ha. Một container là một instance của docker image khi được chạy.
- Service: Một thành phần khác nhau của một ứng dụng được gọi là service. VD: Storage service để lưu trữ, Redis service để cache... Một service sẽ đẩm nhiệm một vai trò riêng ứng với một docker image. Vậy nên, khi run, service sẽ là tập hợp các containers đảm nhiệm một vai trò riêng: storage service, redis, mysql... Chúng ta dùng service để scale số lượng containers cần chạy của nó.
- Stack: Chúng ta tập hợp nhiều service liên quan đến nhau phối lại tạo ra một stack. Khác với service, stack sẽ điều phối tất cả các thành phần của toàn bộ ứng dụng. (Vì stack quản lý tập các service mà)
- Node: Một host hay vps của chúng ta join vào cùng một mạng swarm sẽ được gọi là một node. Node này có role là manager hoặc worker. Trong đó, manager là node chính dùng để khởi tạo swarm, thực hiện các lệnh thay đổi, các worker sẽ thay đổi service theo các lệnh được thực hiện trên manager.
Việc chia để trị app thành nhiều thành phần: service, stack cũng giống như việc phân cấp bộ máy quản lý của một công ty sẽ giúp chúng ta dễ quản lý app hơn khi scale, hay khi theo dõi uptime của các service... Các bạn có thể tìm hiểu thêm các bài viết khác về Docker trên Viblo để hiểu sâu hơn.
Docker Machine
Docker Machine là một tool trong docker platform, nó thực sự quá hữu ích cho việc học tập về docker, docker swarm. Bởi lẽ, nó giúp ta giả lập các server để thực hành các kiến thức đã học. Docker Machine cung cấp một bộ cli api giúp chúng ta tạo và quản lý các server ảo dễ dàng. Các bạn đọc thêm và cài đặt theo hướng dẫn tại đây.
Mình sẽ dùng docker machine để tạo 3 hosts (vps) ảo trên máy local để thực hành các kiến thức về swarm mà không cần các host thật. Mình sẽ dùng driver Virtualbox để tạo các machine (hay host ảo). Một số command cơ bản được sử dụng gồm:
- Tạo một machine
> docker-machine create --driver virtualbox machine_name
- SSH vào một machine
> docker-machine ssh machine_name
- Xem ip của một machine
> docker-machine ip machine_name
- Xem danh sách machine đang có
> docker-machine ls
Thực hành với swarm
Tạo các machine
Chúng ta sẽ tạo một machine đóng vai trò là manager, 2 machines với vai trò là worker. Thao tác lệnh docker-machine như sau:
> docker-machine create --driver virtualbox manager
> docker-machine create --driver virtualbox worker1
> docker-machine create --driver virtualbox worker2
Việc tạo sẽ tốn ít phút. Sau đó, hãy kiểm tra lại bằng việc xem danh sách machines:
> docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
manager - virtualbox Running tcp://192.168.99.100:2376 v18.09.0
worker1 - virtualbox Running tcp://192.168.99.101:2376 v18.09.0
Chúng ta dễ thấy trạng thái running của chúng và ip mà chúng được trỏ vào.
Khởi tạo Swarm
Bạn thấy ở trên, ip con máy manager của mình là 192.168.99.100
. Bây giờ active swarm mode bằng việc SSH vào manager thực hiện lệnh khởi tạo.
Các SSH như sau:
> docker-machine ssh manager
SSH xong chúng ta khởi tạo swarm với ip là IP của con manager:
> docker swarm init --advertise-addr 192.168.99.100
Swarm initialized: current node (rh9krtfftxhjvb25t7k6y8gxs) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0t08e9l15ta4refv1y7jms78er7iguz8wsdrdjunkitylh5wrf-63zl0jxp7retpn7ov6sequk3e 192.168.99.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Thông báo chỉ ra rằng chúng ta tạo thành công, để thêm các worker vào swarm thì chạy command join với cái join-token
nó đưa cho. Nếu bạn lỡ xóa terminal hoặc quên, thì bạn có thể xem lại join-token cho worker bằng cách thực hiện lệnh sau trên manager:
> docker swarm join-token worker
docker swarm join --token SWMTKN-1-0t08e9l15ta4refv1y7jms78er7iguz8wsdrdjunkitylh5wrf-63zl0jxp7retpn7ov6sequk3e 192.168.99.100:2377
Nếu muốn join vào swarm dưới dạng một manager nữa thì:
> docker swarm join-token manager
docker swarm join --token SWMTKN-1-0t08e9l15ta4refv1y7jms78er7iguz8wsdrdjunkitylh5wrf-71idqhdh53pmw66xzk86iqz49 192.168.99.100:2377
Sau tất cả, việc còn lại để join các worker vào swarm chỉ là SSH vào từng woker và chạy command join vừa lấy vừa rồi.
> docker swarm join --token SWMTKN-1-0t08e9l15ta4refv1y7jms78er7iguz8wsdrdjunkitylh5wrf-63zl0jxp7retpn7ov6sequk3e 192.168.99.100:2377
Để kiếm tra xem bạn đã active swarm mode thành công chưa, hãy chạy lệnh:
> docker info
...
Swarm: active
NodeID: rh9krtfftxhjvb25t7k6y8gxs
Is Manager: true
ClusterID: wa5yunqrzc1rnuuw32ndqumda
Managers: 1
Nodes: 2
Default Address Pool: 10.0.0.0/8
SubnetSize: 24
....
Bạn để ý sẽ thấy một đoạn Swarm như bên trên. Trong đó hiện rõ: Swarm: active
kèm các thông tin khác như số Manager, số Node đang có (mỗi Node tương ứng với một host).
Xem danh sách các node đang có trong Swarm bằng cách thực hiện lệnh trên manager:
> docker node ls
Deploy stack và service
Vì traefik các bạn có thể sử dụng để làm reverse-proxy cho nhiều services của nhiều app trên cùng một server. Nên chúng ta sẽ tách nó thành một stack riêng biệt không đụng trạm gì tới bọn khác.
Như vậy, trong bài này chúng ta sẽ có hai stack cơ bản gồm:
reverse-proxy
: Chứa traefik service, làm reverse proxy.web
: Chứa web service để chúng ta test. Service này mình sẽ dùng imagecontainous/whoami:latest
đã dùng trong bài trước Traefik + Let's Encrypt tự động tạo SSL miễn phí.
Trong bài này, và cả trọng thực tế, để ngắn gọn dễ quản lý, mọi người thường sử dụng syntax củadocker-compose
để tạo file định nghĩa cho các stack. Lưu lại và dùng ở các lần thay đổi sau khi cần.
Reverse-proxy stack
Tạo file reverse-proxy.yml
định nghĩa reverse-proxy
stack:
version: '3.5'
services:
traefik:
image: traefik:1.7
command:
- --docker
- --docker.swarmMode
- --docker.exposedByDefault=false
- --docker.watch
- --docker.domain=traefik.lc
ports:
- 80:80
networks:
- reverse-proxy-net
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
placement:
constraints:
- node.role==manager
labels:
- "traefik.enable=true"
- "traefik.docker.network=reverse-proxy-net"
- "traefik.port=8080"
- "traefik.frontend.rule=Host:traefik.lc"
networks:
reverse-proxy-net:
name: reverse-proxy-net
driver: overlay
Stack trên define một service traefik, service này có constraint (ràng buộc) là chỉ deploy trên node là manager. Dashboard của traefik mình chạy dưới domain traefik.lc
. Bây giờ chỉ cần deploy stack bằng lệnh sau:
> docker stack deploy -c reverse-proxy.yml reverse-proxy
Creating network reverse-proxy-net
Creating service reverse-proxy_traefik
Khi update lại stack, bạn chỉ cần sửa file yml rồi chạy lại lệnh deploy bên trên để docker update lại stack.
Kiểm tra lại:
> docker stack ls
NAME SERVICES ORCHESTRATOR
reverse-proxy 1 Swarm
> docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
1zhia5gfdf6d reverse-proxy_traefik replicated 1/1 traefik:1.7 *:80->80/tcp
Web stack
Bây giờ, deploy web stack, mình sẽ định nghĩa stack đơn giản như sau web.yml
:
version: '3.5'
services:
web-app:
image: containous/whoami:latest
networks:
- reverse-proxy-net
- web-net
labels:
- "traefik.enable=true"
- "traefik.docker.network=reverse-proxy-net"
deploy:
replicas: 4
networks:
reverse-proxy-net:
external: true
web-net:
name: web-net
driver: overlay
Trong đó, mình sẽ tạo service web-app
, chạy dưới domain whoami.lc
port 80. Kết quả:
> docker stack deploy -c web.yml web
Creating network web-net
Creating service web_web-app
> docker stack ls
NAME SERVICES ORCHESTRATOR
reverse-proxy 1 Swarm
web 1 Swarm
> docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
1zhia5gfdf6d reverse-proxy_traefik replicated 1/1 traefik:1.7 *:80->80/tcp
5iv47pz3ivaf web_web-app replicated 4/4 containous/whoami:latest
> docker service ps 5iv47pz3ivaf
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
wymsgq2eskep web_web-app.1 containous/whoami:latest manager Running Running 3 minutes ago
llnzx1nn7x5z web_web-app.2 containous/whoami:latest worker1 Running Running 3 minutes ago
cmeeybax15il web_web-app.3 containous/whoami:latest manager Running Running 3 minutes ago
b9k916yii2ye web_web-app.4 containous/whoami:latest worker1 Running Running 3 minutes ago
Mình tạm thời đang tắt thằng worker2 cho máy đỡ nặng (laptop hơi cùi mọi người thông cảm). Chúng ta có thể thấy, swarm sẽ tự động phân bổ 4 container của web app vào 2 machine đang có là manager và worker1. Mỗi machine 2 container.
Kiểm tra kết quả web-app
- Cách 1: dùng lệnh trên máy thật nha các bạn (không phải trong machine của docker-machine):
> curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
- Cách 2, dùng browser:
Các bạn thêm domain ảo là traefik.lc
và whoami.lc
vào /etc/hosts
để DNS và có thể truy cập từ browser như Chrome, Firefox để xem kết quả. Domain trỏ vào ip của machine manager.
192.168.99.100 traefik.lc whoami.lc
Cả hai cách đều cho kết quả có dạng:
Hostname: f3138d15b567
IP: 127.0.0.1
IP: 10.0.0.5
IP: 10.0.0.4
IP: 172.18.0.3
GET / HTTP/1.1
Host: whoami.lc
User-Agent: curl/7.55.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami.lc
X-Forwarded-Proto: http
X-Forwarded-Server: 77fc29c69fe4
Trong đó, hostname các bạn sẽ thấy hostname thay đổi theo hostname của container mà nó được swarm load balancer đến. Việc share dữ liệu giữa các server về file storage, các bạn dùng NFS (network file system với linux), với session, cache, các bạn dựng thêm service redis để làm trung gian trung chuyển nhé!
Bài viết của mình tới đây là kết thúc. Xin cảm ơn các bạn đọc đã quan tậm. Mọi đóng góp, thắc mắc hay khích lệ cho bài viết vui lòng thả một comment xuống bên dưới giúp mình. Đừng quên upvote/clip bài... hay chia sẻ tới mọi người xung quanh trên facebook nhé.
Bài viết tiếp theo của mình xoay quanh Traefik với chủ đề: "Implement Traefik + Elasticsearch - Logstash - Kibana để lưu log cho hệ thống" sẽ được publihsh vào cuối tháng 12 này. Thân mời mọi người đón đọc. Nếu bạn thấy các bài viết của mình hay và hữu ích, nhấn follow mình để nhận thông báo các bài viết mới của mình sớm nhất. Cảm ơn mọi người một lần nữa! ^^
Nếu thấy nội dung này bổ ích, hãy mời tôi một tách cà phê nha! https://kimyvgy.webee.asia
All rights reserved