สัปดาห์นี้เป็นสัปดาห์ที่ 6 แล้ว งานเยอะระดับนึงครับ แน่นเลย และเรื่องวันนี้แน่นมาก และเป็นเรื่องใหม่ เคยได้ยิน แตะบ้าง แต่ไม่ได้ invest กันมันสักเท่าไหรครับ Container Orchestration โดยหัวข้อจะมี ดังนี้
Sketch Note
ภาพรวมของ 2 วันแรก ภาพใหญ่จนเอาขึ้นไม่ได้ 555
Why Kubernetes & Benefit
สัปดาห์ที่ 2 จะมีบอกว่าทำไมต้องใช้ตัว Container Orchestration ย้อนกลับไปดูได้จาก Blog The Cloud Camp Week#02 ครับ) หรือ มาอ่าน Recap สั้นๆ
ยุคแรก เอา Code ไป Deploy ที่เครื่องเป้าหมาย ไม่ว่า Copy/Paster SFTP Git แต่ยังมีปัญหา Version App / Runtime / Library (Dependency) ที่ไม่ตรงกัน
ยุคถัดมา Container เข้ามาช่วยแก้ปัญหาได้ แต่ยังมีปัญหาเวลาที่มี Load เยอะ ต้องเพิ่ม Container ช่วยแบ่ง Load แต่การดูแลจัดการยากเหมือนกัน ถ้าค้าง ขึ้นมา หรือต้อง Upgrade
ตอนนี้ - Container Orchestration เข้ามาช่วยแก้ปัญหาการจัดการ Container ให้สะดวกขึ้น
ตอนนี้ตัวที่เด่น Kubernetes (K8S) ที่นิยมใช้กันโดยจะมีจุดเด่น
- Restart, Redeploy, Create new Application, Rollback Deploy สามารถคุมชีวิตของ App ได้ตามที่กำหนด เราไม่ต้องมาดูเอง
- Deployment Risk free - แยก ReplicaSet เป็นของ V1 / V2
- Continuous Deployment
- Scalability
- Observability
- Security & Compliance
Kubernetes Overview
อันนี้เป็น Keyword 4 คำ เพื่อให้เข้าใจส่วนอื่นๆ ได้แก่ Pods / Deployment / Service / Ingress
- Pods
- มาจากฝักถั่วนะ ตอนแรกผมคิดว่าเป็นหม้อ 55
- Pods เป็น หน่วยที่เล็กที่สุด โดยมี Infra พื้นฐาน เพื่อให้ Container ทำงานได้ พวก Port / Image / Storage / Environment (Config ต่างๆ) เป็นต้น
- Ports - เหมือน docker เลยบอกว่าจะ Expose Container Port ออกมาที่ Port ไหน
- Image - Image Registry
- Resource - Limit Resource ที่ใช้งานได้
- Storage
- ทุก Container ใน Pod Share Storage ร่วมกันนะ
- อย่าลืม Mount ถ้า Pod ตาย หายหมด - Life Cycle
- Pod มีเกิด แก่ เจ็บ และตาย โดยใน K8S มีกำหนด State เหล่านี้ไว้
- และมีทำ Probe เพื่อเอาไว้ตรวจ Check และเลี่ยงไปให้ส่ง Traffic เข้าไป - Environment - ส่วนสำหรับ Set ตัวแปรของแต่ละ Container เข้าไป พวก appsetting.json ของ dotnet เป็นต้น
- ปกติแล้ว 1 Pod ใส่ Container 1 ตัว แต่อาจจะมีบางเคสที่มีหลาย Container ใน 1 pod เช่น ทำ
- adapter เอามาแปลง input ก่อนเข้า container หลัก เช่น การ convert format
- inject ส่วนเสริม เพิ่มความสามารถเข้าไป เช่น network
- distroless จะใช้แนวคิดนี้เข้าไป access ดู distroless container
Keyword: Multi-Container Pod Design Patterns
- Pods มันอยู่ในมี Life Cycle ถ้ามันตายไป ข้อมูลหายนะ
Ref: Pods | Kubernetes
- Deployment
คำนิยามของ Infra ของเรา ว่าจะต้องมีอะไร (desired state) จะทำแบบ Imperative ใช้ command / declarative YAML คล้ายๆกับ docker compose file โดยหลักๆ มาคุมการทำงานของ pods และ ReplicaSet
ReplicaSet = ตัวควบคุมจำนวน pods ให้พร้อมใช้งาน ตามที่กำหนดใน Deployment หรือจะมองเป็น Environment
- เก็บได้ 10 revision ถ้ามีปัญหาเกิดขึ้น Rollback ได้ ปกติจะใช้ 2 - 3 revision
Strategy (spec.strategy.type)
- RollingUpdate - ทยอยสร้าง และลบ pods ตามเงื่อนไข ช่วยเรื่อง Zero Downtime ค่อยๆขยับที่ละ pod แล้วจึง Switch Traffic ของให้ User เข้ามา
- maxSurge: จำนวน pod ที่ถูก create ระหว่างการ update
//The number of pods that can be created above the desired amount of pods during an update
- maxUnavailable: จำนวนของ Pod ที่ใช้งานไม่ได้ (ถูก terminate) ระหว่างการ Update
//The number of pods that can be unavailable during the update process
จริงๆ 2 param นี้ ถ้ากำหนดค่าต่างกัน น่าจะทำได้หลายแบบ Blue/Green , Canary เป็นต้น - Recreate - ลบ pods ให้หมด แล้วสร้างใหม่
- Service (Virtual Load Balancer)
เพราะเรายกหน้าที่ การจัดการ Pods ให้ ReplicaSet ดังนั้นเราจะไม่รู้ว่าการจะเข้าถึง Pod แต่ละอันต้องมา Link ยังไง ดังนั้น Service เป็นตัวที่เข้ามาช่วยจัดการ Requests เข้าไปใน Pod (L4 public ip)
Ref: Service | Kubernetes / - ClusterIP, NodePort, and LoadBalancer: Kubernetes Service Types | Baeldung on Ops
- Ingress
เป็นตัวที่เอามา Map Request จากข้างนอก และมาจัดการส่งต่อ (Routing Rule) ให้กับ Service แต่ละตัว อารมณ์จะเหมือนตัว DNS Service (ทำใน L5-7)
Ref: Ingress | Kubernetes
Kubernetes Architecture (Basic)
ตัว K8S มีการทำงานแบบ Client (kubectl) / Server
- Kubernetes Component
Client: kubectl
Server: แยกเป็น 2 ส่วน
- Controlplane(Master Node) มีตัว
- kube-apiserver รับ Request จาก kubectl มากระจายให้แต่ละ Cluster ต่อ - Node (Worker Node) มีตัว
- kubelet เข้ามาค่อยจัดการ POD
- pod
- Kubernetes Context (group of access parameters)
Context มองว่าเป็น Config อารมณ์แบบ .ssh/config ที่เก็บการตั้งค่า เพื่อให้ kubectl มาปั๊น request (user + key และ cluster) ส่งเข้ามาให้ kube-apiserver รับและจัดการต่อ สำหรับ Context จะเก็บ 2 ที่
- $HOME/.kube/config
ถ้าบน Windows จะเป็น Path C:\Users\<<YourUsername>>\.kube - $KUBECONFIG (env)
Kubernetes Command (Context)
- kubectl config view - ดู Context ทั้งหมดที่มีในเครื่อง ออกมาเป็น YAML
- kubectl config get-clusters - แสดง cluster ที่มี
- kubectl config get-users - แสดง user ที่มี
- kubectl config get-contexts บอก Context ทั้งหมด
- kubectl config current-context บอก Context ปัจจุบัน จริงๆใน get-contexts มี * บอกอยู่นะ
- kubectl config use-context [CONTEXT_NAME] บอกต้องการใช้งาน Cluster ไหน ดูก่อนใช้ก็ดี ผมทำการบ้านผิด Cluster มาแล้ว 5555
kubectl config use-context [CONTEXT_NAME]
Kubernetes Setup
Test Cluster: สำหรับทดสอบ จะมีตัว Minikube / kind / MicroK8S / Docker Desktop มี Build-In K8S
Production Grade:
- Open-Source:
- Kubeadm / kops: Kubernetes Operations (kOps) / kubespray / K3s / Talos (เดี๋ยวมี Blog ตามมา) - Commercial Tools:
- Rancher / Red Hat OpenShift / VMware Tanzu - Cloud Manage Service: เราไม่ต้องมาจัดการ Controlplane(Master Node)
- Regional Amazon (EKS) / Google (GKE) / Microsoft (AKS) / DigitalOcean (DOKS)
- Local Cloud Kubernetes Service - PROEN Cloud
วันนั้นได้ลองเล่น Hello Minikube | Kubernetes อิอิ
Kubernetes Architecture (Advance)
- API - Access Control
[ K8S ] USER ---Request---> [ Authentication > Authorization > Admission Control > Resource]
- Authentication - ตรวจว่าเข้าใช้งานระบบได้ไหม ใช้ตัว x509 แลก key โดย User มี 2 แบบ
- External Account เมื่อตรวจสิทธิผ่านแล้ว จะส่งให้ Service Account จัดการต่อ
- Service Account - เป็นตัวที่เข้าไปจัดการงาน Technical ต่างๆ - Authorization - RBAC ตรวจ Service Account ว่ามีสิทธิ์อะไร
- Admission Control
- ตรวจพวก Policy / Governance ว่าสามารถทำอะไรได้บ้าง เช่น สร้าง Resource อะไรได้บ้าง Max CPU / Mem เท่าไหร่ หรือ ต้องใช้งาน Container Registry ที่ Trust เท่านั้น
- Tools: Open Policy Agent
- Container Runtime in Kube
[ ] kubelet --CRI--> [ <CRI Plugin> | Container ] [ ]
Container Runtime สามารถใช้กับ KUBE ได้หมด ถ้า Implement ตาม Container Runtime Interface มีดังๆ 3 เจ้า
- containerd : ตัว K8S ใช้งาน เพราะเล็ก มี Performance ดี
- cri-o : podman
- docker : dockershim เมื่อก่อนอยู่ใน K8S แต่ถูกเอาออไป (Ref: Don't Panic: Kubernetes and Docker | Kubernetes)
- Control Pane & Node Component
Control Pane (Master Node)
- etcd : เป็น key value database เอาไว้เก็บ State ของ K8S ในกรณีที่ขึ้น K8S แยก ควรแยก ectd ออกมาเป็น manage service อีกตัว จะได้ monitor สะดวก port 2378 / 2379 //เดี๋ยวไปหาเพิ่ม
- kube-scheduler : ตรวจ POD ที่กำลังจะสร้าง ควรลงที่ Node ไหน และมี Resource เพียงพอไหม
- kube-controller-manager : จัดงานพวก non terminate control loop เช่น พวก replicaSet ต้องมี ReplicaSet Controller มาจัดการให้ได้ Pod ตาม Desired ที่กำหนดไว้
ตัวอย่างอื่นๆ มี StateFul / DeamonSet - Cloud Controller Manager (Optional) : สำหรับมาใช้ Resource ที่อยู่บน Cloud เช่น S3 / Azure File
- kube-proxy : มีเหมือนกันนะ Control Pane เป็น node หนึ่งเหมือนกัน
Node (Worker Node)
- kube-proxy
- จัดการ traffic in/out ของ POD เช่น มี Request เข้ามาใช้งาน จริงๆแล้วตัวนี้มัน คือ Service core-dns round-robin
- ถ้ามันตายไป จะหา Resource ไม่เจอ - kubelet ตัวมาเรียกใช้ container runtime อีกที
พวก Seq Diagram จะมันจะมาตอบตรงนี้ ถ้ารู้ว่าอะไรทำอะไร จะได้ดู Log ได้ว่าของ etcd / kube-scheduler (ถ้าdeploy pod ไม่ได้)
How kube-scheduler work
choosing the right node ดูจาก Requirement
- ยุคแรกเป็น Manual - ตอนนี้เป็น Option นึงนะ nodeName / nodeSelector / Node Affinity
- ปัจจุบัน Algorithm Base (ยังไม่เป็น AI นะ) โดยดูจาก
- traffic - traffic เยอะ แต่ resource ว่างก็ไม่ลงนะ traffic มันเต็ม request timeout ได้เหมือนกัน)
- HW: CPU / MEM
มาเทียบกับ Application Requirement ที่เราขอไป (ตอนย้ายไป Cloud เอาพวกนี้ CPU/Mem ใน Application Requirement กำหนด Instance Type ได้ชัดเจน)
apiVersion: v1 kind: Pod .... resources: requests: cpu: 100m memory: 100Mi
ถ้าไม่ได้กำหนด Application Requirement kube-scheduler จะดูจาก Policy เช่น เอา Node เหลือเยอะสุดก่อน เป็นต้น
ในตอนนี้ Pod State เป็น Pending หาที่ลงอยู่ ถ้าได้แล้ว จะเป็นหน้าที่ kubelet - start container แต่ถ้าใน Application Requirement ขอเยอะไปจากที่ Node มันมี Resource เหลือ อยู่ มันจะ Fail และพยายาม Retry หา
ปกติถ้าใช้บน Cloud ส่วนนี้เราจะไม่ได้มาจัดการเอง นอกจากว่าจะใหญ่มากๆ ขอ Dedicate Control Pane เข้ามาจัดการเอง เพื่อปรับจูนให้เสีย Cost น้อย / Perf ดีสุด
ตอนนี้ ARM เริ่มมาและ Cloud หลายๆเจ้ามี Resource ให้ใช้ด้วย
Ref: Assign Pods to Nodes using Node Affinity | Kubernetes
kube-network
สำหรับ K8S มี use-case การใช้ Network ดังนี้
- (1) Container-to-Container communications >> จับรวมอยู่ใน Pod แต่ละ pod มี IP เป็นของตัวเองนะ
- (2) Pod-to-Pod communications >> overlay network มีมาในตัว ไม่ต้องทำเพิ่มแบบ docker
- (3) Pod-to-Service และ (4) External-to-Service ใช้ kube-proxy + packet filter + CoreDNS for Service Discovery
นอกจากนี้แล้วยังมี Node > Pod (ภายใน และข้าม Node) รวมถึงการรองรับ NAT ด้วย ใน K8S เองจะมีคน Implement Network Driver 4 ค่าย
- Project Calico (Default)
- Weave
- Cilium - Service Mesh และไม่ใช่ SideCar ไปใช้ Kernel UserSpace เลย เลยไวขึ้น
- flannel - Support Windows Container
พอมีหลายค่าย แล้วเราจะเลือกจากอะไร
- Container ที่ใช้งาน Linux Based หรือ Windows Based
- รองรับการทำ Network Policies ไหม Internal Firewall อารมณ์แบบ App ต่อได้กับ DB ตาม IP Range หรือ CIDR
How to Create POD
มี 2 แนวทาง Imperative Command และ Declarative file คำสั่งที่จำเป็น
- create new pod จากคำสั่ง run (Imperative Command) บอก image เข้าไป
--image บอกที่มาของ image
--dry-run ยังไม่ได้ Execute บน Cluster(Node) ให้มัน Generate yaml file มี 2 แบบ Client (ใช้งานข้ามเครื่องได้) / Server
Note ถ้าไม่ได้ใช้ Option นี้มันจะสร้างบน Cluster(Node) เลยตาม Context ที่กำหนดไว้
--port=80 เปิดใช้ port
-o = output + type
kubectl run [PODNAME]--image=[IMAGENAME] -o kubectl run nginx --image=nginx --dry-run=client -o yaml > nginx.yaml
apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: nginx name: nginx spec: containers: - image: nginx name: nginx resources: {} dnsPolicy: ClusterFirst restartPolicy: Always status: {}
- Create a nginx pod with nginx.yaml file by apply -f command (Declarative file)
kubectl apply -f [file.yaml หรือ file.json] kubectl apply -f nginx.yaml //ถ้ารันซ้ำ มันจะ redeploy ใหม่
- List the pod with get command
-w options = watch
kubectl get pods -w NAME READY STATUS RESTARTS AGE nginx 0/1 ContainerCreating 0 2s nginx 1/1 Running 0 7s
- Get Pod information
kubectl describe pods kubectl describe pods [POD_NAME]
- Get pod logs
-p = previous pod instance กรณีที่ pod ตายไป หรือมี deploy ทับ
kubectl logs [POD_NAME] kubectl logs nginx -p
- Get pod logs for multiple container in same pod
kubectl logs [POD_NAME] -c [CONTAINER_NAME] kubectl logs [POD_NAME] --all-containers=true #=========================================== #Sample kubectl logs nginx-deployment-7c79c4bf97-c6fx6 -n test-talos -c nginx
- Get pod log for previous container to view crash log.
ref: View log files of crashed pods in kubernetes - Stack Overflow
kubectl logs [POD_NAME] --previous
- Execute a simple shell on the pod
kubectl exec -it nginx -- bin/sh
- Create Sigle Use Pod with --rm
kubectl run busybox2 --image=busybox -it --restart=Never -- /bin/sh -c 'echo hello world' kubectl run --rm -it --tty pingkungcurl1 --image=curlimages/curl --restart=Never -- dbservice.investdb:1433
- Create an nginx pod and set an env value as 'var1=val1'. Check the env value existence within the pod
kubectl run nginx --image=nginx --restart=Never --env=var1=val1 kubectl describe pods nginx | grep val1
K8S Namespace
เอามาจัดกลุ่มของ Pod โดยอาจจะจัดตาม Role / Tools / Teams / Project / Env (Dev, SIT, Prod) แต่ถ้าจะให้เรียกใช้ชื่อได้ ต้องมี Service มาช่วยเสมอ พลาดเรื่องนี้ไปจำแม่นนนน DNS pattern รูปแบบ <service-name>.<namespace> เช่น
curl proddb-svc.prod_db:5001 #service = proddb-svc #namespace = prod_db ดู service namespace และ port จาก kubectl get pod,svc -A
Investigate Note
- Logs ก่อน
- ถ้าเลวร้าย kube-system ตรวจก่อนว่ามันตายไหม ถ้า kube-apiserver ตาย ต้องเข้าเครื่องที่ตั้ง Node นั้นดู Log
วันเสาร์ที่มี Mission ให้ทำร่วมกัน เข้าใจเรื่อง Context / Pod เยอะเลย จริงๆมีทำ Assignment 1 มาก่อนเลย เลยไวอยู่ แต่อีก Namespace ตอนเรียนวันศุกร์เข้าใจผิดว่าเอา Namespace อย่างเดียว curl ได้ 5555 ติดมาพักใหญ่เลย ได้ทำ Mission เข้าใจแจ่มแจ้ง
ปล. วันนี้วันแยกร่างมาก มีแว๊บไปทำงานพักใหญ่ๆด้วย
Reference
- The Cloud Camp by Jumpbox
- What is the difference between namespaces and contexts in Kubernetes? - Stack Overflow
- Docker - Everything curl
- Assigning Pods to Nodes | Kubernetes
- ใครที่สนใจ Sketch Note ดูเพิ่มได้จาก [micro-learning] สรุป Verbal to Visual Note Taking | naiwaen@DebuggingSoft
- Kubernetes for Dummies: A Simple and Practical Introduction to Container Orchestration and Ecosystem (c-sharpcorner.com)
- Kubernetes recipes: Maintenance and troubleshooting – O’Reilly (oreilly.com)
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.