讀書筆記 | Kubernetes in Action

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描述文件類似如下: