k8s核心資源之Replicasse和Deployment控制器(五)


k8s控制器:Replicaset和Deployment

前面我們學習了Pod,那我們在定義pod資源時,可以直接創建一個kind:Pod類型的自主式pod,但是這存在一個問題,假如pod被刪除了,那這個pod就不能自我恢復,就會徹底被刪除,線上這種情況非常危險,所以今天就給大家講解下pod的控制器,所謂控制器就是能夠管理pod,監測pod運行狀況,當pod發生故障,可以自動恢復pod。也就是說能夠代我們去管理pod中間層,並幫助我們確保每一個pod資源始終處於我們所定義或者我們所期望的目標狀態,一旦pod資源出現故障,那么控制器會嘗試重啟pod或者里面的容器,如果一直重啟有問題的話那么它可能會基於某種策略來進行重新布派或者重新編排;如果pod副本數量低於用戶所定義的目標數量,它也會自動補全;如果多余,也會自動終止pod資源。

1、Replicaset控制器:概念、原理解讀

1.1 Replicaset概述

ReplicaSet是kubernetes中的一種副本控制器,簡稱rs,主要作用是控制由其管理的pod,使pod副本的數量始終維持在預設的個數。它的主要作用就是保證一定數量的Pod能夠在集群中正常運行,它會持續監聽這些Pod的運行狀態,在Pod發生故障時重啟pod,pod數量減少時重新運行新的 Pod副本。官方推薦不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高級的概念,它會管理ReplicaSet並提供很多其它有用的特性,最重要的是Deployments支持聲明式更新,聲明式更新的好處是不會丟失歷史變更。所以Deployment控制器不直接管理Pod對象,而是由 Deployment 管理ReplicaSet,再由ReplicaSet負責管理Pod對象。

1.2 Replicaset工作原理:如何管理Pod?

Replicaset核心作用在於代用戶創建指定數量的pod副本,並確保pod副本一直處於滿足用戶期望的數量, 起到多退少補的作用,並且還具有自動擴容縮容等機制。
Replicaset控制器主要由三個部分組成:
1、用戶期望的pod副本數:用來定義由這個控制器管控的pod副本有幾個
2、標簽選擇器:選定哪些pod是自己管理的,如果通過標簽選擇器選到的pod副本數量少於我們指定的數量,需要用到下面的組件
3、pod資源模板:如果集群中現存的pod數量不夠我們定義的副本中期望的數量怎么辦,需要新建pod,這就需要pod模板,新建的pod是基於模板來創建的。

1.3 Replicaset資源清單文件編寫技巧

#查看定義Replicaset資源需要的字段有哪些?

[root@k8s-master1 ~]# kubectl explain rs
KIND:     ReplicaSet
VERSION:  apps/v1
DESCRIPTION:
     ReplicaSet ensures that a specified number of pod replicas are running at
     any given time.
FIELDS:
   apiVersion	<string>  #當前資源使用的api版本,跟VERSION:  apps/v1保持一致
   kind	<string>     #資源類型,跟KIND: ReplicaSet保持一致
   metadata	<Object> #元數據,定義Replicaset名字的
   spec	<Object>     ##定義副本數、定義標簽選擇器、定義Pod模板
   status	<Object> #狀態信息,不能改

#查看replicaset的spec字段如何定義?

[root@k8s-master1 ~]# kubectl explain rs.spec
KIND:     ReplicaSet
VERSION:  apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
     Spec defines the specification of the desired behavior of the ReplicaSet.
     More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
     ReplicaSetSpec is the specification of a ReplicaSet.
FIELDS:
   minReadySeconds	<integer>
   replicas	<integer>  #定義的pod副本數,根據我們指定的值創建對應數量的pod
   selector	<Object> -required-  #用於匹配pod的標簽選擇器
   template	<Object>      #定義Pod的模板,基於這個模板定義的所有pod是一樣的

#查看replicaset的spec.template字段如何定義?
#對於template而言,其內部定義的就是pod,pod模板是一個獨立的對象

[root@k8s-master1 ~]# kubectl explain rs.spec.template
KIND:     ReplicaSet
VERSION:  apps/v1
RESOURCE: template <Object>
DESCRIPTION:
     Template is the object that describes the pod that will be created if
     insufficient replicas are detected。PodTemplateSpec describes the data a pod should have when created from a
     template
FIELDS:
   metadata	<Object>
   spec	<Object>

[root@k8s-master1 ~]# kubectl explain rs.spec.template.spec

通過上面可以看到,ReplicaSet資源中有兩個spec字段。第一個spec聲明的是ReplicaSet定義多少個Pod副本(默認將僅部署1個Pod)、匹配Pod標簽的選擇器、創建pod的模板。第二個spec是spec.template.spec:主要用於Pod里的容器屬性等配置。
.spec.template里的內容是聲明Pod對象時要定義的各種屬性,所以這部分也叫做PodTemplate(Pod模板)。還有一個值得注意的地方是:在.spec.selector中定義的標簽選擇器必須能夠匹配到spec.template.metadata.labels里定義的Pod標簽,否則Kubernetes將不允許創建ReplicaSet。

2、Replicaset使用案例:部署Guestbook留言板

#把frontend.tar.gz上傳到k8s-node2和k8s-node1上,解壓
[root@k8s-node2]# docker load -i frontend.tar.gz
[root@k8s-node1]# docker load -i frontend.tar.gz

2.1 編寫一個ReplicaSet資源清單

[root@k8s-master1 ~]# cat replicaset.yaml 
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: yecc/gcr.io-google_samples-gb-frontend:v3
        imagePullPolicy:  IfNotPresent
## 2.2 資源清單詳細說明
apiVersion: apps/v1  #ReplicaSet 這個控制器屬於的核心群組
kind: ReplicaSet  #創建的資源類型
metadata:
  name: frontend  #控制器的名字
  labels:
    app: guestbook
    tier: frontend
spec:
  replicas: 3   #管理的pod副本數量
  selector:
    matchLabels:
      tier: frontend  #管理帶有tier=frontend標簽的pod
  template:  #定義pod的模板
    metadata:
      labels:
        tier: frontend 
#pod標簽,一定要有,這樣上面控制器就能找到它要管理的pod是哪些了
    spec:
      containers: #定義pod里運行的容器
      - name: php-redis #定義容器的名字
        image: yecc/gcr.io-google_samples-gb-frontend:v3
          ports:    #定義端口
- name: http  #定義容器的名字
containerPort:  80 #定義容器暴露的端口
# 應用配置文件並創建
[root@k8s-master1 ~]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend created
[root@k8s-master1 ~]# kubectl get rs
NAME       DESIRED   CURRENT   READY   AGE
frontend      3          3            3        53m
[root@k8s-master1 replicaset]# kubectl get pod 
NAME             READY   STATUS    RESTARTS   AGE
frontend-n7c9w   1/1     Running   0          66s
frontend-s5kwv   1/1     Running   0          66s
frontend-ttgll   1/1     Running   0          66s

3、Replicaset管理pod:擴容、縮容、更新

3.1 Replicaset實現pod的動態擴容

ReplicaSet最核心的功能是可以動態擴容和回縮,如果我們覺得兩個副本太少了,想要增加,只需要修改配置文件replicaset.yaml里的replicas的值即可
1、聲明式更新
[root@k8s-master1 replicaset]# vim replicaset.yaml
原來replicas: 3,
現在變成replicaset: 4,修改之后,執行如下命令更新:
[root@k8s-master1 replicaset]# kubectl apply -f replicaset.yaml
replicaset.apps/frontend configured
[root@k8s-master1 replicaset]# kubectl get rs
NAME DESIRED CURRENT READY AGE
frontend 4 4 4 19m
[root@k8s-master1 replicaset]# kubectl get pod
NAME READY STATUS RESTARTS AGE
frontend-n7c9w 1/1 Running 0 19m
frontend-pjnl8 1/1 Running 0 2s
frontend-s5kwv 1/1 Running 0 19m
frontend-ttgll 1/1 Running 0 19m
2、也可以直接編輯控制器實現擴容,
kubectl edit rs frontend #退出保存后就把請求提交給了apiserver,實時修改
[root@k8s-master1 ~]# kubectl edit rs frontend

3.2 動態縮容

如果我們覺得4個Pod副本太多了,想要減少,只需要修改配置文件replicaset.yaml里的replicas的值即可,把replicaset:4變成replicaset: 2,修改之后使用apply更新就可以了
第二種方法也是可以使用edit直接編輯rs進行修改,修改完后自動提交給api-server

4、Replicaset實現pod的更新

修改鏡像image: yecc/gcr.io-google_samples-gb-frontend:v3變成- image: ikubernetes/myapp:v2,修改之后保存退出
我們先curl訪問一下已經部署好的pod,如下
image

