Docker 有 yaml,K8s 也有 yaml,兩者都是 yaml,為甚麼完全不同呢?這個就不深究了,但兩者的 yaml 不能共用,已經確認過,所以有必要了解 K8s 是怎樣用 yaml 檔,Docker 那邊忘掉吧。
Kubernetes Object 及 Kubernetes API 不需要太深入研究,稍微知道是甚麼就夠,實戰才是本文重點。
為求方便,這篇用 Google Cloud Shell ( GCS ),不用 Google Cloud SDK 版本,因為 kubectl 之前給 Docker for CE 佔用了,把設定改回來很麻煩,之後的文章,應該會改回用本機 Shell。
Google Cloud 快速入門
https://cloud.google.com/kubernetes-engine/docs/quickstart#choosing_a_shell
yaml 語法
https://javatoybox.blogspot.com/2019/01/kubernetes-yaml.html#try-docker-compose
———————————簡易的分隔線————————————
Kubernetes Object︰
結構圖所示,kubectl 跟 API Server 溝通,怎溝通呢?kubectl 建立 API request ( JSON ) 與 API API Server 溝通,然後生成【Kubernetes Object】。
那麼……用甚麼轉成 JSON 格式呢?那就是 yaml,yaml 可以轉換成 JSON,但 API Server 也是有要求的,在 request 中,一定要包含 apiVersion、kind 及 metadata 三種資料。
上圖嚴格來說並不正確,因為使用 Google Cloud Shell,等於透過 browser 把 command 送過去 Google 那邊的 kubectl 執行,不過算了吧,要做的事情還是一樣 ( kubectl --> API Server --> Kubernetes Object )。
Describing a Kubernetes Object
https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#describing-a-kubernetes-object
What is the difference between YAML and JSON? When to prefer one over the other
https://stackoverflow.com/questions/1726802/what-is-the-difference-between-yaml-and-json-when-to-prefer-one-over-the-other
———————————簡易的分隔線————————————
Kubernetes API︰
現在應該知道,為甚麼每個 K8s 的 yaml 都會有 apiVersion 及 kind 作為開頭,但他們的關係是甚麼?
在 Cloud Shell 輸入 command︰
- kubectl version
會有 major 及 minor 等資訊,這代表現在 kubectl client 及 server 版本,這決定 yaml 可以用甚麼 apiVersion,例如以下官方例子,有註解說如何修改 apiVersion 參數,對應不同版本的 kubectl。
https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/#creating-and-exploring-an-nginx-deployment
Kube <major>.<minor>.<patch>
https://github.com/kubernetes/kubernetes/blob/release-1.1/docs/design/versioning.md
Kubernetes API reference
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.13/#pod-v1-core
———————————簡易的分隔線————————————
Container Registry︰
除了 apiVersion、kind 及 metadata 三種資料,而最重要的 image 從何而來?公開 image,從 Docker hub 來,而 private registry,需另外設定,這裡不會詳述,本人鼓勵 Open Source,怎會教人把東西收起來,要學就看官網。
Use Cases
https://kubernetes.io/docs/concepts/containers/images/#use-cases
Quickstart for Container Registry
https://cloud.google.com/container-registry/docs/quickstart
Private registry
https://kubernetes.io/docs/concepts/containers/images/#configuring-nodes-to-authenticate-to-a-private-registry
———————————簡易的分隔線————————————
YAML︰
稍微了解過 Kubernetes Object、Kubernetes API 及 Container Registry,現在到編寫 yaml。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
apiVersion: apps/v1 | |
kind: Deployment | |
metadata: | |
name: k8s-deployderby-demo | |
labels: | |
app: derby | |
spec: | |
replicas: 2 | |
selector: | |
matchLabels: | |
app: derby | |
template: | |
metadata: | |
labels: | |
app: derby | |
spec: | |
containers: | |
- name: k8s-deployderby-demo-container | |
image: integrityknight/derby:v10.14.2.0.withoutHC | |
lifecycle: | |
preStop: | |
exec: | |
command: ["java", "org.apache.derby.drda.NetworkServerControl", "shutdown", "-h", "0.0.0.0"] | |
# Creating a Deployment | |
# https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#creating-a-deployment | |
# | |
# Shutting down the Network Server | |
# https://db.apache.org/derby/docs/10.14/publishedapi/org/apache/derby/drda/NetworkServerControl.html | |
# | |
# Define postStart and preStop handlers | |
# https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
apiVersion: v1 | |
kind: Pod | |
metadata: | |
name: k8s-derby-demo | |
spec: | |
containers: | |
- name: k8s-derby-demo-container | |
image: integrityknight/derby:v10.14.2.0.withoutHC | |
lifecycle: | |
preStop: | |
exec: | |
command: ["java", "org.apache.derby.drda.NetworkServerControl", "shutdown", "-h", "0.0.0.0"] | |
# Shutting down the Network Server | |
# https://db.apache.org/derby/docs/10.14/publishedapi/org/apache/derby/drda/NetworkServerControl.html | |
# | |
# Define postStart and preStop handlers | |
# https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers |
Pod︰
從最基本玩起,首先來個 derby 試一試。
第一行【---】是 Document header,第二到第四行是必要項目。
- apiVersion︰在 Kubernetes API 一節介紹過。
- kind︰對應 apiVersion,定義這個 yaml 檔建立甚麼 Object,例如 Pod、Deployment、Ingress 等等。
- metadata︰給這個 Object 附加資訊。
spec︰specification 簡寫,詳細定義要這 Object 做甚麼。
image︰如果沒特別設定,預設在 Docker Hub 下載 image,可以去 Docker Hub 看看有沒有公開 dockerfile ,有公開的話,最好看一看內容,例如入面有沒有設定 volume,有沒有 CMD 等等。跟據上面 yaml 第九行,在瀏覽器上開啟 https://hub.docker.com/r/integrityknight/derby 應該會去到 Repo 主頁,查一下有沒有重要資訊。
lifecycle︰其實只要第六到第九行就可以,這個定義建立 container 前後,要做甚麼動作,以 database 為例,關閉前應該要 disconnect,這樣才不會有之前的 lock 問題,不過今次沒用 Persistent volumes,重新建立 Pod 時就會還原,所以沒所謂吧?
YAML 1.1 Reference card
https://yaml.org/refcard.html
Pod Templates
https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/#pod-templates
Deployments︰
現在改造 Pod 成 Deployment,用 Deployment 有甚麼好處?
Replication︰
假如有個 Pod 突然死了,會有其他 Pod 會承接,做到無間斷服務,算做 fault tolerance 的一環。
Rolling Update / Rolling Back︰
Deployment
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
———————————簡易的分隔線————————————
改造 Pod 成 Deployment︰
紅框是修改後結果,要把 kind 改成 Deployment,先要改 apiVersion 成 apps/v1,而 labels 給這個 deployment 一個名稱。
replicas︰定義用兩個 Pod 做 Replication。
selector︰重點來了,入面有一個叫 matchLabels 項目,這個設定一定要跟 template 內 labels 一致才會生效!
template︰把之前 Pod 的 spec 都搬進去,再加點 metadata。記謹!yaml 必須層次分明及只能用空白鍵,不能用 Tab,所以抄的時候不要忘記對齊位置。
———————————簡易的分隔線————————————
上傳 yaml 到 GCP︰
開啟 GCS 上傳 yaml 檔案。
檔案在 userhome,打 ls -a 可看到。
———————————簡易的分隔線————————————
使用 YAML 建立 Pod / Deployment︰
之前講解過 yaml 內寫了甚麼,是時候驗證一下是否正確,首先用 pod-demo.yaml 做示範。
上傳完檔案後,使用 yaml 在 GCS 建立 Pods,command 如下︰
- kubectl create -f pod-demo.yaml
- kubectl get pod k8s-derby-demo
- kubectl exec -it k8s-derby-demo /bin/sh
——————————— ( 補充 start ) ————————————
操作 Derby ︰
以前文章有介紹過 Derby,可看參考 連結 回顧。
以 Derby 內建 ij 測試︰
- java org.apache.derby.tools.ij
- connect 'jdbc:derby://localhost:1527/FirstDB';
- SELECT id, actor, product FROM acg_character.profile;
- disconnect;
- exit;
測試 Deployment ︰
Pod 有的東西,deployment 也有,主要測試 Replication 及 Rolling Update / Rolling Back 是否如之前所說那麼神奇。首先,以上傳的 yaml 做 deployment,謹記加 --record,這個會記錄到 rollout history 中,對 Roll back 有幫助,追溯之前做過甚麼︰
- kubectl create -f deployment-demo.yaml --record
- kubectl get pods
Replication︰
假設,在 Database 加一筆資料後,兩邊 Pod 應該會同步更新。故意弄死一隻 Pod,看看會否同步。
在其中一隻 pod 加一筆資料︰
- kubectl exec -it k8s-deployderby-demo-6bc844ccbb-gwvhf /bin/sh
- java org.apache.derby.tools.ij
- connect 'jdbc:derby://localhost:1527/FirstDB';
- SELECT id, actor, product FROM acg_character.profile;
- INSERT INTO acg_character.profile (actor, product) VALUES ('Leon', 'resident evil');
- SELECT id, actor, product FROM acg_character.profile;
- kubectl delete pods k8s-deployderby-demo-6bc844ccbb-gwvhf
進入另一隻 pod 查看結果
- kubectl exec -it k8s-deployderby-demo-6bc844ccbb-bszvm /bin/sh
- java org.apache.derby.tools.ij
- connect 'jdbc:derby://localhost:1527/FirstDB';
- SELECT id, actor, product FROM acg_character.profile;
對不起,沒有更新,這個假設是錯誤,需要把資料及資料庫程式分開, Pod 只提供服務所以只裝資料庫程式,資料要放 Persistent Volumes,通過 Pod 讀寫資料。
再看一次現在 pods,發現會自動再生一個 pod 補上空缺。
- kubectl get pods
——————————— ( 補充 start ) ————————————
Deployment 及 StatefulSets
簡單點說,Deployment 用來處理 stateless 應用,StatefulSets 用來處理 Database 讀寫。例如開放給公眾查詢資料,只用到讀取,可以用 Deployment 做,而公司職員需要輸入資料,用到寫入,這時候該用 StatefulSets 建立 Pod。
StatefulSets in GKE
https://cloud.google.com/kubernetes-engine/docs/concepts/statefulset
——————————— ( 補充 end ) ————————————
Rolling Update / Rolling Back︰
說起 Update 及 Roll back,其實在做甚麼?只是把 image 更新,要 update image 內容的話,需要重新寫過 dockerfile,上傳到 Docker Hub。
Rolling Update︰
command 詳細不說,請對比 yaml 檔。
- kubectl set image deployment.v1.apps/k8s-deployderby-demo k8s-deployderby-demo-container=integrityknight/derby:v10.14.2.0 --record
Rollout history︰
如上圖,有 revision 號碼,這個數字可以用在 Rolling back 上,順帶一提,預設記錄數是十個。
- kubectl rollout history deployment.apps/k8s-deployderby-demo
Rolling Back︰
不多說,看圖。
- kubectl rollout undo deployment.apps/k8s-deployderby-demo --to-revision=1
Updating a Deployment
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment
Rolling Back a Deployment
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deployment
———————————簡易的分隔線————————————
總結︰
再來個 Persistent Volumes 完成 k8s 系例文章。
下一回【Volumes、Persistent Volumes 及 Persistent Volumes Claims】