ศึกษา Kubernetes ด้วยตนเอง part 2/2: Overview and Practice
บทความนี้เราจะพูดถึงความคิด (concepts) และการจัดการของ Kubernetes สลับกับลงมือเขียนคำสั่งไปด้วยโดยใช้เครื่องมือชื่อ Kubectl ขอเน้นๆโดนๆได้โปรด
Kubernetes นั้นพิพม์ยาวไป บทความก่อนหน้านี้ผมเรียกมันว่า Kube แต่บทความนี้และต่อจากนี้จะเรียกมันว่า K8s นะครับ
บทความก่อนหน้านี้
K8s API
อีกเดี๋ยวเราจะเรียนรู้การทำงานของ K8s ผ่าน Minikube ซึ่งเป็น K8s สำหรับนักพัฒนา
Minikube จะมองว่าเครื่องที่ติดตั้งนี้เป็นเพียงคอมพิวเตอร์เครื่องเดียวใน 1 cluster
การจะคุยกับ K8s เราจะคุยผ่าน K8s API อันเป็นวิธีการที่มันได้จัดเตรียมไว้ให้เราสื่อสารด้วย
สามารถคุยอะไรได้บ้าง?
- application ทั้งหมดที่ต้องการให้รันหรือต้องการให้จัดการ workloads ให้บอกแก่มัน
- application เหล่านั้นของเราใช้ image (Docker images) ใดบ้าง
- จำนวน replica ต้องการเท่าไร
- network และ storage อย่างไรและเท่าไรที่ต้องการใช้งาน
K8s API Objects
สิ่งที่เราต้องการจาก K8s เรียกว่า desired state สามารถสั่งงานผ่าน K8s API โดย API นี้เป็นวิธีการสื่อสารกับ Object ต่างๆของ K8s
K8s Objects ประกอบด้วย
- Pod
- Service
- Volume
- Namespace
ยังไม่พอ K8s ได้เตรียม layer ที่สูงกว่าเพื่ออำนวยความสะดวกแก่การสั่งงานเหล่า K8s Objects ข้างต้น จะได้ตอบสนองต่อ desired state ของเราให้ง่ายขึ้นไปอีกผ่านสิ่งที่เรียกว่า Controller
K8s Controllers ประกอบด้วย
- Deployment
- DaemonSet
- StatefulSet
- ReplicaSet
- Job
You Desired State
desired state ก็คือสิ่งที่เราต้องการ สมมติว่าเป็น application ที่รันอยู่ใน Node
พูดให้ชัดเจนกว่านี้อีกหน่อย
เราต้องการ Spring Boot web application ที่แสดงหน้า Hello ให้ถูกรันอยู่ใน Node ของ K8s
วาดภาพมา
จากภาพจะเห็นว่า local machine คือเครื่องที่เราได้ติดตั้ง Minikube และเพราะการติดตั้ง Minikube ทำให้เครื่องของเราถูกมองว่าเป็นหนึ่ง cluster ซึ่งมีแค่ server เครื่องเดียว
เมื่อขยายตัว K8s หรือ K8s cluster ออกมาจะพบว่าในหนึ่ง cluster นี้ประกอบด้วย master กับ node เพียงอย่างละหนึ่ง ภายใน node มี pod และภายใน pod มี container อันเป็นเป้าหมายของเรา
ติดตั้ง Minikube
ตามนี้เลย
เนื่องจากผมใช้ MacOS ดังนั้น
1.ตรวจสอบว่าเครื่องรองรับ virtualization หรือไม่ ถ้ารองรับจะต้องเห็น VMX ปรากฏอยู่ในรายการผลลัพธ์
sysctl -a | grep -E --color 'machdep.cpu.features|VMX'
machdep.cpu.features: FPU VME DE PSE TSC MSR PAE MCE CX8 APIC SEP MTRR PGE MCA CMOV PAT PSE36 CLFSH DS ACPI MMX FXSR SSE SSE2 SS HTT TM PBE SSE3 PCLMULQDQ DTES64 MON DSCPL VMX SMX EST TM2 SSSE3 FMA CX16 TPR PDCM SSE4.1 SSE4.2 x2APIC MOVBE POPCNT AES PCID XSAVE OSXSAVE SEGLIM64 TSCTMR AVX1.0 RDRAND F16C
2.ผ่านจาก 1. มาด้วยดี ดังนั้นติดตั้ง Minikube ได้
brew install minikube
ใช้เวลาค่อยข้างนาน ให้คอยหน่อย
Run Minikube
ตรวจสอบสถานะปัจจุบัน
minikube status
host:
kubelet:
apiserver:
kubeconfig:
เริ่มการทำงาน
minikube start
😄 minikube v1.6.2 on Darwin 10.15.2
✨ Automatically selected the ‘hyperkit’ driver (alternates: [])
💾 Downloading driver docker-machine-driver-hyperkit:
…
🔥 Creating hyperkit VM (CPUs=2, Memory=2000MB, Disk=20000MB) …
🐳 Preparing Kubernetes v1.17.0 on Docker ‘19.03.5’ …
💾 Downloading kubelet v1.17.0
💾 Downloading kubeadm v1.17.0
🚜 Pulling images …
🚀 Launching Kubernetes …
⌛ Waiting for cluster to come online …
🏄 Done! kubectl is now configured to use “minikube”
มันดาวน์โหลด default hypervisor ชื่อ hyperkit สิ่งนี้คือ driver ที่ต้องกำหนดให้กับ Minikube ก่อนเริ่มใช้งาน มี driver อยู่หลายตัว ได้แก่
- virtualbox
- vmwarefusion
- kvm2
- hyperkit
- hyperv
- vmware
ซึ่งเราสามารถเปลี่ยนไปใช้งานตัวอื่นได้ในภายหลัง (ถ้าต้องการ) ก่อนเริ่ม Minikube ด้วยคำสั่ง
minikube start --vm-driver=<driver_name>
เสร็จแล้วขอดูสถานะอีกครั้ง
minikube status
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
แต่หากพบ error เช่น machine does not exist
ก็สามารถ clear local state ได้
minikube delete
แล้วจึง start ใหม่
ทีนี้ลองถามหา version
minikube version
minikube version: v1.6.2
commit: 54f28ac5d3a815d1196cd5d57d707439ee4bb392
ทำงาน Kubectl
อย่างที่เราทราบว่า Kubectl เป็น command line tool ที่ใช้ส่งคำสั่งถึง K8s Master ให้ดูที่เวอร์ชันโดยพิมพ์คำสั่ง
kubectl version
จะปรากฏ client version และ server version
- สำหรับ client version คือ Kubectl
- ส่วน server version คือ K8s Master
Client Version: version.Info{Major:”1", Minor:”15", GitVersion:”v1.15.5", GitCommit:”20c265fef0741dd71a66480e35bd69f18351daea”, GitTreeState:”clean”, BuildDate:”2019–10–15T19:16:51Z”, GoVersion:”go1.12.10", Compiler:”gc”, Platform:”darwin/amd64"}
Server Version: version.Info{Major:”1", Minor:”17", GitVersion:”v1.17.0", GitCommit:”70132b0f130acc0bed193d9ba59dd186f0e634cf”, GitTreeState:”clean”, BuildDate:”2019–12–07T21:12:17Z”, GoVersion:”go1.13.4", Compiler:”gc”, Platform:”linux/amd64"}
มีงานล่ะ เพราะ client version กับ server version ไม่เท่ากัน เราจะสั่งงาน server (ตัว K8s Master) อย่างน้อยก็ควรมีเวอร์ชันที่เท่ากัน
ตรวจสอบโดยให้ Minikube เชื่อมต่อไปยัง cluster
minikube kubectl
💾 Downloading kubectl v1.17.0
kubectl controls the Kubernetes cluster manager.
เห็นไหม client ทราบเลยว่าต้องใช้เวอร์ชันเดียวกัน จะได้คุยกันรู้เรื่อง แล้วมันก็ไปดาวน์โหลดเวอร์ชันที่เท่ากันนี้มาให้ หรือเปล่า?
ไม่รู้สิ เราเป็นมือใหม่ ฉะนั้นไปดูที่นี่ดีกว่า
เลื่อนไปหัวข้อ Install kubectl on MacOS
จากนั้นบอกไปเลยว่าจะเอาเวอร์ชัน 1.17.0 (ณ เวลานี้)
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/darwin/amd64/kubectl
ทำให้แน่ใจว่าไฟล์นี้มีสมบัติ executable (ในเครื่อง MacOS)
chmod +x ./kubectl
แล้วย้ายมันไปยังที่ที่เราได้ติดตั้ง Minikube ครับ
sudo mv ./kubectl /usr/local/bin/kubectl
ตรวจสอบเวอร์ชัน
kubectl version --client
Client Version: version.Info{Major:”1", Minor:”17", GitVersion:”v1.17.0", GitCommit:”70132b0f130acc0bed193d9ba59dd186f0e634cf”, GitTreeState:”clean”, BuildDate:”2019–12–07T21:20:10Z”, GoVersion:”go1.13.4", Compiler:”gc”, Platform:”darwin/amd64"}
แหม เวอร์ชันเท่ากันซักที
ขอดู info ของ cluster
kubectl cluster-info
Kubernetes master is running at https://192.168.64.2:8443
KubeDNS is running at https://192.168.64.2:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
ขอดู Node ทั้งหมด
kubectl get nodes
ผล
NAME STATUS ROLES AGE VERSION
minikube Ready master 13h v1.17.0
จะเห็นได้ว่าเรามีแค่ Node เดียว มีสถานะคือ ready พร้อมใช้งาน
K8s Deployment
Deployment นี้คืออะไร? ง่ายๆว่ามันเป็นกระบวนการที่ต้องการนำ application ที่เขียนเสร็จแล้วไปทำงานเพื่อใช้งาน จะโดยวิธีการใดก็แล้วแต่ บนสถาปัตยกรรมที่ซับซ้อนมากหรือน้อยก็แล้วแต่ โดยทั่วไปคือจับ application นั้นไป deploy บนเครื่อง server เมื่อ application นั้นทำงานอยู่บน server ก็สามารถเรียกใช้งานได้
เหตุนี้คำว่า K8s Deployment ก็คือการนำ application ไป deploy เพื่อทำงานบนเครื่องที่ติดตั้ง K8s และสามารถเรียกใช้งานได้
ขอขยายความหน่อยนะ
เมื่อใดก็ตามที่เราจะทำงานกับ K8s cluster สิ่งที่มักทำบ่อยๆก็คือการ deploy application ที่มีสมบัติเป็น containerized application (คือเป็น container ได้) แก่ K8s cluster นั่นแหละ
เราจำเป็นต้องสร้างสิ่งที่เรียกว่า K8s Deployment configuration ขึ้นมาก่อน ภายในประกอบด้วยคำสั่งเพื่อบอกแก่ K8s ว่าจะสร้างและปรับปรุงเหล่า instance ทั้งหลายของ application เจ้ากรรมนี้อย่างไรบ้าง ต้มยำทำแกงอะไรว่าไป
และคราวใดก็ตามที่ Deployment ถูกสร้างขึ้นจะเป็นเวลาของ K8s Master น้อมรับคำสั่งและทำตามขั้นตอนดังกล่าวให้ เป็นเสมือนพ่อบ้านแสนดี คือมีสิ่งที่เรียกว่า schedule อยู่ในมือ เขาก็จะสร้างและปรับปรุงเหล่า instance ทั้งหลายไปยังแต่ละ Node ที่อยู่ใน cluster เดียวกันตามตารางงานทุกประการ
ขอเพิ่มเติมอีก
เมื่อ application instance ถูกสร้างขึ้น สิ่งที่เรียกว่า K8s Deployment Controller จะคอย monitor สถานะของ instance นั้นให้อัตโนมัติ หากเกิดสิ่งไม่คาดคิด เช่น Node ที่บรรจุ instance ได้ล่มไปหรือถูกลบ เจ้า K8s Deployment Controller นี่แหละจะแทนที่ instance ใหม่ไปยัง Node อื่นที่อยู่ใน cluster เดียวกัน เรียกกลไกลักษณะนี้ว่า Self-healing
Application Instance ไม่มีวันตายตราบใดที่ยังคงมี Node อื่นเหลืออยู่ใน cluster เดียวกันอย่างนั้นสินะ หึหึหึ
เฮ้ยอันนี้น่าสนใจ! แต่ไว้เรามาคุยกันภายหลังนะครับ มาต่อเรื่อง deployment
ขอดู deployment ทั้งหมดของ cluster นี้
kubectl get deployments
No resources found in default namespace.
ไม่พบเลย — ถูกต้อง
งั้นลองสร้าง 1 deployment ก่อนเป็นไร
- ชื่อ k8s-bootcamp
- และให้ดึง image มาจาก gcr.io/google-samples/kubernetes-bootcamp:v1
kubectl create deployment k8s-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
deployment.apps/k8s-bootcamp created
เท่ากับว่า K8s ได้สร้าง deployment นี้ให้แล้ว
ขอดู deployment ทั้งหมดของ cluster นี้อีกครั้ง
kubectl get deployments
ผล
NAME READY UP-TO-DATE AVAILABLE AGE
k8s-bootcamp 1/1 1 1 4s
พบ 1 deployment
มันยังมีความหมายอีกว่าเราได้ deploy application จำนวน 1 instance ผ่านการสร้าง deployment นี้สำเร็จเรียบร้อยแล้วด้วย
application instance ที่กล่าวมานี้ K8s เรียกมันว่า Pod
ขอดู Pod ทั้งหมด
kubectl get pods
ผล
NAME READY STATUS RESTARTS AGE
k8s-bootcamp-844bd7dd7-swqrt 1/1 Running 0 112m
เหล่า Pod ทั้งหลายหลังจากถูกสร้างขึ้นจะอยู่ในพื้นที่ private คือแยกจาก network ภายนอกโดยสิ้นเชิง ทว่าพวกมันยังคงถูกมองเห็นและเข้าถึงได้จาก Pods และ Services ที่อยู่ใน cluster เดียวกันนี้นะครับ
Kubectl Proxy
ถ้าเราต้องการเข้าถึง Pod จาก network ภายนอก เราต้องการ Kubectl Proxy
คำสั่งต่อไปนี้จะเปิด port 8001 ซึ่งเป็น default port ของ Kubectl Proxy (ยกเลิกใช้งานกด control + c)
kubectl proxy
Starting to serve on 127.0.0.1:8001
เราจะใช้โปรแกรม curl คุยกับมัน รูปแบบที่ใช้สื่อสารคือ REST API
ขอดู server เวอร์ชัน (K8s Master)
curl http://localhost:8001/version
ผล
{
"major": "1",
"minor": "17",
"gitVersion": "v1.17.0",
"gitCommit": "70132b0f130acc0bed193d9ba59dd186f0e634cf",
"gitTreeState": "clean",
"buildDate": "2019-12-07T21:12:17Z",
"goVersion": "go1.13.4",
"compiler": "gc",
"platform": "linux/amd64"
}
อยากทราบชื่อ Pod ที่มี คำสั่งต่อไปนี้จะค้นหาแล้วเก็บไว้ในตัวแปร POD_NAME
export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
จากนั้นขอดูค่าในตัวแปร POD_NAME
echo Name of the Pod: $POD_NAME
Name of the Pod: k8s-bootcamp-844bd7dd7-swqrt
เป็นว่าเราสามารถคุยกับ K8s ได้โดยไม่ผ่าน Kubectl โดยตรง แต่ผ่าน Kubectl Proxy แทน
เสน่ห์ในการสื่อสารกับ K8s ไม่ได้มีแค่ Kubectl Proxy ถ้าไม่ใช้ proxy ก็มี Service object ให้ทำความเข้าใจต่อไป
Deployment File (.yaml)
เมื่อใดก็ตามที่เราต้องการสร้าง K8s Objects เราจะส่งคำสั่งนี้ผ่าน Kubectl บอกเป็น request และแนบ JSON ไปด้วย ระบุไปว่า desired state ที่ต้องการเป็นอย่างไรและมีอะไรบ้าง อีกทางหนึ่งในการปั้น JSON คือเขียน desired state ลงไปในไฟล์ .yaml ซึ่งนักพัฒนาเรียกไฟล์นี้ว่า deployment file อันที่จริงก็ไม่ถูกต้องนัก เพราะ .yaml เป็นแค่วิธีการบรรยายคำสั่งเท่านั้นเอง (หมายถึงถ้า Kubectl มันเข้าใจนามสกุลอื่นนอกจาก .yaml ก็สามารถใช้ได้)
การบอกให้ Kubectl อ่านไฟล์ .yaml คือการบอกให้ Kubectl แปล .yaml เป็น JSON ก่อนจะส่ง request ไปคุยกับ K8s Master นั่นเองครับ
เรามาสร้างไฟล์ .yaml นี้กัน ผมให้ชื่อว่า my-spring-boot-web.yaml ไว้ใน folder ชื่อ k8s ดังนี้
วิธีที่ 1 สร้าง Deployment แบบ manual สุดๆ
สร้าง folder เก็บไฟล์
mkdir -p works/k8s
สร้างไฟล์
touch works/k8s/my-spring-boot-web.yaml
เข้าไป
cd works/k8s
เปิดด้วย VS Code
code .
วิธีที่ 2 ใช้ Kubectl สร้าง Deployment นี้ให้
สร้าง folder เก็บไฟล์ (มีแล้วให้ข้ามไป)
mkdir -p works/k8s
เข้าไป
cd works/k8s
รัน
kubectl create deployment my-spring-boot-web --image=openjdk:8-jdk-alpine --dry-run -o=yaml > my-spring-boot-web.yaml
ไม่ว่าจะสร้าง deployment ด้วยวิธีการไหน สุดท้ายอยากได้แบบนี้
Spring Boot with Gradle Project
ขั้นตอนถัดมาเราก็ต้องมีโปรเจกต์ Spring Boot ก่อน เชื่อว่าหลายคนรู้จักและเขียนพอเป็นแล้ว รายละเอียดโปรเจกต์
- ชื่อ my-spring-boot-web
- build tool: Gradle
- language: Java
- JDK version: 1.8
- spring boot starter: web
วิธีที่ 1 ใช้ Spring Initializr เว็บสร้างต้นแบบโปรเจกต์ให้
วิธีที่ 2 ใช้ curl ส่งคำขอไปดาวน์โหลดต้นแบบโปรเจกต์
curl https://start.spring.io/starter.tgz -d dependencies=web -d language=java -d javaVersion=1.8 -d type=gradle-project -d baseDir=my-spring-boot-web | tar -xzvf -
รายละเอียดการใช้ curl
เพิ่มหน้า index.html เพื่อแสดง Hello
เปิดโปรเจกต์ด้วย VS Code มองหา folder ชื่อ src > main > resources > static
จากนั้นสร้างไฟล์ชื่อ index.html โดยมีเนื้อหาดังนี้
<h1>Hello</h1>
สร้าง Docker File
ตามทฤษฎีแล้วเราจำต้องทำโปรเจกต์ให้เป็น containerized application คือทำให้เป็น container ได้ เครื่องคอมพิวเตอร์เราจึงต้องติดตั้ง Docker (ผมรู้จักแค่ Docker)
ติดตั้ง Docker บน MacOS
ตรวจสอบเวอร์ชัน
docker --version
Docker version 19.03.5, build 633a0ea
เนื่องจากเรายังคงอยู่ใน works/k8s
เข้าไปในโปรเจกต์ my-spring-boot-web แล้วสร้างไฟล์ชื่อ Dockerfile
รายละเอียด
FROM openjdk:8-jdk-alpineARG JAR_FILE=build/libs/*.jarCOPY ${JAR_FILE} app.jarENTRYPOINT ["java","-jar","/app.jar"]
จากนั้นสั่ง gradlew สร้าง jar
./gradlew build
โครงสร้างของ build folder ต้องสอดคล้องกับที่ระบุไว้ในไฟล์ Dockerfile
ตอนนี้เราอยู่ใน works/k8s/my-spring-boot-web นะครับ
สั่ง Docker build image ให้
โดยที่
- ชื่อคือ pros/my-spring-boot-web
- แท็กคือ v1
docker build . -t pros/my-spring-boot-web:v1
โดยที่
- . (dot) หมายถึง directory ปัจจุบัน
- -t หมายถึง tag รูปแบบคือ name:tag
ผล
ending build context to Docker daemon 18MB
Step 1/4 : FROM openjdk:8-jdk-alpine
---> a3562aa0b991
Step 2/4 : ARG JAR_FILE=build/libs/*.jar
---> Running in 2db1e66e40ea
Removing intermediate container 2db1e66e40ea
---> cad60c579e4c
Step 3/4 : COPY ${JAR_FILE} app.jar
---> b7933d1ce73c
Step 4/4 : ENTRYPOINT ["java","-jar","/app.jar"]
---> Running in a2dae0d2b450
Removing intermediate container a2dae0d2b450
---> 598eab900b0d
Successfully built 598eab900b0d
Successfully tagged pros/my-spring-boot-web:v1
ดูว่าตอนนี้มี image อะไรบ้าง
docker images
ผล
REPOSITORY TAG IMAGE ID CREATED SIZE
pros/my-spring-boot-web v1 598eab900b0d 33 minutes ago 122MB
openjdk 8-jdk-alpine a3562aa0b991 8 months ago 105MB
Spring Boot Web นี้ใช้ Apache Tomcat เป็น web server และมี default port ที่ 8080 เราจะรัน image นี้ให้เป็น container และทดลองติดต่อที่ port 9000
docker run -p 9000:8080 pros/my-spring-boot-web:v1
ผล
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.4.RELEASE)
เปิด Browser ส่งคำขอ
localhost:9000/
ผล
จากตรงนี้ขอให้เข้าใจว่าเมื่อไรก็ตาม Docker อ่าน Dockerfile เราได้ระบุไปว่าให้โหลด (FORM) image ชื่อ openjdk แท็ก 8-jdk-alpine จากนั้นประกาศตัวแปรชื่อ JAR_FILE เก็บ path ของ .jar ที่ได้จาก Gradle Build จากนั้นจะคัดลอก (COPY) ไฟล์ .jar ดังกล่าวแล้วเปลี่ยนชื่อเป็น app.jar สุดท้ายระบุคำสั่ง (ตรงไปตรงมา) ว่าจะ execute app.jar นี้อย่างไร
มีการโหลด image หนึ่งครั้งและสร้าง image อีกหนึ่งครั้ง ตอนนี้ในเครื่องของเราจึงมี 2 images พอเข้าใจนะ
Docker Push
เข้าใจว่า image ที่เราสร้างขึ้นสามารถนำไปแชร์ให้ชาวบ้านได้ ใครที่ติดตั้ง Docker ก็คงมี Docker Account กันทุกคน อย่างของผมก็คือ prosbeginner account
login เข้าใช้งาน account บน https://hub.docker.com/
จากนั้นทดลองสร้าง repository (ไว้เก็บ image) มาปล่าวๆสักชื่อก่อน เอาเป็น
spring-boot-web
คราวนี้กลับมาติด tag ให้กับ image เจ้ากรรมกันนะ เราจะได้ส่งมันไปอยู่กับ Docker Hub อิอิ
docker tag pros/my-spring-boot-web:v1 prosbeginner/spring-boot-web:v1
ขึ้นไปเลยจ้า
docker push prosbeginner/spring-boot-web:v1
ผล
แก้ไข Deployment
เอาล่ะ เรามี image ที่ต้องการแล้วอยู่บน Docker Hub มาเร็ว เปิดไฟล์ my-spring-boot-web.yaml ที่ได้สร้างไว้ก่อนหน้านี้
แก้ไข
ให้ deployment นี้ไปดึง image มาจาก Docker Hub ส่วน container name ก็ตั้งเอาตามใจชอบ ผมขอเปลี่ยนเป็น spring-boot-web เฉยๆแล้วกัน
เพียงเท่านี้ภาพในใจเราก็จะสมบูรณ์แล้ว
ถ้าไม่นับรวม Pod ที่เกิดขึ้นก่อนหน้านี้ก็เท่ากับว่าสิ่งที่เราต้องการได้ครบองค์ประกอบแล้ว ทบทวนอีกสักรอบ
- เราติดตั้ง Minikube เท่ากับว่าเครื่องของเรามีสภาพแวดล้อมของ cluster ซึ่งดูแลโดย K8s
- เราได้เตรียม application ที่มีคุณสมบัติเป็น container ได้โดยใช้ Docker
- image ที่ได้จากการเตรียม application เราได้ push ไปไว้บน Docker Hub
- แล้วเราก็จะสั่งให้ Kubectl อ่านไฟล์ deployment เพื่อ pull image จาก Docker Hub สร้างเป็น Pod หรือที่เรียกว่า application instance ภายใน Node
- โดยที่ Node เป็นตัวแทนของเครื่องของเราครับ
ดังนั้น deploy application เข้าสู่ K8s ได้เลย
สั่ง apply deployment ก่อน
kubectl apply -f my-spring-boot-web.yaml
รอสักพักให้มัน pull image จากนั้นพิมพ์ดูสถานะของ deployment นี้
kubectl get deployments
ผล
NAME READY UP-TO-DATE AVAILABLE AGE
k8s-bootcamp 1/1 1 1 9h
my-spring-boot-web 1/1 1 1 35s
งดงาม
ขอดู Pod ทั้งหมดหน่อยสิ
kubectl get pods
ผล
NAME READY STATUS RESTARTS AGE
k8s-bootcamp-844bd7dd7-swqrt 1/1 Running 0 9h
my-spring-boot-web-8bc67bd9c-fr88d 1/1 Running 0 12m
เป็นที่เรียบร้อย desired state ลุล่วงไปด้วยดีครับ สรุปเป็นภาพได้ดังต่อไปนี้
หมายเหตุ
ถ้าต้องการลบ deployment คำสั่ง
kubectl delete -f my-spring-boot-web.yaml
ถ้าต้องการดูรายละเอียดของ Pod ใดๆ ให้เอา Pod Name มาหาดู เช่น
kubectl describe pod my-spring-boot-web-8bc67bd9c-fr88d
ถ้าต้องการดู K8s Object ทั้งหมด
kube get all
ผล
NAME READY STATUS RESTARTS AGE
pod/k8s-bootcamp-844bd7dd7-swqrt 1/1 Running 0 9h
pod/my-spring-boot-web-8bc67bd9c-fr88d 1/1 Running 0 22mNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23hNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/k8s-bootcamp 1/1 1 1 9h
deployment.apps/my-spring-boot-web 1/1 1 1 22mNAME DESIRED CURRENT READY AGE
replicaset.apps/k8s-bootcamp-844bd7dd7 1 1 1 9h
replicaset.apps/my-spring-boot-web-8bc67bd9c 1 1 1 22m
อ่านที่เกี่ยวข้อง
อ้างอิง
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
https://docs.docker.com/engine/reference/commandline/push/
https://spring.io/guides/gs/spring-boot-kubernetes/
https://www.slideshare.net/yokawasa/kubernetes-x-paas-noops