Kubernetes中的workload(工作負載)


Deployment

簡介

Deployment負責管理無狀態應用的部署,管理模式為:
(1)Deployment只負責管理不同版本的ReplicaSet,每個名為${deployment-name}-${template-hash}的ReplicaSet都對應了Deployment template的一個版本
(2)由RepliaSet管理Pod副本數,一個RepliaSet下的Pod都是一模一樣的副本,名為${deployment-name}-${template-hash}-${random-suffix}
 

DeploymentSpec數據結構

  • Replicas
Pod的副本數
所謂擴縮容,就是修改Replicas,Deployment controller會把Replicas同步到當前版本的RS中,由RS執行擴縮容
擴縮容命令實際也是修改了Replicas:
$ kubectl scale deployment nginx-deployment --replicas 10
  • Selector
Pod選擇器,圈定Deployment管理的Pod范圍。所有擴容出來的Pod的Labels必須匹配該標簽。
  • Template
Pod相關的模板(k8s包含了podtemplates這種資源對象,但不能創建,只能包含在workload資源對象中),包含了:
    期望Pod的metadata,其中包含了labels(和selector.matchLabels相匹配的標簽)
    最終創建出的Pod的spec
例如修改template中一個容器的image,Deployment controller會基於新template創建一個新ReplicaSet,然后逐漸修改兩個ReplicaSet中Pod的期望數量,最終完成一次發布。
  • Strategy
為Recreate時,會先停掉所有舊的再起新的;
為RollingUpdate(默認)時,會滾動更新,此時有兩個可配置項:
    MaxUnavailable:滾動過程中最多有多少個Pod不可用;
    MaxSurge:滾動過程中最多存在多少個Pod超過預期replicas數量。
如果用戶的資源足夠,且更注重發布過程中的可用性,可設置MaxUnavailable較小、MaxSurge較大。
如果用戶的資源比較緊張,可以設置MaxSurge較小,甚至設置為0
注意:MaxSurge和MaxUnavailable不能同時為0!
  • MinReadySeconds
默認情況下Deployment會根據Pod是否ready判斷其是否可用。設置了MinReadySeconds后,Deployment會等若干秒之后才認為Pod是available的;
  • RevisionHistoryLimit
除了當前版本外,還保留的歷史版本數量,默認值為10個。
  • Paused
標識Deployment只做數量維持,不做新的發布。所有對spec.template.spec的修改都不會觸發新的rollout,只會把replicas同步到對應的ReplicaSet中,更新一下Deployment的status。在Debug場景下才會設置為true。
  • RollbackTo
回滾的配置,里面只有一個int64的Revision(版本號),決定了回退到哪個版本
 
所謂回滾,其實就把template回滾為舊版本的template。
Deployment會重新修改舊ReplicaSet中Pod的期望數量,逐漸減少新版本ReplicaSet中的replica,最終把Pod從舊版本重新創建出來。
回滾命令其實也是修改了RollbackTo:
$ kubectl rollout undo deployment/nginx-deployment
$ kubectl rollout undo deployment.v1.apps/nginx-deployment —-to-revision=2
--to-revision指定可以回滾到某一個具體的版本,必須先查一下版本號:
$ kubectl rollout history deployment.v1.apps/nginx-deployment
  • ProgressDeadlineSeconds
設置Deployment處於Processing狀態的超時時間。超時后Deployment認為這個Pod進入failed狀態。 
 
 

DeploymentStatus數據結構

  • ObservedGeneration
表示最近一次觀察到的可用的Generation
與metadata中的Generation對應,只有在版本更新的時候會有所不同
查看rollout的狀態,其實就是查看ObservedGeneration是否大於Generation:
$ kubectl rollout status deployment/nginx-deployment
  • Replicas、UpdateReplicas、ReadyReplicas、AvailableReplicas、UnavailableReplicas
  • Conditions
k8s將Deployment的狀態分為Processing(擴容/發布中)、Complete(運行中)以及Failed:
 
 
  • CollisonCount
Deployment的哈希碰撞值,創建RepliaSet時用以避免重復
 

Deployment Controller實現原理

Deployment Controller關注Deployment和ReplicaSet相關的event,收到事件后會加入到隊列中。
從隊列中把事件取出來后,會檢查paused(Deployment是否需要新的發布)
 
ReplicaSet Controller也通過Informer機制監聽ReplicaSet資源來維持應用希望的狀態數量,但是只管理副本數。如果發現replicas比Pod數量大的話擴容,比實際數量小就縮容。
 
