The Cloud Camp Week#07 (K8S Part2:K8S Object)

สัปดาห์นี้เป็นสัปดาห์ที่วุ่นวายอีกสัปดาห์ มีเคส DB2 TableSpace Drop Pending / และ Podman เอ๋อๆครับ เอาหละมาดูหัวข้อที่เรียนของวันนี้กันครับ

เพื่อความไม่ขาดช่วง มาดูของ Week ก่อนได้ครับ The Cloud Camp Week#06 (K8S Part1) | naiwaen@DebuggingSoft

Kubernetes Object

ตัว Object เป็นคำรวมๆที่เอาไว้อธิบาย ส่วนของ K8S (abstract รวบ เพื่อให้จัดกลุ่ม) เพื่อ

  • กำหนดจัดการ (How to handle) เช่น replicaSet / namespace เป็นต้น
  • อธิบาย (Describe) เช่น Pod Life Cycle / Self Healing / Image pull จาก registry ไหน เป็นต้น

ตัว Kubernetes Object ยังแบ่งมุมมองได้อีก 2 มุม

  • Workload (ตามหน้าที่ ภาระ) - สิ่งที่ยุ่งเกี่ยวกับ Traffic + Container เดี๋ยวมีอธิบายหัวข้อต่อไป
  • Infra - ส่วน Foundation เช่น
    - การสื่อสารระหว่าง App
    - Network + Security
    - Node + Auto scale >> HPA
    - การควบคุม Resource

นอกจากการจัด Object แล้ว ตอน Deploy Container ไปยังสามารถจัดกลุ่มด้วย namespace (แยก network) และ label

YAML File

ตัว K8S เราสามารถอธิบายสภาพของระบบว่ามีลักษณะอย่างไร (Desire State) ประกอบด้วย Kubernetes Object อะไรบ้าง หน้าที่ของ K8S มันจะทำข้อตกลง "record of intent" ตามที่เราระบุไป ตอนนี้ที่เห็นแล้วจะเป็นตัว replicaSet ที่มาช่วยให้ Pod อยู่ตามที่ตกลงไว้

การอธิบายไฟล์ที่กำหนดตัว Desire State จะมี 2 รูปแบบ YAML / JSON ตอนนี้จะอธิบายตัว YAML (key:value + เรื่อง indent) ก่อนว่ามีส่วนประกอบอะไรบ้าง

  • apiVersion - บอก Version ของ K8S Object
    ถ้า update node ของ K8S ต้อง แล้วมี apiVersion Update / Deprecate อาจจะเกิด Downtime
  • kind - object ที่ deploy เช่น pod / deployment
  • metadata - ข้อมูลของ object ที่จะ deploy
    - name ต้อง unique ถ้าทำเป็น replicaSet pattern ชื่อ จะเป็น [name]-[replicaSetKey]-[RunningNo] เช่น nginx-wear22359-ff158
    - label
    - namespace
  • spec ความสามารถของ object ตาม kind + apiVersion

สำหรับคำสั่งนอกจาก kubectl apply [-f FILENAME | -k DIRECTORY] มี kubectl create ด้วย
Ref: Kubectl Apply vs. Kubectl Create - What’s the Difference? (spacelift.io)

Workload Object

  • ReplicaSet
    - เป็นตัว Horizontal Scale แบบนึง แต่เป็น Manual นะ โดยหน้าที่ของมัน ทำยังไงก็ได้ให้มี Pod พร้อมตามที่กำหนดไว้ (ensure desire number of POD)
    - Improve Availability
  • Deployment
    - ในภาพผม มันเป็น docker compose ที่รวมไว้ ท้ายที่สุดแล้วตัว Application มีอะไรบ้าง มี lifecycle ยังไง
    - ตอนนี้มีตัว ReplicaSet มาช่วยอยู่ โดยควบคุมจากตัว Deployment Strategy มีจดในหัวข้อถัดไป
  • StatefulSet
    - คุมงานต้องเป็น Stateful มีลำดับขั้นตอน เช่น db / redis / queue / nosql
    - ปกติจะได้ Fix IP
    Note มันจะมี DB อีกแบบที่ไม่ใช้ Stateful เรียกว่า distribute database
  • DaemonSet
    - ตัวที่ช่วยทำให้มั่นใจได้ว่า เมื่อมี node ใหม่ขึ้นมา รวมถึงตัว controlpane จะต้องมี Pod ที่จำเป็นขึ้นมาพร้อมใช้งานเสมอ ตามที่กำหนด
    - งานที่ใช้งานหลักๆจะเป็นพวก monitor logging เช่น ถ้ามีขึ้น node ใหม่ ให้ขึ้น Pod ของ node-exporter ขึ้นมาด้วยเสมอ
  • Job
    - ทำงานพวก batch (run one shot script) แล้วจบ เบื้องหลังสร้าง temporary pod ทำงาน เช่น Curl รวมถึงมี machanism การทำ Flow Retry / ทำซ้ำ
  • CronJob
    - Job ที่ตั้งเวลาได้
  • Pod
    - เล็กสุด ปกติ 1 Container / Pod
    - ถ้าเอาหลาย Container ทำเป็น Multiple Container ได้ แต่ Shared IP ปกติ 3-4 Pattern
    => Sidecar Pattern - เอามาจัด Log Format
    => Adapter
    => Ambassador
    - Init Container

