ศึกษา Kubernetes ด้วยตนเอง part 2/2: Overview and Practice

Phai Panda
9 min readFeb 2, 2020

--

บทความนี้เราจะพูดถึงความคิด (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

วาดภาพมา

Container Deployment

จากภาพจะเห็นว่า 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

~/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
สร้าง empty repository
ยังไม่มี image เลย
ตรงนี้มีปุ่ม Public View กับ docker command สำหรับ push image มาเก็บไว้

คราวนี้กลับมาติด 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 ที่ได้สร้างไว้ก่อนหน้านี้

แก้ไข

เปลี่ยนเป็นชื่อและแท็ก image ที่อยู่บน Docker Hub

ให้ deployment นี้ไปดึง image มาจาก Docker Hub ส่วน container name ก็ตั้งเอาตามใจชอบ ผมขอเปลี่ยนเป็น spring-boot-web เฉยๆแล้วกัน

เพียงเท่านี้ภาพในใจเราก็จะสมบูรณ์แล้ว

Container Deployment

ถ้าไม่นับรวม 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 22m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h
NAME 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 22m
NAME 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

--

--

No responses yet