編輯replicaset.yaml文件,修改images字段
image
再次訪問容器,發現訪問的內容並沒有更新,還是老的內容,這是因為replicaset並不會去更新已經創建好的pod,只會修改新增加的pod
那我們把之前創建的pod刪除掉一個,再次訪問看一下
image
上面可以看到雖然鏡像已經更新了,但是原來的pod使用的還是之前的鏡像,新創建的pod才會使用最新的鏡像
使用get rs查看一下,此時就已經完成了滾動升級
image

生產環境如果升級,可以刪除一個pod,觀察一段時間之后沒問題再刪除另一個pod,但是這樣需要人工干預多次;實際生產環境一般采用藍綠發布,原來有一個rs1,再創建一個rs2(控制器),通過修改service標簽,修改service可以匹配到rs2的控制器,這樣才是藍綠發布,這個也需要我們精心的部署規划,我們有一個控制器就是建立在rs之上完成的,叫做Deployment,也就是更高級的一種控制器

5、Deployment控制器的概念、原理

Deployment官方文檔:
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

5.1 Deployment概述

Deployment是kubernetes中最常用的資源對象,為ReplicaSet和Pod的創建提供了一種聲明式的定義方法,在Deployment對象中描述一個期望的狀態,Deployment控制器就會按照一定的控制速率把實際狀態改成期望狀態,通過定義一個Deployment控制器會創建一個新的ReplicaSet控制器,通過ReplicaSet創建pod,刪除Deployment控制器,也會刪除Deployment控制器下對應的ReplicaSet控制器和pod資源.

使用Deployment而不直接創建ReplicaSet是因為Deployment對象擁有許多ReplicaSet沒有的特性,例如滾動升級和回滾。

擴展:聲明式定義是指直接修改資源清單yaml文件,然后通過kubectl apply -f 資源清單yaml文件,就可以更改資源
Deployment控制器是建立在rs之上的一個控制器,可以管理多個rs,每次更新鏡像版本,都會生成一個新的rs,把舊的rs替換掉,多個rs同時存在,但是只有一個rs運行。
示意圖:
image
rs v1控制三個pod,刪除一個pod,在rs v2上重新建立一個,依次類推,直到全部都是由rs v2控制,如果rs v2有問題,還可以回滾,Deployment是建構在rs之上的,多個rs組成一個Deployment,但是只有一個rs處於活躍狀態.

5.2 Deployment工作原理:如何管理rs和Pod?

Deployment可以使用聲明式定義,直接在命令行通過純命令的方式完成對應資源版本的內容的修改,也就是通過打補丁的方式進行修改;Deployment能提供滾動式自定義自控制的更新;對Deployment來講,我們在實現更新時還可以實現控制更新節奏和更新邏輯。

互動:什么叫做更新節奏和更新邏輯呢?

比如說Deployment控制5個pod副本,pod的期望值是5個,但是升級的時候需要額外多幾個pod,那我們控制器可以控制在5個pod副本之外還能再增加幾個pod副本;比方說能多一個,但是不能少,那么升級的時候就是先增加一個,再刪除一個,增加一個刪除一個,始終保持pod副本數是5個;還有一種情況,最多允許多一個,最少允許少一個,也就是最多6個,最少4個,第一次加一個,刪除兩個,第二次加兩個,刪除兩個,依次類推,可以自己控制更新方式,這種滾動更新需要加readinessProbe和livenessProbe探測,確保pod中容器里的應用都正常啟動了才刪除之前的pod。
啟動第一步,剛更新第一批就暫停了也可以;假如目標是5個,允許一個也不能少,允許最多可以10個,那一次加5個即可;這就是我們可以自己控制節奏來控制更新的方法。

通過Deployment對象,你可以輕松的做到以下事情:
1、創建ReplicaSet和Pod
2、滾動升級(不停止舊服務的狀態下升級)和回滾應用(將應用回滾到之前的版本)
3、平滑地擴容和縮容
4、暫停和繼續Deployment

6、Deployment資源清單文件編寫技巧

#查看Deployment資源對象由哪幾部分組成\

[root@k8s-master1 ~]# kubectl explain deployment
KIND:     Deployment
VERSION:  apps/v1
DESCRIPTION:
     Deployment enables declarative updates for Pods and ReplicaSets.
FIELDS:
   apiVersion	<string>  #該資源使用的api版本
   kind	<string>            #創建的資源是什么?
   metadata	<Object>       #元數據,包括資源的名字和名稱空間
   spec	<Object>           #定義容器的
   status	<Object>       #狀態,不可以修改