ตอนนี้ผมเข้าใจว่า StatefulSet / DaemonSet / Job / CronJob มัน คือ Deployment ที่มี Specific Purpose Deployment

ตัวอื่นๆ เผื่อมีในสัปดาห์ถัดไป What Are Objects Used for in Kubernetes? 11 Types of Objects Explained. (kodekloud.com)

Infra Object

  • Configmap - เก็บข้อมูลเล็กๆ
  • SecretMap - Configmap Encrypt Base64
  • Service - ให้คุยกันโดยใช้ dns name ได้
  • Ingress - เข้าจขากภายนอก
  • Endpoint - Proof ว่า Service เชื่อมต่อกับ IP ได้ - CoreDNS + KubeProxy

Interacting with Kubernetes

Recap คำสั่งต่างที่ควรรู้ว่าจริงๆ มันมีอะไรลึกกว่านั้น

  • kubectl --help
  • kubectl api-resources : บอก Resource ที่ใช้งานงานได้บน K8S ที่เราติดตั้ง
    - apiVersion
    - kind
    - namespace T = ใช้ได้ตามกำหนด / F = ClusterWide
    - สร้าง resource เองก็ได้นะ
  • kubectl explain pod : man ใน linux อธิบาย command ได้ โดยเริ่มต้นจาก apiVersion / kind / metadata / spec / status ถ้าอยากได้อะไรเพิ่ม . ต่อท้ายไปเรื่อยๆ ตามรูปครับ
    ปล. ดูในเว็บได้เหมือนกัน Kubernetes API | Kubernetes

นอกจาก kubectl มี Tools อื่นมาช่วยด้วย

พอเรามี Declarative File เยอะๆ พวก pod / deployment + Specific Purpose Deployment / service สามารถทำเป็นทำ Charts เป็น Package + Template โดยใช้ Helm จัดการ นอกจากนี้มันมีคนอื่นทำไว้ และแชร์ ไว้ใน Artifact Hub โดยเราสามารถใช้ตัว Helm ดึงออกมาใช้งานได้

Deployment Indepth

ไม่แน่ใจเหมือนกันว่าสัปดาห์หน้าจะลงรายละเอียด เพิ่มไหมนะ เพราะ Blog ตอนก่อนหน้ามีอธิบายไว้ระดับนึงแล้วครับ

- Intro มาจาก Week ก่อน

คำนิยามของ 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 ให้หมด แล้วสร้างใหม่
- YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: euraka
  name: euraka
spec:
  replicas: 2
  revisionHistoryLimit: 3   #<< MAX 10
  selector:
    matchLabels:
      app: euraka
  strategy:
   type: RollingUpdate
   rollingUpdate:
       maxUnavailable: 0
       maxSurge: 2
  #template = กำหนด spec ของ pod เอาจาก doc ของ pod มาใส่ได้เลย
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: euraka
    spec:
      containers:
      - image: springcloud/euraka
        name: euraka
        resources: {}
        ports:
        - containerPort: 80
- Deployment Strategy Example

ขยายความจากที่ Intro ตอนต้น Strategy

Rolling Update ทยอยขึ้นที่ Pod ตามค่า maxSurge / maxUnavailable กำหนดได้แบบ % ที่ >=0 และจำนวนเต็ม >= 0 ตัวอย่าง เช่น

  • maxSurge 25%
    > ถ้ามี 5 Pod จะมี ยอมให้ Deploy ได้ทีละ 2 Pod (จริงๆได้ 1.25 แค่เศษปัดชึ้น)
  • maxUnavailable 25%
    > ถ้ามี 5 Pod จะมี ยอมให้ Terminate ได้ทีละ 1 Pod (จริงๆได้ 1.25 แค่เศษปัดลง)
    > best practice = 0 ไม่ให้ Terminate ลด Downtime
    ขึ้นให้ครบ แล้ว switch traffic

