問題1: Deployment、StatefulSet 和 DaemonSet 的區別和聯繫?
這三者都是 K8S中管理 pod 集合的工作負載資源定義。一個工作負載資源可以由若干個分佈到不同節點上的 pod 構成,pod 是 K8S 中創建和管理的最小可部署的計算單元,一個 pod 可以包含多個容器,多個容器之間共享存儲和網絡等,一個 pod 只有一個虛擬 IP。
Deployment 適合無狀態的應用。pod 的名字隨機生成,每次不同。Service 的 clusterIP 非空,具有轉發規則(iptables等)負載均衡功能。
StatefulSet 適合有狀態的應用,比如數據庫。pod 的名字固定、有序,使用無頭服務,Service 的 clusterIP 是 none,可以通過 dns 訪問指定的 pod,訪問 headless_service_name.namespace.svc.cluster.local 將返回所有 pod 的地址。特點是:
- 穩定唯一的網絡標識符;
- 穩定持久的存儲;
- 有序的擴縮容。
DaemonSet 適合每個節點必須放置一個的應用,比如節點監控、日誌收集。當新節點加入時會自動新增一個 Pod;節點被移除時,其上的 Pod 也會被回收。
問題2: Service 原理
Service 是應用的入口,Pod 的邏輯分組,通過 Label Selector 訪問到底層的一組 Pod。
Service 具有服務發現能力,該能力依賴於環境變量和 CoreDNS,CoreDNS 會監控 Kubernetes API 中的新服務,然後自動建立 DNS 記錄。
Service 有四種類型:
(1)ClusterIP
該模式具有 4 層負載均衡能力,該能力依賴於運行在每個節點上的 kube-proxy 捕獲到達 Service 的 clusterIP(虛擬IP)和 Port 的請求,並重定向到後端 Pod。
kube-proxy 的代理模式歷史上有三種。
- userspace 模式,v1.0 的默認模式,請求會從用戶空間進入內核空間的 iptables,再進入用戶空間的 kube-proxy,再回到內核空間的 iptables,再進入用戶空間的 Pod,多次在內核空間和用戶空間之間進出,性能較差。使用輪轉算法。
- iptables 模式,v1.2 的默認模式,請求直接從 iptables 到用戶空間的 Pod,性能較好,但無法支持上萬級的 Service,因其規則表過於龐大,連接處理複雜度爲 O(n)。採用隨機算法。
- IPVS(IP virtual server) 模式,v1.11 實現GA(基本可用),底層數據結構爲哈希表,連接處理複雜度爲 O(1)。可配置使用不同的算法,比如:輪轉、最少連接、最短預期延遲等等。
kube-proxy 的 watch 機制
kube-proxy 會監控 apiServer 中寫入 etcd 中 Pod 的最新狀態信息,然後更新 iptables 或 ipvs 規則。若 ipvs 不可用,會降級爲 iptables。
(2)Headless
無頭服務,沒有 ClusterIP,無法代理轉發,無法負載均衡。可以直接訪問到 Pod。
(3)NodePort
將節點上的一個端口綁定到 Service 中,通過 NodeIP:NodePort 進行訪問。
(4)LoadBalancer
在 NodePort 基礎上,通過雲提供商的負載均衡器實現外部負載均衡。
(5)ExternalName
將外部的服務映射到內部進行使用。
問題3: Ingress 原理
七層代理(HTTP),包含兩個重要的組建:Ingress 和 Ingress Controller。Ingress 爲外部請求提供路由規則,Ingress Controller 監控 Ingress 和 Service 的變化,並根據規則配置負載均衡提供訪問入口。
目前 K8S 官方維護了三種 Ingress Controller:AWS、Ingress-Nginx、GCE,第三方的 Ingress Controller 有 Istio、Kong 等等。