The Cloud Camp Week#06 (K8S Part1:Overview)

สัปดาห์นี้เป็นสัปดาห์ที่ 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:

วันนั้นได้ลองเล่น 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 เจ้า

- 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
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


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.