假如rsA的replicas從2被改到3。
首先,Reflector會watch到ReplicaSet和Pod兩種資源的變化,在DeltaFIFO中塞入了對象是rsA、類型是Updated的記錄。
Informer把新的ReplicaSet更新到Index中並調用Update的回調函數。
ReplicaSet Controller的Update回調函數發現ReplicaSet變化后會把nsA/rsA作為key值加入到工作隊列中,
ReplicaSet Controller會並發啟動多個worker,以處理不同的對象實例。
worker池中一個worker從工作隊列中取到了key(nsA/rsA),並從Index中取到了ReplicaSet rsA的最新數據。
worker通過比較rsA的spec和status里的數值,發現需要對它進行擴容,因此創建了一個Pod。這個Pod的Ownereference指向向了ReplicaSet rsA。
worker如果處理失敗,一般會把key重新加入到工作隊列中,從而方便之后進行重試。
然后Reflector watch到的Pod新增事件,在DeltaFIFO中塞入了對象是Pod、類型是Add的記錄。
Informer把新的Pod更新到Index中並調用ReplicaSet Controller的Add的回調函數。
ReplicaSet Controller的Add回調函數通過檢查Pod的ownerReferences找到了對應的ReplicaSet,並把nsA/rsA字符串塞入到了工作隊列中。
woker在得到新的工作項后,從緩存中取到了新的ReplicaSet記錄,並得到了其所有創建的Pod。因為ReplicaSet 的status不是最新的(創建的Pod總數還未更新)。因此在此時ReplicaSet更新status使得spec和status達成一致。
 

StatefulSet

簡介

Statefulset負責管理有狀態應用的部署,管理模式為:
(1)StatefulSet只負責管理不同版本的ControllerRevision,每個名為${statefulset-name}-${template-hash}的ControllerRevision對應了StatefulSet template的一個版本
(2)一個ControllerRevision下的Pod都是不同的副本:
每個Pod會有Order序號,會按照序號來創建、刪除、更新Pod。例如創建時,依序創建${statefulset-name}-0、${statefulset-name}-1……前一個Pod都Ready之后,才會創建下一個Pod
每個Pod會有一個標簽controller-revision-hash: hbase-master-${template-hash},StatefulSet通過該標簽標識Pod所屬的版本 。
 

StatefulsetSpec數據結構

  • Replicas
  • Selector
  • Template
  • VolumeClaimTemplates
可以定義一個或多個PVC模板。通過這樣的方式使每個Pod都有獨立的PVC,並且掛載到容器中對應目錄。  
例如,定義一個名為www的PVC模板:
  volumeClaimTemplates:
  - metadata:
      name: ${pvc-name}
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi
每個Pod創建前,會順序創建的名為${pvc-name} -0、${pvc-name} -1……的PVC
PVC創建完成后,Pending狀態的Pod和PV進行綁定,然后才會開始調度和ContainerCreating。
注意:當前版本的StatefulSet不會在PVC中添加OwnerReference,刪除StatefulSet之后,StatefulSet創建的ControllerRevision和Pod都會被刪除,但是PVC不會被級聯刪除。
  • ServiceName
通過配置一個headless Service,可以使Statefulset中的每個Pod有一個唯一的網絡標識(hostname)
首先需要創建一個headless Service:
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
ServiceName需要對應Headless Service的名字
PS:也可以隨便取一個錯誤的名字(不會做校驗)。此時不會為Pod分配唯一的hostname
  • PodManagementPolicy
默認是OrderedReady(按序擴縮容),也有Paralel(並行擴縮容)
  • UpdateStrategy
type為OnDelete時,Statefulset controller不會自動更新Pod,必須手動刪除舊的
type為RollingUpdate時,按照2->1->0的順序升級(刪除重建),controller-revision-hash會隨之升級,PVC則會自動復用。
RollingUpdate是更新的配置,里面只有一個partition字段,用於指定部分更新(即只進行一定數量的灰度發布)
PS:假設當前有個replicas為10的StatefulSet,Pod 序號為0~9。partition是8。更新時,會保留0~7這8個Pod為舊版本,只更新2個新版本作為灰度。
PS:若partition≥replicas,更新無法成功
  • RevisionHistoryLimit
要清除的版本,必須沒有Pod。否則該ControllerRevision不能被刪除的。
  • MinReadySeconds
 

StatefulsetStatus數據結構體

  • ObservedGeneration
  • Replicas、UpdatedReplicas、ReadyReplicas、AvailableReplicas、CurrentReplicas
所有值都是一樣時,表示所有Pod已經升級到了所需要的版本。
  • Conditions
k8s目前未對Statefulset的狀態作划分
  • CurrentRevision和UpdateRevision
當前和擬更新到的${statefulset-name}-${template-hash}
  • CollisionCount
 

StatefulSet Controller實現原理

StatefulSet Controller從工作隊列將工作項取出來后,先Update Revision,即查看當前拿到的StatefulSet中的template,有沒有對應的ControllerRevision。如果沒有,說明template已經更新過,Controller就會創建一個新版本的Revision,也就有了一個新的ControllerRevision hash版本號。
Update in order:Controller把所有版本號拿出來,並且按照序號整理一遍。這個整理的過程中,如果發現有缺少的 Pod,就按照序號去創建;如果發現有多余的 Pod,就按照序號去刪除。即查看所有Pod是否滿足序號。
Update status:當保證了Pod數量和序號滿足Replica數量之后,Controller會去查看是否需要更新Pod。即查看Pod期望的版本是否符合要求,並且通過序號來更新。   
Update in order中刪除 Pod后,其實是在下一次觸發事件,Controller才會發現缺少Pod,然后在Update in order中把新的Pod創建出來。在這之后Controller才會Update status(通過命令行看到的status 信息)。   
 

