1. 程式人生 > >新手學習FFmpeg - 如何編寫Kubernetes資原始檔

新手學習FFmpeg - 如何編寫Kubernetes資原始檔

Kubernetes API的使用方式

Kubernetes API屬於宣告式API程式設計, 它和常用的指令式程式設計有一些區別。 通俗的說,指令式程式設計是第一人稱,我要做什麼,我要怎麼做。 作業系統最喜歡這種程式設計正規化了, 作業系統幾乎不用"思考", 只要一對一的將程式碼翻譯成指令就可以了。 而宣告式程式設計則類似於"第二人稱", 也就是你要做什麼。 有點"產品經理"和"開發“之間的關係, "產品經理"只負責提需求,而"開發"怎麼實現他不併關心。

使用者相對Kubernetes就是"產品經理"的角色, 使用者只需要給Kubernetes提需求就可以了,比如說你(Kubernetes)給我(使用者)建立一個執行Mysql服務的Demployment,這個Deployment執行的Pod映象是xxxx,執行引數是xxxxx,掛載的資料卷是xxxxx。。。。。 等等。 開發(Kubernetes)接受到這個需求後,看看需求是否合理(驗證Deployment裡面的引數是否正確),然後就開始建立了。 等待建立成功後,就告訴"產品經理"(使用者)Deployment建立成功。

在建立過程中,使用者並沒有(也不需要)關心服務是如何建立的。 這種操作方式就是宣告式API。

對於Kubernetes來說,宣告式API最大的難點就在於如何提一個正確的需求了。 所以下面來看看如何給Kubernetes提需求。

API的載體 -- Yaml

使用者可以通過kubectl與Kubernetes互動,使用kubectl會通過讀取指定的資源定義檔案來要求kubernetes建立各種資源,這裡的資原始檔指的就是"需求文件",在裡面規定了各種資源的"大小","規格"。 為了使用者可以方便理解裡面的內容(實際使用過程中,感覺使用yaml其實並不方便。尤其是當資料層次多的時候,經常出現空白符不匹配導致解析失敗的問題),資原始檔使用了yaml

格式(yaml對使用者友好,kubectl提交需求時,會將yaml轉換成json格式,所以Kubernetes其實最終讀取的是json格式的需求文件).

我經常在編輯完之後,通過 https://codebeautify.org/yaml-validator 來驗證格式是否正確。

編輯Yaml過程中,有如下幾個注意事項:

  1. 通過空格控制縮排,不支援Tab
  2. 如果引數是以空格開始,則需要單引號將其包含起來, 如果引數中包括單引號,則需要進行轉義操作
  3. 冒號後一定要有空格
  4. 使用一個短橫+一個空格表示列表,同樣的縮排層級表示屬於同一個列表
  5. 空值使用null或者~表示。

API文件總覽

Kubernetes的API文件在 https://kubernetes.io/docs/reference/ 點選版本號,就可以看到相對應的API文件說明。

Kubernetes API大致分為以下幾類(個人起的名稱,未必準確):

  • 計算類
  • 負載類
  • 配置類
  • 管理類

計算類對應是Workload,主要是Pod,Job,Deployment,ReplicaSet之類涉及到CPU計算的各種資源。 負載類指的是LB類資源,配置類指的是ConfigMap之類涉及到外部資源的資料資源, 而管理類指的是對叢集的管理,例如建立名稱空間,節點隔離等

對Kubernetes的資源操作,絕大多數就是對上面四類資源的操作。

一個標準的Kubernetes 資原始檔,其結構大致是下面的樣子:

apiVersion:
kind:
metadata:
spec:
status:

