YAML 基礎


   剛剛寫kubernetes的YAML文件時比較迷糊。

   本文參考https://blog.qikqiak.com/post/use-yaml-create-kubernetes-deployment/

YAML 基礎

YAML 是專門用來寫配置文件的語言,非常簡潔和強大,遠比JSON格式方便。YAML語言(發音 /ˈjæməl/)的設計目標,就是方便人類讀寫。它實質上是一種通用的數據串行化格式。

它的基本語法規則如下:

  • 大小寫敏感
  • 使用縮進表示層級關系
  • 縮進時不允許使用Tab鍵,只允許使用空格。
  • 縮進的空格數目不重要,只要相同層級的元素左側對齊即可
  • # 表示注釋,從這個字符一直到行尾,都會被解析器忽略。

在我們的kubernetes中,你只需要兩種結構類型就行了:

  • Lists
  • Maps

也就是說,你可能會遇到Lists的Maps和Maps的Lists,等等。不過不用擔心,你只要掌握了這兩種結構也就可以了,其他更加復雜的我們暫不討論。

Maps

首先我們來看看Maps,我們都知道Map是字典,就是一個key:value的鍵值對,Maps可以讓我們更加方便的去書寫配置信息,例如:

--- apiVersion: v1 kind: Pod 

第一行的---是分隔符,是可選的,在單一文件中,可用連續三個連字號---區分多個文件。這里我們可以看到,我們有兩個鍵:kind 和 apiVersion,他們對應的值分別是:v1和Pod。上面的 YAML 文件轉換成 JSON 格式的話,你肯定就容易明白了:

{ "apiVersion": "v1", "kind": "pod" } 

我們在創建一個相對復雜一點的 YAML 文件,創建一個 KEY 對應的值不是字符串而是一個 Maps:

--- apiVersion: v1 kind: Pod metadata: name: kube100-site labels: app: web 

上面的 YAML 文件,metadata 這個 KEY 對應的值就是一個Maps了,而且嵌套的 labels 這個 KEY 的值又是一個Map,你可以根據你自己的情況進行多層嵌套。

上面我們也提到了 YAML 文件的語法規則,YAML 處理器是根據行縮進來知道內容之間的嗯關聯性的。比如我們上面的 YAML 文件,我用了兩個空格作為縮進,空格的數量並不重要,但是你得保持一致,並且至少要求一個空格(什么意思?就是你別一會縮進兩個空格,一會縮進4個空格)。我們可以看到 name 和 labels 是相同級別的縮進,所以 YAML 處理器就知道了他們屬於同一個 MAP,而 app 是 labels 的值是因為 app 的縮進更大。

注意:在 YAML 文件中絕對不要使用 tab 鍵。

同樣的,我們可以將上面的 YAML 文件轉換成 JSON 文件:

{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "kube100-site", "labels": { "app": "web" } } } 

或許你對上面的 JSON 文件更熟悉,但是你不得不承認 YAML 文件的語義化程度更高吧?

Lists

Lists就是列表,說白了就是數組,在 YAML 文件中我們可以這樣定義:

args - Cat - Dog - Fish 

你可以有任何數量的項在列表中,每個項的定義以破折號(-)開頭的,與父元素直接可以縮進一個空格。對應的 JSON 格式如下:

{ "args": [ 'Cat', 'Dog', 'Fish' ] } 

當然,list 的子項也可以是 Maps,Maps 的子項也可以是list如下所示:

--- apiVersion: v1 kind: Pod metadata: name: kube100-site labels: app: web spec: containers: - name: front-end image: nginx ports: - containerPort: 80 - name: flaskapp-demo image: jcdemo/flaskapp ports: - containerPort: 5000 

比如這個 YAML 文件,我們定義了一個叫 containers 的 List 對象,每個子項都由 name、image、ports 組成,每個 ports 都有一個 key 為 containerPort 的 Map 組成,同樣的,我們可以轉成如下 JSON 格式文件:

