Docker Swarm: รันแอปแบบ HA ง่ายๆ ไม่ต้องปวดหัวมาก

ช่วงนี้ใครๆ ก็พูดถึง Kubernetes เนอะ แต่เอาจริงๆ มันก็ใหญ่ไปสำหรับหลายๆ โปรเจกต์นะ บางทีเราแค่อยากรันแอปหลายๆ ตัว ให้มันมี HA (High Availability) หน่อย หรืออยากจัดการ service ง่ายๆ Docker Swarm นี่แหละ คือคำตอบที่โคตรง่าย

ทำไมถึงเลือก Swarm?

ก็อย่างที่บอกอ่ะ มันง่ายโคตรๆ ตั้งค่าง่าย จัดการ service ง่าย เหมาะกับโปรเจกต์ขนาดกลางๆ หรือใครที่เริ่มจาก Docker Compose มาแล้วอยากขยับขยายขึ้นมาอีกนิด Swarm มันตอบโจทย์ ไม่ต้องไปเรียนรู้อะไรใหม่เยอะเลย (ซึ่งส่วนตัวชอบตรงนี้แหละ ประหยัดเวลาไปได้เยอะเลย)

ลองมาสร้าง Swarm กัน!

สมมติว่าเรามี server อยู่ 3 ตัวนะ ตั้งชื่อ manager01, worker01, worker02 (อันนี้สมมตินะ ปกติใช้ IP หรือ hostname)

1. เริ่ม Swarm Manager:

ล็อกอินเข้า manager01 แล้วรันคำสั่งนี้เลย:

docker swarm init --advertise-addr <IP_ของ_manager01>

แทนที่ <IP_ของ_manager01> ด้วย IP Address จริงๆ ของเครื่อง manager01 นะ

พอรันแล้วมันจะบอก command ให้เอาไปรันที่ worker เพื่อ join เข้ามาใน swarm ของเรา หน้าตาประมาณนี้เลย:

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

    docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxx <IP_ของ_manager01>:2377

2. เอา Worker เข้ามาใน Swarm:

ไปที่ worker01 กับ worker02 แล้วแปะ command ที่ได้มาจาก manager01 เมื่อกี้เลย (copy มาแปะทั้งบรรทัดนั่นแหละ):

docker swarm join --token SWMTKN-1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxx <IP_ของ_manager01>:2377

เสร็จแล้ว! ทีนี้กลับไปที่ manager01 ลองเช็คดูว่า node มาครบมั้ย:

docker node ls

น่าจะเห็นประมาณนี้:

ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
fjklsdafjsldkfjsdlfkj         manager01           Ready               Active              Leader              24.0.5
dsfsdkfjsdklfjklsdfjs         worker01            Ready               Active                                  24.0.5
ewqrewqrewqrewqrewqre         worker02            Ready               Active                                  24.0.5

เยี่ยมเลย! Swarm ของเราพร้อมใช้งานแล้ว

Deploy แอปง่ายๆ ด้วย Service

ทีนี้เราจะลอง deploy เว็บ Nginx ง่ายๆ ซักตัวให้มันรัน 3 replica แล้วต่อกับ Redis ด้วย (เผื่อเว็บเราต้องใช้ cache หรือเก็บ session อะไรพวกนี้ไง)

สร้างไฟล์ docker-compose.yml อันนี้เลย (ใช่แล้ว! Swarm ใช้ compose file ได้ด้วย เจ๋งมั้ยล่ะ):

version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    deploy:
      replicas: 3 # รัน 3 ตัวเลย เพื่อ HA
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure # ถ้าพังก็ให้มัน restart เอง
    depends_on:
      - redis # อันนี้บอกว่า web service ต้องพึ่ง redis นะ

  redis:
    image: redis:latest
    deploy:
      replicas: 1 # Redis ตัวเดียวพอ
      restart_policy:
        condition: on-failure
    volumes:
      - redis_data:/data # เก็บข้อมูล redis ลง volume ให้มันไม่หายไปไหน

volumes:
  redis_data:

เซฟไฟล์นี้ไว้ที่ manager01 แล้วรันคำสั่งนี้:

docker stack deploy -c docker-compose.yml myapp

myapp นี่คือชื่อ stack ของเรานะ จะตั้งอะไรก็ได้ตามใจเลย

ลองเช็คดู service ที่รันอยู่:

docker service ls

หรืออยากดูละเอียดขึ้นว่าแต่ละ service ไปรันอยู่บน node ไหนบ้าง:

docker service ps myapp_web
docker service ps myapp_redis

เราจะเห็นว่า myapp_web มันรัน 3 ตัวกระจายๆ กันไปใน node ที่เรามี (Swarm จะพยายามกระจายให้เราเอง) ส่วน myapp_redis ก็รัน 1 ตัวตามที่เราสั่ง

ปัญหาที่เคยเจอจริงๆ นะ! (และวิธีแก้)

