一、Deployment控制器概念、原理解读

1.1 Deployment概述

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

# 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 运行

k8s deployment 详解 k8s deployment service_Pod

rs v1 控制三个 pod,删除一个 pod,在 rs v2 上重新建立一个,依次类推,直到全部都是由 rs v2 控制,如果 rs v2 有问题,还可以回滚,Deployment 是建构在 rs 之上的,多个 rs 组成一个 Deployment,

但是只有一个 rs 处于活跃状态

 1.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

二、Deployment资源清单yaml编写技巧

# 查看Deployment资源对象由哪几部分组成
[root@master rs]# 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@master rs]# kubectl explain deployment.spec
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@master rs]# kubectl explain deployment.spec.strategy
FIELDS:
rollingUpdate    <Object>
type    <string>   # 支持2中更新方式:默认RollingUpdate滚动更新;可选 Recreate重建式更新,删除一个更新一个

#RollingUpdate 滚动更新,定义滚动更新方式,也就是 pod 能多几个,少几个
[root@master rs]# kubectl explain deployment.spec.strategy.rollingUpdate
FIELDS:
maxSurge    <string>  #我们更新的过程当中最多允许超出的指定的目标副本数有几个; 它有两种取值方式,第一种直接给定数量,第二种根据百分比,百分比表示原本是 5 个,最多可以超出 20%,那就允许多一个,
最多可以超过 40%,那就允许多两个
maxUnavailable    <string>  ##最多允许几个不可用,假设有 5 个副本,最多一个不可用,就表示最少有 4 个可用

2.1 Deployment.spec字段详细截图

#查看 Deployment 下的 spec.template 字段
#template 为定义 Pod 的模板,Deployment 通过模板创建 Pod
[root@master rs]# kubectl explain deployment.spec.template
Fileds:
metadata    <Object>  #定义模板的名字
spec    <Object>
deployment.spec.template 为 Pod 定义的模板,和 Pod 定义不太一样,template 中不包含apiVersion 和 Kind 属性,要求必须有 metadata。deployment.spec.template.spec 为容器的属性信息,
其他定义内容和 Pod 一致。
#查看 Deployment 下的 spec.template.spec 字段
[root@master rs]# kubectl explain deployment.spec.template.spec
KIND:     Deployment
VERSION:  apps/v1

RESOURCE: template <Object>
activeDeadlineSeconds <integer> #activeDeadlineSeconds 表示 Pod 可以运行的最长时间,达到设置的该值后,Pod 会自动停止。 
affinity <Object> #定义亲和性,跟直接创建 pod 时候定义亲和性类似 
automountServiceAccountToken <boolean> #身份认证相关的 
containers <[]Object> -required- #定义容器属性 
dnsConfig <Object> #设置 Pod 的 DNS

dnsConfig: 
 nameservers: 
 - 192.xxx.xxx.6 
 searches: 
 - xianchao.svc.cluster.local 
 - my.dns.search.xianchao 

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> #定义临时容器 
  1.临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启,因此不适用于构建应用程序。临时容器使用与常规容器相同的 ContainerSpec 段进行描述,但许多字段是不相容且不允许的。 
  2.临时容器没有端口配置,因此像 ports,livenessProbe,readinessProbe 这样的字段是不允许的。 
  3.Pod 资源分配是不可变的,因此 resources 配置是不允许的。 
 
临时容器用途: 
当由于容器崩溃或容器镜像不包含调试应用程序而导致 kubectl exec 无用时,临时容器对于交互式故障排查很有用。 

hostAliases <[]Object> # 登录到pod中,查看hosts文件可以看到增加了域名解析的, 
hostAliases: 
 – ip: "10.1.2.2" 
   hostnames: 
   – "mc.local" 
   – "rabbitmq.local" 
 – ip: "10.1.2.3" 
   hostnames: 
   – "redis.local" 
   – "mq.local" 
例如:hosts:10.1.2.2 mc.local rabbitmq.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> #挂载存储卷

 2.2 pod中添加域名解析

[root@master rs]# kubectl explain rs.spec.template.spec.hostAliases

# 挑选一个yaml文件中加入
    spec:
      containers:
      - name: php-redis
        image: ikubernetes/myapp:v2
        imagePullPolicy: IfNotPresent
      hostAliases:
      - ip: "192.168.199.131"
        hostnames:
        - "master"
        - "master.local"

[root@master rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend created
[root@master rs]# kubectl get pods -n default
NAME             READY   STATUS    RESTARTS   AGE
frontend-rmxdj   1/1     Running   0          12s
frontend-x6gnr   1/1     Running   0          12s
[root@master rs]# kubectl exec -it frontend-rmxdj -- /bin/sh
# cat  /etc/hosts
# Entries added by HostAliases.
192.168.199.131    master    master.local

2.3 Pod中dns配置--dnsConfig和dnsPolicy

[root@master rs]# kubectl explain rs.spec.template.spec.dnsPolicy
[root@master ~]# kubectl explain rs.spec.template.spec.dnsConfig
[root@master ~]# kubectl explain rs.spec.template.spec.dnsConfig.searches


      hostAliases:
      - ip: "192.168.199.131"
        hostnames:
        - "master"
        - "master.local"
      dnsPolicy: None
      dnsConfig:
        nameservers:
        - 192.168.199.131
        - 192.168.199.132
        searches:
        - master.svc.cluster.local
        - my.dns.search.master

[root@master rs]# kubectl delete -f replicaset.yaml 
replicaset.apps "frontend" deleted
[root@master rs]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend created
[root@master rs]# kubectl get pods -n default
NAME             READY   STATUS    RESTARTS   AGE
frontend-bq997   0/1     Pending   0          13s
frontend-fqjqs   0/1     Pending   0          13s

[root@master rs]# kubectl exec -n default -it frontend-bq997 -- /bin/sh
/ # cat /etc/resolv.conf 
nameserver 192.168.199.131
nameserver 192.168.199.132
search master.svc.cluster.local my.dns.search.master

 三、Deployment部署生产环境web项目

3.1 案例:创建一个Web站点

deployment 是一个三级结构,deployment 管理 replicaset,replicaset 管理 pod

# 例子:用 deployment 创建一个 pod
[root@master rs]# cat deploy-demo.yaml 
apiVersion: apps/v1   # deployment对应的api版本
kind: Deployment      # 创建的资源是deployment
metadata:
  name: myapp-v1      # deployment的名字
  namespace: default  # 所属名称空间
spec:
  replicas: 2         # 管理的pod副本数
  selector:           # 选择标签器
    matchLabels:      # matchLabels 下定义的标签需要跟 template.metadata.labels 定义的标 签一致
      app: myapp      
      version: v1
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  template:
    metadata:
      name: test
      labels:
        app: myapp
        version: v1
    spec:             # 定义容器的属性
      containers:
      - name: myapp
        image: janakiramm/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80  # 容器里应用的端口

[root@master rs]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-v1 created

# 查看deploy状态
[root@master rs]# kubectl get deployment -n default
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   0/2     0            0           35s
#创建的控制器名字是 myapp-v1 
1.NAME :列出名称空间中 deployment 的名称。 
2.READY:显示 deployment 有多少副本数。它遵循 ready/desired 的模式。 
3.UP-TO-DATE: 显示已更新到所需状态的副本数。 
4.AVAILABLE: 显示你的可以使用多少个应用程序副本。 
5.AGE :显示应用程序已运行的时间。

[root@master rs]# kubectl get pods -n default
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-86f6b6d8c8-k8c5h   1/1     Running   0          5s
myapp-v1-86f6b6d8c8-p6scj   1/1     Running   0          5s

[root@master rs]# kubectl get rs -n default
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-86f6b6d8c8   2         2         2       2m4s
#创建 deploy 的时候也会创建一个 rs(replicaset),86f6b6d8c8这个随机数字是我们引用 pod 的模板 template 的名字的 hash 值 
1.NAME: 列出名称空间中 ReplicaSet 资源 
2.DESIRED:显示应用程序的所需副本数,这些副本数是在创建时定义的。这是所需的状态。 
3.CURRENT: 显示当前正在运行多少个副本。 
4.READY: 显示你的用户可以使用多少个应用程序副本。 
5.AGE :显示应用程序已运行的时间。

请注意,ReplicaSet 的名称始终设置为[DEPLOYMENT-NAME]-[RANDOM-STRING]。RANDOMSTRING 是随机生成的

3.2 livenessProbe和readiness探测

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      version: v1
  template:
    metadata:
      name: test
      labels:
        app: myapp
        version: v1
    spec:
      containers:
      - name: myapp
        image: janakiramm/myapp:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:
            port: 80
        readinessProbe:
          httpGet:
            port: 80

kubectl describe pods -n default myapp-v1-c5549578-gv4x4

Liveness: http-get http://:80/ delay=0s timeout=1s period=10s #success=1 #failure=3
Readiness: http-get http://:80/ delay=0s timeout=1s period=10s #success=1 #failure=3

3.3 Deployment管理pod:扩容、缩容、滚动更新、回滚

# 1.扩容:通过deployment管理应用,实现扩容,将副本数从2变为3
(1)方法1:将deploy-demo.yaml文件中replicas: 2 改为replicas: 3,然后执行后查看
[root@master rs]# kubectl get pods -n default
NAME                      READY   STATUS    RESTARTS   AGE
myapp-v1-c5549578-gv4x4   1/1     Running   0          9m2s
myapp-v1-c5549578-wfd7b   1/1     Running   0          8m49s
myapp-v1-c5549578-wrknz   1/1     Running   0          2m5s

(2)方法2:kubectl edit deploy -n default myapp-v1
replicas: 4
[root@master rs]# kubectl get pods -n default
NAME                      READY   STATUS    RESTARTS   AGE
myapp-v1-c5549578-gv4x4   1/1     Running   0          14m
myapp-v1-c5549578-j2wpz   1/1     Running   0          7s
myapp-v1-c5549578-wfd7b   1/1     Running   0          13m
myapp-v1-c5549578-wrknz   1/1     Running   0          7m12s

# 2.缩容:将deploy-demo.yaml中replicas: 4 改为replicas: 3
方法1:
[root@master rs]# kubectl get pods -n default
NAME                      READY   STATUS        RESTARTS   AGE
myapp-v1-c5549578-gv4x4   1/1     Running       0          16m
myapp-v1-c5549578-j2wpz   0/1     Terminating   0          2m50s
myapp-v1-c5549578-wfd7b   1/1     Running       0          16m
myapp-v1-c5549578-wrknz   1/1     Running       0          9m55s
[root@master rs]# kubectl get pods -n default
NAME                      READY   STATUS    RESTARTS   AGE
myapp-v1-c5549578-gv4x4   1/1     Running   0          17m
myapp-v1-c5549578-wfd7b   1/1     Running   0          16m
myapp-v1-c5549578-wrknz   1/1     Running   0          10m
方法2:将replicas: 3改为2
[root@master rs]# kubectl edit deploy -n default myapp-v1
deployment.apps/myapp-v1 edited
[root@master rs]# kubectl get pods -n default
NAME                      READY   STATUS    RESTARTS   AGE
myapp-v1-c5549578-gv4x4   1/1     Running   0          18m
myapp-v1-c5549578-wfd7b   1/1     Running   0          18m
3.通过deployment管理应用,实现滚动更新
#步骤:
(1) 将新版本导入到节点:docker load -i myapp-v2.tar.gz
(2)修改yaml文件将image: janakiramm/myapp:v1修改为image: janakiramm/myapp:v2,
(3)然后执行kubectl apply -f deploy-demo.yaml

# 查看步骤执行过程
[root@master ~]# kubectl get pods -n default -w
NAME                      READY   STATUS    RESTARTS   AGE
myapp-v1-c5549578-gv4x4   1/1     Running   0          35m
myapp-v1-c5549578-wfd7b   1/1     Running   0          35m

myapp-v1-787b9bc78c-bbftz   0/1     Pending             0          0s
myapp-v1-787b9bc78c-bbftz   0/1     Pending             0          0s
myapp-v1-787b9bc78c-bbftz   0/1     ContainerCreating   0          0s
myapp-v1-787b9bc78c-bbftz   0/1     ContainerCreating   0          1s
myapp-v1-787b9bc78c-bbftz   0/1     Running             0          2s
myapp-v1-787b9bc78c-bbftz   1/1     Running             0          7s
myapp-v1-c5549578-wfd7b     1/1     Terminating         0          35m
myapp-v1-787b9bc78c-95qjb   0/1     Pending             0          0s
myapp-v1-787b9bc78c-95qjb   0/1     Pending             0          0s
myapp-v1-787b9bc78c-95qjb   0/1     ContainerCreating   0          0s
myapp-v1-c5549578-wfd7b     1/1     Terminating         0          35m
myapp-v1-787b9bc78c-95qjb   0/1     ContainerCreating   0          1s
myapp-v1-c5549578-wfd7b     0/1     Terminating         0          35m
myapp-v1-787b9bc78c-95qjb   0/1     Running             0          2s
myapp-v1-787b9bc78c-95qjb   1/1     Running             0          9s
myapp-v1-c5549578-gv4x4     1/1     Terminating         0          35m
myapp-v1-c5549578-gv4x4     1/1     Terminating         0          36m
myapp-v1-c5549578-gv4x4     0/1     Terminating         0          36m
myapp-v1-c5549578-wfd7b     0/1     Terminating         0          35m
myapp-v1-c5549578-wfd7b     0/1     Terminating         0          35m
myapp-v1-c5549578-gv4x4     0/1     Terminating         0          36m
myapp-v1-c5549578-gv4x4     0/1     Terminating         0          36m

pending 表示正在进行调度,ContainerCreating 表示正在创建一个 pod,running 表示运行一个 pod,running 起来一个 pod 之后再 Terminating(停掉)一个 pod,以此类推,直到所有 pod 完成滚动升级

[root@master rs]# kubectl get rs -n default
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-787b9bc78c   2         2         2       8m39s
myapp-v1-86f6b6d8c8   0         0         0       56m

#上面可以看到 rs 有两个,上面那个是升级之前的,已经被停掉,但是可以随时回滚

v1版本的时候 curl IP可以看到 background-color: blue;
v2版本的时候 curl IP可以看到 background-color: green;
# 4.回滚
[root@master rs]# kubectl get rs -n default
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-787b9bc78c   2         2         2       28m
myapp-v1-86f6b6d8c8   0         0         0       76m

[root@master rs]# kubectl rollout --help
Available Commands:
  history     显示 rollout 历史
  pause       标记提供的 resource 为中止状态
  restart     Restart a resource
  resume      继续一个停止的 resource
  status      显示 rollout 的状态
  undo        撤销上一次的 rollout

[root@master rs]# kubectl rollout undo --help
Examples:
  # Rollback to the previous deployment
  kubectl rollout undo deployment/abc
  
  # Rollback to daemonset revision 3
  kubectl rollout undo daemonset/abc --to-revision=3
  
  # Rollback to the previous deployment with dry-run
  kubectl rollout undo --dry-run=server deployment/abc

Usage:
  kubectl rollout undo (TYPE NAME | TYPE/NAME) [flags] [options]

# 查看历史版本
[root@master rs]# kubectl rollout history --help
Examples:
  # View the rollout history of a deployment
  kubectl rollout history deployment/abc
  
  # View the details of daemonset revision 3

  kubectl rollout history daemonset/abc --revision=3
Usage:
  kubectl rollout history (TYPE NAME | TYPE/NAME) [flags] [options]

# 查询历史版本
[root@master rs]# kubectl rollout history deployment/myapp-v1 -n default
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

# 回滚版本
[root@master rs]# kubectl rollout undo deployment/myapp-v1 -n default --to-revision=1
[root@master rs]# kubectl get rs -n default
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-787b9bc78c   2         2         2       38m
myapp-v1-86f6b6d8c8   0         0         0       86m

[root@master rs]# kubectl get rs -n default
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-787b9bc78c   0         0         0       43m
myapp-v1-86f6b6d8c8   2         2         2       91m

curl IP 请求可以看到改变 background-color: blue;

# 回滚完成后,再次查看版本
[root@master rs]# kubectl rollout history deployment/myapp-v1 -n default
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>   # 代表之前版本,请求背景色为绿色
4         <none>   # 代表当前版本,请求背景色为蓝色

# 再次回滚
[root@master rs]# kubectl rollout undo deployment/myapp-v1 -n default --to-revision=3
deployment.apps/myapp-v1 rolled back
# 回滚中
[root@master rs]# kubectl get rs -n default
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-787b9bc78c   1         1         0       54m
myapp-v1-86f6b6d8c8   2         2         2       102m
# 回滚完成
[root@master rs]# kubectl get rs -n default
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-787b9bc78c   2         2         2       56m
myapp-v1-86f6b6d8c8   0         0         0       104m

[root@master rs]# kubectl rollout history deployment/myapp-v1 -n default
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
2         <none>
4         <none>
5         <none>

3.4 自定义滚动更新策略

kubectl explain deploy.spec.strategy.rollingUpdate
maxSurge 和 maxUnavailable 用来控制滚动更新的更新策略 
取值范围
数值 
1. maxUnavailable: [0, 副本数] 
2. maxSurge: [0, 副本数] 
注意:两者不能同时为 0。 
比例 
1. maxUnavailable: [0%, 100%] 向下取整,比如 10 个副本,5%的话==0.5 个,但计算按照 0 个;

2. maxSurge: [0%, 100%] 向上取整,比如 10 个副本,5%的话==0.5 个,但计算按照 1 个; 
注意:两者不能同时为 0。 
建议配置 
1. maxUnavailable == 0 
2. maxSurge == 1 
这是我们生产环境提供给用户的默认配置。即“一上一下,先上后下”最平滑原则: 
1个新版本 pod ready(结合 readiness)后,才销毁旧版本 pod。此配置适用场景是平滑更新、保证服务平稳,但也有缺点,就是“太慢”了。

总结: 
maxUnavailable:和期望的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑; 
maxSurge:和期望的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。
自定义策略: 
修改更新策略:maxUnavailable=1,maxSurge=1 
[root@master ~]# kubectl patch deployment myapp-v1 -p 
'{"spec":{"strategy":{"rollingUpdate": {"maxSurge":1,"maxUnavailable":1}}}}' 
 
查看 myapp-v1 这个控制器的详细信息 
[root@master ~]# kubectl describe deployment myapp-v1 
 
显示如下: 
RollingUpdateStrategy: 1 max unavailable, 1 max surge 
 
上面可以看到 RollingUpdateStrategy: 1 max unavailable, 1 max surge 
这个 rollingUpdate 更新策略变成了刚才设定的,因为我们设定的 pod 副本数是 3,1 和 1 表示最少不能少于 2 个 pod,最多不能超过 4 个 pod 
这个就是通过控制 RollingUpdateStrategy 这个字段来设置滚动更新策略的

3.5 重建式更新

[root@master deploy]# kubectl explain deploy.spec.strategy.type
KIND:     Deployment
VERSION:  apps/v1

FIELD:    type <string>

DESCRIPTION:
     Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
     RollingUpdate.

     Possible enum values:
     - `"Recreate"` Kill all existing pods before creating new ones. 重建式更新
     - `"RollingUpdate"` Replace the old ReplicaSets by new one using rolling
     update i.e gradually scale down the old ReplicaSets and scale up the new
     one.  # 滚动式更新

# 重建式更新,先杀死现有需要更新的所有pod,再创建新更新副本
# 生产环境一般都不使用,风险大

spec:
  strategy:  # 更新策略方式
    type: Recreate  # 重建式更新

四、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: XXX/portal:v1
        imagePullPolicy: ALWAYS# 一般使用IfNotPresent
        ports:
        - protocol: TCP
          containerPort: 8080
        resources:  # 资源配置
          limits:   # 资源限制,最多可用多少cpu和内存
            cpu: 1
            memory: 1Gi
        requests:   # 最少需要多少资源才可以运行pod,才会被分配,1核=1000m
          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 端口