{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "kube100-site", "labels": { "app": web" } }, "spec": { "containers": [{ "name": "front-end", "image": "nginx", "ports": [{ "containerPort": "80" }] }, { "name": "flaskapp-demo", "image": "jcdemo/flaskapp", "ports": [{ "containerPort": "5000" }] }] } }

是不是覺得用 JSON 格式的話文件明顯比 YAML 文件更復雜了呢?

使用 YAML 創建 Pod

現在我們已經對 YAML 文件有了大概的了解了,我相信你應該沒有之前那么懵逼了吧?我們還是來使用 YAML 文件來創建一個 Deployment 吧。當然如果你的kubernetes集群還沒搭建完成的話,可以繼續閱讀前面 手動搭建高可用的 kubernetes 集群 的文章。

創建 Pod

--- apiVersion: v1 kind: Pod metadata: name: kube100-site labels: app: web spec: containers: - name: front-end image: nginx ports: - containerPort: 80 - name: flaskapp-demo image: jcdemo/flaskapp ports: - containerPort: 5000 

這是我們上面定義的一個普通的 POD 文件,我們先來簡單分析下文件內容:

  • apiVersion,這里它的值是v1,這個版本號需要根據我們安裝的kubernetes版本和資源類型進行變化的,記住不是寫死的
  • kind,這里我們創建的是一個 Pod,當然根據你的實際情況,這里資源類型可以是 Deployment、Job、Ingress、Service 等待。
  • metadata:包含了我們定義的 Pod 的一些 meta 信息,比如名稱、namespace、標簽等等信息。
  • spec:包括一些 containers,storage,volumes,或者其他Kubernetes需要知道的參數,以及諸如是否在容器失敗時重新啟動容器的屬性。你可以在特定Kubernetes API找到完整的Kubernetes Pod的屬性。

讓我們來看一個典型的容器的定義:

spec: containers: - name: front-end image: nginx ports: - containerPort: 80

在這個例子中,這是一個簡單的最小定義:一個名字(front-end),基於 nginx 的鏡像,以及容器 將會監聽的一個端口(80)。在這些當中,只有名字是非常需要的,你也可以指定一個更加復雜的屬性,例如在容器啟動時運行的命令,應使用的參數,工作目錄,或每次實例化時是否拉取映像的新副本。以下是一些容器可選的設置屬性:

  • name
  • image
  • command
  • args
  • workingDir
  • ports
  • env
  • resources
  • volumeMounts
  • livenessProbe
  • readinessProbe
  • livecycle
  • terminationMessagePath
  • imagePullPolicy
  • securityContext
  • stdin
  • stdinOnce
  • tty

明白了 POD 的定義后,我們將上面創建 POD 的 YAML 文件保存成pod.yaml,然后使用kubectl創建 POD:

$ kubectl create -f pod.yaml pod "kube100-site" created 

然后我們就可以使用我們前面比較熟悉的kubectl命令來查看 POD 的狀態了:

$ kubectl get pods NAME READY STATUS RESTARTS AGE kube100-site 2/2 Running 0 1m 

到這里我們的 POD 就創建成功了,如果你在創建過程中有任何問題,我們同樣可以使用前面的kubectl describe進行排查。我們先刪除上面創建的 POD:

$ kubectl delete -f pod.yaml pod "kube100-site" deleted 

創建 Deployment

現在我們可以來創建一個真正的 Deployment。在上面的例子中,我們只是單純的創建了一個 POD 實例,但是如果這個 POD 出現了故障的話,我們的服務也就掛掉了,所以kubernetes提供了一個Deployment的概念,可以讓kubernetes去管理一組 POD 的副本,也就是副本集,這樣就可以保證一定數量的副本一直可用的,不會因為一個 POD 掛掉導致整個服務掛掉。我們可以這樣定義一個Deployment

--- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kube100-site spec: replicas: 2 

注意這里的apiVersion對應的值是extensions/v1beta1,當然kind要指定為Deployment,因為這就是我們需要的,然后我們可以指定一些 meta 信息,比如名字,或者標簽之類的。最后,最重要的是spec配置選項,這里我們定義需要兩個副本,當然還有很多可以設置的屬性,比如一個 Pod 在沒有任何錯誤變成准備的情況下必須達到的最小秒數。

我們可以在Kubernetes v1beta1 API參考中找到一個完整的 Depolyment 可指定的參數列表。

現在我們來定義一個完整的 Deployment 的 YAML 文件:

--- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kube100-site spec: replicas: 2 template: metadata: labels: app: web spec: containers: - name: front-end image: nginx ports: - containerPort: 80 - name: flaskapp-demo image: jcdemo/flaskapp ports: - containerPort: 5000 

看起來是不是和我們上面的pod.yaml很類似啊,注意其中的template,其實就是對 POD 對象的定義。將上面的 YAML 文件保存為deployment.yaml,然后創建 Deployment:

$ kubectl create -f deployment.yaml deployment "kube100-site" created 

同樣的,想要查看它的狀態,我們可以檢查Deployment的列表:

$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kube100-site 2 2 2 2 2m 

我們可以看到所有的 Pods 都已經正常運行了。

到這里我們就完成了使用 YAML 文件創建 Kubernetes Deployment 的過程,在了解了 YAML 文件的基礎后,定義 YAML 文件其實已經很簡單了,最主要的是要根據實際情況去定義 YAML 文件,所以查閱 Kubernetes 文檔很重要。

下面是一個完整的yaml格式定義的文件

apiVersion: v1            //版本
kind: pod                 //類型,pod
metadata:                 //元數據
  name: String            //元數據,pod的名字
  namespace: String       //元數據,pod的命名空間
  labels:                 //元數據,標簽列表
    - name: String        //元數據,標簽的名字
  annotations:            //元數據,自定義注解列表
    - name: String        //元數據,自定義注解名字
spec:                     //pod中容器的詳細定義
  containers:             //pod中的容器列表,可以有多個容器
  - name: String
    image: String         //容器中的鏡像
    imagesPullPolicy: [Always|Never|IfNotPresent]//獲取鏡像的策略
    command: [String]     //容器的啟動命令列表(不配置的話使用鏡像內部的命令)
    args: [String]        //啟動參數列表
    workingDir: String    //容器的工作目錄
    volumeMounts:         //掛載到到容器內部的存儲卷設置
    - name: String
      mountPath: String
      readOnly: boolean
    ports:                //容器需要暴露的端口號列表
    - name: String
      containerPort: int  //容器要暴露的端口
      hostPort: int       //容器所在主機監聽的端口(容器暴露端口映射到宿主機的端口)
      protocol: String
    env:                  //容器運行前要設置的環境列表
    - name: String
      value: String
    resources:            //資源限制
      limits:
        cpu: "250m"       //m表示cpu的千分之一,250m表示占用0.25個CPU
        memory: "64Mi"    //64MiB內存 
      requeste:
        cpu: "500m"
        memory: "128Mi"
    livenessProbe:         //pod內容器健康檢查的設置
      exec:
        command: [String]
      httpGet:             //通過httpget檢查健康
        path: String
        port: number
        host: String
        scheme: Srtring
        httpHeaders:
        - name: Stirng
          value: String 
      tcpSocket:           //通過tcpSocket檢查健康
        port: number
      initialDelaySeconds: 0//首次檢查時間
      timeoutSeconds: 0     //檢查超時時間
      periodSeconds: 0      //檢查間隔時間
      successThreshold: 0
      failureThreshold: 0
      securityContext:      //安全配置
        privileged: falae
    restartPolicy: [Always|Never|OnFailure]//重啟策略
    nodeSelector: object    //節點選擇
    imagePullSecrets:
    - name: String
    hostNetwork: false      //是否使用主機網絡模式,默認否
  volumes:                  //在該pod上定義共享存儲卷
  - name: String
    meptyDir: {}
    hostPath:
      path: string
    secret:                 //類型為secret的存儲卷
      secretName: String
      item:
      - key: String
        path: String
    configMap:             //類型為configMap的存儲卷
      name: String
      items:
      - key: String
        path: String

 

 

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM