官术网_书友最值得收藏!

3.2 對象類資源格式

Kubernetes API僅接受及響應JSON格式的數據(JSON對象),同時,為了便于使用,它也允許用戶提供YAML格式的POST對象,但API Server需要事先自行將其轉換為JSON格式后方能提交。API Server接受和返回的所有JSON對象都遵循同一個模式,它們都具有kind和apiVersion字段,用于標識對象所屬的資源類型、API群組及相關的版本。

進一步地,大多數的對象或列表類型的資源還需要具有三個嵌套型的字段metadata、spec和status。其中metadata字段為資源提供元數據信息,如名稱、隸屬的名稱空間和標簽等;spec則用于定義用戶期望的狀態,不同的資源類型,其狀態的意義也各有不同,例如Pod資源最為核心的功能在于運行容器;而status則記錄著活動對象的當前狀態信息,它由Kubernetes系統自行維護,對用戶來說為只讀字段。

每個資源通常僅接受并返回單一類型的數據,而一種類型可以被多個反映特定用例的資源所接受或返回。例如對于Pod類型的資源來說,用戶可創建、更新或刪除Pod對象,然而,每個Pod對象的metadata、spec和status字段的值卻又是各自獨立的對象型數據,它們可被單獨操作,尤其是status對象,是由Kubernetes系統單獨進行自動更新,而不能由用戶手動操作它。

3.2.1 資源配置清單

3.1節中曾使用curl命令通過代理的方式于API Server上請求到了kube-system這個Namespace活動對象的狀態信息,事實上,用戶也可以直接使用“kubectl get TYPE/NAME-o yaml”命令獲取任何一個對象的YAML格式的配置清單,或者使用“kubectl get TYPE/NAME -o json”命令獲取JSON格式的配置清單。例如,可使用下面的命令獲取kube-system的狀態:

     ~]$ kubectl get namespace kube-system -o yaml
        apiVersion: v1
        kind: Namespace
        metadata:
          creationTimestamp: 2018-08-11T02:33:23Z
          name: kube-system
          resourceVersion: "33"
          selfLink: /api/v1/namespaces/kube-system
          uid: eb6bf659-9d0e-11e8-bf0d-000c29ab0f5b
        spec:
          finalizers:
          - kubernetes
        status:
          phase: Active

除了極少數的資源之外,Kubernetes系統上的絕大多數資源都是由其使用者所創建的。創建時,需要以與上述輸出結果中類似的方式以YAML或JSON序列化方案定義資源的相關配置數據,即用戶期望的目標狀態,而后再由Kubernetes的底層組件確保活動對象的運行時狀態與用戶提供的配置清單中定義的狀態無限接近。因此,資源的創建要通過用戶提供的資源配置清單來進行,其格式類似于kubectl get命令獲取到的YAML或JSON形式的輸出結果。不過,status字段對用戶來說為只讀字段,它由Kubernetes集群自動維護。例如,下面就是一個創建Namespace資源時提供的資源配置清單示例,它僅提供了幾個必要的字段:

        apiVersion: v1
        kind: Namespace
        metadata:
          name: dev
        spec:
          finalizers:
          - kubernetes

將如上所述配置清單中的內容保存于文件中,使用“kubectl create -f /PATH/TO/FILE”命令即可將其創建到集群中。創建完成后查看其YAML或JSON格式的輸出結果,可以看到Kubernetes會補全其大部分的字段,并提供相應的數據。事實上,Kubernetes的大多數資源都能夠以類似的方式進行創建和查看,而且它們幾乎都遵循類似的組織結構,下面的命令顯示了第2章中使用kubectl run命令創建的Deployment資源對象myapp的狀態信息:

     ~]$ kubectl get deployment myapp -o yaml
        apiVersion: extensions/v1beta1
        kind: Deployment
        metadata:
        ……
          name: myapp
        spec:
          replicas: 3
          selector:
            matchLabels:
              run: myapp
          ……
        status:
          ……

為了節約篇幅,上面的輸出結果省去了大部分內容,僅保留了其主體結構。從命令結果可以看出,它也遵循Kubernetes API標準的資源組織格式,由apiVersion、kind、metadata、spec和status五個核心字段組成,只是spec字段中嵌套的內容與Namespace資源幾乎完全不同。