maxSurge = ต้องดู Resource ของ Server ด้วยนะ ถ้ามี 1000 Pod กำหนด maxSurge 25% แสดงว่า มันจะสร้างอีก 250 ตัว ตัว Server มี Resource รองรับ Pod 1,250 ตัว

maxSurge / maxUnavailable มีค่า default ที่ 25%

Recreate

  • มันเป็น Rolling ที่ maxSurge=100% / maxUnavailable=100%
  • พอย้ายครบ Replica จะทำให้เกิดการ Keep Revision (อารมณ์ Blue/Green)
  • ใช้กับพวก Stateful Set

เหมือนมีหลาย Pattern เลย 8 Kubernetes Deployment Strategies: Roll Out Like the Pros - Spot.io

- Deployment revisionHistoryLimit
  • เป็น History ของ replicaSet โดยจะ Keep Revision เมื่อย้าย Pod ครบทุกตัวใน replicaSet
  • เก็บได้สูงสุด 10 ตัว แต่ปกติ จะใช้ 3 revision หรือไม่ใช่เลยไปทำ GitOps แทน
  • มี revision เยอะๆไม่ได้กินพื้นที่เยอะ มันเก็บ Config และ Restore กลับตามที่เราสั่ง ถ้าสั่งแล้ว มันจะดึง image จาก cache ใน k8s ถ้าไม่มีไปใช้ internet ไปดึงจาก registry
- Command
  • Create Deployment
kubectl create deployment euraka --image=springcloud/euraka --dry-run=client -o yaml > euraka.yaml
#List all files from current directory in your terminal:
ls
cat euraka.yaml
  • Scale Replica จริงๆเข้าไปแก้ไฟล์ yaml ตรงๆได้
kubectl scale deployment euraka--replicas 2

#get the YAML (Server Side) of this deployment
kubectl get deployment euraka -o yaml > euraka.yaml
  • Set New Image Version
kubectl set image deployments euraka euraka=netflixoss/eureka:1.3.1
  • Roll Out New Version
kubectl rollout status deployment euraka 

Pod LifeCycle

stateDiagram-v2 Pending: Pending note left of Pending kube-scheduler หา node pod pull image / create container end note Running: Running note left of Running At least one container is still running, or is in the process of starting or restarting end note Succeeded: Succeeded note right of Succeeded terminated in success [Graceful Shutdown exit(0)] end note Failed: Failed note right of Failed terminated [exit != 0 ] เช่น PullImageError / CrashLoopBackOff / ImagePullBackOff end note Unknown: Unknown note right of Unknown ไม่สามารถติดต่อกับ Node / Pod ได้ end note [*] --> Pending Pending --> Running Running --> Succeeded Running --> Failed Pending --> Unknown Running --> Unknown Succeeded --> [*] Failed --> [*]

Ref: K8S Pod Life Cycle (github.com)

Labels and Selectors

Labels ที่จัดกลุ่ม K8S Object โดยจะกำหนดไว้ในส่วน metadata ในรูปแบบ key-value pairs โดยเอาไปใช้ในการทำ Grouping หรือ อธิบายความหมาย (อารมณ์เหมือน Tags ของ Azure) ให้

  • คน - monitor / ทำ Report ดู Cost
  • K8S Object อื่นๆ Search เช่น ตัว replicaSet / deamonSet

ดังนั้นกำหนดชื่อให้สื่อความหมาย

นอกจากนี้ ยังมีตัว annotation ปกติจะใช้ส่วนของ ingress

Selector เอาไว้ใช้ Filter ตัว K8S Object

  • command
#==================================================
#Add Label with command 
kubectl run nginx --image=nginx --labels app=backend

#==================================================
#Change
kubectl label pods nginx2 app=v2 --overwrite
kubectl get pods --show-labels

#==================================================
#Remove 
kubectl label pods nginx1 nginx2 nginx3 app-
#or
kubectl label pods nginx{1..3} app-
#or
kubectl label pods -lapp app-

#==================================================
#Use kubectl get pods to get the pod with label app=backend :
#Filter by Key
kubectl get pods -l app

#Filter by Key&Value
kubectl get pods -l app=v2
#or
kubectl get pods -l 'app in (v2)'
#or
kubectl get pods --selector=app=v2

#==================================================
kubectl get pods --show-labels

#Custom Column Name
kubectl get pods -L app
#or
kubectl get pods --label-columns=app

Label แปะ Resource อื่นๆได้ด้วยนะ มันใช้ได้หมด เป็น metadata เท่านั้น

kubectl label deployments nginx-deployment project=demo --overwrite -n test-talos

kubectl get deployments.apps --show-labels -n test-talos
NAME               READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
nginx-deployment   2/2     2            2           13d   app=v2,project=demo 
  • ใน YAML อย่างในตัว Deployment จะมีตัว matchLabels เพื่อให้ตัว replicaSet มาใช้การจับ pod ที่สนใจ
 selector:
    matchLabels:
      app: euraka

Labels vs Namespace

  • ไม่คล้ายกัน เพราะตัว Namespace จะใช้แยกวง Network ด้วยส่วนตัว Label จัดกลุ่มได้ละเอียดกว่า เช่น แบ่งย่อยภายใน namespace และเพิ่มมุมมองการ Filter ได้ดีกว่า
    Namespace = VPC / VNET
    Labels = Tags

Service

Service = Software Defined Load Balance โดยที่จะ redirect traffic จาก selector จาก label หัวข้อตะกี้ โดย group pod ออกมาเป็น 1 endpoint เช่น มี microservice cart อยู่ 5 pod ตัว service จับกลุ่ม 5 pod มาเป็น 1 endpoint ชื่อ cart (service map ip / name ให้)

Service Type

  1. Cluster IP (Default)
    - no external access
    - mapping name + IP

headless
- expose ip ของ pod ออกไป ส่วนมาใช้กับ stateful ที่ต้องการ fixed ip

  1. nodePort เปิด port ของเครื่อง Node / VM จริงๆ แต่ไม่ได้เปิด Firewall ให้
    - เปิดให้ External Service เข้าถึง Resource โดยถ้าไม่กำหนด port มันจะเป็นการ Random 30000-32767 มั้ง
    - กำหนดเองในส่วน service.port.nodePorts //Lock Range ไว้สะดวกในการ Manage
    - ส่วนมากใช้กับตัว Monitor Tools / DaemonSet และ Protocol อื่นๆ เช่น SRV
    - security leak ถ้าคุมไม่ดี
  2. loadBalancer
    - ต่างกับ cluster IP ตรงที่มันจะ ontop nodePort และเปิดตัว Public IP
  3. externalName
    - เอาไว้ map external resource เช่น Database / 3rd Party API เป็น config กลางให้ทุก pod รู้จักได้ ลด Effort เวลา external resource เปลี่ยนชื่อ เช่น
external name อารมณ์ map2 ชั้น 
- เดิม app ต่อ db dns investment.abc
- ใหม่ app ต่อ db inv.db

external name service จะmap inv.db = investment.abc 
apiVersion: v1
kind: Service
metadata:
  name: external-google-access
  namespace: web
spec:
  type: ExternalName
  externalName: google.com
curl external-google-access

Ref: Service | Kubernetes

Ingress

Forward request จาก domain มายัง service

ยังมีอีกตัว Ingress Controller != Ingress
- จับ kind ingress แล้วสร้าง LB Layer 7 ขึ้นมา เดี๋ยวต้องลองไปเล่น
- grpc เหมือนจะ Layer 7 ได้แล้ว

K8S Object หลายตัวควรแยกไฟล์นะ เดี๋ยวงง

Data Inter Change Concept

สำหรับวันเสาร์ มี workshop ให้ลองทำ 2 อัน

  • Deployment + replica ได้เจอเคสแปลกๆเยอะครับ 555 แบบ Node เต็ม ตอนแรกลอง 12 replica ไม่ได้ ลด 8 ... 5 อย่างน้อยได้เห็น State จริงๆ อย่าง ContainerStatusUnknow ลองในคอมตัวเองไม่น่าจะเจอ
  • อีกอันได้ลองเยอะเลย Ingress > Service > Deployment ผมได้ลอง 2 แบบ
    - แบบแรก(V1) ไปปรับทาง App ให้ Controller รับหลาย path
    - แบบสอง(V2) แยก App ออกมา มองว่าเป็น Microservice มี Path เดียว แต่แลกมาด้วย Service / Deployment กระจายออกมา

Git: k8s_IngSvcDeployment_Example/javascript/README.md at main · pingkunga/k8s_IngSvcDeployment_Example (github.com)

Reference


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.