讀書筆記 | Kubernetes in Action
- 2020 年 9 月 13 日
- 筆記
- k8s, Kubernetes
1 Kubernetes介紹
Kubernetes(以下簡稱K8s) 是一個部署和管理容器化應用的軟體系統。它將底層基礎設施抽象,簡化了應用的開發、部署,以及對開發和運維團隊的管理。
K8s由一個主節點和若干工作節點組成。開發者把應用描述提交到主節點,K8s會將描述中包含的容器鏡像部署到集群的工作節點,開發者可以指定某些應用必須在一個工作節點一起運行(例如上圖五邊形和三角形應用),否則將被分散部署到集群中。
2 在K8s中運行應用
2.1 運行容器
pod
K8s處理應用描述時,會指示容器運行時(例如Docker)拉取所需的鏡像並運行容器。但是,K8s並不直接處理單個容器,它的基本構建模組稱為pod。
一個pod是一組緊密相關的容器,總是一起運行在同一個工作節點上。使用這種方式,可以讓每個應用進程運行與自己的容器中,不相關的應用互相隔離,而密切相關的進程又可以作為一個單元進行管理。
pod的YAML描述文件類似如下:
可以使用命令 kubectl create -f kubia-manual.yaml
創建一個pod。
下面是一些常用命令:
kubectl get po kubia-manual –o yaml #查看描述
kubectl get pods #列出pod
kubectl logs kubia-manual #查看日誌
kubectl delete po kubia-manual #刪除pod
Job
一般pod都是持續運行的,即使容器內的進程執行結束,也會被調度重啟,永遠沒有完成狀態。而Job用於運行完成工作後就終止的情況。
Job會創建一種pod,該pod在內部進程成功結束時,不重啟容器,pod將處於完成狀態。由Job管理的pod,如果在節點上異常退出,會一直被重新安排,直到它完成任務。因此,需要保證任務是冪等的。
Job的YAML描述文件類似如下:
下面是一些常用描述:
- restartPolicy——需要明確設置重啟策略為OnFailure或Never(默認為Alwayse);
- completions——需要一個Job運行的次數;
- parallelism——同一Job並行運行的pod數量;
- activeDeadlineSeconds——限制pod運行時間,超過將嘗試終止pod,並將pod標記為失敗;
- backoffLimit——標記為失敗前可重試次數,默認為6;
下面是一些常用命令:
kubectl get jobs #列出Job
CronJob
CronJob是一種特殊的Job,用於在特定時間執行任務,或者在指定的時間間隔內重複運行。
CronJob的YAML描述文件類似如下:
下面是一些常用描述:
- restartPolicy——cron表達式;
- jobTemplate——創建任務資源;
- startingDeadlineSeconds——指定最遲必須在預定時間多少秒後開始運行,如未運行,任務將不會運行,並將顯示為Failed;
2.2 保持容器運行
Probe
一旦程式運行起來,K8s定期對pod進行狀態診斷,監控應用是否停止了工作,這種機制稱為探針(Probe)。
有三種探針:
- livenessProbe——指示容器是否正在運行。如果失敗則終止容器,容器將遵循其重新啟動策略。需要使用
initialDelaySeconds
屬性設置初始延遲,保證容器已完成啟動再探測; - readinessProbe——指示容器是否準備好響應請求。如果失敗將刪除該pod的IP地址;
- startupProb——指示容器中的應用程式是否啟動。如果提供了啟動探測,所有其他探測都將被禁用,直到它成功為止。如果失敗則終止容器,容器將遵循其重新啟動策略;
livenessProbe的YAML描述文件類似如下:
每種探針有三種探測機制:
- httpGet——對指定的埠和路徑執行HTTP GET 請求,如果響應狀態碼不是2xx和3xx則探測失敗;
- tcpSocket——與指定埠建立TCP連接,如果連接失敗則探測失敗;
- exec——在容器內執行任意命令,如果命令的退出狀態碼不是0則探測失敗;
ReplicaSet
如果pod停止工作,K8s會重新啟動它們,但是如果工作節點故障,那麼節點上的pod將會丟失。
ReplicaSet通常用來保證給定數量的、完全相同的 pod 的可用性,K8s會持續監控由ReplicaSet創建的正在運行的pod列表,並保證相應類型的pod的數目與期望相符。
ReplicaSet的YAML描述文件類似如下:
下面是一些常用描述:
- replicas——指定pod實例的目標數目;
- selector.matchLabels——匹配pod的標籤,還可以用matchExpressions屬性重寫選擇器;
下面是一些常用命令:
kubectl get rs #列出ReplicaSet
kubectl describe rs #描述ReplicaSet
Deployment
當需要更新運行在pod的應用程式時,如何保證一組pod的實例正常運行?答案就是Deployment。
Deployment用於部署應用程式並以聲明的方式升級應用。Deployment由ReplicaSet組成,並由它接管Deployment的pod。使用Deployment可以直接定義單個Deployment資源需要達到的狀態,並讓K8s處理中間的狀態。
Deployment的YAML描述文件類似如下:
升級需要做的就是在pod模板中修改鏡像的tag,K8s會收斂系統,匹配期望的狀態。
下面是一些常用描述:
- maxSurge——期望的副本數之外,最多允許超出的pod實例數量;
- maxUnavailable——相對於期望副本數,能夠允許有多少pod實例處於不可用狀態;
- minReadySeconds——指定新創建的pod至少要運行多久之後,才能將其視為可用;
- progressDeadlineSeconds——判定滾動升級失敗的超時時間;
2.3 遷移容器
Service
容器可能會重啟,或者增加、停止pod副本,如果容器需要給集群中的其他容器或外部客戶端提供使用,如何讓客戶端發現正確的pod並與之通訊?
K8s服務是一種為一組功能相同的pod提供單一不變的接入點的資源。當服務存在時,它的IP地址和埠不會改變。
客戶端不需要知道單獨pod的地址,始終通過服務的IP地址和埠號建立連接。
Service的YAML描述文件類似如下:
下面是一些常用描述:
- sessionAffinity——設置成ClientIP讓特定客戶端產生的請求每次都指向同一個pod;
K8s為客戶端提供了多種服務發現方式:
- 環境變數——創建了kubia服務,環境變數中有KUBIA_SERVICE_HOST和 KUBIA_SERVICE_PORT ,分別代表了 kubia 服務的 IP 地址和埠號;
- 將服務類型設為NodePort——每個集群節點都會打開一個埠;
- 將服務類型設為LoadBalance——通過一個專用的負載均衡器訪問;
- 創建Ingress資源——它運行在HTTP層,可以將不同的服務映射到相同主機的不同路徑;
requests和limits
開發人員通常不關心應用程式運行在哪台伺服器上,只要伺服器能夠為應用程式提供足夠的系統資源。
可以指定容器對CPU和記憶體的資源請求量(requests)和資源限制量(limits),確保pod公平地使用K8s集群資源,同時也影響著整個集群pod的調度方式。
requests的YAML描述文件類似如下:
調度器只關注節點上部署的所有pod的資源requests之和,並不關注實際使用量。另外,CPU requests不僅僅在調度時起作用,也決定了未使用的CPU時間在容器之間會按照CPU requests比例分配。
limits的YAML描述文件類似如下:
所有limits的總和可以超過節點資源的總量的100%——即超賣。如果節點使用量超過100%,一些容器將被殺掉。
在一個超賣的系統,QoS等級決定了哪個容器第一個被殺掉(BestEffort->Burstable->Guaranteed)。
HPA
指望靠人工干預來處理不可預測的流量增長不太現實,K8s可以檢測CPU使用率或其他度量增長時自動對它擴容。
HorizontalpodAutoscaler (HPA)資源啟用和配置Horizontal控制器,該控制器周期性檢查pod度量, 計算滿足HPA資源所配置的目標數值所需的副本數量, 進而調整目標資源的replicas欄位。
HPA的YAML描述文件類似如下: