3.3 控制器——Deployments(部署)

3.3 Deployments(部署)

 Deployments控制器(Deployment controller,Deployment应该也是控制器的一种吧)提供了Pod和ReplicaSets的声明式更新。在Deployment对象中,可以描述对应的desired state,Deployments controller将会已可控的频率去改变实际状态变成desired state,可以定义Deployments创建新的ReplicaSets,或者移除已有的Deployments并让新的Deployment接管已有的Pod。类似的,不推荐直接管理ReplicaSets,而应该通过操纵Deployment对象去管理。

【使用场景】

  1. 创建Deployment,用于推出副本集:副本集子在幕后创建,检查推出的状态是否成功;
  2. 声明Pod的新状态:更新Deployment的Pod模板规约PodTemplateSpec,一个新的ReplicationSet将会被创建,Deployment管理将Pod以一个可控的速度移到新的副本集中,每个新的副本集都会更新Deployment的修改。
  3. 回滚Deployment的早期版本:如果当前的Deployment的状态不稳定,每个回滚更新Deployment;
  4. 扩大Deployment以方便更多的负载;
  5. 暂停Deployments以对其podTemplatespec应用多个修复程序,然后恢复Deployments以启动新的滚动;
  6. 使用Deployment的状态作为滚动卡住的标识;
  7. 清理不再需要的老的ReplicaSets;

【创建Deployment】

Deployment需要一个apiVersionkindmetadata字段,当然也需要.spec的东西了,其中.spec.template.spec.selector是必需的,.spec.strategy表示替换旧Pod的策略,.spec.strategy.type可以设置为Recreate(在新Pod创建之前杀死所有已有的Pod)或RollingUpdate(默认值,可以指定maxUnavailablemaxSurge控制升级进程)。

下面是创建一个Nginx的Deployment的实例,3个Pod副本:

apiVersion: apps/v1
kind: Deployment
metadata:
  # Deployment的名字
  name: nginx-deployment
  labels:
    app: nginx
spec:
  # Pod的副本数,默认为1,可缺省
  replicas: 3
  # 定义了Deployment发现Pod的标签选择器
  selector:
    # 这里的选择器必须和下面的template.metadata.labels一样!否则api不接受该请求
    matchLabels:
      # 选择那些带有 app: nginx 标签的Pod进行管理
      app: nginx
  # Pod的创建模板
  template:
    metadata:
      # Pod的标签
      labels:
        app: nginx
    spec:
      containers:
      # 指定运行容器的名字为 nginx
      - name: nginx
        # 指定镜像版本
        image: nginx:1.7.9
        ports:
        # 指定容器端口
        - containerPort: 80

注:matchLabels也是键值对,如果内部只有一对{key: value},就和matchExpressions一样。

创建上述的Deployment可以使用kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml,查看集群中的Deployments:

# 获取默认命名空间中的deployments
kubectl get deployments

# 结果
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
curl       1/1     1            1           16d
jenkins    1/1     1            1           12d
my-nginx   0/0     0            0           16d

返回的结果有如下字段:

  • NAME:即Deployment的名字;
  • READY:是x/x的格式,其实就是旧版的CURRENTDESIRED参数,前者表示当前正在运行副本的数量(即.status.replicas),后者表示期待的副本数量,就是创建Deployment定义的.spec.replicas那个数字;
  • UP-TO-DATE:表示已经更新到desired state的Pod的数量,通过.status.updatedReplicas值获取;
  • AVAILABLE:表示用户可得APP副本的数目,通过.status.availableReplicas获取;
  • AGE:表示应用运行的时间;

上述的值都可以从Deployment的规约中得到,查看Deployment的推出状态信息,可以通过kubectl rollout status deployment.v1.apps/nginx-deployment,也可以查看由Deployment创建的副本集(ReplicaSet):kubectl get rs,如下的一些形式:

# 查看副本集
kubectl  get rs

# 结果
NAME                  DESIRED   CURRENT   READY   AGE
curl-66959f6557       1         1         1       16d
jenkins-7958858b5d    1         1         1       12d
my-nginx-64fc468bd4   2         2         2       16d

副本集的名字都是[DEPLOYMENT-NAME]-[RANDOM-STRING]的形式,其中[RANDOM-STRING]随机串是由 pod-template-hash 产生的,使用--show-labels可以获取每个pod的自动生成的标签:

