อธิบายการสร้าง Kubernetes External Services และ Networking ด้วย Service Resource

NSLog0
Algorithml
Published in
3 min readAug 5, 2021

--

หัวข้อนี้เป็นหัวข้อย่อยมาจากบทความ Kubernetes Components แบบละเอียด เพื่อแสดงการสร้าง Service สำหรับการจัดการเรื่อง Network Routing ด้วยการใช้ Service Resources และอธิบายโครงสร้าง yaml และในบทความนี้จะเป็นส่วนต่อขยายจากการอธิบายการสร้าง Kubernetes Internal Services และ Networking ด้วย Service Resource เพื่อทำการแสดงวิธีการเข้าใช้งาน k8s Pod จาก IP ครับ

Prerequisite

ต่อจากความเดิมตอนที่แล้วถ้าใครยังไม่ได้อ่าน อธิบายการสร้าง Kubernetes Pod ด้วย Deployments Resources และ อธิบายการสร้าง Kubernetes Internal Services และ Networking ด้วย Service Resource ย้อนกลับไปอ่านก่อนนะครับ

Introduction

ถ้าใครได้อ่านในส่วนของ อธิบายการสร้าง Kubernetes Internal Services และ Networking ด้วย Service Resource แล้วในตอนนี้ผมจะมาสาธิตการสร้าง External service ด้วยการนำ Mongo Express หรือตัว DBMS ที่ใช้จัดการ mongodb มาต่อเข้ากับ mongo-service ที่ผมได้ทำการสร้างไว้เมื่อบทความก่อนหน้านี้ จากนั้นผมจะทำการสร้าง Service ของ Mongo Express และ Assign IP ให้มันครับ

mongo-express-deployment.yamlapiVersion: apps/v1
kind: Deployment
metadata:
name: mongo-express-deployment
labels:
app: mongo-express
spec:
replicas: 1
selector:
matchLabels:
app: mongo-express
template:
metadata:
labels:
app: mongo-express
spec:
containers:
- name: mongo-express
image: mongo-express
ports:
- containerPort: 8081
env:
- name: ME_CONFIG_MONGODB_ADMINUSERNAME
value: admin
- name: ME_CONFIG_MONGODB_ADMINPASSWORD
value: 12345
- name: ME_CONFIG_MONGODB_SERVER
value: mongo-service

ตัวไฟล์นี้จะมีการใส่ env เพิ่มเข้ามาเพื่อใช้ในการทำ Authetication กับตัว MongoDB จริงๆ และผมก็มีการเพิ่ม env ชื่อ ME_CONFIG_MONGODB_SERVER ที่จะทำหน้าที่เก็บ URL ของ MongoDB

หากสังเกตที่ ME_CONFIG_MONGODB_SERVER จะเห็นว่าตัว url นั้น ไม่ได้เป็น URL แต่เป็นชื่อ metedata ของ mongo-service จากบทความก่อนหน้านี้ การนำชื่อมาใส่แบบนี้ถ้าใครเคยทำ docker มาก่อนจะรู้ดีกว่า หากต้องการต่อ Container สองตัวเข้าด้วยกันจะต้องเอาชื่อมันมาใส่แทน URL จากนั้นตัว docker จะทำการใช้ตัว service-discovery เพื่อหา IP ที่แท้จริงของ Container เอง จากนั้นก็เชื่อม service กันให้ ใน k8s ก็ใช้หลักการคล้ายๆ กันครับ

สำหรับตัว ME_CONFIG_MONGODB_SERVER นั้นการเขียน hard code แบบนี้ก็ไม่ดีครับ เหมือนกันการนำ username/password มาใส่กันตรงๆ สาเหตุที่ไม่ควรทำเพราะ ถ้าเมื่อไรตัว mongo-service หรือ Pod หายไปเราต้องมาแก้ไฟล์ yaml ทุกครั้ง เพราะ IP ของ Pod เปลี่ยนและหากเรามีหลายๆ service นั้นหมายความว่าต้องแก้เยอะมาก ดังนั้น k8s จริงมีจริง ConfigMap ที่ผมจะพูดในบทความ Kubernetes Components แบบละเอียด ตรงส่วนของ Configuration layer ย้อนกลับไปอ่านกันได้ครับ

ถัดมาเราจะมาสร้าง External Service ด้วยการประกาศ type ของ service ครับ ลองมาดูไฟล์ ymal กัน

# mongo-express-service.yamlapiVersion: v1
kind: Service
metadata:
name: mongo-express-service
spec:
selector:
app: mongo-express
type: LoadBalancer
ports:
- protocol: TCP
port: 8081
targetPort: 8081
nodePort: 30000

สิ่งที่เพิ่มมาจากบทความก่อนหน้านี้คือ:

spec.type: ที่โดยปกติถ้าเราไม่ได้ประกาศลงไปเวลาเราสร้าง Service เราจะได้เป็น ClusterIP นั้นหมายความว่าเป็น internal service แต่เมื่อไรเราต้องทำเป็น External service ก็ใส่ LoadBalancer เข้า จริงๆ แล้วตัว service type มีแบบอื่นด้วย แต่ผมขอไม่พูดถึงนะครับ ลองแวะไปอ่านได้ที่ kubernetes.io docs

ports.nodePort: เป็นอีกตัวที่เพิ่มเข้ามาในตัวของ spec เป็นตัวที่ใช้ประกาศว่าเราต้องการให้ Public IP เข้าได้จาก port ไหนที่อยู่ระหว่าง 30000–32767

Running

  1. สร้าง Deployment จากไฟล์ yml
  2. สร้าง Service จากไฟล์ ymal ที่มีการใส่ค่าเพื่อทำ External Service ไว้
  3. ลองสั่ง List service ออกมาดูจเห็นได้ว่า ตัว mong-express-service มีส่วนของ EXTERNAL-IP เป็น pending หมายความว่ามันกำลัง Assing IP ให้เราเข้าไปใช้งานและหากสังเกตที่ PORT จะเห็นว่ามีการ Mapping 8081 คือตัว internal port กับ Public Port รีบร้อย
  4. ลอง debug ออกมาดูว่า Service เชื่อมกัน Deployment ถูก IP หรือไม่ ในส่วนของ Endpoints
  5. เช็ค IP deployment เทียบกับข้อ 4

ในการทดสอบบน local เราจะทำบน minikube นั้นหมายความว่าข้อที่ 3 ตัว EXTERNAL-IP จะเป็น pending จะไม่ได้ IP แต่ถ้าเราทำส่วนนี้ใน server จริงๆ มันจะได้ IP มาจริงๆ ตรงนี้เป็นข้อจำกัดของ minikube ครับ วิธีแก้คือต้องสั่งรัน

$ minikube service [service-name]

ผลที่ได้ก็คือ:

Result

ฝากติดตามบทความและโพสต่างๆ ที่เป็นประโยชน์ที่แฟนเพจ Algorithml

--

--