Kubernetes CKA課程筆記 1
解說K8s世界,可以先概述一下K8s定義了哪些元件(或說物件/抽象物件)
從考量最基本的應用系統,以Container化形式運作的架構如下來看
依據我們要談到的K8s元件依序如下
1.Node(又如上架構下稱為Worker Node,或簡單稱為Node)
可能是一個單純的Server,可以是實體或虛擬環境
2.pod
在K8s中,各種應用系統的Container是運作在K8s最小的元件單位 — Pod
- 2.1 pod是K8s中的最小(基礎)元件
- 2.2 K8s內的Container的上層,抑是一個抽象層
- (K8s操作pod,而不操作pod內的Container)
- 2.3 pod內通常只有一個Container(實際上1個pod內可以多個Containers)
- 2.4 每個pod都各自擁有自己的IP
- 2.5 pod是ephemeral(短命的),但是當一個指定的pod掛掉,K8s會再長新的
- (例如既有DB-container的pod掛了,會再長新IP的DB-conatiner的pod)
這時候可能有個疑問,那APP連接新長出來的DB-container的pod IP不就要換!?
所以接著要提到解決這個問題的元件 — Service
3.Service(svc)
- 3.1 Service內提供固定的IP位置
- 3.2 Service可以被pod連接使用
- (如範例系統,APP的pod將有對應的Service,DB的pod也有自己的Service)
- 3.2 Service的life cycle與pod間沒有連結
- (如上面提到的如DB的pod掛了,新的DB pod起來,但是DB pod對應的Service還會在,並固定著IP位置)
- 3.3如上解說,在DB pod掛掉並長新的DB pod狀況下,APP的pod將不用更改連線DB的IP位置,只要連的是DB pod對應的Service物件即可!
- 3.4 Service有分External(APP用) & Internal(DB用),只有External暴露在外部Resource
如上Service提供了static的IP位置,但是數字型的IP對於測試等很好用
但是當在提供實際服務的情況下,給出真實IP位置會有各種資安等疑慮
所以最好的URL應該是用host(domain name)方式
面對上述問題,接著引入K8s另一個元件 — Ingress
4.Ingress(ing)
- 導入Ingress後
- 4.1實際外界打API到http://app.com.tw首先截獲請求的將是Ingress
- 4.2截獲請求的Ingress再往前推給對應的Service
以上只是很常見又簡單的系統架構所需的最基本構成的K8s元件
還有其他關連的K8s元件繼續介紹如下
一般APP的pod連接到DB的pod內的DB
在APP內通常要寫上DB endpoint描述(URL(可能包含DB名稱),DB帳號密碼)
通常這些資訊會寫在APP內的設定檔
又或是在環境變數宣告(K8s這部分可能就定義在build image內)
考慮到比如DB名稱更改(也就是造成DB的URL名稱更改)
這意味著我們需要重新建立新的APP image
也就是re-build這個APP的image,並且push到repo
接著重新pull這個新版的image下來做pod重建
只是小小改動卻非常費工!!
這時可以引用K8s的元件 — ComfigMap
5.ComfigMap(cm)
- 5.1這是一個獨立於pod外的Configuration物件
- 5.2供存放Configuration資料像帳號,密碼,URLs...etc
- 5.3然後只要將ComfigMap物件連接到pod,pod就能拿到Configuration資料!
- 5.4所以之後更改設定就不用重新re-build等後續操作
- 5.5但是ComfigMap物件唯一缺點是裡面是明碼存放這些資料!
針對Configuration設定明碼儲存在ConfigMap元件問題
若是像帳號密碼敏感資訊,就不該明碼,這時就可引入K8s另一個元件 — Secret
6.Secret
- 6.1基本上跟ConfigMap元件一樣,但主要用來儲存秘密資料(密碼憑證等)
- 6.2儲存資料以base64加密,但是base64加密通常不夠安全
- 6.3所以K8s的Secret是使用第三方工具來做
- 6.4亦即可以使用雲端或其他第三方工具來做資料加密Secret
至此APP pod內的APP程式可以透過三個地方拿到設定檔:(ConfigMap,Secret,APP內部properties設定檔)
接著需要加以改進的問題是 — Data的儲存,又或說Data Storage
考量上面的DB pod的部分,若產生儲存的資料是在pod內
最上面介紹中我們知道pod特性是ephemeral(短命的)
DB pod一掛掉,就代表儲存的Data就消失在世界上
此時可以引入K8s的元件來解決這個問題,這元件叫 — Volume
7.Volume(vol)
- 7.1 Volume連接實際儲存的空間可以是local(i.e. 與pod的Node同台機台)
- 7.2 Volume亦可連接遠端儲存空間(Node之外,甚至K8s cluster之外甚至雲)
- 7.3 重要概念 →K8s不管理Data的persistence
以上基本運行元件,接著考量到只有單一個APP pod在pod掛掉會有downtime
這在正式環境幾乎是不允許發生的,所以我們可能會做以下配置
一樣的APP pod複製體運行在另一個Node上,並共同使用同一個Service
如前面解說的Service就像是固定的IP位置(並可以是DNS名稱)
在上述圖中情況下,Service也提供了基本的load balance
將過來的http request往前推個其中一個APP pod
但是重要的是如何讓第二個APP pod產生呢,此時需要定義pods的藍圖
pods的藍圖也是K8s元件稱作 — Deployment
8.Deployment
- 8.1 是pods的藍圖
- 8.2 Deployment裡面就可以定義APP pod到底可以分裂長出幾個
- 8.3 Deployment也可以認為是pods的抽象層
在上面圖兩個APP pods情況,其中一個掛掉
Service就會將http request推給還存活的那一個
但是需要注意的是DB pod的Deployment設定的Replicate,不該是複數個
因為DB是有狀態的(state)
因為如果同時有兩個DB pods對儲存資料的persistence空間做寫入
將造成Data Inconsistencies
但是如果DB單個pod真的不夠用怎麼辦!?
可能真的會起到兩個DB pod,但是!!!!
同一時間僅一個DB pod可以對儲存空間寫入,而另一個DB pod可以繼續讀取
能夠做到這件事就必須仰賴類似Deployment的另一種藍圖 — StatefulSet
9.StatefulSet
- 9.1 StatefulSet通常當作各種DB pod的藍圖
- (例如MySQL,mongoDB,elastic search,或其他stateful app)
結論:
Deployment:是stateLESS APP pods藍圖
StatefulSet:是stateFUL APP pods藍圖
但是講師有特別提醒,使用StatefulSet來部屬DB pod不太容易!!
使用上StatefulSet將比Deployment麻煩許多
所以通常都是DB建在K8s cluster之外
然後K8s cluster內大多只使用Deployment建立stateLESS APP pods
但是總歸上面的應用,當一個Node掛了
我們還有一個Node內有完整的APP pod & DB pod,即可避免downtime…
接著還要談到應用系統常常要觸及的東西 — log
在每一個Node當中,我們可能會各個Node建立各一個專做log收集的pod
又或是建置kube-proxy的pod,供給每個Node的proxy的設置
可能的pod佈署方式如下圖:
經過一陣子後可能要在長出新的Node,或減少Node
那麼就要跟著在新的Node上佈署同樣的log-coll與kube-proxy的pod
而刪減的Node上面的log-coll與kube-proxy的pod則要移除
所以這類要依據Node數量來平均佈署的pod
這樣的佈署策略就可以使用K8s的另一個元件 — DaemonSet
10.DaemonSet
- 10.1 類似於Deployment與StatefulSet,但是會依據Node數量來分配佈署
- 10.2 並且主要策略是一個Node佈署一個pod
- 10.3 在新增Node的時候會自動加入如上的log-coll與kube-proxy的pod
- 10.4 在移除Node的時候會自動移除如上的log-coll與kube-proxy的pod
- 10.5 亦即每個Node只有一個replica
總結以上內容:
在K8s世界中:
- Pod:可以當作是Container的抽象元件
- Service:負責聯絡溝通的通路(communication)
- Ingress:到達K8s cluster的路由交通
- ConfigMap & Secret:提供外部設定
- Volume:持久層的Data儲存
- Deployment & StatefulSet:pod的藍圖,並設定replica數量,其中StatefulSet較適合多個DB使用