[Kubernetes] อยากใช้ Load Balancer แต่รัน Cluster บน Bare Metal ทำยังไงดี ?

Thanwa Jindarattana
3 min readSep 16, 2018

หลายคนเคยเจอปัญหา

NAME               TYPE           CLUSTER-IP      EXTERNAL-IP   
hello-kubernetes LoadBalancer 10.100.179.79 <pending>

EXTERNAL-IP ทำไมถึง pending อยู่ตลอดเวลานะ มันต้องมีอะไรผิดพลาดแน่ๆ

เพราะว่า cluster ของเราไม่ support Layer 4 Load Balancer ยังไงล่ะ

ทำยังไงดี ในเมื่อใช้ LoadBalancer ไม่ได้ก็อย่าหวังว่าจะใช้ Ingress ได้เลย

วันนี้เลยอยากจะนำเสนอโปรเจคที่มีชื่อว่า MetalLB (ย่อมาจาก Metal Load Balance) ซึ่งตอนนี้อยู่ในช่วง Beta และเป็นโปรเจค Unofficial ของ Google https://github.com/google/metallb ถ้าจะใช้บน Production ก็ระวังกันหน่อยครับ

MetalLB เป็น “Pure Software Solution” ที่จะจัดการเรื่อง network load-balancer ที่ implement บน Kubernetes โดยใช้ Standard Routing Protocols

https://metallb.universe.tf/

หากสังเกตดีๆ จะมีคราบคล้ายเลือดติดอยู่บน Logo ฮ่าๆ (สงสัย dev กันจนแทบกระอักเลือด)

หากเรารัน Kubernetes บน Cloud ก็จะมี Network Topology หน้าตาประมาณนี้ (คร่าวๆ)

https://kubernetes.github.io/ingress-nginx/deploy/baremetal/

แต่ถ้าเป็น Bare-metal หรือ On-premises ล่ะ?

https://kubernetes.github.io/ingress-nginx/deploy/baremetal/

ตรงสีแดง เราจะเอาอะไรมากั้นให้ client เรียกผ่านตัวนั้น

คิดแบบบ้านๆ เลย

“ งั้นเราก็สร้างอีก 1 VM ขึ้นมารัน Nginx เลยสิ ความรู้ Nginx พอไปวัดไปวา น่าจะทำได้หน่า”

จะทำแบบนั้นก็ได้ แต่จะทำไปทำไม เดี๋ยวมันก็จะกลายเป็น Single point of failure (SPOF) อีก

“แล้วจะทำยังไงล่ะ”

ก็ติดตั้ง MetalLB ไง

Requirements:

  • Kubernetes cluster เวอร์ชัน 1.9.0 หรือมากกว่า (ตรวจสอบได้จากคำสั่งkubectl verion ในส่วนของ Server Version)
  • Network addon ที่ติดตั้งต้องรองรับ (ดูจากตารางด้านล่าง)
  • IPv4 สำหรับ assign ให้ MetalLB
Network addon ที่ MetalLB รองรับ

ในที่นี้ ผมใช้ addon ที่ชื่อว่า Flannel ซึ่งวิธีติดตั้งก็แค่ใช้คำสั่ง

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

อย่าลืมตั้งค่าใน /etc/sysctl.conf ตามนี้ด้วยนะ

net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_forward = 1

เมื่อติดตั้งเสร็จแล้ว เราจะต่อด้วย MetalLB กัน

วิธีติดตั้ง MetalLB

รันคำสั่ง

kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.3/manifests/metallb.yaml

รอจน pull image จนเสร็จ จะได้ Pod “controller-xxxx-xxxx” โดยมี namespace เป็น metallb-system หากเข้าไปใน Pod แล้วไม่มี error ใดๆ แสดงว่าผ่าน

MetalLB รองรับ protocols ดังต่อไปนี้

ซึ่งบทความนี้ผมจะกล่าวเพียง Layer 2 เท่านั้น

การ config MetalLB

apiVersion: v1kind: ConfigMapmetadata:namespace: metallb-systemname: configdata:config: |address-pools:- name: defaultprotocol: layer2addresses:- 111.201.40.100-111.201.40.125

โปรดสังเกตตรง protocol ว่าผมใช้เป็น layer2 และ addresses ที่ใช้จะอยู่ใน range ระหว่าง 111.201.40.100–111.201.40.125 IP นี้ผมใช้เป็นตัวเลข Public IP (ผมสมมติขึ้นมา)

ข้อควรระวัง

  • ต้องตั้งค่าไม่ให้ DHCP แจก IP เหล่านี้ เพราะจะเกิด IP conflict

ลองทดสอบกับ application เบาๆ อย่าง hello-app โดยใช้ docker image ของ Google

สร้าง Deployment ชื่อว่า hello-app มีจำนวน replica เท่ากับ 3 ใช้ image gcr.io/google-samples/hello-app:1.0 และระบุ port ใน container เป็น 8080

kubectl run hello-app --replicas=3 --image=gcr.io/google-samples/hello-app:1.0 --port=8080

จะได้

Deployment

เมื่อเข้าไปดูใน Replica sets

Replica sets

ของผม Age แสดงเป็น 19 ชั่วโมง แต่ของท่านน่าจะเป็นหลักวินาที

ต่อไปใช้คำสั่งนี้เพื่อสร้าง Service แบบ LoadBalancerโดยใช้ Deployment ชื่อว่า hello-app และ expose port หมายเลข 80

kubectl expose deployment hello-app --type=LoadBalancer --port=80 --target-port=8080 --name=hello-app
Services

เมื่อเข้าไปดูข้างใน

Service ทำการรวบทุก Internal endpoint ไว้ที่เดียว

ขั้นตอนสุดท้าย คือการทดสอบเรียก Service จาก Client โดยใช้ curl จาก Terminal ของเครื่องผมเอง

จะเห็นว่าชื่อของ hostname ได้เปลี่ยนไปเมื่อ request ซ้ำๆ ซึ่งเป็นผลมาจาก Service กระจาย request ให้

ขอจบเพียงเท่านี้ หากมีตรงไหนผิดพลาดหรือข้อติชมประการใดรบกวนช่วยคอมเมนต์ด้านล่างจะเป็นพระคุณยิ่งครับ

--

--