K8s快速實戰(三)
今天是學習Kubernetes的第三天,昨天我們學習了許多Kubernetes中重要的元件,像是Deployment、Pod、Namespaces等等。今天我們要繼續學習更多Kubernetes的元件,透過了解這些元件的功能知道Kubernetes是怎麼在各種情境中運用的。
Selector
Selector的功能相當簡單,它的功能就是將兩個不同的元件可以彼此掛勾,它使用labels來辨識、描述以及把資源組合在一起,它使用key-value組合。
以下方的例子來說,Service 會根據 selector 找尋到對應的 Pod,啟動後我們可以利用 kubectl get ep [serviceName] 查看Service是否有連接到指令的Pod。
1 | |
測試時遇到的突發狀況
我原先以為port80可以直接連線,但是實際上出錯了。因為type沒有設定,預設的ClusterIP是沒有辦法對外連線的,ClusterIP 類型,它只在 Kubernetes Cluster 內部可用。解決方法有
- 明確定義type,以及
- 使用port forwarding把本地的8080forward到80之中。
如:kubectl port-forward service/myservice 8080:80
多容器的Pods
你可能會有疑問說,為甚麼要在一個Pods裡面跑多個Container呢?我們已經可以在Node外層管理自動建立與移除Pods,向是這樣在一個Pods裡面建立多個Container難道不會很不好管理嗎?
以下我們舉出幾個例子,告訴你這麼做有什麼好處。
1. Sidecar - Typical pattern
假設你有一個App會把API的log寫入一個log檔案中,而每天你要把log檔案拋到一個整合的FTP中。
這時拆開的好處有:
- 主程式碼會很乾淨,拋送FTP的邏輯不會寫在App裡面,實現了關注點分離。
- 拆開之後,元件的重用性就提升了,如果之後我們需要拋報表的話,拋送這段可以完全照用,不必重寫。

2. Adapter - Typical pattern
假設你有一個App會回傳一個複雜的監控資訊,你就可以建立一個Adapter將App複雜的監控資訊,封裝成Monitor Service方便使用的通用格式。透過實作這個模式,你可以在不必調整App的程式碼的狀況下得到你的簡潔結果。
3. Ambassador - Typical pattern
假設你今天有一個App需要把資料存入到資料庫中,但是問題來了,DB近期可能因應上雲政策要把MySQL移動到Amazon Aurora,在沒有辦法確認資料庫的最終選擇前,透過建立一個Ambassador,你可以讓App只關注在重要的邏輯上,實際資料庫使用的Driver等等的交給Ambassador處理就好。
Kubernetes網路
Kubernetes網路的小整理

同一個Pod的Container的溝通

位於不同Pod的Container溝通

來自Node之外的請求

Workloads
- 簡單來說,
Workload就是一個跑在Kubernetes上面的應用程式,包含以下元件都是一個Workload。Pod(Represents a set of running containers)ReplicaSetDeploymentDeamonSet(Provide node-local facilities, such as a storage driver or network plugin)- Tasks that run to completion
JobCronJob
ReplicaSet
ReplicaSet負責管理Pod Replica與生命週期,以提供自我修復能力。目的就是為了確保Pod數量符合預期。
雖然聽起來ReplicaSet已經有完整的功能了,但實務上當可以建立ReplicaSet時,建議先建立Deployments。
注意!雖然Deployment有包含ReplicaSet的功能,但這兩者不是對立的關係,原因是因為建立Deployment時,也會隱含建立ReplicaSet。我們建議應該操作高級的抽象而不是底層的元件。
yaml

Deployment
- 跟剛才提到的一樣,他是ReplicaSet的高級抽象,元件提供了以下功能:
Self-heal、Scale、Update、Rollback. - 實務上你的每一個微服務就代表一個Deployment。詳情可以看看下圖。
透過ReplicaSet與Deployment管理Pods

Deployment 重要欄位解說

yaml

