LFS258 [5/15]: Kubernetes API Object
Sawit M.
Posted on February 10, 2020
จากบทที่แล้ว เราได้รู้จักการเรียกใช้ API ของ Kubernetes กันไปแล้ว บทนี้เราจะมาลองลงลึกไปที่ API Object เบื้องต้นของ Kubernetes กันบ้างว่า ในการที่เราจะ run งานของเรานั้น kubernetes มี Object แบบไหน ให้เราเลือกใช้งานกันบ้าง พร้อมแล้ว ? ลุยกันเลย
Index
- Overview
- v1 API Group
- Discovering API Groups
- Deploying an Application
- DaemonSets
- StatefulSets
- Autoscaling
- Jobs and Cronjobs
- RBAC
Overview
ถ้าพูดถึง API ของ Kubernetes แน่นอนว่า group และ version (group/version) เป็นสิ่งที่สำคัญมาก เพราะเราต้องระบุมันทุกครั้ง ที่จะสั่งงานผ่าน API ในบทความนี้จะกล่าวถึงเฉพาะ API ที่อยู่ในสถานะ stable แล้วเท่านั้น นั่นคือ v1 โดย API Object ที่พบบ่อยในการ run งานได้แก่
-
app/v1
-
DeamonSet:
เป็น object ที่สร้าง pod จำนวนหนึ่งจาก image เดียว แล้วกระจาย pod ไป run ทุก node ใน cluster node ละ 1 pod
-
StatefulSet:
เป็น object ที่สร้าง pod จำนวนหนึ่งจาก image เดียว และจะมอง pod ที่เกิดขึ้นเป็นคนละ pod กัน ในการ start จะ start ตามลำดับ
-
DeamonSet:
-
batch/v1
-
Jobs:
เป็น object ที่สร้าง pod ขึ้นมา 1 pod แล้วส่งไป run ใน node ที่เหมาะสม ถ้างานเสร็จแล้วคือจบ จุดมุ่งหมายคืองานต้องสำเร็จ จะมีการกำหนดจำนวนครั้งในการ retry ไว้ถ้า retry ครบ แล้วงานไม่สำเร็จถือว่างานนั้น fail แล้วจบการทำงาน
-
Cronjobs:
เป็น jobs ที่ทำตามเวลาที่เรากำหนด เช่น ทุกวันตอน 10 โมงเช้า หรือ ทุก 5 นาที เป็นต้น
-
Jobs:
-
rbac.authorization.k8s.io/v1
-
RBAC:
เป็น object ที่ช่วยให้เราสามารถกำหนด authorization ผ่านทาง Roles ของ Kubernetes ได้
-
RBAC:
เนื่องจาก Kubernetes เป็น Opensource Project ที่เติบโตเร็วมาก เพื่อติดตาม features ที่สำคัญหรือที่เราสนใจ สามารถดูได้จาก Kubernetes Enhancement หรือ Release Note ของแต่ละ version ที่ออกมา
ตั้งแต่ v1.16, ถ้ามีการเรียกใช้งาน Object ที่ยกเลิกการใช้งาน (deprecated) ไปแล้ว kubernetes จะตอบ ERROR ไม่เหมือนก่อนหน้านี้ที่จะยังคงรับไปทำงาน
v1 API Group
ใน v1 API จะมีการแบ่ง API ออกเป็นกลุ่มๆ เพื่อให้ง่ายต่อการพัฒนา โดยกลุ่มที่ใช้บ่อยๆ มีดังนี้
-
Node:
คือ server อาจเป็น virtual หรือ physical ก็ได้ ซึ่งถูกเอามา join ใน kubernetes cluster
-
Service Account:
เป็นตัวจัดการเรื่องสิทธิ์ (authorization) ของ process ที่ run ใน pod ในการเข้าถึง API ของ kubernetes
-
Resource Quota:
เป็นตัวจัดการเรื่อง resource quota เช่น CPU, memory และ local ephemeral storage ในแต่ละ namespace
-
Endpoint:
โดยปกติเราไม่ได้จัดการ endpoint ตรง แต่
service
เป็นคนทำให้ โดย endpoint ในที่นี้คือ กลุ่มของ IP:Port ของ Pod ที่มี label ตรงกับ label ที่กำหนดไว้ที่ service
Discovering API Groups
ถ้าเราลอง debug command kubectl
ด้วย option --v=9
ดู จะเห็นว่า URL ที่ kubelet
เรียกไปนั้น มีการระบุ API group ลงไปด้วย เช่น http://localhost:6443/apis/apiregistrationk8s.io/v1beta1
เราสามารถ list api groups ที่ cluster ของเรา support ได้ด้วยวิธีนี้
# Get access token
$ TOKEN=$(kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 --decode )
# Get Stable API Object
$ curl -s https://localhost:6443/apis --header "Authorization: Bearer $TOKEN" -k | jq -c '.groups[].versions[] | select( .version == "v1") | .groupVersion'
"apiregistration.k8s.io/v1"
"apps/v1"
"authentication.k8s.io/v1"
"authorization.k8s.io/v1"
"autoscaling/v1"
"batch/v1"
"networking.k8s.io/v1"
"rbac.authorization.k8s.io/v1"
"storage.k8s.io/v1"
"admissionregistration.k8s.io/v1"
"apiextensions.k8s.io/v1"
"scheduling.k8s.io/v1"
"coordination.k8s.io/v1"
"crd.projectcalico.org/v1"
Deploying an Application
การ deploy application บน kubernetes cluster นั้นทำได้ง่ายมาก เพียงแค่ใช้ command kubectl create ...
เมื่อเรา create แล้วก็จะได้ pod มา 1 pod ข้างใน run container ที่บรรจุ application ของเราอยู่ แต่ถ้าลองเจาะเข้าไปลึกๆ เราจะพบว่ามี object 3 ชนิดเกิดขึ้นได้แก่
-
Deployment:
เป็น controller คอยจัดการ ReplicaSet และ Pods ของมัน ทำให้การจัดการ Pods ทำได้ง่ายขึ้น ถ้าไม่รู้จะใช้อะไร จงใช้ Deployment
-
ReplicaSet:
เป็นตัวที่คอยดูแล Pods ว่ายังมีชีวิตอยู่ปกติดีหรือไม่ ถ้าไม่ก็ restart pods และ update pods หาก admin สั่งมา
-
Pod:
ตัวที่ run container ให้เรา
ตัวอย่าง
# Create deployment which have nginx container running inside
$ kubectl create deployment --image nginx myapp
deployment.apps/myapp created
# Check Deployment status
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
myapp 1/1 1 1 14s
# Check ReplicaSet status
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp-57c9b8fc4 1 1 1 16s
# Check Pod status
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-57c9b8fc4-wgpj2 1/1 Running 0 20s
DaemonSets
DaemonSets เป็น controller ช่วยทำให้เรามั่นในว่าทุก node ใน cluster จะมี pod ที่เราระบุไว้ run อยู่เสมอ ถ้ามี node เพิ่ม มันจะคอยเอา pods ที่เราระบุไว้ไป run ให้อัตโนมัติ ในทางกลับกันถ้า node ถูก remove ออกไปจาก cluster มันจะไป down pod ให้เช่นกัน เรามาสามารถ configure ให้ exclude บาง node ออกไปจาก list ที่ต้องเอา pod ไป run ได้
ปกติเราจะใช้ controller ประเภทนี้กับ การ stream log และ metrics ออกจาก cluster หรือแม้กระทั้งดูแลเกี่ยวกับเรื่อง security
ตัวอย่างของ DaemonSets ที่ต้องมีทุก cluster คือ kube-proxy
# Get all nodes in the cluster
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ubuntu-s-2vcpu-4gb-nyc1-01 Ready <none> 20d v1.16.1
ubuntu-s-4vcpu-8gb-nyc1-01 Ready master 20d v1.16.1
# Show pods of DaemonSets which reside in each node
$ kubectl get pods -n kube-system -l k8s-app=kube-proxy -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system kube-proxy-8ppm2 1/1 Running 1 20d 157.245.241.29 ubuntu-s-2vcpu-4gb-nyc1-01 <none> <none>
kube-system kube-proxy-m8xvp 1/1 Running 1 20d 157.245.138.142 ubuntu-s-4vcpu-8gb-nyc1-01 <none> <none>
StatefulSets
StatefulSets เป็น controller ที่ช่วยให้ stateful application สามารถ run ใน kubernetes cluster ได้ ตัวอย่างของ stateful application เช่น Elasticsearch, Kafka และ Cassandra เป็นต้น
StatefulSets ทำงานเหมือน ReplicaSet แต่ StatefulSet มองว่าแต่ละ pod ไม่เหมือนกัน สังเกตง่ายๆ จาก suffix ของชื่อของ pod จะไม่ใช่ random character แต่เป็นตัวเลขที่เรียงกัน เช่น app-0
, app-1
และ app-2
เป็นต้น ตัวเลขที่เรียงนั้นไม่ใช่เรียงกันเล่นๆ แต่มันแสดงถึง ลำดับในการ start pod ด้วย เช่น app-0
ต้อง start จน Ready ก่อนถึง app-1
จะถูก start
Update strategy ของ StatefulSet ทำได้ 2 แบบคือ
-
On Delete:
ถ้าสั่ง update ไปแล้ว pod จะไม่ update ให้อัตโนมัติ เราต้อง delete pod เอง มันถึงจะ update ให้
-
Rolling Updates:
เป็น default strategy โดย pod จะถูก delete และ recreate โดยอัตโนมัติ โดย StatefulSets จากลำดับมากไปหาน้อย
StatefulSets ถูก promote ให้เป็น Stable ตั้งแต่ v1.9
Autoscaling
การที่จะทำ Autoscaling ได้ สิ่งที่ต้องมีใน cluster คือ metric-server โดย Autoscaling มีด้วยกัน 3 แบบ คือ
-
Horizontal Pod Autoscalers (HPA):
เป็นตัวเดียวที่เป็น stable version ความสามารถของมันคือการเพิ่มหรือลดจำนวน Pod ตาม workload โดย support ทั้ง ReplicationControllers, ReplicaSets และ Deployments โดย default การ scale จะเกิดขึ้นเมื่อมีการใช้งาน CPU ถึง 50% ของที่ limit ไว้เป็นเวลา 3 นาที
-
Cluster Autoscalers (CA):
เป็นการเพิ่มหรือลด node ใน cluster ตาม workload ของ clusters โดย CA เกิดขึ้นได้เมื่อ
cluster ไม่สามารถ deploy pod เพิ่มได้อีกแล้ว
node ใด node หนึ่ง มีการใช้งานสูงมาก (low utilization) เป็นเวลาอย่างน้อย 10 นาที
เมื่อถึงเวลาที่จะต้องเพิ่มหรือลด node, CA จะสั่งงานไปยัง cloud provider ให้ทำงานให้ โดย CA จะ ตรวจสอบ utilization ของ node ทุก 10 วินาที
ในการ scale out (เพิ่ม nodes) จะเกิดขึ้นเมื่อ cluster มี utilization ถึง threshold เป็นเวลา 10 นาที
ในการ scale in (ลด nodes) จะเกิดขึ้นเมื่อ cluster มี utilization ต่ำกว่า threshold เป็นเวลา 10 นาที ถ้าหาก scale ไม่สำเร็จ CA จะ recheck เป็นเวลา 3 นาที และหลังจาก 5 นาที หากยัง fail อยู่ cluster จะไม่สนใจ node นั้นอีกต่อไป
Vertical Pod Autoscalers (VPA):
ยังอยู่ในขั้น development โดย VPA จะเพิ่มหรือลด limit ของ CPU และ memory ให้เหมาะสมกับ workload
Jobs and Cronjobs
Jobs
Jobs จะเป็น pods ที่ run งานใดงานหนึ่งจนเสร็จแล้วก็ตายไป (one-off pods) มันไม่ได้ run ค้างเป็น daemon เหมือน Deployment
, DaemonSet
หรือ StatefulSet
แบบที่ผ่านมา อาจเรียกได้ว่า Jobs คือ การ run batch processing ใน kubernetes cluster
specification ของ jobs มี 2 ค่าที่น่าสนใจคือ
- parallelism: จำนวน pods ของงานที่สามมารถ run พร้อมกันได้
- completion key: จำนวน pods ขั้นต่ำที่ต้อง run ให้ success จึงจะยอกรับได้ว่างานนั้นจบ
ถ้าหากไม่ได้ระบุ 2 ค่านี้ ค่า default คือ 1 และ ถ้าหาก pods ที่ run งานอยู่ fail มันจะถูก restart จนกว่าจำนวน pod ที่ success เท่ากับ completion key
ตัวอย่าง YAML file ของ Jobs
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
Cronjobs
Cronjobs ของ Kubernetes ทำงานเหมือน Cronjobs ใน Linux เลย โดยจะ run pods ในเวลาที่กำหนด ซึ่งการตั้งเวลาในการ run pods นั้นจะใช้ syntax เดียวกับ Linux ด้วยเหตุนี้ อาจเกิดปัญหาเหมือน linux หาก pod หนึ่งยัง run งานไม่จบแต่ถึงเวลาที่จะต้อง run pod นั้นซ้ำอีกรอบ ดังนั้น application ใน pod ต้องออกแบบให้ run ซ้อนกันและ run ซ้ำกันได้ (idempotent)
ทั้งนี้ Cronjobs สามารถกำหนด .spec.concurrencyPolicy
เพื่อจัดการกับการ run pod ซ้อนได้ด้วย โดยมี policy ดังต่อไปนี้
-
Allow (default):
สามารถ run ซ้อนได้
-
Forbid:
ถ้างานเก่ายัง run ไม่เสร็จ งานใหม่จะถูก skip
-
Replace:
ยกเลิกงานเก่า แล้ว run งานใหม่แทนทันที
ตัวอย่าง YAML file ของ Cronjobs
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
RBAC
RBAC ประกอบด้วย 4 resources ย่อย ได้แก่
-
ClusterRoleBinding:
เป็นการ grant role ให้กับ user ในระดับ cluster
-
ClusterRole:
Role ในระดับ cluster
-
RoleBinding:
เป็นการ grant role ให้กับ user ในระดับ namespace
-
Role:
Role ในระดับ namespace
RoleBinding
สามารถ bind ClusterRole
ให้ user ได้ แต่จะมีผลแค่ใน namespace ที่ระบุไว้เท่านั้น
Posted on February 10, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.