事實上,對幾乎所有的資源來說,apiVersion、kind和metadata字段的功能基本上都是相同的,但spec則用于資源的期望狀態,而資源之所以存在類型上的不同,也在于它們的嵌套屬性存在顯著差別,它由用戶定義和維護。而status字段則用于記錄活動對象的當前狀態,它要與用戶在spec中定義的期望狀態相同,或者正處于轉換為與其相同的過程中。

3.2.2 metadata嵌套字段

metadata字段用于描述對象的屬性信息,其內嵌多個字段用于定義資源的元數據,例如name和labels等,這些字段大體可分為必要字段和可選字段兩大類。名稱空間級別的資源的必選字段包括如下三項。

?□namespace:指定當前對象隸屬的名稱空間,默認值為default。

?□name:設定當前對象的名稱,在其所屬的名稱空間的同一類型中必須唯一。

?□uid:當前對象的唯一標識符,其唯一性僅發生在特定的時間段和名稱空間中;此標識符主要是用于區別擁有同樣名字的“已刪除”和“重新創建”的同一個名稱的對象。

可選字段通常是指由Kubernetes系統自行維護和設置,或者存在默認,或者本身允許使用空值等類型的字段,常用的有如下幾個:

?□labels:設定用于標識當前對象的標簽,鍵值數據,常被用作挑選條件。

?□annotations:非標識型鍵值數據,用來作為挑選條件,用于labels的補充。

?□resourceVersion:當前對象的內部版本標識符,用于讓客戶端確定對象變動與否。

?□generation:用于標識當前對象目標狀態的代別。

?□creationTimestamp:當前對象創建日期的時間戳。

?□deletionTimestamp:當前對象刪除日期的時間戳。

此外,用戶通過配置清單創建資源時,通常僅需要給出必選字段,可選字段可按需指定,對于用戶未明確定義的嵌套字段,則需要由一系列的finalizer組件自動予以填充。而用戶需要對資源創建的目標資源對象進行強制校驗,或者在修改時需要用到initializer組件完成,例如,為每個待創建的Pod對象添加一個Sidecar容器等。不同的資源類型也會存在一些專有的嵌套字段,例如,ConfigMap資源還支持使用clusterName等。

3.2.3 spec和status字段

Kubernetes用spec來描述所期望的對象應該具有的狀態,而用status字段來記錄對象在系統上的當前狀態,因此status字段僅對活動對象才有意義。這兩個字段都屬于嵌套類型的字段。在定義資源配置清單時,spec是必須定義的字段,用于描述對象的目標狀態,即用戶期望對象需要表現出來的特征。status字段則記錄了對象的當前狀態(或實際狀態),此字段值由Kubernetes系統負責填充或更新,用戶不能手動進行定義。Master的controller-manager通過相應的控制器組件動態管理并確保對象的實際狀態匹配用戶所期望的狀態,它是一種調和(reconciliation)配置系統。

例如,Deployment是一種用于描述集群中運行的應用的對象,因此,創建Deployment類型的對象時,需要為目標Deployment對象設定spec,指定期望需要運行的Pod副本數量、使用的標簽選擇器以及Pod模板等。Kubernetes系統讀取待創建的Deployment對象的spec以及系統上相應的活動對象的當前狀態,必要時進行對象更新以確保status字段吻合spec字段中期望的狀態。如果這其中任一實例出現問題(status字段值發生了變化),那么Kubernetes系統則需要及時對spec和status字段的差異做出響應,例如,補足缺失的Pod副本數目等。

spec字段嵌套的字段對于不同的對象類型來說各不相同,具體需要參照Kubernetes API參考手冊中的說明分別進行獲取,核心資源對象的常用配置字段將會在本書后面的章節中進行講解。

3.2.4 資源配置清單格式文檔

定義資源配置清單時,盡管apiVersion、kind和metadata有章可循,但spec字段對不同的資源來說卻是千差萬別的,因此用戶需要參考Kubernetes API的參考文檔來了解各種可用屬性字段。好在,Kubernetes在系統上內建了相關的文檔,用戶可以使用“kubectl explain”命令直接獲取相關的使用幫助,它將根據給出的對象類型或相應的嵌套字段來顯示相關的下一級文檔。例如,要了解Pod資源的一級字段,可以使用類似如下的命令,命令結果會輸出支持使用的各一組字段及其說明:

     ~]$ kubectl explain pods

