一、Pod 控制器類型
Pod概念
當一個 Pod 創建后,Pause 容器就會隨着 Pod 啟動,只要是有 Pod,Pause 容器就要被啟動。
在同一個 Pod 里面的容器不能出現端口沖突,否則這個 Pod 可能會出現無法啟動、無限重啟。
一個 Pod 里面的容器數量是大於等於1。
Pod 里面的容器都是共享 Pause 的網絡棧,在同一個 Pod 里即共享網絡又共享存儲卷。
RC和RS概念
Replication Controller 用來確保容器應用的副本數始終保持在用戶定義的副本數,即如果有容器異常退出,會自動創建新的 Pod 來代替;而如果異常多出來的容器也會自動回收。
在 K8s 新版本中,官方不再使用RC(Replication Controler),建議使用 RS(ReplicaSet)代替,因為RS支持集合式的 selector。
ReplicaSet 跟 Replication Controller 沒有本質區別,只是名字不一樣,並且 ReplicaSet 支持集合式的 selector。
支持集合式的 selector 作用:
在創建 Pod 的時候會為它打上標簽(tag),也會為 Pod 里面的容器打上標簽,當需要刪除容器或者進行其他操作的時候,可以通過標簽來進行相關操作。
Deployment原理:
RS 不支持滾動更新,但是 Deployment 支持滾動更新,RS 和 Deployment 建議一起使用的原因是 Deployment 不負責 Pod 創建,Deployment 需要創建 RS 來達到創建 Pod 的能力。
Deployment 結合 RS 使用,滾動更新:
Deployment 創建出來之后,它會去創建一個 RS,Deployment 再去負責創建對應 Pod;
當某一天需要版本更新,Deployment 會去新建一個RS-2版本,在RS-2下啟動v2版本的第一個容器,則退出v1版本的第一個容器,以此類推...到達滾動更新狀態。
回滾:
回滾的機制是因為 Deployment 在滾動更新之后,RS-1並沒有刪除,而是被停用狀態,當執行回滾的時候,Deployment 就好啟動舊版本的RS-1,到達一個回滾效果。
StatefulSet概念
StatefulSet 是為了解決有狀態服務的問題,有狀態服務分為 MySQL、MongoDB 等,無狀態服務分為 Nginx、Apache 等。
應用場景包括:
- 穩定的持久化存儲,即Pod重新調度后還是能訪問到相同的持久化數據,基於PVC來實現;
- 穩定的網絡標志,即Pod重新調度后其PodName和HostName不變,基於Headless Service 來實現;
- 有序部署,有序擴展;
- 有序收縮,有序刪除。
DaemonSet概念
DaemonSet 確保全部(或者一些)Node上運行一個 Pod 的副本。當有 Node 加入集群時,也會為他們新增一個 Pod。當有 Node 從集群移除時,這些 Pod 也會被回收。刪除 DaemonSet 將會刪除它創建的所有 Pod。
使用 DaemonSet 的一些典型用法:
- 運行集群存儲 daemon,例如在每個 Node 上運行 glusterd、ceph。
- 在每個 Node 上運行日志收集 daemon,例如fluentd、logstash。
- 在每個 Node 上運行監控 daemon,例如Prometheus Node Exporter。
Job
Job 負責批處理任務,即僅執行一次的任務,它保證批處理任務的一個或多個 Pod 成功結束。
Job 如果判斷這個腳本不是正常退出,則重新執行一遍,直到正常退出為止,並且還可以設置正常退出次數,比如正常退出次數兩次,才允許這個腳本執行成功。
CronJob
CronJob 是一個計划任務,跟 Linux 的 Crontab 類似,編寫的格式跟 Linux 的 Crontab 一樣。
可以通過一些參數來自定義任務,比如:
failedJobHistoryLimit: # 為失敗的任務執行保留的歷史記錄數,默認為1
successfulJobHistoryLimit:# 為成功的任務執行保留的歷史記錄數,默認為3
startingDeadlineSeconds: # 因各種原因缺失執行作業的時間點所導致的啟動作業錯誤的超時時長,會被計入錯誤歷史記錄
suspend: # 是否掛起后續的任務執行,默認為false,對運行中的作業不會產生影響
二、服務發現
service概念
如果 Pod 之間沒有相干性,是無法通過一個 Service 代理或者收集的。
Service收集的機制:
第一、比如是通一個 RC、RS、Deployment 創建的 Pod;
第二、或者擁有同一組標簽,Service 通過標簽來收集 Pod。
三、網絡通信方式
同一個 Pod 內部通信
同一個 Pod 共享同一個網絡命名空間,共享同一個Linux協議棧,使用回環網卡(lo)通信。
兩個不同 Pod 之間訪問
Pod1 與 Pod2 不在同一台主機的情況:
Pod 的地址是與 docker0 在同一個網段的,但是 docker0 網段與宿主機網卡是兩個完全不同的IP網段,並且不同 Node 之間的通信只能通過宿主機的物理網卡進行。
將 Pod 的 IP 和所在 Node 的IP關聯起來,通過這個關聯讓 Pod 可以互相訪問。
假設 Web APP2 需要訪問 Backend:
源地址寫自己的(10.1.15.2/24),目標地址寫(10.1.20.3/24);
由於目標地址不是跟 Web app2 同一網段,所以發送數據包到網關(Docker0);
Docker0網關發送到 Flannel0,Flannel0 有一個路由表存儲在 Etcd 中,根據路由表來進行轉發;
Flannel0 將數據包轉發到 Flanneld,因為 Flannel0 是 Flanneld 中的一個網橋;
到 Flanneld 之后,它會對該數據報文進行二次封裝,請看上圖右邊數據封裝結構;
此時數據包到了66.12這台機器上:
Flanneld 收到數據包后,解封數據包之后轉發到 Flannel0 網橋中;
Flannel0 轉發到 Docker0,Docker0 根據目標IP地址轉發到 Backend 容器中;
因為 Docker0 只能看到第二層源IP地址和目標IP地址,第一層源IP地址和目標IP地址已經被砍掉了。
Pod1 與 Pod2 在同一台主機情況:
由 docker0 網橋直接轉發請求到 Pod2,不需要經過 Flannel。
組件通訊示意圖
節點網絡:真實網絡,就是節點主機的物理網卡;
Pod 網絡:虛擬網絡,所有的 Pod 之間通信都是通過該網絡;
Service 網絡:虛擬網絡,通過 Service 網絡訪問后端Pod。
以上有不恰當或者講得不對的地方,希望各位留言指正,謝謝!
站在巨人的肩膀上!