k8s如何滚动升级应用
介绍在k8s平台手动升级应用和借助Deployment进行升级
本文基于《Kubernetes in Action》第9章整理。
在进入正文前,不得不感慨一下标签选择器的设计对解耦k8s各模块发挥的作用。k8s的service, replicaSet, 滚动升级,调度的亲缘性和污点容忍度都离不开标签选择器。标签选择器让k8s对资源的操作更加灵活。
手动进行滚动升级
我们先用如下的配置创建一个ReplicationController
apiVersion: v1
kind: ReplicationController
metadata:
name: kubia-v1
spec:
replicas: 3
selector:
matchLabels:
app: kubia
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: test:v1
name: my-container
并创建一个service,其标签选择器是 “app: kubia”
现在我们想要更新镜像,可以执行如下步骤进行滚动升级。
- 新建一个新的ReplicationController,如下所示
apiVersion: v1
kind: ReplicationController
metadata:
name: kubia-v2
spec:
replicas: 0
selector:
matchLabels:
app: kubia
deployment: 757d16 # 增加标签,用于标记此次的升级记录
template:
metadata:
name: kubia
labels:
app: kubia
deployment: 757d16 # 增加标签,用于标记此次的升级记录
spec:
containers:
- image: test:v2 # 修改镜像
name: my-container
- 为原pod和ReplicationController增加标签:deployment: 343der。此时,kubia-v1还是管理着原先的pod,kubia-v2新建的pod不会被kubia-v1管理。但是不论kubia-v1还是kubia-v2创建的pod,都会和之前建的service关联。
- 逐步扩容kubia-v2,并逐步缩容kubia-v1,直至所有pod都是由kubia-v2管理,则此次滚动升级结束
上述的步骤,也是之前kubectl的roling-update命令执行的大概过程。
这个过程存在以下弊端
- 过程繁琐。需要多次和API服务器交互
- 是在客户端执行,因此无法保证一致性,如果在滚动升级过程中和API服务器的交互出现问题,则pod, rc等资源会处于中间状态
- 不符合k8s的设计理念。应该通过设置期望的状态而不是告诉需要做哪些事情
通过Deployment滚动升级
首先创建以下配置,命名为deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
progressDeadlineSeconds: 600 # 滚动升级失败的超时时间
minReadySeconds: 10 # 需要容器就绪多久后才能认为可用,在可用前,滚动升级不会继续。这个可以用于控制滚动升级的速率
strategy:
rollingUpdate:
maxSurge: 1 # 在期望副本数基础上,最多允许超出的pod实例数量,允许设置绝对值和百分比
maxUnavailable: 25% # 相对于期望副本数,允许有多少pod实例处于不可用状态,允许设置绝对值和百分比
type: RollingUpdate # 表示滚动升级。也可以配置成 Recreate,其会一次性删除所有旧版本的pod,然后创建新的pod
selector:
matchLabels:
app: kubia
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- image: test:v1
name: my-container
执行下面命令会创建Deployment
kubectl create -f deployment.yaml --record
--record会记录历史版本号,在回滚时会很有用
随后,这个deployment会创建一个ReplicaSet,然后新建的ReplicaSet再去创建pod,不过这个都不需要我们关注。所以,Deployment是比ReplicaSet更高级的资源,是用于协调多个ReplicaSet的。
修改pod模板才会触发滚动升级,因此修改deployment本身的配置,以及pod关联的ConfigMap等都不会触发滚动升级。当滚动升级开始的时候,会新建一个ReplicaSet,根据新的pod模板创建新的pod,并不断扩容新的ReplicaSet,缩容旧的ReplicaSet。过程类似上面介绍的手动滚动升级,区别是Deployment不会删除旧的ReplicaSet,因此可以方便的进行回滚。
滚动升级相关的命令是kubectl rollout,可以查看其都有哪些子命令
kubectl rollout history deployment my-deployment # 可以查看my-deployment的滚动升级历史
kubectl rollout pause deployment my-deployment # 可以暂停滚动升级
kubectl rollout resume deployment my-deployment # 可以恢复滚动升级
kubectl rollout status deployment my-deployment # 可以查看滚动升级中的状态
kubectl rollout undo deployment my-deployment --to-revision=1 # 回滚到指定版本
聊一下服务的上线
服务的上线是一个危险的动作,很多事故都是因为上线引起的。之所以危险,原因有很多,比如测试不到位,服务没有优雅退出,没有做好兼容等。所以对于服务的上线,需要足够的敬畏。
为了减少服务上线带来的事故,采取的措施一般有
- 封线。比如节假日前后,流量高峰期时一般不允许上线
- 周知。周知相关服务的负责人,让他们协助在服务上线期间一起观察服务有无异常
- 分阶段升级。比如第一次只升级其中一个实例,第二次升级3个实例,逐步放量,缓慢上线
- 做好观察。在服务上线期间,需要盯监控,关注告警,观察失败日志,在出现异常的时候第一时间会滚
更多推荐
所有评论(0)