Kubernetes学习笔记(八):Deployment--声明式的升级应用

概述

本文核心问题是:如何升级应用。
对于Pod的更新有两种策略:

  • 一是删除全部旧Pod之后再创建新Pod。好处是,同一时间只会有一个版本的应用存在;缺点是,应用有一段时间不可用。
  • 二是先创建新Pod,再删除旧Pod。可以一次性创建全部,再删除全部,也可以逐渐创建删除。好处是应用一直可用,缺点是要同时支持两个版本。

蓝绿部署

对于应用的版本v1和版本v2:

  • 在运行v1前,流量一直都在v2上
  • 部署v1,然后测试通过后,将流量切换到v2,v2就成为了新的生产环境
  • 一旦v2出现问题,可以在切回v1

金丝雀部署(也称灰度部署)

金丝雀部署一种增量发布,先是在小范围内发布,然后观察测试,如无问题逐渐发布全部。

kubectl rolling-update

因为kubectl rolling-update的方式已经过时,所以只是做一下简介。
假设现在有一个名为test-v1,Pod选择器为app=order的ReplicationController要升级为test-v2,则执行下面命令可升级:

k rolling-update test-v1 test-v2 --image=test:v2

运行此命令后:

  1. 立刻创建一个名为test-v2的ReplicationController,他的Pod模板镜像正是test:v2,并添加一个标签deployment=xxxx
  2. test-v1以及app=order选中的Pod都会被加上一个标签:deployment=yyyy。如此做法是防止Pod的管理混乱。
  3. 先将test-v2的Pod扩展为1,使用更新后的模板创建新Pod;再将test-v1缩小1,如此循环。
  4. 因为在滚动过程中Service的标签选择器一直是app=order,所以新老版本都会接收到流量。

过时的原因是:伸缩的请求时由kubectl发起的,如果因为任何原因丢失了网络连接,升级将处于中间状态。另一个原因是:期望只修改Pod定义中的镜像tag,就能时Kubernetes运行升级工作

使用Deployment声明式的升级

Deployment是一种更高阶的资源,用于部署程序并以声明的方式升级应用,而不是通过ReplicationController或ReplicaSet进行部署。

在使用Deployment时,Pod是由Deployment的ReplicaSet创建的。

准备镜像

将之前的文章(Kubernetes学习笔记(四):服务)里的拿过来做一下微小的改动,生成两个镜像。改动内容就是在输出内容加上版本号。

fmt.Fprintf(w,"this is v1, hostname: %v\n",hostname)
docker push registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1

fmt.Fprintf(w,"this is v2, hostname: %v\n",hostname)
docker push registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v2

创建Deployment

Deployment与ReplicaSet的配置相似,都含有标签选择器、副本数量和Pod模板。此外Deployment还会包含一个部署策略。

定义Service

定义了一个NodePort类型的Service

# goweb-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: goweb
spec:
  type: NodePort
  selector:
    app: goweb
  ports:
    - port: 80
      targetPort: 8000
      nodePort: 31234

定义Deployment

# goweb-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goweb
spec:
  replicas: 3
  selector:
    matchLabels:
      app: goweb
  template:
    metadata:
      labels:
        app: goweb
    spec:
      containers:
      - name: goweb
        image: registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1

运行查看

可以看到名为goweb-fdfcfdcc6的RS,有个label是pod-template-hash=fdfcfdcc6,顾名思义,fdfcfdcc6就是pod模板的hash值。

创建Deployment时指定 --record 记录历史版本号,非常有用

-> [root@kube0.vm] [~] k create -f goweb-svc.yaml
service/goweb created

-> [root@kube0.vm] [~] k create -f goweb-deployment.yaml --record

deployment.apps/goweb created
-> [root@kube0.vm] [~] k get all -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
pod/goweb-fdfcfdcc6-4wklw   1/1     Running   0          9s    10.244.2.37   kube2.vm   <none>           <none>
pod/goweb-fdfcfdcc6-bw8c4   1/1     Running   0          9s    10.244.2.36   kube2.vm   <none>           <none>
pod/goweb-fdfcfdcc6-xjcwf   1/1     Running   0          9s    10.244.1.33   kube1.vm   <none>           <none>

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE   SELECTOR
service/goweb        NodePort    10.100.193.94   <none>        80:31234/TCP   28s   app=goweb
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP        54s   <none>

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES                                            SELECTOR
deployment.apps/goweb   3/3     3            3           9s    goweb        registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1   app=goweb

NAME                              DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                                            SELECTOR
replicaset.apps/goweb-fdfcfdcc6   3         3         3       9s    goweb        registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v1   app=goweb,pod-template-hash=fdfcfdcc6

升级Deployment

只要修改Deployment的Pod模板定义,Kubernetes会自动的将实际状态收敛为修改后的状态。对于升级,只需要修改Pod中镜像的tag。

升级策略由deployment.spec.strategy.type定义,值是Recreate或RollingUpdate,默认RollingUpdate。

kubectl patch及minReadySeconds

使用kubectl patch定义deployment.spec.minReadySeconds来减慢滚动升级时间,以便观察升级过程

-> [root@kube0.vm] [~] k patch deployment goweb -p '{"spec":{"minReadySeconds":5}}'
deployment.apps/goweb patched

循环请求服务

在执行升级前新开窗口,运行下面的命令查看输出

-> [root@kube0.vm] [~] while true; do curl http://192.168.199.231:31234/ ; sleep 1; done
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
# 以上是升级之前的输出、以下是开始升级后的
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-pw7b4
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
this is v1, hostname: goweb-fdfcfdcc6-x8n7h
this is v1, hostname: goweb-fdfcfdcc6-j4mz8
this is v2, hostname: goweb-65cc575865-bfd98
this is v2, hostname: goweb-65cc575865-bfd98
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
this is v2, hostname: goweb-65cc575865-25988
# 这之后就是升级完成了

kubectl set

使用 kubectl set image 更新任何包含容器资源的镜像。

-> [root@kube0.vm] [~] k set image deployment goweb goweb=registry.cn-hangzhou.aliyuncs.com/orzi/goweb:v2
deployment.apps/goweb image updated

kubectl rollout

查看升级状态信息。执行完kubectl set image,立刻执行下面的命令。手速得快,不然赶不上热乎的。

-> [root@kube0.vm] [~] k rollout status deployment goweb
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "goweb" rollout to finish: 1 old replicas are pending termination...
deployment "goweb" successfully rolled out

修改Deployment或其他资源的方式

方法 作用
kubectl edit 使用编辑器打开资源配置
kubectl patch 在命令行以merge的方式修改配置
kubectl apply 通过yaml或者json文件,修改新改动的值。如果指定的对象不存在则创建。
kubectl replace 使用yaml或者json文件替换一个必须已存在的对象配置。
kubectl set image 修改镜像

回滚

使用kubectl rollout undo 回滚到上一个版本

-> [root@kube0.vm] [~] k rollout undo deployment goweb
deployment.apps/goweb rolled back

使用 kubectl rollout history 查看版本记录

-> [root@kube0.vm] [~] k rollout history deployment goweb
deployment.apps/goweb
REVISION  CHANGE-CAUSE
6         kubectl create --filename=goweb-deployment.yaml --record=true
7         kubectl create --filename=goweb-deployment.yaml --record=true

回滚到特定版本

-> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=5
error: unable to find specified revision 5 in history

-> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=7
deployment.apps/goweb skipped rollback (current template already matches revision 7)

-> [root@kube0.vm] [~] k rollout undo deployment goweb --to-revision=6
deployment.apps/goweb rolled back

通过deployment.spec.revisionHistoryLimit指定历史版本个数,默认为2。也就是当前和上一个版本。

控制滚动升级速率

deployment.spec.strategy.rollingUpdate下有两个字段,用来控制升级速率

  • maxSurge:超出期望副本数的Pod实例的比例或个数。默认25%,转换成绝对值后四舍五入,也可以直接指定为绝对值。
  • maxUnavailable:滚动升级时,最多允许有多少实例不可用,默认25%,转换成绝对值后四舍五入,也可以直接指定为绝对值。

暂停、恢复升级

  • 使用kubectl rollout pause暂停升级
  • 使用kubectl rollout resume取消暂停

阻止出错版本的滚动升级

  • minReadySeconds:指定新创建的Pod至少要运行多久才视为可用。
  • 配置就绪探针
  • 为滚动升级配置progressDeadlineSeconds

小结

  • kubectl rolling-update 过时的原因:伸缩的请求时由kubectl发起的,如果因为任何原因丢失了网络连接,升级将处于中间状态
  • Deployment是一种更高阶的资源,用于部署程序并以声明的方式升级应用,而不是通过ReplicationController或ReplicaSet进行部署。
  • 创建Deployment时指定 --record 记录历史版本号
  • Deployment下的ReplicaSet命名是DeploymentName+Pod模板Hash,而ReplicaSet下的Pod是在此基础拼接个随机字符串。
  • 升级策略由deployment.spec.strategy.type定义,值是Recreate或RollingUpdate,默认RollingUpdate。
  • 定义deployment.spec.minReadySeconds来减慢滚动升级时间
  • maxSurge与maxUnavailable控制滚动升级速率
  • 命令:patch、set、rollout
  • kubectl rollout:status、undo、pause、resume、history。
上一篇:Linux修改主机名


下一篇:ArcGIS API本地化部署