###### tags: `LSA` `k8s` `study group` # Chapter 4: Introducing the Kubernetes API objects [TOC] ## 這章節包括的範圍 - 管理 k8s cluster 和 經由 k8s api 部屬在這個 cluster 的 application - K8s API object - 取得/理解 k8s object's YAML or JSON manifest - 藉由 Node Object 查看 cluster 的健康程度 status - 藉由 Event Object 查看 cluster 的 events ## 前情提要 上一章我們使用了 3 個 object - deployment object - 生成 3 個 pod object - pod object - 代表獨立的 instance(application) - service object - deploy a load balencer to expose the whole the application ## What is k8s API ### k8s API architecture - HTTP-base [RESTful(Representational **State** Transfer)](https://zh.wikipedia.org/wiki/%E8%A1%A8%E7%8E%B0%E5%B1%82%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2) API - API 的 state 代表 resources 的集合,可以根據不同的 HTTP method 對特定的 resource 進行(Create, Read, Update, Delete) - Create: `POST` - Read: `GET` - Update: `PUT` / `PATCH` - Delete: `DELETE` :::info k8s 的管理和部屬到 cluster 都是基於利用 RESTful API 對 Object 進行操作 or 設定 ![](https://i.imgur.com/I9d2ksR.png) ::: ### difference between resources and objects k8s 社群常常混用 resource 和 object,在正常情形下是可以混用的,但兩者有些微的不一樣 #### 最重要的差別 - resources: **在 k8s API 中一定會有 URI 代表** - 指的不是硬體的 resources(cpu, ram...),而是指我們 or k8s control plane 獲得 k8s 當前 cluster 狀況的入口 - 這裡會有 `apiVersion` 和 `kind` 來讓我們知道 k8s 應該去哪個 API 找這些資料 - example - `http://localhost:8001/api/v1/namespaces/default/events` - `kubectl get events -o yaml -v=6` ```yaml= I0122 20:24:13.622715 1093334 loader.go:372] Config loaded from file: /home/efficacy38/.kube/config I0122 20:24:13.623436 1093334 cert_rotation.go:137] Starting client certificate rotation controller I0122 20:24:13.635556 1093334 round_trippers.go:553] GET https://192.168.49.2:8443/api/v1/namespaces/default/events?limit=500 200 OK in 8 milliseconds kind: List apiVersion: v1 items: - action: Binding apiVersion: v1 eventTime: "2022-01-19T07:37:35.593578Z" firstTimestamp: null involvedObject: apiVersion: v1 kind: Pod name: kiada-8744d76c8-lsczc [...] ``` > Note that kubectl and other tools sometimes output collections of resources as **`kind: List`**. Keep in mind that **`kind: List`** is **not part of the Kubernetes API**; it is exposing an implementation detail from **client-side code in those tools**, used to handle groups of **mixed resources**. > [k8s List and eventList, and other List](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#types-kinds) > - `kubectl get events -o yaml -v=6` > - `v=6`: Display requested resources. > - `v=7`: Display HTTP request headers. > - `v=8`: Display HTTP request contents. > - `v=9`: Display HTTP request contents without truncation of contents. > - [verbose level](https://kubernetes.io/docs/reference/kubectl/cheatsheet/#kubectl-output-verbosity-and-debugging) > [name=Jerry] - object: **不一定會有 URI 代表** - 存儲著所有的 k8s 的 cluster 狀態的最小單位 - 不一定可以直接觀察到,部份要藉由 resources 觀察 - example - event object 不能直接被觀察,但可以從 resources 觀察到 :::info what is URL, URN, URI - URL 著重強調 "如何取得" 資料的方式 可能是 network location(http, ftp...) - `https://www.manning.com/books/Kubernetes-in-action-second-edition` 代表我可以從這個 URL "得到" content-type, encoding, `Kubernetes in Action, Second Edition` 這本書的方式... - Uniform Resource Name(URN) 著重在一個 namespace 下的資源,不需要取得的方法 - k8s in action 2ed 的 URN 是 urn:isbn:9781617297618 - URI 是以 string 表示虛擬 or 實體的資源 - URN 和 URL 都是 URI 的 subset - 可以說 k8s in action 2ed 這本書的 uri 是 `https://www.manning.com/books/Kubernetes-in-action-second-edition` 和 `urn:isbn:9781617297618` [man page(uri)](https://linux.die.net/man/7/uri) [w3c uri classification](https://www.w3.org/TR/uri-clarification/#uri-partitioning) difference between resource and object [specification of `resource` and `object`](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#resources) ::: #### 例子 ![](https://i.imgur.com/Q4W1Zw8.png) - 圖的 resource 顏色代表意義 - 紫色: 不包含 object - 黃色: 新版本的 resources - 綠色: 舊版本的 resources - resources 的一些特性 - 一個 object 可以同時被好幾個 resources expose 出來 - 像是 query `deployments` 時 mydeploy 作為一個集合中的一個 object 回傳 - or query `deployments/mydeploy` 作為一個 object 回傳 - 一個 object 同樣可以被不同版本的 resources expose 出來 - 新版本的 v1 `/apis/apps/v1/deployments` - 舊版本的 v1beta1 `/apis/extensions/v1beta1/deployments` - 兩者可以回傳同樣的 object ,不代表 v1 和 v1beta 是不同的 deployment 集合而只是表達的方式不同 - 有時候一個 resources 不包含 object - 我們可以透過 `/apis/authorization.k8s.io/v1/subjectaccessreviews` 確認 deployment or user 是否具有權限查看 subject :::info 以上的例子說明了 **"object"** 和 **"resource"** 不同之處,**但**在這本書為了避免誤會,使用 **"object"** 代表 **"resoruces"** ::: ## Understanding the structure of an object manifest ### main parts of an object - Type Metadata - object type - `kubectl api-resources`: 當前有哪些 support object - group to which the type belongs - API version - ... - Object Metadata - object instance name - time of creation - identifying information - 這個 metadata 包含的欄位和其他 object 一樣,不管其他的 object type 是什麼 - Spec - 我們對這個 object 的期望狀態 - 這裡包含的欄位因 object 種類而異 - if pods - specifies the pod’s containers, storage volumes... - Status - 現在這個 object 的實際狀況 - if pods - the condition of the pod, the status of each of its containers, its IP address, the node it’s running on... ### Example(user operate k8s object via k8s API) ![](https://i.imgur.com/RkzBQJ1.png) - **write spec**: user 提供 spec part of object 更新 object 的期望狀態 - **read state**: user 讀 state part of object 得知 object 的實際狀況 :::info 圖上是 user 寫入 spec 讀 state,但現實情況是 `PUT` 整包資料(包含上述的 4 個部份),`GET` 也會拿到整包資料 ::: ### what happened after we change the spec? >The **Kubernetes Control Plane** runs several **components** called **controllers** that **manage the objects** you create. Each controller is usually only **responsible for one object** type. For example, the Deployment controller manages Deployment objects. #### Controller 同樣利用 k8s API 獲取/更新 object 狀態 ![](https://i.imgur.com/6mwd6mn.png) 1. **read spec**: controller 會不斷的透過 k8s API 觀察 spec,幫我們向 cluster 做出變更 cluster object 狀態的操作 2. **write state**: 變更後利用 k8s API 告知我們 state - controller 做的事情 - object 當前狀態 :::info - 剛剛討論集中在 spec/status ,但不是所有 object 都有 spec or status,why? - 一些 object 只是 static 的資料,甚至沒有 controller,沒必要區分期望狀態 (spec) 和當前狀態 (status) - 等等的 Event Object 就是這種類型 - 有什麼部份是 object 一定會有的? - Type Metadata - Object Metadata ::: ## Node Object’s individual properties 每個 node object 可以簡單的被想成我們安裝 k8s 的 host,並且可以透過 k8s API 查看每個 Node Object ![](https://i.imgur.com/A3dZXDT.png) - `kubectl get nodes`: 獲取 node list by k8s API ```csv NAME STATUS ROLES AGE VERSION minikube Ready control-plane,master 7d10h v1.22.3 minikube-m02 Ready <none> 2m1s v1.22.3 minikube-m03 Ready <none> 108s v1.22.3 minikube-m04 Ready <none> 92s v1.22.3 minikube-m05 Ready <none> 77s v1.22.3 ``` - `kubectl get node <node-name> -o yaml`: 查看 Node Object 每個欄位在 k8s 內代表的意義 - Type Metadata: - apiVersion: - 當前架構 ( schema ) 版本 - 可能同時被多個版本的 API expose - `v1` - `v1beta` - 原先目的是為了區分不同版本的 API,但後來也用來區分 API group - deployment's apiversion: `app/v1` - Node's apiversion: `v1` - 因為屬於 core API group, 省略 API group - kind - object 類型 - `Node` - `Deployment` - `Service` - ... - Object Metadata: - `name` of object - `labels` and `annotations` - will introduce at ch9 - `resourceVersion` and `managedFields` - will introduce at ch12 - Spec section - 就像的設定檔,在這通常有更多可以被當作設定的欄位 - `podCIDR`: pod IP range - `taint` - not important at this point, will introduce at ch18 - Staus section - 就是當前的 Node 狀態 - node's ip address - hostname - capacity to provide compute resources - current conditions of the node - container images already install at this node - OS - ... - **不用翻文件查看 field 定義的好指令** - `kubectl explain nodes` - `kubectl explain node.spec` - `kubectl explain pods --recursive`: check 每個欄位的 data type - `kubectl explain pods --api-version <api-version>`: check 不同版本的定義 ### example using `condition` field in Node object's `status` - `spec` 和 `status` 會根據 object `kind`(in object's `metadata`) 不同而有不同的欄位 - 為什麼使用 object 的 condition 來介紹 `status`? - 在大部份的 object 都可以看到的欄位 - 提供當下 object 的狀況 - 有助於 **trouble shooting** #### condition 欄位 - condition 有幾個欄位可以注意 - status: - 只能是 `Ture`, `False` or `Unknown` - type: object condition 的類別 - lastTransitionTime: 上次狀態改變的時間 - lastHeartbeatTime: controller 接收到更新的時間 #### 實際例子 - `kubectl get node kind-control-plane -o yaml` or `kubectl get nodes minikube-m02 -o yaml | yq e .status.conditions -` ```yaml= ... status: ... conditions: - lastHeartbeatTime: "2020-05-17T13:03:42Z" lastTransitionTime: "2020-05-03T15:09:17Z" message: kubelet has sufficient memory available reason: KubeletHasSufficientMemory status: "False" type: MemoryPressure - lastHeartbeatTime: "2020-05-17T13:03:42Z" lastTransitionTime: "2020-05-03T15:09:17Z" message: kubelet has no disk pressure reason: KubeletHasNoDiskPressure status: "False" type: DiskPressure - lastHeartbeatTime: "2020-05-17T13:03:42Z" lastTransitionTime: "2020-05-03T15:09:17Z" message: kubelet has sufficient PID available reason: KubeletHasSufficientPID status: "False" type: PIDPressure - lastHeartbeatTime: "2020-05-17T13:03:42Z" lastTransitionTime: "2020-05-03T15:10:15Z" message: kubelet is posting ready status reason: KubeletReady status: "True" type: Ready ``` :::info - yq: yaml 格式化工具 - `kubectl get node <name> -o yaml | yq e .spec.podCIDR -` - `-` stand for read from STDIN - jq: json 格式化工具 - `kubectl get node <name> -o json | jq .status.conditions` ::: ![](https://i.imgur.com/RKxKZuS.png) - condition 的意義 - `Ready`: 最重要的, Node 是否準備好了 - `MemoryPressure`: 這個 Node 是否記憶體不足 - `DiskPressure`: 這個 Node 是否硬碟硬碟不足 - `PIDPressure`: 這個 Node 是否 PID 不足 :::info 如果發現 Node 很奇怪的時候可以來這裡檢查一下 ::: ### 查看其他的欄位 - `kubectl describe <resources>` - 比起 `kubectl get <resources>` 提供更人性化的資料 - 提供一些不在 object 內的欄位資料, `kubectl` CLI 會幫忙收集資料 - 像是 events 的部份 ## Observing cluster events via Event objects 當 controllor 想要根據 object 的 spec 協調 object 的狀態時,會在更新時產生 event object 儲存到 etcd 內 ![](https://i.imgur.com/I2ErQxn.png) ### Intro of event object - event object 有幾個類別 - Normal - Warning - 有其他原因阻止 controller 變更 object 的狀態 - event object 會在創建後存到 etcd - 預設會在 1 hr 後清除( configurable ) ### listing event object - event 不包括在與它關聯的一些 resources - event 可能會在短時間產生一堆,放在關聯的 resources 的欄位就不是很合適 - but 可以透過 `kubectl describe <resource>` 來看到和某個 resource 相關的 event - `kubectl get ev`: 取得當前的 events - `kubectl get ev -o wide`: 查看所有 event 的欄位 - `kubectl get ev --field-selector type=Warning`: 查看 warning 的 event - 如果沒輸出就代表現在還沒有出現 warning 的 event :::info 因為 controllor 在**改變 object 狀態**時會產生 event object,所以 event object 在 **setting/debug** 時是非常重要的 object ,所以在探索新的 object 時,可以先注意 events 的含意,與此同時也可以比較清楚 **K8s 在 CLI 背後幫我們做了哪些事情** ::: ### events 的各種欄位 - Name: 這 event 的名字(`minikube-m02.16cbdeda94d70a6a`),在想透過 API 抓 event object 資料時很方便 - Type: `Normal` or `Warning` - Reason: machine-facing description - Source: 回報 event 的角色,通常是 controller - Object: 這 event 的對象,通常不是 controller(e.g. node/xyz) - Sub-object: 這 event 對象的擁有者(e.g. 在哪個 pod 的 container) - Message: human faceing description - First seen: 第一次發生這個 event 的時間 - Last seen: 最後一次發生 event 的時間 - Count: 發生的幾次 :::info 因為 `kubectl explain events`: 在 event object 內**沒有 spec 和 status** 所以 `kubectl get events minikube-m02.16cbdeda94d70a6a -o yaml` 會顯得雜亂無章,讓人討厭處理 yaml :cry: ~ ::: ## summary - k8s 提供 RESTful API 讓我們操作 cluster, API object 對應到整個構成 cluster 的元件(application, load balancers, nodes, storage volume, ...) - object 可以同時被好幾個 resources 釋出 - k8s API object 是 YAML or JSON manifest - 用 `POST` method 創建 object - 用 `GET` method retrieve object status - object 一定有 Type 和 Object Metadata, 大多都有 `spec` 和 `status`,有些 object 因為只含 static 資料, 所以沒有 `spec` 和 `status` - 當 controllers 管理 object 時,會釋出 k8s event object,所有的 event 都可以經過 k8s API 取得,可以得知 cluster 被做了什麼事情 - `kubectl explain` 可以提供查看欄位定義的地方 - `kubectl describe <resources>` 會提供更多的資訊,有些甚至不在這個 resouces 的 object 內 - `kubectl describe nodes <nodename>`: 會看到 events object 的資訊 - 很多 object 利用 condition 描述 object 當前情況, condition 內的 status 只能是 `True`, `False`, `Unknown` 代表 condition 狀態,`reason` 和 `message` 提供 condition 定義 - node's condition - `MemoryPressure` - `DiskPressure` - `PIDPressure`