查看Deployment下的spec字段

[root@k8s-master1 ~]# kubectl explain deployment.spec
KIND:     Deployment
VERSION:  apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
     Specification of the desired behavior of the Deployment.
     DeploymentSpec is the specification of the desired behavior of the
     Deployment.
FIELDS:
    minReadySeconds	<integer>
#Kubernetes在等待設置的時間后才進行升級
#如果沒有設置該值,Kubernetes會假設該容器啟動起來后就提供服務了
paused	<boolean>  #暫停,當我們更新的時候創建pod先暫停,不是立即更新
    progressDeadlineSeconds	<integer>
# k8s 在升級過程中有可能由於各種原因升級卡住(這個時候還沒有明確的升級失敗),比如在拉取被牆的鏡像,權限不夠等錯誤。那么這個時候就需要有個 deadline ,在 deadline 之內如果還卡着,那么就上報這個情況,這個時候這個 Deployment 狀態就被標記為 False,並且注明原因。但是它並不會阻止 Deployment 繼續進行卡住后面的操作。完全由用戶進行控制。
    replicas	<integer>  #副本數
    revisionHistoryLimit	<integer> #保留的歷史版本,默認是10
    selector	<Object> -required- #標簽選擇器,選擇它關聯的pod
    strategy	<Object>     #更新策略
    template	<Object> -required  #定義的pod模板

#查看Deployment下的spec.strategy字段

[root@k8s-master1 ~]# kubectl explain deploy.spec.strategy
KIND:     Deployment
VERSION:  apps/v1
RESOURCE: strategy <Object>
DESCRIPTION:
     The deployment strategy to use to replace existing pods with new ones.
     DeploymentStrategy describes how to replace existing pods with new ones.
FIELDS:
   rollingUpdate	<Object>
   type	<string>
     Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
     RollingUpdate.
#支持兩種更新,Recreate和RollingUpdate
#Recreate是重建式更新,刪除一個更新一個

#RollingUpdate滾動更新,定義滾動更新方式,也就是pod能多幾個,少幾個
#查看Deployment下的spec.strategy.rollingUpdate字段

[root@k8s-master1 ~]# kubectl explain deploy.spec.strategy.rollingUpdate
KIND:     Deployment
VERSION:  apps/v1
RESOURCE: rollingUpdate <Object>
DESCRIPTION:
     Rolling update config params. Present only if DeploymentStrategyType =
     RollingUpdate.
     Spec to control the desired behavior of rolling update.
FIELDS:
   maxSurge	<string>
#我們更新的過程當中最多允許超出的指定的目標副本數有幾個; 
它有兩種取值方式,第一種直接給定數量,第二種根據百分比,百分比表示原本是5個,最多可以超出20%,那就允許多一個,最多可以超過40%,那就允許多兩個
   maxUnavailable	<string>
\#最多允許幾個不可用
假設有5個副本,最多一個不可用,就表示最少有4個可用

查看Deployment下的spec.template字段
template為定義Pod的模板,Deployment通過模板創建Pod

[root@k8s-master1 ~]# kubectl explain deploy.spec.template
KIND:     Deployment
VERSION:  apps/v1
RESOURCE: template <Object>
DESCRIPTION:
     Template describes the pods that will be created.
     PodTemplateSpec describes the data a pod should have when created from a template
FIELDS:
   metadata	<Object>  #定義模板的名字
   spec	<Object>   
deployment.spec.template為Pod定義的模板,和Pod定義不太一樣,template中不包含apiVersion和Kind屬性,要求必須有metadata。deployment.spec.template.spec為容器的屬性信息,其他定義內容和Pod一致。

查看Deployment下的spec.template.spec字段

[root@k8s-master1 ~]# kubectl explain deploy.spec.template.spec
KIND:     Deployment
VERSION:  apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
     PodSpec is a description of a pod.
FIELDS:
   activeDeadlineSeconds	<integer>
#activeDeadlineSeconds表示Pod 可以運行的最長時間,達到設置的該值后,Pod 會自動停止。
   affinity	<Object>  #定義親和性,跟直接創建pod時候定義親和性類似
   automountServiceAccountToken	<boolean> #身份認證相關的
   containers	<[]Object> -required- #定義容器屬性
   dnsConfig	<Object>  #設置Pod的DNS
