ศัพท์ของ Kubernetes ครอบคลุมหลายชั้นพร้อมกัน: workload object (Pod, Deployment, StatefulSet, DaemonSet, Job) ที่บอกว่าอะไรควรรัน, cluster service (Service, Ingress, Gateway API, NetworkPolicy) ที่บอกว่า traffic ไปถึงมันได้ยังไง, storage กับ config object (ConfigMap, Secret, PV/PVC, StorageClass) ที่บอกว่ามันต้องการอะไร และ control plane (API server, etcd, controller, scheduler) ที่ reconcile ทุกอย่างพวกนี้เข้าหา state ที่เราประกาศไว้อยู่ตลอดเวลา ทับซ้อนอยู่บนนี้คือ RBAC กับ admission control สำหรับควบคุมว่าใครทำอะไรได้ และ toolchain — kubectl, Helm, GitOps — สำหรับ operate cluster จริง ๆ เวลาอ่านบทเรียนแล้วเจอคำที่ไม่คุ้น หรือไม่แน่ใจว่ายังใช้ได้อยู่กับ Kubernetes 1.37 ไหม ให้กลับมาดูที่นี่
Term ความหมาย บทเรียน admission webhook callback แบบ HTTP ที่ API server เรียกระหว่าง admission (validating และ/หรือ mutating) ก่อนจะบันทึก object ลงไป ValidatingAdmissionPolicy/MutatingAdmissionPolicy ครอบคลุมหลายเคสในคลัสเตอร์ได้โดยไม่ต้องมี webhook เอง แต่ Kyverno กับ Gatekeeper ก็ยังรันเป็น webhook สำหรับอะไรก็ตามที่ policy แบบ CEL แสดงออกมาไม่ได้ Pod & Cluster Security affinity / anti-affinity podAffinity จะ schedule Pod ให้อยู่ ใกล้ กับ Pod ที่ match label selector (node/zone/topology domain เดียวกัน) ส่วน podAntiAffinity จะ schedule ให้อยู่ ห่าง จากมัน — ทั้งคู่รองรับทั้งแบบ requiredDuringSchedulingIgnoredDuringExecution (บังคับ) และ preferred... (ขอไว้เฉย ๆ) และทั้งคู่ถูกประเมินแบบ all-or-nothing ต่อหนึ่ง termNode Affinity, Taints & Tolerations annotation key/value pair บน metadata ของ object ที่ไม่ได้ใช้ระบุตัวตน มีไว้ให้ tooling หรือ library แปะข้อมูลอะไรก็ได้เข้าไป — ต่างจาก label ตรงที่ annotation ไม่เคยถูกใช้เป็นเป้าหมายของ selector kubectl & Declarative YAML API server (kube-apiserver) ประตูหน้าเดียวของคลัสเตอร์ Kubernetes ทั้งหมด: ทุกการอ่านและเขียน — จาก kubectl, controller หรือ component อื่นของ control plane — ผ่านมันทั้งหมด และมันคือ component เดียวใน control plane ที่คุยกับ etcd ตรง ๆ Architecture: Control Plane & Nodes
Term ความหมาย บทเรียน bound token (ServiceAccount) ตั้งแต่ Kubernetes 1.22 token ของ ServiceAccount เป็น JWT อายุสั้น ผูก audience และ rotate อัตโนมัติ ได้มาจาก TokenRequest API (หรือ projected volume แบบ serviceAccountToken ที่มี expirationSeconds) — ไม่มีการสร้าง Secret token อายุยืนให้อัตโนมัติอีกต่อไป RBAC & Service Accounts CEL (Common Expression Language) ภาษา expression ที่ ValidatingAdmissionPolicy กับ MutatingAdmissionPolicy ใช้เขียนกฎ validate/mutate ตรง ๆ กับ object ที่เข้ามา (object.spec...) แทนที่จะต้องส่ง webhook server ไปรันเช็คแบบเดียวกัน Pod & Cluster Security Chart (Helm) directory ของ manifest ของ Kubernetes ที่ template ไว้ พร้อม metadata Chart.yaml และค่า default values.yaml — หน่วยที่ Helm packages, versions และติดตั้งออกมาเป็น Release Helm Package Management CNI (Container Network Interface) plugin interface ที่ต่อ networking ของ Pod ให้จริง ๆ และ — สำหรับ plugin ที่ implement มันไว้ (Calico, Cilium และตัวอื่น ๆ) — บังคับใช้ NetworkPolicy ด้วย; CNI ที่ไม่ implement การบังคับใช้ policy จะรับ object NetworkPolicy ไว้เฉย ๆ โดยไม่บล็อก traffic อะไรเลย Network Policies Cluster Autoscaler เพิ่มหรือลด Node ทั้งตัวตามแรงกดดันในการ schedule Pod — scale up เมื่อ Pod ค้างอยู่ที่ Pending เพราะ capacity ไม่พอ, scale down Node ที่ใช้งานน้อยด้วยการ cordon แล้ว drain ก่อน (เป็น voluntary disruption จึงเคารพ PodDisruptionBudget ต่างจาก preemption) Pod Disruption & Cluster Autoscaling ConfigMap object ระดับ namespace ที่เก็บข้อมูล configuration แบบ key/value ที่ไม่ลับ ให้ Pod ใช้เป็น environment variable, ค่า env ทีละตัว หรือ mount เป็น volume ของไฟล์ ConfigMaps & Secrets containerd container runtime ที่ kubelet คุยด้วยผ่าน CRI เพื่อ pull image และ start/stop container จริง ๆ บน Node — เป็น runtime default ของ kind, managed Kubernetes ส่วนใหญ่ และคลัสเตอร์ของคอร์สนี้ Architecture: Control Plane & Nodes controller control loop ที่ watch object หนึ่งชนิด (หรือหลายชนิด) เทียบ observed state กับ desired state แล้วยิง API call เพื่อขยับคลัสเตอร์เข้าหา desired state — เป็น pattern ที่ workload controller built-in ทุกตัวและ Operator ทุกตัวใช้ What is Kubernetes? cordon / drain kubectl cordon <node> ทำเครื่องหมายว่า Node นั้น unschedulable โดยไม่แตะอะไรที่รันอยู่แล้ว; kubectl drain <node> เพิ่มการ evict Pod ที่มีอยู่ผ่าน Eviction API (ที่เคารพ PodDisruptionBudget) — คู่นี้ใช้ก่อนจะบำรุงรักษาหรือแทนที่ Node แบบ voluntaryPod Disruption & Cluster Autoscaling CoreDNS DNS server ของคลัสเตอร์: เป็น Deployment ที่รันอยู่ใน kube-system ตอบ query <service>.<namespace>.svc.cluster.local (และ DNS ของ Pod) ด้วยการ watch Service กับ Endpoints/EndpointSlice ทำให้ client เรียก Service ด้วยชื่อได้แทนที่จะต้องใช้ ClusterIP DNS & Service Discovery CronJob สร้าง Job ตามตารางเวลา (syntax แบบ cron มาตรฐาน) ควบคุมด้วย concurrencyPolicy (Allow/Forbid/Replace), startingDeadlineSeconds สำหรับตารางที่พลาดไป และ history limit ของความสำเร็จ/ความล้มเหลวแยกกัน Jobs & CronJobs CRD (CustomResourceDefinition) ลงทะเบียน object Kind ใหม่เอี่ยมกับ API server พร้อม schema แบบ OpenAPI v3 สำหรับ validate — พอลงแล้ว kubectl get/apply/watch ใช้กับมันได้เหมือน object built-in ทุกประการ และมันถูกเก็บใน etcd แบบเดียวกัน Operators & Custom Resources CRI (Container Runtime Interface) interface แบบ gRPC ระหว่าง kubelet กับ container runtime (containerd, CRI-O) — เป็นตัวที่ทำให้ kubelet จัดการ container ได้โดยไม่ต้อง hardcode API ของ runtime ตัวใดตัวหนึ่ง Architecture: Control Plane & Nodes CSI (Container Storage Interface) plugin interface (GA ตั้งแต่ Kubernetes 1.13) ที่ให้ driver ของ vendor storage เสียบเข้ากับ Kubernetes ได้โดยไม่ต้องอยู่ใน tree kubernetes/kubernetes หลัก — เกือบทุก StorageClass ใน production ระบุ provisioner เป็น driver แบบ CSI PVs, PVCs & Storage Classes custom resource instance ของ Kind ที่ CRD กำหนดไว้ — CRD คือ schema ส่วน custom resource คือ object หนึ่งตัวที่ตรงกับ schema นั้น เหมือนกับที่ Pod เป็น instance ของ Kind Pod ที่ built-in มาให้Operators & Custom Resources
Term ความหมาย บทเรียน DaemonSet รัน Pod หนึ่งชุดบนทุก Node ที่ match node selector (ถ้ามี) เพิ่มหรือลบ Pod ให้อัตโนมัติเมื่อ Node เข้าหรือออกจากคลัสเตอร์ — รูปแบบสำหรับ agent ประจำ Node อย่าง log shipper หรือ CNI plugin StatefulSets & DaemonSets Deployment จัดการ ReplicaSet (และระหว่าง update ก็จัดการ ReplicaSet เก่ากับใหม่พร้อมกัน) เพื่อให้ rolling update และ rollback แบบ declarative และมี version ให้กับ workload แบบ stateless — chain ความเป็นเจ้าของคือ Deployment → ReplicaSet → Pod Deployments & ReplicaSets dry-run (client vs server) kubectl apply --dry-run=client แค่ render manifest ในเครื่อง ไม่มีการส่งไปหา server เลย; --dry-run=server ส่ง request ผ่าน chain validation และ admission ของ API server ทั้งหมด (เลยจับ rejection จริงจาก schema หรือ policy ได้) โดยไม่บันทึก object ลงจริงkubectl & Declarative YAML emptyDir volume ที่ถูกสร้างขึ้นแบบว่างเปล่าตอน Pod ถูก schedule และถูกลบถาวรตอน Pod ถูกเอาออกจาก Node — เป็นพื้นที่ scratch ที่แชร์กันระหว่าง container ใน Pod เดียวกัน ไม่ใช่ storage แบบถาวร Volumes & Volume Types Endpoints (deprecated) list ของ IP ของ Pod ที่รองรับ Service แบบเดิม เป็น object เดียวต่อ Service หนึ่งตัว (core/v1) มันไม่ shard เลยขยายได้ไม่ดีถ้ามี backend เกินสองสามร้อยตัว — EndpointSlice (GA ตั้งแต่ Kubernetes 1.21) เป็นตัวแทนที่แนะนำ ซึ่ง kube-proxy และ CoreDNS ก็อ่านมันอยู่แล้ว Services: ClusterIP, NodePort, LoadBalancer EndpointSlice ตัวแทน Endpoints ที่ scale ได้และ shard ได้ (discovery.k8s.io/v1, GA ตั้งแต่ 1.21): Pod ที่รองรับ Service หนึ่งตัวถูกแบ่งเก็บใน EndpointSlice หลายตัว (จำกัดจำนวนต่อ slice) แทนที่จะเป็น object Endpoints เดียวที่โตขึ้นเรื่อย ๆ และทั้ง kube-proxy กับ CoreDNS ก็ watch ตัวนี้โดยตรง Services: ClusterIP, NodePort, LoadBalancer ephemeral container container แบบใช้แล้วทิ้ง (GA/stable ตั้งแต่ Kubernetes 1.25) ที่แปะเข้าไปใน Pod ที่ กำลังรันอยู่แล้ว ผ่าน kubectl debug แชร์ process namespace กับ container เป้าหมายเพื่อ troubleshoot — มันไม่ restart Pod เลยและไม่สามารถเพิ่มเข้าไปใน Pod spec เดิมได้ Logging & Metrics etcd key-value store แบบ distributed ที่เป็น single source of truth ของคลัสเตอร์ — ทุก object ที่ API server เสิร์ฟถูกอ่านและเขียนจาก etcd และมีแค่ API server เท่านั้นที่คุยกับมันตรง ๆ Architecture: Control Plane & Nodes extensions/v1beta1 (removed)API group ที่ยังไม่ stable ที่ resource ยุคแรกของ Kubernetes (Deployment, DaemonSet, ReplicaSet, NetworkPolicy) เคยอยู่ชั่วคราว หยุดถูกเสิร์ฟไปตั้งแต่ Kubernetes 1.16 (ย้ายไป apps/v1/networking.k8s.io/v1) ส่วน Ingress เองที่อยู่ใต้ extensions/v1beta1/networking.k8s.io/v1beta1 ก็ถูกเอาออกใน 1.22 — manifest ที่ใช้มันวันนี้จะถูก reject ตรง ๆ ไม่ใช่ downgrade แบบเงียบ ๆ kubectl & Declarative YAML
Term ความหมาย บทเรียน field manager / managedFields Server-Side Apply จะติดตามว่า ใคร เป็นเจ้าของ field ไหน ของ object ไว้ใน metadata.managedFields โดย key ด้วยชื่อ field manager (ค่า default ของ kubectl, ชื่อของ controller, …) — สอง manager ที่เขียน field เดียวกันด้วยค่าที่ขัดกันคือ conflict จริงที่ถูก reject ไม่ใช่การเขียนทับแบบเงียบ ๆ kubectl & Declarative YAML filter, score, bind (scheduling cycle) pipeline ต่อ Pod หนึ่งตัวของ scheduler: Filter ตัด Node ที่รัน Pod นี้ไม่ได้เลยออกไป (NodeResourcesFit, TaintToleration, PodTopologySpread, … เหลือเป็นชุด Node ที่ feasible ), PostFilter รัน DefaultPreemption ก็ต่อเมื่อไม่มี Node ไหน feasible เลย, Score จัดอันดับ Node ที่ feasible และ Bind ยืนยัน Pod เข้ากับ Node ที่ชนะ The Scheduler & Resource Requests Gateway API ตัวสืบทอด Ingress ที่แสดงออกได้มากกว่าและแบ่งตาม role (gateway.networking.k8s.io) แยก object เดียวก้อนใหญ่ออกเป็น GatewayClass (ผู้ให้บริการ infrastructure), Gateway (instance ของ listener/load balancer) และ route type ต่าง ๆ (HTTPRoute, GRPCRoute, …) ที่ทีมต่างกันเป็นเจ้าของได้ Ingress & Gateway API Gateway (resource)object ของ Gateway API ที่ขอ infrastructure จัดการ traffic จริง ๆ (cloud load balancer, proxy ในคลัสเตอร์) จาก GatewayClass ที่ระบุชื่อไว้ ประกาศ listener ของมัน (protocol, port, hostname) — route ต่าง ๆ จะมาแนบกับมันทีหลัง Ingress & Gateway API GatewayClassobject ของ Gateway API ที่ระบุชื่อ controller implementation (คล้ายกับ IngressClass หรือ StorageClass) ที่ Gateway อ้างถึงผ่าน gatewayClassName — เป็น cluster-scoped ปกติทีม platform ติดตั้งไว้ครั้งเดียว Ingress & Gateway API GitOps โมเดล deploy แบบ pull-based ที่ controller ซึ่งรันอยู่ ข้างใน คลัสเตอร์ (Argo CD, Flux) reconcile live state เข้ากับ manifest ใน Git repository อย่างต่อเนื่อง แทนที่จะให้ CI pipeline สั่ง kubectl apply จากข้างนอก — repository เองต่างหากที่เป็น source of truth ไม่ใช่การรัน pipeline ครั้งหนึ่ง GitOps & CI/CD for Kubernetes GRPCRouteroute type ของ Gateway API สำหรับ traffic แบบ gRPC (stable ที่ gateway.networking.k8s.io/v1 เหมือนกับ HTTPRoute) match ตาม service/method ของ gRPC แทนที่จะเป็น path แบบ HTTP — ต้องการให้ listener ของ Gateway พูด HTTP/2 Ingress & Gateway API
Term ความหมาย บทเรียน headless Service Service ที่สร้างด้วย clusterIP: None มันไม่ได้ virtual IP เลย และชื่อ DNS ของมัน resolve ตรงไปที่ IP ของ Pod แต่ละตัวข้างหลังมัน (หรือสำหรับ StatefulSet คือชื่อ DNS ต่อ Pod แบบคงที่หนึ่งชื่อ) แทนที่จะ load balance ผ่าน address เดียว — เป็นสิ่งที่ตัวตนของ StatefulSet ต้องพึ่งพา DNS & Service Discovery Helm package manager ของ Kubernetes: packages ชุด manifest ที่ template ไว้เป็น Chart แบบมี version เติมค่า placeholder ของ values.yaml ตอนติดตั้ง และติดตามการติดตั้งแต่ละครั้งเป็น Release ที่มีประวัติ upgrade/rollback ของตัวเอง Helm Package Management HorizontalPodAutoscaler (HPA) ปรับ จำนวน replica ของ workload ขึ้นลงตาม metric ที่สังเกตได้ (CPU/memory ผ่าน metrics-server, หรือ metric แบบ custom/external) — ต้องตั้ง resources.requests ให้ทุก container และมี metrics-server รันอยู่ก่อน ไม่งั้นมันทำอะไรไม่ได้เลย Horizontal Pod Autoscaling hostPath mount path จาก filesystem ของ Node เอง เข้าไปใน Pod ตรง ๆ — ผูก Pod ไว้กับสิ่งที่บังเอิญมีอยู่แล้วบน Node ตัวนั้น และเป็นช่องโหว่ด้าน security ที่พบบ่อย ต่างจาก emptyDir หรือ PV จริง ๆ Volumes & Volume Types HTTPRouteroute type ของ Gateway API สำหรับ traffic แบบ HTTP (stable ที่ gateway.networking.k8s.io/v1) — แนบเข้ากับ listener ของ Gateway แล้ว match ตาม path/header/method เทียบเท่ากับ rule ของ Ingress ใน Gateway API แต่แสดงออกมาเป็น object ของตัวเอง Ingress & Gateway API informer กลไกของ client-go ที่ controller ใช้เป็นฐาน: มัน list สถานะปัจจุบันของ object ชนิดที่ watch อยู่ครั้งเดียว แล้วเก็บ cache ในเครื่องให้ sync ผ่าน watch ที่เปิดค้างไว้นาน ๆ ทำให้ reconcile loop ของ controller อ่านจาก cache แทนที่จะยิง API server ทุกรอบ Architecture: Control Plane & Nodes Ingress route traffic แบบ HTTP(S) จากภายนอกไปหา Service ตามกฎ host/path — ตัว API เองถูก freeze ไว้ (ไม่พัฒนาต่อแล้ว) ตั้งแต่ Gateway API กลายเป็นตัวสืบทอดที่แสดงออกได้มากกว่าและถูกพัฒนาต่ออย่างจริงจัง; object Ingress เพียงอย่างเดียวไม่ทำอะไรเลยถ้าไม่มี ingress controller ที่ implement มันจริง ๆ Ingress & Gateway API ingress-nginx (retiring) ingress controller ที่ถูก deploy กว้างที่สุด; โปรเจกต์นี้กำลัง retire (ประกาศ retirement มีผลมีนาคม 2026) ซึ่งเป็นเหตุผลหนึ่งที่จับต้องได้ว่าทำไมคอร์สนี้ถึงมอง Gateway API เป็นตัวเลือกที่มองไปข้างหน้า ไม่ใช่แค่ทางเลือกเสริม Ingress & Gateway API init container รันจนเสร็จ ตามลำดับ ก่อนที่ container ปกติตัวไหนใน Pod เดียวกันจะเริ่ม — ใช้รอ dependency หรือเตรียม state ที่แชร์กัน; ต่างจาก native sidecar ตรงที่มันไม่ได้รันต่อไปพร้อมกับแอป Pods: the Atomic Unit
Term ความหมาย บทเรียน Job รัน Pod (หรือหลายตัว) จน เสร็จสมบูรณ์ แทนที่จะรันตลอดไป ติดตามจำนวนที่สำเร็จเทียบกับ completions แล้วยอมแพ้ตาม backoffLimit/activeDeadlineSeconds — รูปแบบสำหรับงานแบบ one-off หรือ batch ต่างจาก Deployment Jobs & CronJobs Karpenter node-lifecycle autoscaler ที่ provision Node ขนาดพอดีตรง ๆ กับ API ของ cloud provider เพื่อตอบสนอง Pod ที่ schedule ไม่ได้ แทนที่จะ scale node group ที่กำหนดไว้ตายตัวแบบที่ Cluster Autoscaler ทำ Pod Disruption & Cluster Autoscaling kind รัน Node ของ Kubernetes (kind.sigs.k8s.io ) เป็น container ของ Docker/Podman บนเครื่องเราเอง — เป็นคลัสเตอร์ของคอร์สนี้เอง; kind 0.33 default เป็น Kubernetes 1.37 และ config แบบ multi-node จริง ๆ (kind.x-k8s.io/v1alpha4) ก็แค่ไฟล์ YAML เดียว Running Kubernetes Locally k3d รัน k3s — Kubernetes distribution แบบ certified และเบา — อยู่ข้างใน container ของ Docker คล้ายกับ kind แต่สร้างขึ้นรอบ ๆ footprint ที่เล็กกว่าของ k3s และมีบาง component (Traefik, servicelb) built-in มาให้แล้ว Running Kubernetes Locally kube-proxy รันอยู่บนทุก Node และเขียนกฎ rewrite packet ในเครื่อง (iptables หรือ IPVS แล้วแต่โหมด) จาก Service กับ Endpoints/EndpointSlice ที่มัน watch อยู่ — เป็น component ที่ทำให้ virtual IP ของ Service ทำงานได้จริง ๆ ส่งทุก packet ที่มาถึงมันไปหา Pod ที่รองรับตัวหนึ่งอย่างโปร่งใส Services: ClusterIP, NodePort, LoadBalancer kubeconfig / context ไฟล์ kubeconfig รวม endpoint ของคลัสเตอร์, credential ของ user และ context ที่ตั้งชื่อไว้ (cluster + user + namespace default); kubectl config get-contexts/use-context คือวิธีดูและสลับว่าคำสั่งถัดไปของเราคุยกับคลัสเตอร์ไหนอยู่ Running Kubernetes Locally kubectl apply (client-side vs Server-Side Apply)client-side apply คำนวณ diff ที่จะส่งโดยเทียบกับ annotation last-applied-configuration ที่เก็บไว้ในเครื่องจากการรันครั้งก่อน; Server-Side Apply (--server-side) ให้ API server เอง merge request ทีละ field เทียบกับ managedFields แทน — การใช้สองแบบผสมกันบน object เดียวกันคือสิ่งที่ทำให้เกิด field-manager conflict จริง ๆ kubectl & Declarative YAML kubectl debugแปะ ephemeral container (หรือทั้ง debug Pod แยกต่างหาก สำหรับ Node) เข้าไป troubleshoot Pod หรือ Node ที่กำลังรันอยู่ โดยไม่ restart หรือแทนที่อะไรที่มีอยู่แล้ว — เป็นทางแก้ตอนที่ image แบบ distroless ทำให้ kubectl exec ... -- sh fail เพราะไม่มี shell ใน $PATH Logging & Metrics kubectl explain / kubectl diffkubectl explain <kind>.<field.path> เช็คว่า field นั้นมีอยู่จริงเทียบกับ schema ของ API server ที่รันอยู่จริง (field ที่มโนขึ้นมาจะพิมพ์ error “does not exist” จริง ๆ); kubectl diff โชว์ว่า apply จะเปลี่ยนอะไรก่อนที่เราจะ commit มันจริงkubectl & Declarative YAML kubelet agent ประจำ Node ที่ลงทะเบียน Node กับ API server รับ Pod spec ที่ถูก assign มา แล้วสั่ง container runtime (ผ่าน CRI) ให้ start, stop และ probe container ข้างใน Pod แต่ละตัวจริง ๆ Architecture: Control Plane & Nodes Kustomize วิธี customize ชุด manifest ธรรมดาต่อ environment แบบ patch-based ไม่ต้อง template (overlay ด้วย strategic merge หรือ JSON patch) built-in อยู่ใน kubectl ตั้งแต่ 1.14 (kubectl apply -k) เป็นทางเลือกแทนแนวทาง templating ของ Helm — คอร์สนี้สอนโมเดล Chart/Release ของ Helm เป็นเครื่องมือ packaging หลัก Helm Package Management
Term ความหมาย บทเรียน label key/value pair บน metadata ของ object ที่ใช้ระบุตัวตนและ เลือก มัน — Service, ReplicaSet หรือ NetworkPolicy ล้วนเลือกเป้าหมายของตัวเองผ่าน label selector ทั้งนั้น ไม่เคยใช้ชื่อหรือ list ตายตัว kubectl & Declarative YAML LimitRangeค่า default และขอบเขตระดับ namespace สำหรับ Pod/container แต่ละตัว — เติมค่า requests/limits ให้ container ที่ไม่ได้กำหนดไว้แบบเงียบ ๆ และยังจำกัด maximum/minimum ที่ container ใน namespace นั้นขอได้ด้วย Namespaces & Resource Quotas liveness probe / readiness probe liveness probe ที่ fail จะ restart container (kubelet ตัดสินว่ามันค้าง); readiness probe ที่ fail จะเอา Pod ออกจาก Endpoints/EndpointSlice ของ Service โดยไม่ restart — การชี้ทั้งสองไปที่ endpoint เดียวกันโดยไม่มี startupProbe บน container ที่ warm-up ช้าจะทำให้เกิด restart loop ที่สร้างขึ้นเองProbes: Liveness, Readiness & Startup metrics-serverเก็บ usage ของ CPU/memory จากทุก kubelet แล้วเปิดผ่าน API metrics.k8s.io — พอสำหรับขับเคลื่อน kubectl top และ HPA แบบ CPU/memory แต่มันไม่เก็บประวัติเลยและไม่ใช่ตัวแทนของ Prometheus Logging & Metrics minikube รันคลัสเตอร์แบบ single- หรือ multi-node ข้างใน VM หรือ container driver ที่เราเลือก พร้อม addon ecosystem built-in ที่หลากหลาย (minikube addons enable dashboard/ingress/metrics-server) เปิดใช้ได้ทีละคำสั่ง Running Kubernetes Locally MutatingAdmissionPolicyการ mutate object ในกระบวนการ admission แบบ in-process ด้วย CEL — stable ตั้งแต่ Kubernetes 1.36 (ไม่ต้องมี feature gate) ต้องมี spec.reinvocationPolicy — ครอบคลุมหลายเคสที่เมื่อก่อนต้องมี mutating webhook server เต็มรูปแบบ Pod & Cluster Security
Term ความหมาย บทเรียน namespace วิธีแบ่งคลัสเตอร์เดียวออกเป็นคลัสเตอร์เสมือนหลายอันสำหรับชื่อ, RBAC และ quota — object ส่วนใหญ่ (Pod, Service, ConfigMap, …) อยู่ใน namespace เดียวเท่านั้น แต่บางอย่าง (Node, PersistentVolume, ตัว CRD เอง) เป็น cluster-scoped และอยู่นอกทุก namespace Namespaces & Resource Quotas ndotsตัวเลือก config DNS ของ Pod (default 5) ควบคุมว่าชื่อต้องมีจุดกี่จุดก่อนที่ resolver จะลองมันเป็นชื่อ absolute ก่อน แทนที่จะต่อท้ายด้วย search domain ของคลัสเตอร์ — ชื่อ Service สั้น ๆ อย่าง my-svc มีจุดน้อยกว่า 5 จุด ทุกการ lookup เลยลอง suffix ของ search domain หลายแบบก่อน (หรือแทนที่) ชื่อภายนอกตรง ๆ DNS & Service Discovery NetworkPolicy กฎแบบ allow-list ที่เลือก Pod ด้วย label แล้วอนุญาต traffic ขาเข้า/ขาออกที่เจาะจงไปหรือมาจากมัน — default ของคลัสเตอร์คือ network แบบเปิดโล่งเต็มที่ ดังนั้น NetworkPolicy จะจำกัดอะไรได้ก็ต่อเมื่อ CNI plugin บังคับใช้ policy object นั้นจริง ๆ (ไม่ใช่ CNI ทุกตัวที่ทำ) Network Policies Operator pattern การจับคู่ CRD กับ controller ที่เข้ารหัสความรู้ในการ operate จริง ๆ (backup, failover, การอัปเกรด version) ไว้ใน reconcile loop — CRD เดี่ยว ๆ เป็นแค่ schema ตัว controller ต่างหากที่ทำให้มันกลายเป็น Operator Operators & Custom Resources
Term ความหมาย บทเรียน Pod หน่วยที่ deploy ได้เล็กที่สุด: container หนึ่งตัวหรือมากกว่านั้นที่แชร์ network namespace เดียวกัน (IP เดียว, คุยกันผ่าน localhost ได้) และแชร์ volume กันได้ — ไม่เคยถูกสร้างตรง ๆ ใน production เสมอไปต้องผ่าน controller อย่าง Deployment Pods: the Atomic Unit PodDisruptionBudget (PDB) ประกาศ minAvailable หรือ maxUnavailable สำหรับกลุ่ม Pod และเส้นทาง eviction แบบ voluntary ใด ๆ (kubectl drain, Eviction API, Cluster Autoscaler scale-down) ต้องเคารพมัน — มันไม่ป้องกันอะไรเลยจากการ preemption ของ scheduler หรือการ evict จาก node-pressure ของ kubelet ซึ่งไม่ผ่าน Eviction API เลย Pod Disruption & Cluster Autoscaling PodSecurityPolicy (removed) วิธีบังคับใช้ security baseline ทั้งคลัสเตอร์แบบ built-in ดั้งเดิม ถูกเอาออกใน Kubernetes 1.25 แทนที่ด้วย Pod Security Admission ที่บังคับใช้ Pod Security Standards (ที่ตัวมันเองไม่บังคับอะไร) ที่ระดับ namespace Pod & Cluster Security preemption ตอนที่ไม่มี Node ไหน feasible สำหรับ Pod เลย ขั้นตอน PostFilter/DefaultPreemption ของ scheduler จะหา Pod priority ต่ำกว่ามา evict เพื่อเปิดที่ว่าง — เป็น involuntary disruption ที่ข้าม PodDisruptionBudget ไปเลย ต่างจากการ drain แบบ voluntary The Scheduler & Resource Requests preStop hookคำสั่งหรือ HTTP call ที่ kubelet รัน ก่อน จะส่ง SIGTERM ให้ container ตอน terminate — มักใช้ซื้อเวลาให้ container หยุดรับ traffic ใหม่ในขณะที่ Pod ของมันยังถูกเอาออกจาก Service Endpoints อยู่ Pods: the Atomic Unit PriorityClassกำหนด priority เป็นตัวเลขให้ Pod; Pod ที่ priority สูงกว่าสามารถกระตุ้นให้เกิด preemption กับ Pod priority ต่ำกว่าได้เมื่อไม่มี Node ไหน feasible เลย และ priority ยังมีผลกับลำดับที่ Pod ถูกพิจารณาภายใต้แรงกดดันด้าน resource ด้วย The Scheduler & Resource Requests projected volume รวมแหล่งข้อมูล volume หลายแบบ (ConfigMap, Secret, ไฟล์จาก downward API และ serviceAccountToken) เข้าเป็น mount point เดียวใน Pod spec เดียว — เป็นกลไกที่ bound ServiceAccount token แบบใหม่มาถึง Pod จริง ๆ Volumes & Volume Types PSA / PSS (Pod Security Admission / Pod Security Standards) Pod Security Standards กำหนด baseline สามระดับ (privileged, baseline, restricted); Pod Security Admission (stable ตั้งแต่ Kubernetes 1.25) บังคับใช้ระดับใดระดับหนึ่งต่อ namespace ผ่าน label pod-security.kubernetes.io/enforce — เป็นตัวแทน built-in ของ PodSecurityPolicy Pod & Cluster Security PV / PVC (PersistentVolume / PersistentVolumeClaim) PersistentVolume คือชิ้นส่วน storage จริงที่ provision ไว้ในคลัสเตอร์; PersistentVolumeClaim คือคำขอ storage ของ Pod ที่ตรงกับขนาด/access-mode/class บางแบบ — PVC คือสิ่งที่ Pod mount จริง ๆ และมันถูก bind กับ PV ที่ match กัน (หรือถูก provision แบบ dynamic) อยู่เบื้องหลังPVs, PVCs & Storage Classes
Term ความหมาย บทเรียน QoS class Guaranteed, Burstable หรือ BestEffort — ได้มาอัตโนมัติจาก requests/limits ของ Pod เอง (ไม่เคยตั้งตรง ๆ) และเป็นสิ่งแรกที่ kubelet ใช้ตัดสินว่าจะ evict Pod ตัวไหนก่อนตอนที่ Node มีแรงกดดันด้าน memory จริง ๆThe Scheduler & Resource Requests RBAC (Role / ClusterRole / RoleBinding / ClusterRoleBinding) Role/ClusterRole ประกาศว่า อนุญาตอะไร (verb บน resource) ระดับ namespace หรือทั้งคลัสเตอร์ตามลำดับ; RoleBinding/ClusterRoleBinding ประกาศว่า ใครได้สิทธิ์นั้น ผูก Role/ClusterRole เข้ากับ user, group หรือ ServiceAccount — ClusterRole เองก็ผูกด้วย RoleBinding เพื่อจำกัดสิทธิ์ระดับคลัสเตอร์ให้เหลือแค่ namespace เดียวได้ด้วยRBAC & Service Accounts reconcile / reconciliation loop การกระทำหลักของ control loop: อ่าน desired state, อ่าน observed state แล้วยิง API call อะไรก็ตามที่ปิดช่องว่างระหว่างสองอย่างนี้ — ทำซ้ำต่อเนื่องตลอด ดังนั้นการแก้ field ที่ controller จัดการอยู่ด้วยมือจะถูกเขียนทับในรอบถัดไปเฉย ๆ What is Kubernetes? ReferenceGrantobject ของ Gateway API (gateway.networking.k8s.io/v1beta1 ยังไม่ถูกเลื่อนเป็น v1) ที่อนุญาตการอ้างอิงข้าม namespace — เช่น HTTPRoute ใน namespace หนึ่งชี้ไปที่ Service ใน namespace อื่น — ต้องการการ opt-in ชัดเจนจาก namespace เป้าหมาย แทนที่จะเชื่อ object ที่อ้างอิงมาฝ่ายเดียว Ingress & Gateway API Release (Helm) instance หนึ่งที่ตั้งชื่อและถูกติดตามของ Chart ที่รันอยู่ในคลัสเตอร์ พร้อมประวัติ revision ของตัวเอง — helm upgrade/helm rollback ทำงานกับ resource ทั้งชุดที่ Release นั้นจัดการร่วมกัน ไม่ใช่ทีละ Deployment Helm Package Management ReplicaSet รักษาจำนวน Pod ที่ match selector (ตายตัว แก้ไม่ได้) ของมันให้เท่ากับ replicas อยู่ตลอดเวลา — แทบไม่เคยถูกสร้างตรง ๆ; Deployment สร้างและจัดการ ReplicaSet ให้เราเพื่อทำ rolling update ทับบน guarantee เรื่องจำนวนคงที่นี้ Deployments & ReplicaSets requests / limits requests คือพื้นที่ขั้นต่ำที่ scheduler จองไว้เทียบกับ Allocatable capacity ของ Node (และเป็นตัวเลขที่ QoS class ถูกคำนวณมาจาก); limits คือเพดานตอน runtime ที่ kubelet/cgroups บังคับใช้ — เกิน CPU limit จะถูก throttle, เกิน memory limit container จะถูก OOMKilledThe Scheduler & Resource Requests ResourceQuota เพดานแข็งระดับ namespace สำหรับการใช้ resource รวม (requests/limits ของ CPU/memory รวมกัน, จำนวน object) — ในขณะที่ LimitRange จำกัด Pod ทีละตัว ResourceQuota จำกัดทั้ง namespace พร้อมกัน Namespaces & Resource Quotas
Term ความหมาย บทเรียน scheduler (kube-scheduler) component ของ control plane ที่เลือกว่า Pod ที่ยังไม่ผูกกับ Node ตัวไหนจะรันบน Node ไหน ผ่าน pipeline filter/score/bind — มันไม่รันอะไรเองเลย มันแค่เขียนการตัดสินใจ binding กลับไปที่ API server ให้ kubelet เอาไปทำต่อ The Scheduler & Resource Requests Secret รูปร่างเหมือน ConfigMap เป๊ะ (ข้อมูล key/value ใช้เป็น env var หรือ mount เป็น volume) แต่ตั้งใจไว้สำหรับข้อมูลที่ sensitive — default เป็นการ encode แบบ base64 ไม่ใช่การ encrypt เลยไม่ได้เป็นความลับตอนอยู่นิ่ง ๆ เว้นแต่คลัสเตอร์จะตั้งค่า encryption-at-rest แยกไว้ ConfigMaps & Secrets securityContextการตั้งค่า harden ระดับ container (หรือระดับ Pod) — runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation: false, ตัด Linux capability ทิ้ง — เป็นชั้นแรกสุดของการ harden Pod แยกอิสระจากระดับ Pod Security Admission ที่ namespace บังคับใช้อยู่ Pod & Cluster Security selector label query (matchLabels/matchExpressions) ที่เลือกกลุ่ม object แบบ dynamic — Service เลือก Pod ที่รองรับตัวเองด้วยวิธีนี้ และเป็นเหตุผลว่าทำไม Pod ที่มาแล้วไปไม่เคยต้องแก้ตัว Service เอง Services: ClusterIP, NodePort, LoadBalancer Server-Side Apply (SSA) kubectl apply --server-side ให้ API server เอง merge แบบ three-way เทียบกับ managedFields แทนที่จะให้ kubectl คำนวณเองในเครื่องจาก annotation last-applied-configuration — เป็นโมเดลที่ GitOps controller ใช้ และเป็นที่มาของ conflict จริงที่มองเห็นได้ตอนที่ apply ธรรมดาของคนกับ SSA ของ controller แตะ field เดียวกันด้วยค่าต่างกันkubectl & Declarative YAML Service (ClusterIP / NodePort / LoadBalancer / ExternalName) virtual IP และชื่อ DNS ที่คงที่ วางไว้หน้าชุด Pod ที่เปลี่ยนไปเรื่อย ๆ ClusterIP (default) เป็น internal เท่านั้น; NodePort เพิ่มการเปิด port เดียวกัน (30000-32767) บนทุก Node; LoadBalancer เพิ่ม cloud load balancer ภายนอกไว้หน้า NodePort อีกที; ExternalName คืนค่าเป็น CNAME ไปหาชื่อ DNS ภายนอก แทนที่จะ load balance ไปหา Pod ตัวไหนเลย Services: ClusterIP, NodePort, LoadBalancer ServiceAccount ตัวตนที่ Pod ใช้ authenticate กับ API server (ต่างจาก user ที่เป็นคน) — ทุก Pod รันในฐานะ ServiceAccount ตัวใดตัวหนึ่งเสมอ (default ถ้าไม่ได้ตั้งไว้) และ RBAC binding ที่ผูกกับมันต่างหากที่จำกัดว่า kubectl/client call ของ Pod นั้นเองทำอะไรได้บ้างจริง ๆ RBAC & Service Accounts sidecar container (native sidecar) ตั้งแต่ Kubernetes 1.29 init container ที่มี restartPolicy: Always จะรันต่อไปพร้อมกับ container หลักของ Pod แทนที่จะออกไปหลังรันครั้งเดียว — และตอน Pod terminate native sidecar จะถูกหยุด สุดท้าย หลัง container หลัก ทำให้ proxy ของ service mesh หรือ log shipper ไม่หายไปจากใต้แอปที่มันกำลังซัพพอร์ตอยู่ Pods: the Atomic Unit StatefulSet จัดการ Pod ที่มีตัวตนคงที่และมีลำดับ (<name>-0, <name>-1, …) พร้อม PVC ต่อ Pod ที่คงที่ตามตัวตนนั้นไปแม้จะถูก reschedule — สิ่งที่ database หรืออะไรก็ตามที่ต้องการ “Pod เดิม ดิสก์เดิม” ทุกครั้งต้องการจริง ๆ ต่างจาก Deployment StatefulSets & DaemonSets startupProbeรันก่อนที่ liveness/readiness probe จะเริ่มนับเลยด้วยซ้ำ ให้พื้นที่กับ container ที่ boot ช้าให้ boot จนเสร็จ — ควรตั้งขนาดให้ failureThreshold * periodSeconds ครอบคลุมเวลา boot ที่แย่ที่สุด ไม่งั้น liveness probe จะ restart container กลางคันตอน boot รีเซ็ตนาฬิกาใหม่ทุกครั้ง Probes: Liveness, Readiness & Startup StorageClass ระบุชื่อ provisioner (เกือบทุกครั้งเป็น CSI driver) พร้อม parameter สำหรับสร้าง PersistentVolume แบบ dynamic ตามความต้องการเมื่อ PVC อ้างถึงมัน — เป็นทางเลือกแทนการ provision PV เองล่วงหน้า และเป็นที่ตั้ง reclaim policy (Delete กับ Retain) PVs, PVCs & Storage Classes
Term ความหมาย บทเรียน taint / toleration taint บน Node จะผลัก Pod ออกไป (NoSchedule, PreferNoSchedule หรือ NoExecute — ที่ evict Pod ที่รันอยู่แล้วด้วย เลือกได้ว่าหลัง tolerationSeconds); toleration ที่ match บน Pod ต่างหากที่ทำให้มันถูก schedule ที่นั่นได้ (หรืออยู่ต่อได้) — เป็นทิศตรงข้ามกับ affinity ที่ Pod ใช้ดึงตัวเองเข้าหา Node Node Affinity, Taints & Tolerations terminationGracePeriodSecondsเวลาที่ kubelet รอระหว่างการส่ง SIGTERM (และรัน preStop hook ขนานกันไปด้วยถ้ามี) กับการ force-kill container ด้วย SIGKILL ตอน Pod terminate — ตั้งเป็น 0 จะข้าม grace period ไปเลยทั้งหมด และอันตรายจริง ๆ กับอะไรก็ตามที่ต้องการปิดตัวแบบสะอาด Pods: the Atomic Unit topologySpreadConstraintsกระจาย Pod ให้เท่า ๆ กันข้าม topology domain ที่ระบุชื่อไว้ (zone, hostname, …) ภายใน maxSkew ที่ปรับได้; matchLabelKeys (ยัง beta อยู่ ณ Kubernetes 1.37) จำกัดการคำนวณให้เหลือแค่ Pod จาก rollout ปัจจุบันเท่านั้น และ nodeTaintsPolicy: Honor (default เป็น Ignore) จำเป็นเพื่อไม่ให้ Node ที่ taint ไว้และ unschedulable ยังถูกนับเป็น topology domain ที่ว่างเปล่าอยู่ Node Affinity, Taints & Tolerations ValidatingAdmissionPolicyการ validate ในกระบวนการ admission แบบ in-process ด้วย CEL — stable ตั้งแต่ Kubernetes 1.30 — ประกาศว่าจะเช็คอะไรและเช็คยังไงตรง ๆ ใน object ของ policy เอง พร้อม object ...Binding แยกต่างหากที่ให้ paramRef/match มาจำกัดขอบเขต ไม่ต้องมี validating webhook server เต็มรูปแบบสำหรับการเช็คทั่ว ๆ ไปหลายแบบ Pod & Cluster Security values.yaml (Helm)ไฟล์ configuration default ของ Chart ถูกอ้างถึงจาก template ด้วย {{ .Values.xxx }}; Chart เดียวกัน deploy ไปที่ dev, staging และ prod ได้ด้วยการ override values.yaml ตอนติดตั้งเท่านั้น (ไฟล์ override ค่าหรือ flag --set) ไม่เคยต้องแก้ template เอง Helm Package Management VolumeSnapshot snapshot ณ จุดเวลาหนึ่งของ storage เบื้องหลัง PVC (snapshot.storage.k8s.io, GA ตั้งแต่ Kubernetes 1.20) สร้างผ่าน CSI driver ที่รองรับการ snapshot — เป็นกลไกเบื้องหลังการ restore หรือ clone PVC กลับไปที่ state ก่อนหน้า PVs, PVCs & Storage Classes VPA (VerticalPodAutoscaler) ปรับ requests/limits ของ container เองไปเรื่อย ๆ ตาม usage ที่สังเกตได้ แทนที่จะเปลี่ยนจำนวน replica แบบที่ HPA ทำ — การรัน HPA กับ VPA บน metric เดียวกันของ workload เดียวกันคือ conflict จริงที่มีบันทึกไว้ ไม่ใช่การรวมกันที่รองรับ Pod Disruption & Cluster Autoscaling watch / resourceVersion ทุก response ของ list จะพก resourceVersion มาด้วย; client เปิด watch จากจุดนั้นแล้วได้ stream ของ event add/update/delete แทนที่จะ poll — นี่คือวิธีที่ controller และ informer ทุกตัวสังเกตเห็นการเปลี่ยนแปลงได้ทันที แทนที่จะรอตามช่วงเวลาคงที่ Architecture: Control Plane & Nodes
Mark as complete