kubectl get pods --show-labels

# 结果
NAME                        READY   STATUS    RESTARTS   AGE   LABELS
curl-66959f6557-pn49b       1/1     Running   2          16d   pod-template-hash=66959f6557,run=curl
jenkins-7958858b5d-27qlx    1/1     Running   1          12d   name=jenkins,pod-template-hash=7958858b5d
my-nginx-64fc468bd4-cgd7r   1/1     Running   0          20m   pod-template-hash=64fc468bd4,run=my-nginx
my-nginx-64fc468bd4-ss95t   1/1     Running   0          21m   pod-template-hash=64fc468bd4,run=my-nginx

【更新Deployment】

 修改Deployment的Pod模板(即.spec.template)将会触发一个Deployment的推出,比如标签或容器的镜像更新了,但其他的更新,如Deployment的伸缩将不会触发一个rollout。比如现在想将之前Nginx的Pod使用的镜像改变为nginx:1.9.1,那可以这么干:

# 第一个my-nginx为deployment的名字,第2个my-nginx,第3个my-nginx是容器的名字
kubectl --record deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx:1.9.1

# 输出
deployment.apps/my-nginx image updated
deployment.apps/my-nginx image updated

查看对应的信息,注意看Age:

# 查看副本集的信息
kubectl get rs
# 结果
NAME                  DESIRED   CURRENT   READY   AGE
curl-66959f6557       1         1         1       16d
jenkins-7958858b5d    1         1         1       12d
my-nginx-5fbd7db759   2         2         2       3m55s
my-nginx-64fc468bd4   0         0         0       16d

# 查看pod
kubectl get pods
# 结果
NAME                        READY   STATUS    RESTARTS   AGE
curl-66959f6557-pn49b       1/1     Running   2          16d
jenkins-7958858b5d-27qlx    1/1     Running   1          12d
my-nginx-5fbd7db759-fxp6m   1/1     Running   0          5m38s
my-nginx-5fbd7db759-rgr22   1/1     Running   0          6m4s

所以下次需要更新Pod的时候只需要更新Deployment中的Pod模板即可。Deployment在升级Pod时可以确保仅有部分数量的Pod可能会被停止,默认情况确保至少比所需的Pod数量少25%(最多25%不可用)。

 Rollover(又叫multiple updates in-flight),每次一个新的Deployment对象都会被Deployment controller监测到,如果没有副本集ReplicationSet接管这些Pod就会创建一个新的副本集。现存的副本集控制的Pod的标签应该和.spec.selector一致,但那些模板不和.spec.selector匹配的副本集应该按比例缩减,最终的结果应该是:新副本集ReplicationSet将会伸展成.spec.replicas数量,旧的副本集ReplicationSet应该缩减为0。如果在更新Deployment过程中还存在rollout,Deployment将会创建新的ReplicationSet,并开始向上扩展该副本集,同时将回滚以前正在扩展的副本集–将其添加到旧副本集列表中,并开始向下扩展(其实就是扩大新副本集的规模、缩减旧副本集的规模)。

 选择器更新,一般是不推荐去更新选择器的,如果非要这么干,请谨慎!

【回滚Deployment】

有时如果Deployment不稳定需要回滚到之前的版本,比如下面的更新了一个Nginx的Deployment,先看一下它的信息:

# 查看
kubectl describe deployment/my-nginx

# 结果
Name:                   my-nginx
Namespace:              default
CreationTimestamp:      Mon, 08 Apr 2019 17:28:01 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 4
                        kubectl.kubernetes.io/last-applied-configuration:
                          {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"my-nginx","namespace":"default"},"spec":{"replicas":2,"se...
                        kubernetes.io/change-cause: kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx:1.7.9 --record=true
Selector:               run=my-nginx
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  run=my-nginx
  Containers:
   my-nginx:
    Image:        nginx:1.7.9
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   my-nginx-55bbf58cd5 (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  118s  deployment-controller  Scaled up replica set my-nginx-765c8d656d to 1
  Normal  ScalingReplicaSet  107s  deployment-controller  Scaled down replica set my-nginx-765c8d656d to 0
  Normal  ScalingReplicaSet  107s  deployment-controller  Scaled up replica set my-nginx-55bbf58cd5 to 1
  Normal  ScalingReplicaSet  87s   deployment-controller  Scaled down replica set my-nginx-5fbd7db759 to 1
  Normal  ScalingReplicaSet  87s   deployment-controller  Scaled up replica set my-nginx-55bbf58cd5 to 2
  Normal  ScalingReplicaSet  64s   deployment-controller  Scaled down replica set my-nginx-5fbd7db759 to 0
[root@k8s-node1 networking]# kubectl rollout history deployment.v1.apps/my-nginx
deployment.apps/my-nginx
REVISION  CHANGE-CAUSE
1         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx nginx=nginx:1.9.1 --record=true
2         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx:1.9.1 --record=true
3         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx: --record=true
4         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx:1.7.9 --record=true

可以看到当前的奖镜像版本是之前更新的nginx:1.7.9,再看一下Deployment的Rollout历史:

# 查看my-nginx的历史版本
kubectl rollout history deployment.v1.apps/my-nginx

# 输出,最近的升级在最下面
deployment.apps/my-nginx
REVISION  CHANGE-CAUSE
1         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx nginx=nginx:1.9.1 --record=true
2         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx:1.9.1 --record=true
3         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx: --record=true
4         kubectl deployment.apps/my-nginx set image deployment.v1.apps/my-nginx my-nginx=nginx:1.7.9 --record=true

目前的镜像版本是nginx:1.7.9,我本地更新过4次,现在进行回滚到最近一次:kubectl rollout undo deployment.v1.apps/my-nginx,或者直接使用--to-revision指定回滚到某个版本,比如:kubectl rollout undo deployment.v1.apps/my-nginx --to-revision=1,然后describe一下可以看到改变。

【伸缩Deployment】

 可以已经部署的Deployment进行伸缩:kubectl scale deployment.v1.apps/my-nginx --replicas=1,如果集群开启了“自动水平Pod伸缩”的功能,那就可以基于已存在的Pod所在的CPU效率选择Pod的最大值和最小值,比如:kubectl autoscale deployment.v1.apps/my-nginx --min=10 --max=15 --cpu-percent=80

 按比例伸缩,滚动升级支持APP的多个版本同时运行,当在rollout期间在对Deployment进行滚动升级,那Deployment Controller为了降低风险将会在现有的副本集中平衡额外的副本,这种行为就是按比例伸缩(proportional scaling)。

【Deployment的暂停和继续】

 在触发1个或多个更新前可以暂停Deployment,然后再继续,这将允许在暂停和恢复之间应用多个修复程序,而不会触发不必要的rollout,比如之前的Deployment,暂停:kubectl rollout pause deployment.v1.apps/my-nginx,然后更新Deployment:kubectl set image deployment.v1.apps/my-nginx my-nginx=nginx:1.9.1,这样不会有新的rollout开始,可以查看:kubectl rollout history deployment.v1.apps/my-nginx,在暂停的这个时间段可以做很多资源的更新,并且资源的更新是可以被使用的,比如:kubectl set resources deployment.v1.apps/my-nginx -c=my-nginx --limits=cpu=200m,memory=512Mi-c表示容器的名字)。Deployment初始状态要比暂停的优先级高,所以他会继续运行,但只要Deployment是暂停的Deployment新的更新将不会影响Deployment,最后恢复Deployment:kubectl rollout resume deployment.v1.apps/my-nginx,可以看到新的副本集出现:kubectl get rs -wkubectl get rs

【Deployment status】

 Deployment有各种状态,可以通过kubectl rollout status deployments.v1.apps/my-nginx查看,主要有如下的几种:

  1. Progressing Deployment:即正在运行状态,Deployment此时应该出现某些行为:创建新的副本集ReplicaSet、扩大最新的副本集、缩减旧的副本集、新Pod变为ready或avaliable状态;
  2. Complete Deployment:即完成状态,Deployment应该是:所有和Deployment相关的副本集都已经更新至最新、且这些副本都处于available状态、没有Deployment的旧副本在运行;
  3. Failed Deployment:即失败状态,Deployment发生这种情况的因素可能是:配额不足、准备就绪探测器(即就绪探针)故障、镜像拉取错误、权限不足、配置错误;

【清理策略】

 可以指定通过设置.spec.revisionHistoryLimit字段指定Deployment要维护多少旧的副本集ReplicaSet,重置后台将会进行垃圾清理,默认为10,这个其实就是在Deployment的更新历史记录的数量,如果将它设置为0,那就不能进行回滚了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值