dnsConfig:
    nameservers:
      - 192.xxx.xxx.6
    searches:
      - hxu.svc.cluster.local
      - my.dns.search.hxu
   dnsPolicy	<string> # dnsPolicy決定Pod 內預設的DNS 配置策略

None 無任何策略:使用自定義的策略
Default 默認:使用宿主機的dns配置,/etc/resolv.conf
ClusterFirst 集群DNS優先,與 Default 相反,會預先使用 kube-dns (或 CoreDNS ) 的信息當預設置參數寫入到該 Pod 內的DNS配置。
ClusterFirstWithHostNet 集群 DNS 優先,並伴隨着使用宿主機網絡:同時使用 hostNetwork 與 kube-dns 作為 Pod 預設 DNS 配置。

   enableServiceLinks	<boolean>
   ephemeralContainers	<[]Object> #定義臨時容器
臨時容器與其他容器的不同之處在於,它們缺少對資源或執行的保證,並且永遠不會自動重啟,因此不適用於構建應用程序。臨時容器使用與常規容器相同的 ContainerSpec 段進行描述,但許多字段是不相容且不允許的。
    臨時容器沒有端口配置,因此像 ports,livenessProbe,readinessProbe 這樣的字段是不允許的。
    Pod 資源分配是不可變的,因此 resources 配置是不允許的。
  
**臨時容器用途:**
當由於容器崩潰或容器鏡像不包含調試應用程序而導致 kubectl exec 無用時,臨時容器對於交互式故障排查很有用。
   hostAliases	<[]Object> #在pod中增加域名解析的
  hostAliases:
  – ip: "10.1.2.2"
    hostnames:
    – "mc.local"
    – "rabbitmq.local"
  – ip: "10.1.2.3"
    hostnames:
    – "redis.local"
    – "mq.local"
   hostIPC	<boolean> #使用主機IPC
   hostNetwork	<boolean>  #是否使用宿主機的網絡
   hostPID	<boolean> #可以設置容器里是否可以看到宿主機上的進程。True可以
   hostname	<string>
   imagePullSecrets	<[]Object>
   initContainers	<[]Object> #定義初始化容器
   nodeName	<string>  #定義pod調度到具體哪個節點上
   nodeSelector	<map[string]string> #定義節點選擇器
   overhead	<map[string]string> #overhead是1.16引入的字段,在沒有引入 Overhead 之前,只要一個節點的資源可用量大於等於 Pod 的 requests 時,這個 Pod 就可以被調度到這個節點上。引入 Overhead 之后,只有節點的資源可用量大於等於 Overhead 加上 requests 的和時才能被調度上來。
   preemptionPolicy	<string>
   priority	<integer>
   priorityClassName	<string>
   readinessGates	<[]Object> 
   restartPolicy	<string>   #Pod重啟策略
   runtimeClassName	<string>
   schedulerName	<string>
   securityContext	<Object> #是否開啟特權模式
   serviceAccount	<string>
   serviceAccountName	<string>
   setHostnameAsFQDN	<boolean>
   shareProcessNamespace	<boolean>
   subdomain	<string>
   terminationGracePeriodSeconds	<integer>
#在真正刪除容器之前,K8S會先發終止信號(kill -15 {pid})給容器,默認30s
   tolerations	<[]Object>  #定義容忍度
   topologySpreadConstraints	<[]Object
   volumes	<[]Object>  #掛載存儲卷

7、Deployment使用案例:創建一個web站點

deployment是一個三級結構,deployment管理replicaset,replicaset管理pod,
例子:用deployment創建一個pod
#把myapp-blue-v1.tar.gz和myapp-blue-v2.tar.gz上傳到k8s-node1和k8s-node2上,手動解壓:

[root@k8s-node1 ~]# docker load -i myapp-blue-v1.tar.gz
[root@k8s-node2 ~]# docker load -i myapp-blue-v1.tar.gz
[root@k8s-node1 ~]# docker load -i myapp-blue-v2.tar.gz
[root@k8s-node2 ~]# docker load -i myapp-blue-v2.tar.gz
[root@k8s-master1 ~]# cat deploy-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
spec:
  replicas: 2
  selector:
   matchLabels:
    app: myapp
    version: v1
  template:
   metadata:
    labels:
     app: myapp
     version: v1
   spec:
    containers:
    - name: myapp
      image: janakiramm/myapp:v1
      imagePullPolicy: IfNotPresent
      ports:
      - containerPort: 80
