新手學習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過程中,有如下幾個注意事項:
- 通過空格控制縮排,不支援Tab
- 如果引數是以空格開始,則需要單引號將其包含起來, 如果引數中包括單引號,則需要進行轉義操作
- 冒號後一定要有空格
- 使用一個短橫+一個空格表示列表,同樣的縮排層級表示屬於同一個列表
- 空值使用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/v1beta2
, apps/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,apiVersion
和kind
此時都已經確定了(如果仍然不明白,建議再看一下上面一節)。 然後開始寫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
應該如何定義。
同樣,直接點選deployment
spec下面的型別定義,
每個資源的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:
metadata
和spec
. 其中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慢慢建立資源了