Scale load balancer flask api using docker swarm & nginx

นายใจซื่อ
Chaos Theory blog
Published in
4 min readMay 7, 2020

สวัสดีอย่างกันเองอีกครั้งนะครับ ผมนายใจซื่อ

วันนี้จะมาพูดถึงการทำ Scaling ซึ่งจะมีอยู่ 2 แบบคือ Verical และ Horizontal ซึ่งควรต้องคำนึงถึงความเหมาะสมของงานที่จะทำเป็นหลักเสียก่อน หากเป็น Web Application หรือ API ที่ออกแบบมาดีเพียงพอแล้ว เราสามารถทำ Horizontal Scaling ได้แน่ และในหลายๆ กรณี การทำ Horizontal Scaling ให้ผลดีกว่า Verical Scaling ครับ

Horizontal Scaling

จากรูปเห็นว่าการทำ Horizontal Scaling เป็นการเพิ่มขนาดรถไปเป็นแนวนอนซึ่งจะเพิ่มจำนวนคนใช้งานได้เรื่อยเพิ่มไป 1 เป็น 2,3,4 ตามที่เราต้องการ แตกต่างจาก Vertical Scaling เป็นการเพิ่มขนาดรถไปเป็นแนวตั้ง ซึ่งจะมีขีดจำกัดเช่นในรูปรถไม่สามารถสูงขึ้นไปได้เรื่อยๆ เป็นหลายๆชั้นเพราะมีข้อจำกัดอยู่

วันนี้ผมจะ Focus ไปที่การทำ Horizontal Scaling เพียงอย่างเดียวนะครับ ^^

หลักการของการทำ Horizontal Scaling คือการเพิ่มจำนวน Node หรือ Worker เข้าไป เพื่อให้ทำงานได้มากขึ้น หรือเร็วขึ้นครับ

ยกตัวอย่างง่ายๆ คือ ถ้าเรามี Server 1 เครื่อง สามารถรับคนได้ 1,000 คน และถ้าเราเพิ่ม Server ไปอีก 1 เครื่อง นั่นแปลว่า เราจะรับคนได้ 2,000 คนเลยครับ เริ่มเห็นความสำคัญแล้วใช่ใหมละครับ

Docker Swarm

เราเรียกการควบคุมดูแลของ docker swarm ว่า “orchestration”

ลองนึกภาพวง orchestra ที่มี conductor เป็นคนค่อยควบคุมวงดนตรี ว่าตอนนี้ต้องเล่นอย่างไร ใครเน้น ใครผ่อน ต้องเล่นแบบเร้าใจ หรือว่าเนิบๆ เพื่อให้สอดคล้องเข้ากันของแต่ละเครื่องดนตรี (harmony) ในเพลง

คำว่า “orchestration” ในความหมายของ docker swarm เน้นไปที่ความสอดคล้องเข้ากัน (harmony) เช่นกัน แต่จะเป็นเรื่องของการ deploy resources ต่างๆ

ผลที่ได้คือ application ที่มีลักษณะเป็น module ที่ run ได้ด้วยตัวตัวเอง นอกจากนั้นยังสามารถเพิ่มหรือลดความสามารถ ด้วยการเพิ่มหรือลด module เข้าไป หรือ เปลี่ยนเป็นของใหม่ที่เหมาะสมกว่าในขณะนั้นได้

เริ่มกันเลยดีกว่าครับ !!

สิ่งที่ต้องเตรียม Server 4 เครื่อง Ubuntu 18.04.4 LTS พร้อมลง Docker

  • Master 1 เครื่อง (Docker Swarm )
  • Worker 2 เครื่อง (Docker Swarm )
  • NginX 1 เครื่อง

SSH เข้าเครื่องแรก ก่อนเลยครับ เพื่อจะเครื่องนั้นเป็น Master

docker swarm init --advertise-addr <ip node master>

ทำการ Generates token ขึ้นมา และเก็บ token นี้ไว้เพื่อให้เครื่อง Worker ที่เราต้องการ join เข้ามาใน Cluster Swarm

ต่อไปทำเครื่อง worker กันต่อไปครับ ลุยๆๆ