更新資源清單文件:
kubectl apply -f deploy-demo.yaml

#kubectl apply:表示聲明式的定義,既可以創建資源,也可以動態更新資源
查看deploy狀態:

kubectl get deploy 
顯示如下:
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1     2/2      2               2           60s

#創建的控制器名字是myapp-v1
1.NAME :列出名稱空間中deployment的名稱。
2.READY:顯示deployment有多少副本數。它遵循ready/desired的模式。
3.UP-TO-DATE: 顯示已更新到所需狀態的副本數。
4.AVAILABLE: 顯示你的可以使用多少個應用程序副本。
5.AGE :顯示應用程序已運行的時間。

kubectl get rs 顯示如下:
創建的控制器名字是myapp-v1

kubectl get rs 
顯示如下:
AME                     DESIRED   CURRENT   READY   AGE
myapp-v1-67fd9fc9c8     2         2            2       2m35s

創建deploy的時候也會創建一個rs(replicaset),67fd9fc9c8 這個隨機數字是我們引用pod的模板template的名字的hash值
1.NAME: 列出名稱空間中ReplicaSet資源
2DESIRED:顯示應用程序的所需副本數,這些副本數是在創建時定義的。這是所需的狀態。
3.CURRENT: 顯示當前正在運行多少個副本。
4.READY: 顯示你的用戶可以使用多少個應用程序副本。
5.AGE :顯示應用程序已運行的時間。

請注意,ReplicaSet的名稱始終設置為[DEPLOYMENT-NAME]-[RANDOM-STRING]。RANDOM-STRING是隨機生成的

kubectl get pods
顯示如下:
myapp-v1-67fd9fc9c8-fcprr   1/1     Running   0           3s
myapp-v1-67fd9fc9c8-hw4f9   1/1     Running   0          2m21s
[root@k8s-master1 ~]# kubectl get pods -o wide | grep myapp
myapp-v1-67fd9fc9c8-fcprr   1/1   Running  0    10.244.187.78   k8s-node2   
myapp-v1-67fd9fc9c8-hw4f9  1/1   Running   0   10.244.209.136  k8s-node1   
#請求剛才創建的pod資源
[root@k8s-master1 ~]# curl 10.244.187.78
      background-color: blue;
[root@k8s-master1 ~]# curl 10.244.209.136
      background-color: blue;

#資源清單文件詳細解讀

apiVersion: apps/v1  #deployment對應的api版本
kind: Deployment    #創建的資源是deployment
metadata:
  name: myapp-v1   #deployment的名字
spec:
  replicas: 2     #deployment管理的pod副本數
  selector:       #標簽選擇器
   matchLabels:  # matchLabels下定義的標簽需要跟template.metadata.labels定義的標簽一致
    app: myapp
    version: v1
  template:
   metadata:
    labels:
     app: myapp
     version: v1
   spec:   #定義容器的屬性
    containers:  
    - name: myapp
      image: janakiramm/myapp:v1 #容器使用的鏡像
      imagePullPolicy: IfNotPresent  #鏡像拉取策略
      ports:
      - containerPort: 80     #容器里的應用的端口

8、Deployment管理pod:擴容、縮容、滾動更新、回滾

#通過deployment管理應用,實現擴容,把副本數變成3 
[root@k8s-master1 ~]# cat  deploy-demo.yaml 
直接修改replicas數量,如下,變成3
spec:
  replicas: 3
修改之后保存退出,執行
[root@k8s-master1 ~]# kubectl apply -f deploy-demo.yaml 
注意:apply不同於create,apply可以執行多次;create執行一次,再執行就會報錯復。
kubectl get pods 
顯示如下:
NAME                         READY   STATUS    RESTARTS   AGE
myapp-v1-67fd9fc9c8-fcprr   1/1     Running   0          15m
myapp-v1-67fd9fc9c8-h9js5   1/1     Running   0          11s
myapp-v1-67fd9fc9c8-hw4f9   1/1     Running   0          17m
#上面可以看到pod副本數變成了3個 

#查看myapp-v1這個控制器的詳細信息