需要了解某一級字段表示的對象之下的二級對象字段時,只需要指定其一級字段的對象名稱即可,三級和四級字段對象等的查看方式依此類推。例如查看Pod資源的Spec對象支持嵌套使用的二級字段,可使用類似如下的命令:

     ~]$ kubectl explain pods.spec
        RESOURCE: spec <Object>

        DESCRIPTION:
              Specification of the desired behavior of the pod. ……

              PodSpec is a description of a pod.

        FIELDS:
            activeDeadlineSeconds          <integer>
              Optional duration in seconds the pod may be active on the node relative to
              StartTime before the system will actively try to mark it failed and kill
              associated containers. Value must be a positive integer.
        ……
            containers    <[]Object> -required-
              List of containers belonging to the pod. Containers cannot currently be
              added  or  removed.  There  must  be  at  least  one  container  in  a  Pod.  Cannot
                  be updated.
        ……

對象的spec字段的文檔通常包含RESOURCE、DESCRIPTION和FIELDS幾節,其中FIELDS節中給出了可嵌套使用的字段、數據類型及功能描述。例如,上面命令的結果顯示在FIELDS中的containers字段的數據類型是一個對象列表([]Object),而且是一個必選字段。任何值為對象類型數據的字段都會嵌套一到多個下一級字段,例如,Pod對象中的每個容器也是對象類型數據,它同樣包含嵌套字段,但容器不支持單獨創建,而是要包含于Pod對象的上下文中,其詳細信息可通過三級字段來獲取,命令及其結果示例如下:

     ~]$ kubectl explain pods.spec.containers
        RESOURCE: containers <[]Object>

        DESCRIPTION:
              List of containers belonging to the pod. Containers cannot currently be added
        or removed. There must be at least one container in a Pod. Cannot be updated.

              A single application container that you want to run within a pod.

        FIELDS:
            args <[]string>
              Arguments to the entrypoint. The docker image's CMD is used if this is not
                  provided. ……

            command        <[]string>
              Entrypoint array. Not executed within a shell. The docker image's
              ENTRYPOINT is used if this is not provided. ……

            env   <[]Object>
              List of environment variables to set in the container. Cannot be updated.

            ……

內建文檔大大降低了用戶手動創建資源配置清單的難度,嘗試使用某個資源類型時,explain也的確是用戶的常用命令之一。熟悉各常用字段的功用之后,以同類型的現有活動對象的清單為模板可以更快地生成目標資源的配置文件,命令格式為“kubectl get TYPE NAME -o yaml --export”,其中--export選項用于省略輸出由系統生成的信息。例如,基于現在的Deployment資源對象myapp生成配置模板deploy-demo.yaml文件,可以使用如下命令:

     ~]$ kubectl get deployment myapp -o yaml --export > deploy-demo.yaml

通過資源清單文件管理資源對象較之直接通過命令行進行操作有著諸多優勢,具體包括命令行的操作方式僅支持部分資源對象的部分屬性,而資源清單支持配置資源的所有屬性字段,而且使用配置清單文件還能夠進行版本追蹤、復審等高級功能的操作。本書后續章節中的大部分資源管理操作都會借助于資源配置文件進行。

3.2.5 資源對象管理方式

Kubernetes的API Server遵循聲明式編程(declarative programming)范式而設計,側重于構建程序程序邏輯而無須用戶描述其實現流程,用戶只需要設定期望的狀態,系統即能自行確定需要執行的操作以確保達到用戶期望的狀態。例如,期望某Deployment控制器管理三個Pod資源對象時,而系統觀察到的當前數量卻是兩個,于是系統就會知道需要創建一個新的Pod資源來滿足此期望。Kubernetes的自愈、自治等功能都依賴于其聲明式機制。

