在ACK叢集中配置工作負載(Deployment、StatefulSet、DaemonSet、Job、CronJob等)時,您需考慮多種因素,以確保應用可以穩定、可靠地運行。
聲明每個Pod的Requests和Limits
在 Kubernetes 叢集中,節點上調度過多 Pod 會導致負載過高,無法正常提供服務。配置Pod時,建議聲明其所需的requests和limits,以便叢集在部署Pod時可以根據資源需求找到合適的節點。
下方樣本中,Nginx Pod的資源配置為:
CPU請求:1核;記憶體請求:1024MiB
CPU限制:2核;記憶體限制:4096MiB
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
resources: # 資源聲明
requests:
memory: "1024Mi"
cpu: "1000m"
limits:
memory: "4096Mi"
cpu: "2000m"Kubernetes採用靜態資源調度機制。每個節點的剩餘資源的計算公式為節點剩餘資源 = 節點總資源 - 已指派資源。手動運行資源密集型程式時,Kubernetes無法感知其實際資源使用量。因此公式中基於已指派資源進行計算,而非實際使用資源。
此外,所有Pod都應聲明resources。如果Pod未聲明resources,調度到節點後,Kubernetes不會為其預留資源。這可能導致節點上調度過多Pod,進而引發資源爭用問題。
推薦使用ACK提供的資源畫像功能,基於資源使用量的歷史資料獲得容器粒度的資源規格推薦,簡化容器requests和limits的配置複雜度。
啟動時等待下遊服務,不要直接退出
有些應用可能存在一些外部依賴,例如需要從資料庫(DB)讀取資料或者依賴另外一個服務的介面。應用啟動時,外部依賴可能無法完全滿足。在傳統手動營運中,通常採用“依賴不滿足即退出”的方式(即failfast)。但在Kubernetes中,大多營運操作是自動化的,無需人工幹預。例如部署應用時系統會自動選擇節點並啟動應用,應用失敗時系統會自動重啟,負載增加時可以通過HPA(Horizontal Pod Autoscaler)實現自動擴容。
假設有兩個應用A和B,A依賴B,並且它們運行在同一節點上。如果該節點因某種原因重啟,重啟後A先啟動,而B尚未啟動,此時A的依賴無法滿足。如果A按照傳統方式直接退出,即使B啟動後,A也不會自動回復,需要人工幹預。
在Kubernetes叢集中,建議在啟動時檢查依賴。如果依賴不滿足,可以通過輪詢等待,而不是直接退出。這一功能可以通過Init Container實現。
配置restart policy
Pod 運行期間,進程退出是一種常見現象。代碼缺陷或記憶體佔用過多等問題都可能導致應用程式進程退出,從而導致 Pod 終止。您可以為 Pod 配置restartPolicy,確保在 Pod 退出後能夠自動重啟。`
apiVersion: v1
kind: Pod
metadata:
name: nginx-test
spec:
restartPolicy: OnFailure
containers:
- name: nginx
image: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6restartPolicy可選值如下:
Always:總是自動重啟。OnFailure:異常退出時自動重啟(進程退出狀態非0)。Never:從不重啟。
配置Liveness Probe和Readiness Probe
Pod 處於 Running 狀態並不等同於Pod能夠正常提供服務。對於處於Running狀態的 Pod,其內部進程可能發生死結,導致無法正常提供服務。但由於 Pod 仍處於 Running 狀態,Kubernetes 不會自動重啟它。
因此,建議為所有 Pod 配置探針:
Liveness Probe用於探測 Pod 是否真正存活並具備服務能力。當Liveness Probe 檢測到問題時,Kubernetes 會自動重啟該 Pod。
Readiness Probe用於檢測 Pod 是否已準備好對外提供服務。在應用啟動期間,初始化過程可能需要一定時間,在此期間 Pod 無法對外提供服務。Readiness Probe可以通知 Ingress 或 Service 是否可將流量轉寄至該 Pod。當 Pod 出現問題時,它能夠防止新流量繼續轉寄到該 Pod。
apiVersion: v1
kind: Pod
metadata:
name: tomcat
spec:
containers:
- name: tomcat
image: tomcat
livenessProbe:
httpGet:
path: /index.jsp
port: 8080
initialDelaySeconds: 3
periodSeconds: 3
readinessProbe:
httpGet:
path: /index.jsp
port: 8080每個進程一個容器
部分開發人員習慣將容器當作虛擬機器(VM)使用,並在一個容器中運行多個進程,例如監控進程、日誌進程、sshd 進程,甚至整個 Systemd。這種做法會帶來以下問題:
判斷 Pod 的整體資源佔用會更加複雜,也不利於正確配置 Requests 和 Limits。
如果容器內僅運行單個進程,當該進程中斷時,外部容器引擎能夠立即感知並重啟容器。若容器內運行多個進程,即使其中一個進程崩潰,外部容器引擎也無法感知,可能導致容器無法正常工作。
Kubernetes支援多個進程的協同工作。例如,Nginx 和 PHP-FPM 可通過 Unix Domain Socket 通訊,您可建立一個包含2個容器的 Pod,並將 Unix Domain Socket 存放於兩者的共用 Volume 中。
確保不存在SPOF(Single Point of Failure)
如果應用僅有一個執行個體,當該執行個體發生故障時,儘管 Kubernetes 能夠自動重啟執行個體,但在這期間不可避免地會出現短暫的服務中斷。即使在更新應用或發布新版本時,也可能出現類似的服務中斷情況。
在 Kubernetes 中,應盡量避免直接管理 Pod,而是通過 Deployment 或 StatefulSet 來管理,並確保應用至少運行兩個以上的 Pod 執行個體。這種做法能夠有效提升系統的高可用性,避免因單個執行個體故障導致的服務中斷。