[root@k8s-master1 ~]# kubectl describe deploy myapp-v1
Name:                   myapp-v1
Namespace:              default
CreationTimestamp:      Tue, 21 Sep 2021 10:58:05 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=myapp,version=v1
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=myapp
           version=v1
  Containers:
   myapp:
    Image:        janakiramm/myapp:v1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   myapp-v1-67fd9fc9c8 (3/3 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  18m   deployment-controller  Scaled up replica set myapp-v1-67fd9fc9c8 to 2
  Normal  ScalingReplicaSet  51s   deployment-controller  Scaled up replica set myapp-v1-67fd9fc9c8 to 3

#通過deployment管理應用,實現縮容,把副本數變成2
[root@k8s-master1 ~]# cat deploy-demo.yaml
直接修改replicas數量,如下,變成2
spec:
replicas: 2
修改之后保存退出,執行
[root@k8s-master1 ~]# kubectl apply -f deploy-demo.yaml
[root@k8s-master1 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-v1-67fd9fc9c8-fcprr 1/1 Running 0 18m
myapp-v1-67fd9fc9c8-hw4f9 1/1 Running 0 20m

#通過deployment管理應用,實現滾動更新
在一個終端窗口執行如下:
[root@k8s-master1 ~]# kubectl get pods -l app=myapp -w
NAME READY STATUS RESTARTS AGE
myapp-v1-67fd9fc9c8-fcprr 1/1 Running 0 19m
myapp-v1-67fd9fc9c8-hw4f9 1/1 Running 0 22m

打開一個新的終端窗口更改鏡像版本,按如下操作:
[root@k8s-master1 ~]# vim deploy-demo.yaml
把image: janakiramm/myapp:v1 變成image: janakiramm/myapp:v2
保存退出,執行
[root@k8s-master1 ~]# kubectl apply -f deploy-demo.yaml
再回到剛才執行監測kubectl get pods -l app=myapp -w的那個窗口,可以看到信息如下:
NAME READY STATUS RESTARTS AGE
myapp-v1-67fd9fc9c8-fcprr 1/1 Running 0 23m
myapp-v1-67fd9fc9c8-hw4f9 1/1 Running 0 26m
myapp-v1-75fb478d6c-fskpq 0/1 Pending 0 0s
myapp-v1-75fb478d6c-fskpq 0/1 Pending 0 0s
myapp-v1-75fb478d6c-fskpq 0/1 ContainerCreating 0 0s
myapp-v1-75fb478d6c-fskpq 0/1 ContainerCreating 0 1s
myapp-v1-75fb478d6c-fskpq 1/1 Running 0 4s
myapp-v1-67fd9fc9c8-fcprr 1/1 Terminating 0 24m
myapp-v1-75fb478d6c-x8stq 0/1 Pending 0 0s
myapp-v1-75fb478d6c-x8stq 0/1 Pending 0 0s
myapp-v1-75fb478d6c-x8stq 0/1 ContainerCreating 0 0s
myapp-v1-67fd9fc9c8-fcprr 1/1 Terminating 0 24m
myapp-v1-75fb478d6c-x8stq 0/1 ContainerCreating 0 1s
myapp-v1-67fd9fc9c8-fcprr 0/1 Terminating 0 24m
myapp-v1-75fb478d6c-x8stq 1/1 Running 0 1s
myapp-v1-67fd9fc9c8-hw4f9 1/1 Terminating 0 26m
myapp-v1-67fd9fc9c8-hw4f9 1/1 Terminating 0 26m
myapp-v1-67fd9fc9c8-hw4f9 0/1 Terminating 0 26m
myapp-v1-67fd9fc9c8-hw4f9 0/1 Terminating 0 26m
myapp-v1-67fd9fc9c8-hw4f9 0/1 Terminating 0 26m
myapp-v1-67fd9fc9c8-fcprr 0/1 Terminating 0 24m
myapp-v1-67fd9fc9c8-fcprr 0/1 Terminating 0 24m

pending表示正在進行調度,ContainerCreating表示正在創建一個pod,running表示運行一個pod,running起來一個pod之后再Terminating(停掉)一個pod,以此類推,直到所有pod完成滾動升級

在另外一個窗口執行

[root@k8s-master1 ~]# kubectl get rs 
顯示如下:
myapp-v1-67fd9fc9c8    0         0         0       27m
myapp-v1-75fb478d6c   2         2         2       79s

上面可以看到rs有兩個,上面那個是升級之前的,已經被停掉,但是可以隨時回滾

查看myapp-v1這個控制器的歷史版本

[root@k8s-master1 ~]# kubectl rollout history deployment myapp-v1
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

回滾

[root@k8s-master1 ~]# kubectl rollout undo deployment myapp-v1 --to-revision=1
deployment.apps/myapp-v1 rolled back
[root@k8s-master1 ~]# kubectl rollout history deployment myapp-v1
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

8.1 自定義滾動更新策略

maxSurge和maxUnavailable用來控制滾動更新的更新策略
取值范圍
數值

  1. maxUnavailable: [0, 副本數]
  2. maxSurge: [0, 副本數]
    注意:兩者不能同時為0。
    比例
  3. maxUnavailable: [0%, 100%] 向下取整,比如10個副本,5%的話==0.5個,但計算按照0個;
  4. maxSurge: [0%, 100%] 向上取整,比如10個副本,5%的話==0.5個,但計算按照1個;
    注意:兩者不能同時為0。
    建議配置
  5. maxUnavailable == 0
  6. maxSurge == 1
    這是我們生產環境提供給用戶的默認配置。即“一上一下,先上后下”最平滑原則:
    1個新版本pod ready(結合readiness)后,才銷毀舊版本pod。此配置適用場景是平滑更新、保證服務平穩,但也有缺點,就是“太慢”了。

總結:
maxUnavailable:和期望的副本數比,不可用副本數最大比例(或最大值),這個值越小,越能保證服務穩定,更新越平滑;
maxSurge:和期望的副本數比,超過期望副本數最大比例(或最大值),這個值調的越大,副本更新速度越快。

自定義策略:
修改更新策略:maxUnavailable=1,maxSurge=1
[root@k8s-master1 ~]# kubectl patch deployment myapp-v1 -p '{"spec":{"strategy":{"rollingUpdate": {"maxSurge":1,"maxUnavailable":1}}}}' -n blue-green

查看myapp-v1這個控制器的詳細信息

[root@k8s-master1 ~]# kubectl describe deployment myapp-v1 -n blue-green

顯示如下:
RollingUpdateStrategy:  1 max unavailable, 1 max surge

上面可以看到RollingUpdateStrategy: 1 max unavailable, 1 max surge
這個rollingUpdate更新策略變成了剛才設定的,因為我們設定的pod副本數是3,1和1表示最少不能少於2個pod,最多不能超過4個pod
這個就是通過控制RollingUpdateStrategy這個字段來設置滾動更新策略的

9、Deployment資源清單詳解

apiVersion: apps/v1
kind: Deployment 
metadata:
  name: portal
  namespace: ms 
spec:
  replicas: 1
  selector:
    matchLabels:
      project: ms
      app: portal
  template:
    metadata:
      labels:
        project: ms 
        app: portal
    spec:
      containers:
      - name: portal
        image:  hxu/portal:v1
        imagePullPolicy: Always
        ports:
          - protocol: TCP
            containerPort: 8080 
        resources:  #資源配額
          limits:  #資源限制,最多可用的cpu和內存
            cpu: 1
            memory: 1Gi
         requests: #最少需要多少資源才可以運行Pod
            cpu: 0.5
            memory: 1Gi
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10

livenessProbe: 
 #存活性探測
#用於判斷容器是否存活,即Pod是否為running狀態,如果LivenessProbe探針探測到容器不健康,則kubelet將kill掉容器,並根據容器的重啟策略是否重啟。如果一個容器不包含LivenessProbe探針,則Kubelet認為容器的LivenessProbe探針的返回值永遠成功。
    tcpSocket: 
       port: 8080   #檢測8080端口是否存在
    initialDelaySeconds: 60  #Pod啟動60s執行第一次檢查
periodSeconds: 10    #第一次檢查后每隔10s檢查一次

  readinessProbe:  #就緒性探測
有時候應用程序可能暫時無法接受請求,比如Pod已經Running了,但是容器內應用程序尚未啟動成功,在這種情況下,如果沒有ReadinessProbe,則Kubernetes認為它可以處理請求了,然而此時,我們知道程序還沒啟動成功是不能接收用戶請求的,所以不希望kubernetes把請求調度給它,則使用ReadinessProbe探針。

ReadinessProbe和livenessProbe可以使用相同探測方式,只是對Pod的處置方式不同,ReadinessProbe是將Pod IP:Port從對應的EndPoint列表中刪除,而livenessProbe則Kill容器並根據Pod的重啟策略來決定作出對應的措施。

ReadinessProbe探針探測容器是否已准備就緒,如果未准備就緒則kubernetes不會將流量轉發給此Pod。

     tcpSocket:
       port: 8080
        initialDelaySeconds: 60
        periodSeconds: 10
在Pod運行過程中,K8S仍然會每隔10s檢測8080端口


免責聲明!

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



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