SSH เข้าเครื่อง Worker 1 และ Worker 2

Copy คำสั่ง ตั้งแต่ “docker swarm join –token …..” เพื่อเอาไปสั่งให้ Work Node เข้ามา Join ใน Cluster Swarm

docker swarm join --token SWMTKN-1-0xqvnisfoiw8rls1xjsrf7li5onk1r2r3eajcbwavud6om35er-01b37aqsd75dc4olr3raf6bol 10.148.0.31:2377

ต่อไปกลับไปที่เครื่อง Master เลยคับบบ ^^

ใช้คำสั่ง เพื่อเช็ค node ใน Swarm Cluster

docker node ls

สังเกตุได้ว่ามี 3 เครื่องถูก Join เข้ามาใน Cluster Swarm ละมี 1 เครื่องเป็น Leader

ลุย !! ถึงเวลาสร้าง Flask API แล้ว

mkdir flask-api
cd flask-api

Dockerfile:

$ cat DockerfileFROM python:3.4-alpine
ADD . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

The application code:

$ cat app.pyfrom flask 
import Flask
import os
import uuid

app = Flask(__name__)

@app.route('/')
def index():
hostname = os.uname()[1]
randomid = uuid.uuid4()
return 'Container Hostname: ' + hostname + ' , ' + 'UUID: ' + str(randomid) + '\n'

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)

Python Package Dependencies:

$ cat requirements.txtflask

docker-compose.yml :

$ cat docker-compose.ymlversion: '3.3'

services:
flask:
image: rbekker87/flask-containername
ports:
- "80:8080"
networks:
- appnet
deploy:
mode: replicated
replicas: 1
networks:
appnet:
driver: overlay

ถึงเวลา Deploy แล้วครับ

docker stack deploy --compose-file docker-compose.yml apps
docker stack ls
docker service inspect apps_flask
docker service ls -f name=apps

ต่อไปถึงเวลาพระรองของเราแล้วครับ การ Scale up Service

docker service scale apps_flask=3

เราจะ scale up service apps_flask จาก 1 เป็น 3 หรือตามจำนวนที่เราต้องการได้เลยครับ ตามความเหมาะสมของงานเรา

docker stack ps apps

สังเกตุได้ว่ามีการ Scale Service ไปที่เครื่อง worker1 , worker2 แล้วตามที่เราต้องการแล้วครับ

อันนี้ผมลอง Scale ขึ้นมาเป็น 10

พูดถึงเวลาพระรองไปแล้ว ถึงเวลาของพระเอกซักที การ Scale load balancer

SSH เข้าเครื่องจะใช้ Run Service NginX เลยครับ เพื่อจะเครื่องนั้นเป็นตัวจัดการ load balancer

mkdir -p /opt/haproxy/
cd /opt/haproxy/

ลุยต่อเลยครับไหวกันมั๊ย :X

haproxy.cfg :

$ cat haproxy.cfgglobal
debug
defaults
log global
mode http
timeout connect 5000
timeout client 5000
timeout server 5000
frontend main
bind *:80
default_backend app
backend app
balance roundrobin
mode http
server srv1 <server Master>:80
server srv2 <server Worker1>:80
server srv3 <server Worker2>:80

ทุกอย่างครบแล้วมา build Service กันเลยครับ

docker run -d --name my-running-haproxy -p 80:80 -v /opt/haproxy:/usr/local/etc/haproxy:ro haproxy:1.7

เช็คสถานะ Service กันหน่อย

ต่อไปเราก็สามารถเรียกใช้ Service ทั้งหมดที่เราทำการ load balance ไว้ผ่านเครื่องนี้เลยครับ

เสร็จแล้วครับ ^^ เป็นไงบ้างครับง่ายใช่ไหมละครับ Ez

หวังว่าจะมีประโยชน์กับทุกๆ คนนะครับ อาจผิดพลาดตรงไหนขอโทษด้วยนะครับ

ผมนายใจซื่อ ยินดีที่รู้จักทุกคนที่เข้ามาอ่านนะครับ ติดตรงไหนแอดมาคุยกันได้ครับ

--

--