อันนี้เจอเองบ่อยมากๆ เลย คือตอน deploy service ที่ใช้ ports แบบ publish port (เช่น 80:80 เหมือน Nginx เมื่อกี้) บางทีมันไปชนกับ port ที่รันอยู่บน host นั้นๆ พอดี ทำให้ service มันรันไม่ได้แล้วก็วนลูป restarting ไปเรื่อยๆ

ตัวอย่าง error ที่เคยเห็นใน docker service ps หรือ docker logs <container_id> ก็ประมาณนี้:

Error response from daemon: driver failed programming external connectivity on endpoint myapp_web.1.<container_id> (<hash>): Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use

เห็นคำว่า bind: address already in use นี่รู้เลยว่า port ชนแน่นอน วิธีแก้ก็คือ ต้องไปหาว่าโปรแกรมอะไรมันใช้ port นั้นอยู่ (ใช้ sudo netstat -tulpn | grep :80 ดูได้) แล้วก็จัดการปิดมันซะ หรือไม่ก็เปลี่ยน port ของ service เราให้ไม่ชนกับใครเลย

อีกอันที่เจอบ่อยคือ เวลาอัปเดตอิมเมจ แล้ว service มันไม่ยอมดึงอิมเมจใหม่มาใช้ ทั้งๆ ที่เรา build ใหม่แล้วแท็กเดิม (เช่น myapp:latest) อันนี้ต้องบังคับให้มันดึงใหม่ด้วย docker service update --force --with-registry-auth myapp_web หรือเปลี่ยนแท็กอิมเมจไปเลยเป็นเวอร์ชันใหม่ๆ แทน (ซึ่งส่วนตัวแนะนำอันหลังสุด เพราะมันจัดการเวอร์ชันได้ง่ายกว่าเยอะ)

สรุปนะ

Docker Swarm มันเป็นเครื่องมือที่เรียบง่ายแต่ทรงพลังโคตรๆ สำหรับการทำ container orchestration ไม่ต้องเสียเวลาไปเรียนรู้อะไรที่ซับซ้อน ถ้าโปรเจกต์เราไม่ได้ใหญ่โตมโหฬารเท่า Google Swarm ก็คือคำตอบที่ดีเลยแหละ ลองเล่นดูนะ ไม่ผิดหวังแน่นอน! เหมาะสำหรับคนอยากเริ่มจัดระเบียบ Docker containers ของตัวเองจริงๆ

Read more

Google ส่ง Gemini ลง Mac แบบ Native พร้อมตัวช่วย AI สุดล้ำ ยกระดับงานเดสก์ท็อป

Google ส่ง Gemini ลง Mac แบบ Native พร้อมตัวช่วย AI สุดล้ำ ยกระดับงานเดสก์ท็อป

Google เปิดตัว Gemini เวอร์ชัน Native บน Mac พร้อมฟีเจอร์ AI ล้ำสมัย ช่วยเพิ่มประสิทธิภาพการทำงาน ปลดล็อกความคิดสร้างสรรค์ และเชื่อมต่อข้อมูลส่วนตัวได้อย่างชาญฉลาด

By ทีมงาน devdog
เจาะลึก UEFA Champions League: สุดยอดความตื่นเต้นที่แฟนบอลทั่วโลกรอคอย

เจาะลึก UEFA Champions League: สุดยอดความตื่นเต้นที่แฟนบอลทั่วโลกรอคอย

เจาะลึก UEFA Champions League การแข่งขันระดับโลกที่แฟนบอลรอคอย พร้อมติดตามข่าวสารรอบโลกและการถ่ายทอดสดสุดพิเศษ ไม่พลาดทุกความมันส์!

By ทีมงาน devdog
Google อัปเกรด Chrome ครั้งใหญ่ เพิ่มฟีเจอร์ "Skills" ให้ AI จำคำสั่งโปรดของคุณ

Google อัปเกรด Chrome ครั้งใหญ่ เพิ่มฟีเจอร์ "Skills" ให้ AI จำคำสั่งโปรดของคุณ

อัปเกรด Chrome ด้วยฟีเจอร์ Skills ใหม่ ให้ AI จดจำและเรียกใช้คำสั่งโปรดของคุณได้ทันที ไม่ต้องพิมพ์ซ้ำ พร้อมเชื่อมต่อ Gemini ทั่วระบบ

By ทีมงาน devdog
CARTIER Santos-Dumont โฉมใหม่: เมื่อออบซิเดียนผสานตำนานนักบิน สู่ความงามเหนือกาลเวลา

CARTIER Santos-Dumont โฉมใหม่: เมื่อออบซิเดียนผสานตำนานนักบิน สู่ความงามเหนือกาลเวลา

คาร์เทียร์เปิดตัว Santos-Dumont หน้าปัดออบซิเดียน หินภูเขาไฟธรรมชาติผสานดีไซน์นักบินระดับตำนาน สะท้อนงานฝีมือร่วมสมัยและความหรูหรา

By ทีมงาน devdog