apiVersion表示API版本,服務端會通過讀取這個版本號,來進行內容驗證。 這個版本號可以通過API文件獲取,例如要編寫一個Deployment資源,首先檢視API文件(https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#daemonset-v1-apps)如下:

版本號由Group/Version這樣的格式組成,因此Deployment的apiVersion就是apps/v1。 需要注意下面一行小字: "Other API versions of this object exist: v1beta2 v1beta1 v1beta1",因此apps/v1beta2apps/v1beta1這樣的版本號也是合法的。 具體使用哪個版本號,最終要取決於叢集支援哪個版本號。

kind表示操作的是什麼資源, 向上面要操作Deployment,kind就是Deployment。 如果要建立Pod,則Kind就是Pod。

metadata則是此資源的一些元資料, 如何設定後面會聊到

spec是具體如何建立這個資源,同樣放到後面再聊

status是此資源狀態資料,使用者不需要設定,即便設定,叢集也會過濾掉

總結一下:

使用者通過apiversion+kind告之叢集,準備按照哪個API版本所規定的協議建立何種資源。 叢集確認支援指定版本和資源後,就會讀取後面的資源詳細引數。 但需要注意,未必所有資源都有這幾項,例如Configmap就沒有Spec,但卻增加了data. 後面會聊到如何通過API文件來組織資原始檔

建立資源

來看metadata。每種資源有不同的metadata規範, 大部分場景中可以通用的,也就是說雖然資源不同,但metadata格式相同,只是裡面的引數不同。 當需要檢視具體metadata時,直接點選metadata下面的ObjectMeta,如下圖:

會跳到ObjectMeata定義頁面中:

這裡仍然假設需要建立一個Deployment,apiVersionkind此時都已經確定了(如果仍然不明白,建議再看一下上面一節)。 然後開始寫metedata. 通過ObjectMeta可以看到裡面有很多屬性,例如annotations表示一些註釋資訊,型別是obejct,通過後面的連結: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ 可以得知是一個key=value格式的map。 如果要添加註釋資訊,可以按照如下方式編寫:

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"

在建立任何資源時,name和namesapce都是需要指定的(namespace如果不指定,預設是default,但指定namespace是一個好習慣)。檢視name和namespace的定義:

都是字串格式,因此在上面基礎之上在新增name和namespace:

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  name: envoy-01
  namespace: tio

在某些場景中(其實是大多數場景),需要通過label來篩選對應的workload,所以有必要給我的Deployment新增特定的Label, 檢視一下Label的定義:

檢視後面的連結 (https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) 可以看出也是一個key=value格式的map,和annotations一樣,所以新增label如下:

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    k8s-app: envoy-01
  name: envoy-01
  namespace: tio

metadata的定義就先看到這裡,下面來看spec應該如何定義。

同樣,直接點選deploymentspec下面的型別定義,

每個資源的spec都不同,下面是DeploymentSpec的定義:

每個屬性都有解釋,這裡就不逐一翻譯了, 我們假設這個Deployment預期兩個Pod,因此replicas=2,通過selector來匹配ReplicaSet,設定strategy為滾動更新。 在上面資原始檔的基礎之上,我們繼續定義spec,如下:

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    k8s-app: envoy-01
  name: envoy-01
  namespace: tio
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: envoy-01
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate

selector可以參考(https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#labelselector-v1-meta)規定的規範, strategy可以參看(https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#deploymentstrategy-v1-apps)。

這些定義完成後,就剩下Template了,這個用來定義應該如何來建立Pod(或者說表示使用者想要一個什麼樣的Pod)。

點選下面的Pod資料定義:

可以看到Pod Template有兩個屬性:

因此資原始檔大致應該是如下的樣子:

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    k8s-app: envoy-01
  name: envoy-01
  namespace: tio
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: envoy-01
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
    spec:

metadataspec. 其中metadata和上面我們所設定的metadata一樣,這裡就不贅述了。spec通過下面的定義可以得知是podspec

點選podspec後可以看到和經常設定的docker container引數有一些類似了:

我們繼續在上面資原始檔基礎上補充podspec的內容

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
  labels:
    k8s-app: envoy-01
  name: envoy-01
  namespace: tio
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: envoy-01
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        k8s-app: envoy-01
    spec:
      containers:
      - args:
        - -c
        - /etc/envoy/envoy.yaml
        - --service-node
        - sn1
        - --service-cluster
        - sc1
        command:
        - envoy
        image: envoyproxy/envoy
        imagePullPolicy: IfNotPresent
        name: envoy
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 250m
            memory: 256Mi
        securityContext:
          privileged: false
          procMount: Default
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /etc/envoy
          name: conf

至此,一個最簡單的Deployment資原始檔就寫好了。 剩下的就是通過kubectl提交這個需求給Kubernetes叢集,然後就可以等待Kubernetes慢慢建立資源了