สานฝัน Microservices ง่ายๆ ด้วย Docker Swarm
สานฝัน Microservices ง่ายๆ ด้วย Docker Swarm
เฮลโหล่ววว! วันนี้มาคุยกันเรื่อง Docker Swarm หน่อย หลายคนคงคุ้นเคยกับการใช้ Docker Compose กันอยู่แล้วเนอะ เวลาจะรันหลายๆ เซอร์วิสบนเครื่องเดียวก็ใช้ docker-compose up จบข่าว
แต่ถ้าวันนึงแอปเรามันโตขึ้น ต้องรันบนหลายๆ เซิร์ฟเวอร์ล่ะ? หรืออยากจะทำให้มัน Failover ได้ดีขึ้น (เผื่อเซิร์ฟเวอร์นึงเดี้ยง อีกอันก็รันแทนได้) อันนี้แหละที่ Swarm มันเจ๋ง! มันช่วยให้เราเอาเซิร์ฟเวอร์หลายๆ ตัว มารวมกันเป็น “Swarm” แล้วจัดการ deploy แอปเราเหมือนอยู่บนเครื่องเดียวเลย โคตรคูล!
เริ่มต้นกับ Swarm: จัดการให้เครื่องมารวมกัน
ก่อนอื่นเลย แต่ละเครื่องต้องลง Docker ไว้แล้วนะ อันนี้พื้นฐาน ใครยังไม่ลง ไปลงก่อนเด้อ
สมมติเรามีเซิร์ฟเวอร์ 2 เครื่อง server-01 (จะเป็น manager) กับ server-02 (เป็น worker)
ที่ server-01 (Manager Node): เราต้องสั่งให้มันเป็น Swarm Manager ก่อน อันนี้ง่ายสุดๆ ละ
docker swarm init --advertise-addr <IP_ของ_server-01>
หลังรันคำสั่งนี้ มันจะปริ้นท์ข้อความออกมาเพียบๆ เลย พร้อมกับคำสั่งสำหรับ Join Node มาให้ด้วย แบบนี้:
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxxxxxxx \
--advertise-addr <IP_ของ_server-02> <IP_ของ_server-01>:2377
To add a manager to this swarm, run 'docker swarm join --token ...' as above, but omit the '--advertise-addr' flag.
อันนี้แหละโคตรสำคัญ! เก็บคำสั่ง docker swarm join ... ไว้ให้ดีๆ เลยนะ
ที่ server-02 (Worker Node): เอาคำสั่ง docker swarm join ... ที่ได้จาก server-01 มาแปะรันที่เครื่องนี้เลย
docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxxxxxxx \
--advertise-addr <IP_ของ_server-02> <IP_ของ_server-01>:2377
พอรันเสร็จ ทั้งสองเครื่องก็จะกลายเป็นส่วนนึงของ Swarm แล้ว! ง่ายป่ะล่ะ
ลองเช็คดูที่ server-01:
docker node ls
ควรจะเห็นทั้ง server-01 (เป็น Manager) และ server-02 (เป็น Worker) โผล่ขึ้นมาในลิสต์
Deploy แอปง่ายๆ ด้วย Docker Stack
ปกติเราใช้ docker-compose.yml ใช่ปะ? ทีนี้พอมาอยู่บน Swarm เราจะใช้ไฟล์ docker-stack.yml (จริงๆ มันก็เหมือนกันแหละ ชื่อเรียกต่างกันนิดหน่อย) เพื่อ Deploy แอปของเรา
มาลองสร้างไฟล์ app-stack.yml แบบง่ายๆ กัน:
version: '3.8'
services:
web:
image: nginxdemos/hello:plain-text
ports:
- "80:80"
deploy:
replicas: 3 # รัน 3 instances
restart_policy:
condition: on-failure
placement:
constraints:
- node.role == worker # ให้รันบน worker เท่านั้น
visualizer:
image: dockersamples/visualizer:latest
ports:
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
placement:
constraints:
- node.role == manager # ตัวนี้ให้รันบน manager พอ
ไฟล์นี้เราบอกว่า: - มี web service ใช้ nginxdemos/hello รัน 3 instance (ถ้ามี 2 เครื่อง แต่ละเครื่องก็อาจจะได้ 1-2 instance แล้วแต่ Swarm จะจัดให้) - มี visualizer service เอาไว้ดูว่าคอนเทนเนอร์เราไปอยู่ตรงไหนบ้าง ตัวนี้โคตรดี! รันแค่ 1 instance พอ แล้วบังคับให้มันรันบน manager ด้วย node.role == manager
จากนั้นก็ deploy เลย! ที่ server-01 (Manager Node) นะ
docker stack deploy -c app-stack.yml myapp
myapp นี่คือชื่อ Stack ของเรา อยากตั้งอะไรก็ตั้ง
ลองเช็คสถานะ:
docker stack ps myapp
คุณจะเห็นว่าแต่ละ service ถูก deploy ไปบน node ต่างๆ ใน Swarm ของเรา
ทีนี้ลองเข้าเบราว์เซอร์ไปที่ http://<IP_ของ_server-01>:8080 เพื่อดู Visualizer คุณจะเห็นภาพรวมว่า service ต่างๆ กระจายอยู่บน node ไหนบ้าง โคตรเข้าใจง่าย!
ปัญหาที่เคยเจอ (และแก้ไขไงดีวะ)
บอกตรงๆ ว่าแรกๆ ที่ลองเล่น Swarm นี่ก็มีงงๆ เหมือนกันนะ โดยเฉพาะเรื่อง Network Overlay คือพอเราสั่ง Deploy แล้ว บางทีคอนเทนเนอร์มันก็คุยกันไม่ได้เฉยเลย ทั้งๆ ที่ใน docker-compose เคยทำได้ปกติ
มันขึ้น Error ประมาณว่า connection refused หรือ no route to host อะไรพวกเนี้ย คือคอนเทนเนอร์พยายามคุยกันข้าม Node แต่ไม่สำเร็จ
ปัญหาคือ firewall มันบล็อก! ถ้าคุณไม่ได้เปิด Port 7946 (TCP/UDP) กับ 4789 (UDP) สำหรับการสื่อสารของ Swarm Overlay Network เนี่ย มันจะไม่ทำงานนะเว้ย!
ตอนแรกผมนึกว่าแค่เปิด 2377 (สำหรับ Swarm management) ก็พอละ โง่ไปพักใหญ่ กว่าจะรู้ โคตรเสียเวลาไปงม T_T
ถ้าใช้ ufw:
sudo ufw allow 2377/tcp # Swarm management
sudo ufw allow 7946/tcp # Container orchestration
sudo ufw allow 7946/udp # Container orchestration
sudo ufw allow 4789/udp # Overlay network traffic
sudo ufw reload
คือไอ้ 4789/udp นี่แหละตัวแสบ ถ้าปิดอยู่ คอนเทนเนอร์ข้าม Node มันมองไม่เห็นกันจริงๆ นะ!
อีกเรื่องคือการอัปเดต ถ้าเราอัปเดต image แล้วอยากให้ Swarm มันดึง image ใหม่มาใช้ ก็แค่รัน docker stack deploy ซ้ำอีกรอบ มันฉลาดพอที่จะรู้ว่า image เปลี่ยนแล้วก็จะค่อยๆ ทยอยอัปเดตให้เอง แบบ Rolling Update เลย ไม่ต้องดาวน์ไทม์เยอะ โคตรสะดวก!
สรุปนะ
Docker Swarm มันเหมาะมากสำหรับโปรเจกต์ขนาดกลางที่อยากจะเริ่มทำ Microservices หรืออยากได้ High Availability แบบไม่ต้องไปง้อ Kubernetes ที่มันซับซ้อนกว่าเยอะ
ข้อดีคือมัน setup ง่ายโคตรๆ syntax ก็คล้าย docker-compose เดิมๆ แต่ได้พลังของ Cluster Management มาเต็มๆ
ข้อเสีย (สำหรับบางคนนะ) คือฟีเจอร์มันอาจจะไม่เท่า Kubernetes แต่สำหรับงานที่ต้องการความเร็วในการ deploy และไม่ต้องมีฟีเจอร์ซับซ้อนเว่อร์วัง Swarm นี่แหละคือคำตอบ! ส่วนตัวใช้แล้วรู้สึกว่ามันช่วยชีวิตได้เยอะเวลาต้องจัดการหลายๆ เซอร์วิสบนหลายๆ เครื่องพร้อมกัน
ลองเอาไปเล่นกันดูนะ!