DaemonSet
DaemonSet是一種控制器,它常常用來確保在每一個Node上都執行一個特定的Pod。這種設計常見於固定的系統需求,比方說收集log、監控服務等等。
它會
- 每個 Node 都會部署一個 Pod(除非被排除)
- 自動新增 Pod 到新加入的 Node
- 刪除 DaemonSet 時不會自動刪除其產生的 Pod(除非加上 –cascade)
此外你還可以做一些特別設定,比方說使用Toleration參數,讓DaemonSet不在master node上面執行。
yaml

StatefulSet
StatefultSet是一個有點特別的元件,一般來說在Kubernetes中的服務屬於**Stateless(無狀態)**的,Stateless意思是它本身不保存狀態,像是資料不會被暫存在應用程式內,每一次的Pod重啟,其實都是不同的IP等等。但當應用需要保存資料狀態(例如資料庫、叢集節點、主從架構),就需要StatefulSet。
Statefult的特性
- 與
Deployment不同,StatefulSet維持讓每一個Pods都有一個固定的辨認身分。 - 每一個
Pods都有持久化的,固定的辨認身分。如 web-0, web-1, web-2。 - 如果
Pod掛了,他會使用同樣的辨認身分換一個新的Pod出來。 - 建立與刪除都是有序地,也就是以
0~X的順序建立Pods, 以X~0的順序刪除Pods。 Containers本身以Stateless設計的。實務上,最好是使用Cloud provider database services來取代StatefulSet功能。- 刪除
StatefulSet不會刪除PVCs,你必須手動刪除。
StatefulSet怎麼設定
想要建立一個StatefulSet,你應該先將Service的clusterIP定義為None,使它變成一個Headless service,Headless service意思是這個Pod不會擁有一個虛擬IP,而是會使用DNS名稱,比如說:mysql-0.mysql。
接著,在你定義好的StatefulSet中綁定剛剛的Service,這樣一來你的StatefulSet中每一個Pod都會有一個固定名稱(mysql-0, mysql-1, mysql-2…)與一個固定的儲存空間(pvc/data-mysql-0 等),設定如圖:
補充:
剛剛提到了StatefulSet可以用來在資料庫上面,那當我們可以有多個資料庫時,就會誕生出資料庫之間的同步問題,此時一個常見的同步解決方案是,採用讀寫分離的架構設計資料庫。
但資料庫此時我們就必須要分得出,哪一個資料庫是允許WRITE的,哪些資料庫只允許READ,這點原先的Stateless設計中是做不到的。
如果是StatefulSet,我們就可以透過將mysql-0.mysql固定成一個可以寫入的資料庫,讓其他的mysql-1.mysql、mysql-2.mysql…只允許讀取。
1 | |
常見Kubernetes 指令
| Command | Description | |
|---|---|---|
| 1 | kubectl create -f [yml file] |
Create a pod |
| 2 | kubectl exec -it [podName] -c [containerName] -- /bin/sh |
Exec into a container |
| 3 | kubectl logs [podname] -c [containerName] |
Get the logs for a container |
| 4 | kubectl delete [yaml file] --force --grace-period=0 |
Clean up |
| 5 | kubectl apply -f [definition.yml] |
Create a ReplicaSet |
| 6 | kubectl get rs |
List all ReplicaSet |
| 7 | kubectl describe rs [rsName] |
Get Info |
| 8 | kubectl delete -f [yml file] |
Delete a ReplicaSet |
| 9 | kubectl delete rs [rsName] |
Delete a ReplicaSet |
| Deployment cheatsheet | ||
| 1 | kubectl create deploy [deploymentName] --image=[imageName] --replicas=X --port=80 |
The imperative way |
| 2 | kubectl get deploy |
List deployments |
| 3 | kubectl describe deploy [deploymentName] |
Get Info |
| 4 | kubectl get rs |
List Replica |
| 5 | kubectl delete deploy [deploymentName] |
Delete a deployment |
| 6 | kubectl get ds |
List DaemonSets |
| 7 | kubectl describe ds [rsName] |
Get info |
| StatefulSet | ||
| 1 | kubectl get sts |
List StatefulSets |
| 2 | kubectl describe sts [rsName] |
Get info |