Job

簡介

Job的管理模式為:
(1)Job直接管理名為${job-name}−{random-suffix}的Pod,會跟蹤Job的狀態,根據配置重試或者繼續創建
(2)根據並行配置,保證上一批Pod完成之后再運行下一批Pod
 
直接看Job的yaml文件無法看出Job創建了哪些Pod
只能通過kubectl describe job xxx看相應的Event,也可以從Pod的Ownerferences看出它歸由哪個Job管理:
 

JobSpec數據結構

  • Parallelism
若要並行運行Job時使用,代表並行執行的Pod個數
  • Completions和CompletionMode
當有Completions個Pod執行成功時認為此Job成功,但CompletionMode分為兩種:
    NonIndexed模式下,只要有任意Completions個Pod執行成功即可
    Indexed模式下會給Pod加index,必須是第0~Completions-1個Pod執行成功才行
  • ActiveDeadlineSeconds和BackoffLimit
ActiveDeadlineSeconds為job安排一個最大運行時間,BackoffLimit則表示一個Job到底能重試多少次。
ActiveDeadlineSeconds的優先級高於BackoffLimit
  • Selector和ManualSelector
Selector無需手動指定。生成的Job中,會自動加上此Pod選擇器:
  selector:
    matchLabels:
      controller-uid: df858f2d-82cf-4726-85e9-8e7899d13d74
創建的Pod會自動加上controller-uid:xxx的標簽
ManualSelector設置為true時,表示希望手動進行設置
  • Template
通過設置Pod的重啟策略來設置Job的重啟策略
  • TTLSecondsAfterFinished
Job執行結束后多久自動刪除此Pod
  • Suspend
如果為true,不會創建新的Pod,且會刪除已創建的Pod
 

JobStatus數據結構

  • Conditions
k8s將Job的狀態分為Suspended、Complete以及Failed
如果job運行失敗,會顯示Failed的reson和message:
status:
  conditions:
  - lastProbeTime: "2020-10-20T12:09:53Z"
    lastTransitionTime: "2020-10-20T12:09:53Z"
    message: Job has reached the specified backoff limit
    reason: BackoffLimitExceeded
    status: "True"
    type: Failed
  failed: 2
  startTime: "2020-10-20T12:09:07Z"
  • StartTime和CompletionTime
  • Active、Succeed、Failed
  • CompletedIndexes
CompletionMode為Indexed模式時,會保存執行成功的Pod的index
例如,CompletedIndexes為"1,3-5,7"時,表示第1、3、4、5、7個Pod執行成功
 

Job Controller實現原理

 
 

CronJob

簡介

CronJob主要是用來運作一些定時任務(如Jenkins構建等)
 

CronSpec數據結構

  • Schedule
Cron格式的字符串,形如"*/1 * * * *"
  • StartingDeadlineSeconds
每次運行Job的時候最長可以等多長時間,超過時間CronJob就會停止這個 Job
  • ConcurrencyPolicy
表示是否允許並行運行。分為Allow、Forbid、Replace三種
PS:並行運行指的是,如果Job運行的時間特別長,第二個Job需要運行的時候上一個Job還沒完成,會同時運行兩個Job。
  • Suspend
  • JobTemplate
  • SuccessfulJobsHistoryLimit和FailedJobsHistoryLimit
定時Job的執行歷史的存留數。
 

CronStatus數據結構

  • Active
目前哪些Job是跑着的
  • LastScheduleTime和lastSuccessfulTime
 

DaemonSet

簡介

DaemonSet也是Kubernetes提供的一個default controller,它是一個守護進程的控制器,能幫我們做到以下幾件事情:
(1)保證集群內的每一個節點都運行一個名為{$DaemonsetName}−{random-suffix}的Pod
(2)根據節點的狀態,保證新加入的節點自動創建對應的Pod,移除的節點能自動刪除對應的Pod
 
常用於以下場景:
    存儲:需要每台節點上都運行一個類似於Agent的東西
    日志收集:如logstash或者fluentd,需要每台節點都運行一個Agent
    監控:如Promethues
 

DaemonsetSpec數據結構

  • Selector
  • Template
  • UpdateStrategy
RollingUpdate(默認):先更新第一個Pod,然后老的Pod被移除,通過健康檢查之后再建第二個Pod
OnDelete:模板更新后,Pod不會有任何變化。除非手動刪除某一個節點上的Pod
  • MinReadySeconds
  • TemplateGeneration
  • RevisionHistoryLimit
 

DaemonsetStatus數據結構

  • CurrentNumberScheduled、NumberMisscheduled、DesiredNumberScheduled、NumberReady、UpdatedNumberScheduled、NumberAvailable、NumberUnavailable
  • ObservedGeneration
  • CollisionCount
  • Conditions
k8s目前未對Daemonset的狀態作划分
 

DaemonSet Controller實現原理

大體上與Job Controller類似,不過它還會監控Node的狀態,根據配置的affinity或者label去選擇對應的節點后,進行Pod的創建、Pod的版本比較和升級等。
更新完了之后,它會更新整個DaemonSet的狀態
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM