k8s部署无状态应用后,若需要更新应用时,可以通过使用ReplicationController或ReplicaSet实现升级,主要有两种方式:
Pod:每个Pod是一个或一组紧密相关的容器,每个Pod就像是一个独立的逻辑机器,拥有自己的IP、主机名、进程等,运行一个独立的应用程序,是K8S调度的基本单位。
ReplicationController:简称RC,旨在创建和管理一个Pod的多个副本(replicas)。当Pod副本数少于指定数目,RC就会启动运行新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。
ReplicaSet:是新一代的RC,其相比于RC,Pod选择器的表达能力更强,其选择器可匹配缺少某个标签或特定标签名的Pod。
假设ReplicationController管理一组v1版本的pod,直接通过将pod模板修改为v2版本的镜像,删除旧的pod实例,RC检测到当前没有pod匹配标签选择器,就会创建新的实例。
如果客户不能接受升级更新期间出现短暂的不可用的服务,那就需要先创建新的pod,再删除旧pod,这需要更多的硬件资源来支撑新旧pod同时存在的场景。
pod一般是通过Service来暴露服务的,在运行新版本pod前,Service都是访问的旧版本pod,当新版本pod创建且正常运行后,修改服务标签选择器切换Service流量至新pod,切换完毕后,删除旧RC,就可以删除所有旧pod。这种方式就是所谓的蓝绿部署
。
除了一次性创建新pod再一次性删除旧pod,我们还可以逐步递进的对旧版本pod进行删除,对新版本pod进行创建。这个可以通过对旧版本RC逐步缩容,同时对新版本RC进行扩容来实现。
ReplicationController和ReplicaSet这两种资源对象需要其他控制器进行配合才可以实现滚动升级,并且难度大,因此k8s提供了一种基于ReplicaSet的资源对象Deployment可以支持声明式
地更新应用。
Deployment是K8s在1.2版本引入的,是一种更高阶的资源,用于部署应用程序并以声明的方式升级应用,从而更好地解决pod编排问题。
Deployment在内部使用了ReplicaSet实现编排pod功能,当创建一个Deployment时,ReplicaSet资源会随之创建,ReplicaSet是新一代的ReplicationController,并推荐使用它替代ReplicationController来复制和管理Pod,在使用Deployment时,实际的Pod是由Deployment的ReplicaSet创建和管理的。
假设Deployment的服务名称为test-tomcat-deploy,yaml模板文件名为test-tomcat.yaml。使用命令时,deploy等价于deployment等价于deployments。若需要指定命名空间ns_name时,需要加上-n ns_name
。
kubectl create -f test-tomcat.yaml
kubectl delete -f test-tomcat.yaml
kubectl delete deployment test-tomcat-deploy
kubectl apply -f test-tomcat.yaml
kubectl edit deploy/test-tomcat-deploy
kubectl get deploy test-tomcat-deploy -o yaml
kubectl describe deployments test-tomcat-deploy
kubectl get deploy
[root@localhost ~]# kubectl get deploy -n kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
st-ui-wnunzeyg 1 1 1 1 1d
st-ui-x3w4xumy 1 1 1 1 1d
DESIRED
:pod副本数量的期望值(Deployment中定义的Replica数)CURRENT
:当前Replica值(Deployment实际创建的ReplicaSet中Replica值),该值会一直增加到DESIRED值为止才算整个应用实例创建完毕,部署才算完成。UP-TO-DATE
:最新版本的pod副本数量,用于指示在滚动升级过程中,有多少pod副本已成功升级。(Deployment滚动升级过程中ReplicaSet的Replica成功数)AVAILABLE
:当前集群中可用pod副本数。(Deployment创建的ReplicaSet中Replica存活数)AGE
:表示距离最后一次操作的时长。[root@localhost ~]# kubectl get rs -n kube-system
NAME DESIRED CURRENT READY AGE
st-ui-wnunzeyg-391614280 1 1 1 1d
st-ui-x3w4xumy-1656786196 1 1 1 1d
我们可以看到ReplicaSet的命名和Deployment是相关的,ReplicaSet命名是以Deployment名为前缀,在Deployment名字基础上又加了一串随机数。
[root@localhost ~]# kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
st-ui-wnunzeyg-391614280-3brk8 1/1 Running 0 1d
st-ui-x3w4xumy-1656786196-f4w8z 1/1 Running 0 1d
pod名称以Deployment中的ReplicaSet名称为前缀,在此基础上又加了随机字符串。
在Deployment中,可以通过spec.strategy指定Pod更新的策略,目前支持:Recreate(重建)
和RollingUpdate(滚动更新)
,默认是RollingUpdate。
Recreate:设置spec.strategy.type=Recreate
,更新方式为:Deployment在更新Pod时,会先杀掉所有正在运行的Pod,然后创建新的Pod。
RollingUpdate:设置spec.strategy.type=RollingUpdate
,更新方式为:Deployment会以滚动的方式来渐变性的更新Pod,即Pod新版本的递增,旧版本的递减的一个过程。
“滚动”,给人的是一种“圆”的印象,持续,不中断的意思,类似于“持续交付”的理念。RollingUpdate策略指一次仅更新一个Pod
,并且逐个更新,而不是一次性将所有的服务都关闭,避免业务中断。
回滚:通过滚动升级的策略可以平滑的升级Deployment,若升级出现问题,需要最快且最好的方式回退到上一次能够提供正常工作的版本。为此K8S提供了回滚机制。
revision:更新应用时,K8S都会记录当前的版次,即为revision,当升级出现问题时,可通过回滚到某个特定的revision,默认配置下,K8S只会保留最近的几个revision,可以通过Deployment配置文件中的spec.revisionHistoryLimit属性增加revision数量。
更新或回滚:每次更新或回滚时,revision都会自增1,回滚可以看作是一次更新,是一次更新为原版本的操作。
kubectl rollout history deployment deployment_name
kubectl rollout history deployment deployment_name --revision=2
其中--revision
表示指定修订版本;
kubectl rollout undo deployment deployment_name
kubectl rollout undo deployment deployment_name --to-revision=2
其中,--to-revision
表示回滚到指定的修订版本。
POST
/apis/apps/v1beta1/namespaces/{
namespace}/deployments/{
name}/rollback
如:
curl -k -H 'Authorization: Bearer token_xxxx' -H 'Content-Type:application/json' -X POST -d '{
"kind": "DeploymentRollback",
"apiVersion": "extensions/v1beta1",
"name": "deployment_name",
"rollbackTo": {
"revision": 2
}
}' https://localhost:6443/apis/extensions/v1beta1/namespaces/default/deployments/deployment_name/rollback
其中:name和rollbackTo.revision为必须字段,name为资源名称,rollbackTo.revision为回退的版本,若要回退上一个版本,即为0。
除了声明式,我们一般还有指令式,也就是命令式。我们看看这两者定义和区别。
指令式:
定义
:使用计算机某种语言的指令(命令)来完成程序的运行,比如我们通过编写shell脚本、python脚本运行程序应用。编写
:编写复杂,强依赖开发人员的经验,需要考虑目标环境以及流程细节,处理各种异常情况和边缘情况等。事务性
:较难保持事务性,强依赖脚本流程,若脚本在执行过程中出现异常,程序应用会处于一个中间状态,所以多次运行,可能会达到不同的状态和结果。维护性
:开发后,需要有对应的运维文档来协助运维人员维护同一个脚本,不便于维护。声明式:
定义
:使用配置文件直接描述最终状态,比如k8s中的yaml文件,描述最终要启动多少副本,要多少cpu之类的状态和结果。编写
:易于编写,只要会写配置文件,告诉应用达到什么样的结果和状态即可,不需要考虑流程和目标环境的细节,事务性
:天然的事务性,要么执行成功,要么失败,不会出现多种中间状态,重复执行保持一致的状态和结果。维护性
:配置文件中直接描述了最终状态和结果,无需过多的运维文档来描述信息。参考
《Kubernetes in Action》
《Kubernetes权威指南》
k8s官网