與此對應的另一種范式稱為陳述式編程(imperative programming),代碼側重于通過創建一種告訴計算機如何執行操作的算法來更改程序狀態的語句來完成,它與硬件的工作方式密切相關,通常,代碼將使用條件語句、循環和類繼承等控制結構。為了便于用戶使用,Kubernetes的API Server也支持陳述式范式,它直接通過命令及其選項完成對象的管理操作,前面用到的run、expose、delete和get等命令都屬于此類,執行時用戶需要告訴系統要做什么,例如,使用run命令創建一個有著3個Pod對象副本的Deployment對象,或者通過delete命令刪除一個名為myapp的Service對象。

Kubernetes系統的大部分API對象都有著spec和status兩個字段,其中,spec用于讓用戶定義所期望的狀態,系統從中讀出相關的定義;而status則是系統觀察并負責寫入的當前狀態,用戶可以從中獲取相關的信息。Kubernetes系統通過控制器監控著系統對象,由其負責讓系統當前的狀態無限接近用戶所期望的狀態。

kubectl的命令由此可以分為三類:陳述式命令(imperative command)、陳述式對象配置(imperative object configuration)和聲明式對象配置(declarative object configuration)。第一種方式即此前用到的run、expose、delete和get等命令,它們直接作用于Kubernetes系統上的活動對象,簡單易用,但不支持代碼復用、修改復審及審計日志等功能,這些功能的使用通常要依賴于資源配置文件,這些文件也稱為資源清單。在這種模式下,用戶可以訪問每個對象的完整模式,但用戶還需要深入學習Kubernetes API。

如3.2.4節所述,資源清單本質上是一個JSON或YAML格式的文本文件,由資源對象的配置信息組成,支持使用Git等進行版本控制。而用戶可以資源清單為基礎,在Kubernetes系統上以陳述式或聲明式進行資源對象管理,如圖3-4所示。

圖3-4 基于資源配置清單管理對象

陳述式管理方式包括create、delete、get和replace等命令,與陳述式命令的不同之處在于,它通過資源配置清單讀取需要管理的目標資源對象。陳述式對象配置的管理操作直接作用于活動對象,即便僅修改配置清單中的極小一部分內容,使用replace命令進行的對象更新也將會導致整個對象被替換。進一步地,混合使用陳述式命令進行清單文件帶外修改時,必然會導致用戶丟失活動對象的當前狀態。

聲明式對象配置并不直接指明要進行的對象管理操作,而是提供配置清單文件給Kubernetes系統,并委托系統跟蹤活動對象的狀態變動。資源對象的創建、刪除及修改操作全部通過唯一的命令apply來完成,并且每次操作時,提供給命令的配置信息都將保存于對象的注解信息(kubectl.kubernetes.io/last-applied-configuration)中,并通過對比檢查活動對象的當前狀態、注解中的配置信息及資源清單中的配置信息三方進行變更合并,從而實現僅修改變動字段的高級補丁機制。

陳述式對象配置相較于聲明式對象配置來說,其缺點在于同一目錄下的配置文件必須同時進行同一種操作,例如,要么都創建,要么都更新等,而且其他用戶的更新也必須反映在配置文件中,不然其更新在一下次的更新中將會被覆蓋。因此,聲明式對象配置是優先推薦給用戶使用的管理機制。

然而,對于新手來說,陳述式命令的配置方式最易于上手,對系統有所了解后易于切換為使用陳述式對象配置管理方式。因此,若推薦給高級用戶則推薦使用聲明式配置,并建議同時使用版本控制系統存儲所期望的狀態,以及跨對象的歷史信息,并啟用變更復審機制。另外,推薦使用借助于kube-applier等一類的項目實現自動化聲明式配置,用戶將配置推送到Git倉庫中,然后借助此類工具即能將其自動同步于Kubernetes集群上。

主站蜘蛛池模板: 嘉禾县| 峡江县| 阿拉善右旗| 青州市| 怀安县| 蓝田县| 嘉禾县| 洛川县| 沧州市| 开封县| 建瓯市| 永昌县| 西贡区| 徐水县| 新巴尔虎左旗| 聂荣县| 平凉市| 历史| 溧水县| 孟州市| 确山县| 金乡县| 沂源县| 抚顺县| 塘沽区| 英吉沙县| 巫溪县| 兰考县| 多伦县| 偏关县| 类乌齐县| 自治县| 莱芜市| 大同县| 谢通门县| 鹤岗市| 嘉黎县| 宜黄县| 疏勒县| 石城县| 柞水县|