สวัสดีครับ กลับมาเจอกันอีกครั้งกับ Series “Kubernetes Zero-2-Hero” ใน EP.2 นี้เราจะแนะนำวิธีการ Deploy Application ขึ้นไปบน Kubernetes Cluster ว่าสามารถทำได้อย่างไรบ้าง
ก่อนจะเริ่มขั้นตอนการ Deploy Application เราต้องมาทำความรู้จักกับ Resource Type ของ Kubernetes กันก่อน โดยใน EP นี้ เราจะขอพูดถึง 4 Type ก่อน ดังนี้
Pods
ReplicaSet
Deployments
Namespace
ส่วนใครที่พึ่งจะเข้ามาอ่านก็สามารถย้อนกลับไปอ่าน EP.1 ได้ที่ ลิงค์นี้ ได้เลย
ก่อนจะมาเริ่มกันใน EP นี้ และ EP ถัด ๆ ไป เราจะมีการใช้งานไฟล์เพื่อทดลองการ Deploy Application สามารถเข้าไป Download จากลิงค์ หรือใครใช้ GIT ก็สามารถ Clone เอาไปใช้งานได้เลย
https://gitlab.com/settakit.sirisoft/kubernetes-zero-2-hero-blog.git
Pods
มาเริ่มกันที่ Pod กันก่อนเลยนะครับ
Pod เป็นส่วนที่เล็กที่สุดของ Kubernetes ภายใน Pod จะประกอบไปด้วย Container, Volume, และ IP Address เป็นของตัวเอง ให้มองว่า Pod เป็นเหมือนกับคอมพิวเตอร์เครื่องเล็ก ๆ ที่มี Container Runtime อยู่ภายในสำหรับการรัน Container และ มี IP Address และ Volume สำหรับเก็บข้อมูลเป็นของตัวเอง
IP Address: ทุกๆ Pod จะมี IP Address เป็นของตัวเองซึ่งจะถูกแจกแบบ Dynamic โดยตัว kube-proxy
Volumes: เป็นส่วนที่เอาไว้เก็บข้อมูลสำหรับ Container แต่เมื่อ Pod หายไป Volume ภายใน Pod ก็จะหายไปด้วย นั้นหมายความว่าข้อมูลต่าง ๆ ที่ถูกเก็บไว้ภายใน Pod นั้นก็จะหายไปด้วย
Container: เป็นส่วนของ Application ที่รันอยู่ภายใน Pod ซึ่งสามารถมีได้มากกว่า 1 Container ใน 1 Pod ขึ้นอยู่กับการออกแบบว่าเราจะให้ Pod มีกี่ Container
ต่อไปเราจะมาลองสร้าง Pod กันดูนะครับ โดยวิธีการสร้าง Pod สามารถสร้างได้ 2 วิธีดังนี้
สร้าง Pod ผ่าน kubectl command
เราจะสร้าง Pod ชื่อ “first-pod” ด้วย Image “nginx”
kubectl run first-pod --image=nginx --port=80# เมื่อสร้างสำเสร็จแล้วจะได้ผลลัพธ์ดังนี้
pod/first-pod created
เราสามารถตรวจสอบได้ว่าตอนนี้เรามี Pod อะไรรันอยู่บน Cluster บ้าง
kubectl get po# output
NAME READY STATUS RESTARTS AGE
first-pod 1/1 Running 0 2m52s
สร้าง Pod ด้วยไฟล์
เราสามารถสร้าง Pod ได้ด้วยไฟล์ Config ที่เป็นไฟล์ YAML ภายในไฟล์จะกำหนดคุณสมบัติต่าง ๆ ของ Pod ไว้ภายในตามตัวอย่างดังนี้
# second-pod.yamlapiVersion: v1
kind: Pod # ประเภทของ Resource
metadata:
labels: # กำหนด Labels เพื่อเป็นป้ายกำกับสำหรับ Pod
app: second-pod # Label ของ Pod
name: second-pod # ชื่อของ Pod
spec: # ส่วนนี้จะเป็นส่วนที่กำหนดคุณสมบัติของ Pod
containers:
- image: nginx # image ที่ใช้ในการรัน Container
name: second-pod # ชื่อของ Container ภายใน Pod
ports:
- containerPort: 80 # port ของ container
เราสามารถสร้าง Pod จากไฟล์ด้วยคำสั่งดังต่อไปนี้
# kubectl create -f <FILE>
# โดยในที่นี้ไฟล์ของเรามีชื่อว่า second-pod.yamlkubectl create -f second-pod.yaml# output
pod/second-pod created
ตรวจสอบว่า Pod ของเราทำงานอยู่
kubectl get po# output
NAME READY STATUS RESTARTS AGE
first-pod 1/1 Running 0 19m
second-pod 1/1 Running 0 46s
จะเห็นได้ว่า Pod ของเรากำลังทำงานอยู่
ต่อไปเราจะมาดูกันว่า IP ของ Pod เป็นหมายเลขอะไรด้วย Command ดังนี้
kubectl get po -o wide# output
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-pod 1/1 Running 0 32m 10.1.1.125 docker-desktop <none> <none>
second-pod 1/1 Running 0 13m 10.1.1.126 docker-desktop <none> <none>
จะเห็นว่า IP ของ Pod นั้นจะไม่เหมือนกันโดยแต่ละ Pod จะมี IP Address เป็นของตัวเอง แต่ IP Address นี้จะไม่สามารถเข้าใช้งานได้จากภายนอก Cluster จะสื่อสารกันแค่ภายใน Cluster เท่านั้น สามารถทดสอบได้ดังนี้
# your pc terminal
curl http://10.1.1.125 -m 3 # ip ของ first-pod# output
curl: (28) Connection timed out after 3004 milliseconds# on container in pod on kubernetes cluster
kubectl exec second-pod -- sh -c "curl http://10.1.1.125 -m 3"# output
<html>
<head>
<title>Welcome to nginx!</title>
### More Output ###
จะสังเกตุได้ว่าเราไม่สามารถเข้าใช้งาน Pod จากภายนอก Cluster ได้
โดยถ้าเราต้องการให้ภายนอกเข้ามาใช้งาน Pod ของเราได้เราต้องใช้งาน Resource Type ที่ชื่อว่า “Service” เข้ามาจัดการในเรื่องนี้ ด้านล่างนี้จะเป็นตัวอย่างการใช้งาน Service เท่านั้นส่วนรายละเอียดเราจะพูดถึงกันใน EP ถัดไป
kubectl expose po first-pod --type=NodePort --target-port=80 --port=80# output
service/first-pod exposedkubectl get svc# output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
first-pod NodePort 10.107.44.192 <none> 80:31239/TCP 40s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 38d# curl ไปที่ localhost port ตามที่เราได้ get service ออกมาดู
curl http://localhost:31239# output
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
### More Output ###
จากตัวอย่างเราก็จะเห็นได้ว่าเราสามามารถเข้าใช้งาน Pod จากภายนอก Cluster ได้แล้ว
ReplicaSet
ต่อไปเราจะมาพูดถึงเรื่องของ ReplicaSet กันนะครับ
เมื่อเราต้องการสร้าง Pod มากกว่าหนึ่ง Pod โดยที่ Pod นั้นเป็น Application เดียวกันเราต้องการ Deploy ขึ้นมาหลาย Pod เพื่อให้ Pod ช่วยกันรับ Request ที่เข้ามาจาก User แล้ว Response ผลลัพธ์ออกไปให้กับ User โดยที่เราไม่จำเป็นต้องสร้างเองทีละ Pod และ ReplicaSet จะคอยตรวจสอบอยู่เสมอว่า Pod ที่เรา Deploy นั้นมีจำนวนเท่ากับที่เรากำหนดไว้ตอนแรกด้วยหรือไม่ ถ้า Pod จำนวนไม่เท่ากับที่เรากำหนด ReplicaSet จะทำให้ Pod มีจำนวนเท่ากับที่กำหนดไว้ในตอนแรก
วิธีการสร้าง ReplicaSet นั้นก็สามารถสร้างได้จากไฟล์เท่านั้น ดังตัวอย่าง
# first-rs.yamlapiVersion: apps/v1
kind: ReplicaSet # ประเภทของ Resource
metadata:
name: first-rs # ชื่อของ ReplicaSet
labels:
app: first-rs # Label ของ ReplicaSet
spec:
replicas: 3 # จำนวน Pod
selector:
matchLabels:
app: first-rs-pod # Label ของ Pod ที่จะให้ ReplicaSet คอยเฝ้าดู
template:
metadata:
labels:
app: first-rs-pod # Label ของ Pod
spec:
containers:
- name: nginx # ชื่อของ Container
image: nginx # ชื่อของ Image
ports:
- containerPort: 80 # port ของ container# สร้าง ReplicaSet
kubectl create -f first-rs.yaml# output
replicaset.apps/first-rs created
ตรวจสอบว่า ReplicaSet ของเราทำงาน พร้อมกับดูว่า Pod ของเราถูกสร้างขึ้นมาตามจำนวนที่กำหนดไว้หรือไม่
kubectl get rs,po# output
NAME DESIRED CURRENT READY AGE
replicaset.apps/first-rs 3 3 3 67sNAME READY STATUS RESTARTS AGE
pod/first-pod 1/1 Running 0 109m
pod/first-rs-5lvjt 1/1 Running 0 67s
pod/first-rs-ng7nq 1/1 Running 0 67s
pod/first-rs-pnr52 1/1 Running 0 67s
pod/second-pod 1/1 Running 0 90m
จะเห็นได้ว่า Pod ของเราจะถูกสร้างขึ้นมาตามจำนวนที่เรากำหนดไว้ในตอนแรก ซึ่งเราก็สมารถเพิ่มลดจำนวนของ Pod ได้ด้วย command ดังนี้
kubectl scale rs first-rs --replicas=5# output
replicaset.apps/first-rs scaled
เมื่อเราตรวจสอบ Pod ดูอีกครั้งจะพบว่าจำนวนของ Pod จะเพิ่มขึ้นหรือลดลงเท่ากับจำนวนตัวเลข replicas ที่เรากำหนดไว้
kubectl get po# output
NAME READY STATUS RESTARTS AGE
first-pod 1/1 Running 0 112m
first-rs-5lvjt 1/1 Running 0 4m48s
first-rs-c2qv5 1/1 Running 0 84s
first-rs-ng7nq 1/1 Running 0 4m48s
first-rs-nx7lq 1/1 Running 0 84s
first-rs-pnr52 1/1 Running 0 4m48s
second-pod 1/1 Running 0 94m
Deployments
ต่อไปเราจะมาพูดถึง Deployments กันนะครับ
Deployments เป็นเหมือนกับการรวมคุณสมบัติของ ReplicaSet และ Pods เข้ามาไว้ด้วยกัน แต่สิ่งนึงที่เพิ่มเข้ามาก็คือเรื่องของการจัดการเวอร์ชันของ Application เช่น เมื่อเรา Update Application ของเราไปเป็นเวอร์ชันใหม่แล้วเกิดปัญหาเราสามารถย้อนกลับไปใช้งาน Application เวอร์ชันเก่าที่ทำงานสมบูรณ์ได้
การทำงานของ Deployment เมื่อ Deployment ถูกสร้างขึ้น Deployment จะไปสร้าง ReplicaSet และเก็บเป็นหมายเลขเวอร์ชันไว้ จากนั้น ReplicaSet ก็จะไปสร้าง Pod ตามคุณสมบัติที่ถูกกำหนดไว้ โดยเมื่อเรา Update เวอร์ชัน image ที่ใช้ Deploy Application Deployment จะสร้าง ReplicaSet ขึ้นมาใหม่ จากนั้น ReplicaSet ก็จะไปสร้าง Pod ชุดใหม่ขึ้นมา และ Pod ชุดเดิมก็จะถูกลบออกไป ส่วน ReplicaSet ตัวเก่าก็ยังถูกเก็บไว้อยู่จะไม่ได้ลบออกไป เพื่อเอาไว้สำหรับการย้อนกลับไปใช้ Application เวอร์ชันเก่า ส่วนวิธีจัดการกับเวอร์ชันเราจะพูดถึงใน EP ถัด ๆ ไป
ต่อไปจะเป็นวิธีการสร้าง Deployment ซึ่งเราสามารถสร้างได้ด้วย command หรือ จากไฟล์ดังตัวอย่างต่อไปนี้
สร้าง Deployment ชื่อ first-deployment ด้วย image “nginx” รันที่ port 80 และมีจำนวน 2 Pods
kubectl create deployment first-deployment --image=nginx --port=80 --replicas=2# output
deployment.apps/first-deployment created
ตรวจสอบว่า Deployment ของเราทำงาน พร้อมกับสร้าง ReplicaSet และ Pods ขึ้นมาแล้ว
# เพิ่ม -l เพื่อเลือกเฉพาะ Resource ที่มี label app=first-deployment
kubectl get deploy,rs,po -l app=first-deployment# output
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/first-deployment 2/2 2 2 4m49sNAME DESIRED CURRENT READY AGE
replicaset.apps/first-deployment-6dbdd9c6ff 2 2 2 4m49sNAME READY STATUS RESTARTS AGE
pod/first-deployment-6dbdd9c6ff-c4m82 1/1 Running 0 4m49s
pod/first-deployment-6dbdd9c6ff-n9vzr 1/1 Running 0 4m49s 138m
จะเห็นว่า ReplicaSet จะถูกสร้างขึ้นมา และมี Pods ตามจำนวนที่เรากำหนดไว้
ต่อไปทดลองแก้ไขเวอร์ชันสำหรับ Application ที่ Deployment ด้วย Command ดังนี้
# command update image ให้กับ deployment
kubectl set image deployment first-deployment nginx=nginx:1.19# output
deployment.apps/first-deployment image updated
และเมื่อเราลองแก้ไขเวอร์ชันดูแล้วก็จะพบว่า ReplicaSet จะถูกขึ้นมาใหม่ และ Pod ใหม่ก็จะถูกสร้างขึ้น (สังเกตุได้จากชื่อของ Pods)
kubectl get deploy,rs,po -l app=first-deployment# output
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/first-deployment 2/2 2 2 10mNAME DESIRED CURRENT READY AGE
replicaset.apps/first-deployment-6dbdd9c6ff 0 0 0 10m
replicaset.apps/first-deployment-7fb6db4798 2 2 2 84sNAME READY STATUS RESTARTS AGE
pod/first-deployment-7fb6db4798-24bhq 1/1 Running 0 77s
pod/first-deployment-7fb6db4798-hqt4l 1/1 Running 0 84s
Namespace
Namespace เป็นตัวที่ใช้แบ่ง Environment สำหรับการ Deploy Application บน Cluster เพื่อแยกการทำงานของแต่ละ Environment อย่างชัดเจน และช่วยให่เราสามารถจัดการกับ Application ของเราได้ง่ายขึ้น โดย Namespace ยังสามารถกำหนดสิทธิ์การเข้าถึงในแต่ละ Namespace ของ Client ที่จะเข้ามาใช้งาน Kubernetes Cluster และยังสามารถกำหนดขอบเขตการใช้งานทรัพยากรของแต่ละ Namespace ได้อีกด้วย
คำสั่งในการสร้าง Namespace
# kubectl create namspace <NAMESAPCE_NAME>kubectl create namespace dev# output
namespace/dev created
สามารถดู Namespace ทั้งหมดภายใน Cluster ได้ดังนี้
kubectl get namespace# output
NAME STATUS AGE
auth-system Active 35d
cert-manager Active 36d
default Active 38d
dev Active 24s
ingress-nginx Active 21d
kube-node-lease Active 38d
kube-public Active 38d
kube-system Active 38d
kubernetes-dashboard Active 21d
เราสามารถ Deploy Application ของเราไปยัง Namespace ที่ต้องการได้ดังนี้
# เพิ่ม -n เพื่อระบุ Namespace
kubectl run third-pod --image=nginx --port=80 -n dev# output
pod/third-pod created
ถ้าหากเราไม่กำหนด Namespace ให้กับ Application ของเรา Application ของเราก็จะไป Deploy ที่ Default Namespace
เมื่อเราเรียกดู Pods โดยไม่ระบุ Namespace จะพบว่าไม่มี “third-pod” ที่เราสร้างไปก่อนหน้านี้ เนื่องจากถ้าเราไม่กำหนด Namespace มันก็จะไปเรียกในส่วนของ Default Namespace มาแสดงให้เราดู
kubectl get po# output
NAME READY STATUS RESTARTS AGE
first-deployment-7fb6db4798-24bhq 1/1 Running 0 18m
first-deployment-7fb6db4798-hqt4l 1/1 Running 0 18m
first-pod 1/1 Running 0 3h
first-rs-5lvjt 1/1 Running 0 72m
first-rs-c2qv5 1/1 Running 0 69m
first-rs-ng7nq 1/1 Running 0 72m
first-rs-nx7lq 1/1 Running 0 69m
first-rs-pnr52 1/1 Running 0 72m
second-pod 1/1 Running 0 162m
แต่เมื่อเรากำหนด Namespace เข้าไปก็จะพบกับ “third-pod” ที่ถูกสร้างขึ้น
kubectl get po -n dev# output
NAME READY STATUS RESTARTS AGE
third-pod 1/1 Running 0 4m42s
Conclusion
- Pods เป็นส่วนที่เล็กที่สุดของ Kubernetes Cluster เป็นที่อยู่ของ Application เรา โดยภายใน Pod จะประกอบไปด้วย Container อย่างน้อยหนึ่ง Container มี Volume และ IP Address เป็นของตัวเอง เปรียบได้กับคอมพิวเตอร์เครื่องเล็ก ๆ ที่มี Container Runtime อยู่ภายใน
- ReplicaSet ที่สามารถสร้าง Pods ขึ้นมาตามที่เราต้องการครั้งละหลาย ๆ Pods และยังคอยทำให้ Pods มีจำนวนตามที่กำหนดไว้อยู่ตลอดเวลา
- Deployment เป็นการรวมกันของการสร้าง ReplicaSet และ Pods โดยเพิ่มในส่วนของการจัดการเวอร์ชันเข้ามา
- Namespace เป็นตัวที่ช่วยแบ่ง Environment ให้กับ Application ภายใน Cluster สามารถแบ่งสิทธ์การเข้าถึงในแต่ละ Namespace และจำกัดการใช้งานทรัพยากรในแต่ละ Namespace ได้
- ทดลองการ Deploy Application ขึ้นไปยัง Cluster ด้วย Pod, ReplicaSet และ Deployment
- ความแตกต่างระหว่าง Pod, ReplicaSet และ Deployment
ใน EP นี้ใครอยากเรียนรู้ในเรื่องของ kubectl ให้มากขึ้นก็สามารถเข้าไปได้ตาม ลิงค์นี้ ได้เลยนครับ มันมีเยอะมาก ๆ ไว้มีโอกาสผมจะทำสรุปที่สำคัญ ๆ เอาไว้ให้นะครับ
สำหรับวันนี้ใน EP.2 ก็ขอจบไว้แต่เพียงเท่านี้ก่อนนะครับ สำหรับตอนถัดไปจะมาพูดถึงเรื่อง Service และ Ingress ที่จะทำให้ User สามารถเข้ามาใช้งาน Application ของเราได้ และแถมด้วย Feature ที่ทุกคนต้องว้าวว! นั้นก็คือการทำ Auto Scaling ให้กับ Application ตามความต้องการใช้งานของ User
เพื่อนๆสามารถติดตามกันได้ที่ https://www.facebook.com/sirisoft แล้วพบกันใหม่เร็วๆนี้ ขอบคุณครับ 👋🏻👋🏻👋🏻
ALL EPISODE
EP.1 มารู้จักกับ Kubernetes พร้อมหลักการทำงาน ไปจนถึงวิธีการติดตั้งบนเครื่อง Local !!
EP.2 ทำความรู้จัก Resource Type และ การ Deploy Application บน Kubernetes
EP.3 สร้าง Service Ingress และการทำ Horizontal Pod Autoscaler
EP.4 สร้าง Secret ConfigMap และสำรองข้อมูลด้วย PersistentVolume
EP.5 สร้าง Health Check ด้วย Liveness Readiness และ การใช้งาน Rollout