Deployment控制器
Deployment官方文档:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
Deployment是kubernetes控制器的又一种实现,它构建于ReplicaSet控制器之上,可为Pod和ReplicaSet资源提供声明式更新。在Deployment对象中描述一个期望的状态,Deployment控制器就会按照一定的控制速率把实际状态改成期望状态,通过定义一个Deployment控制器会创建一个新的ReplicaSet控制器,通过ReplicaSet创建pod,删除Deployment控制器,也会删除Deployment控制器下对应的ReplicaSet控制器和pod资源。
Deployment控制器资源的主要职责同样是为了保证pod资源的健康运行,其大部分功能均可通过调用ReplicaSet控制器来实现,同时增加了部分特性:
1)事件和状态查看:必要时可以查看Deployment对象升级的详细进度和状态。
2)回滚:升级操作完成后发现问题,支持使用回滚机制将应用返回到前一个或由用户指定的历史记录中的版本上。
3)版本记录:对Deployment对象的每一次操作都予以保存,以供后续可能执行的回滚操作使用。
4)暂停和启动:对于每一次升级,都能够随时暂停和启动。
5)多种自动更新方案:一个是Recreate,即重建更新机制,全面停止、删除旧的pod后用新版本替代;另一个是RollingUpdate,即滚动升级机制,逐步替换旧有的pod至新的版本。
1. Deployment资源清单文件编写的字段说明
可以看出一个Deployment拥有多个ReplicaSet,而一个ReplicaSet拥有一个或多个Pod。一个Deployment控制多个rs主要是为了支持回滚机制,每当Deployment操作时,Kubernetes会重新生成一个ReplicaSet并保留,以后有需要的话就可以回滚至之前的状态。
Deployment是构建于ReplicaSet资源之上,于是其spec字段中嵌套使用的字段包含了ReplicaSet控制器支持的replicas,selector,template,minReadySeconds,它也正是利用这些信息完成了其二级资源ReplicaSet对象的创建。
[root@k8s-master1 ~]# kubectl explain deployment KIND: Deployment VERSION: apps/v1 DESCRIPTION: Deployment enables declarative updates for Pods and ReplicaSets. FIELDS: apiVersion <string> #该资源使用的api版本 APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources kind <string> #创建的资源是什么? Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds metadata <Object> #元数据,包括资源的名字和名称空间 Standard object metadata. spec <Object> #定义容器的 Specification of the desired behavior of the Deployment. status <Object> #状态,不可以修改 Most recently observed status of the Deployment.
查看Deployment下的spec字段
[root@k8s-master1 ~]# kubectl explain deployment.spec KIND: Deployment VERSION: apps/v1 RESOURCE: spec <Object> DESCRIPTION: Specification of the desired behavior of the Deployment. DeploymentSpec is the specification of the desired behavior of the Deployment. FIELDS: minReadySeconds <integer> #Kubernetes在等设置的时间后才进行升级,如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了 Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) paused <boolean> #暂停,当更新的时候创建pod先暂停,不是立即更新 Indicates that the deployment is paused. progressDeadlineSeconds <integer> # k8s 在升级过程中有可能由于各种原因升级卡住(这个时候还没有明确的升级失败),比如在拉取不到镜像,权限不够等错误。那么这个时候就需要有个 deadline ,在 deadline 之内如果还卡着,那么就上报这个情况,这个时候这个 Deployment 状态就被标记为 False,并且注明原因。但是它并不会阻止 Deployment继续进行卡住后面的操作。完全由用户进行控制。 The maximum time in seconds for a deployment to make progress before it is considered to be failed. The deployment controller will continue to process failed deployments and a condition with a ProgressDeadlineExceeded reason will be surfaced in the deployment status. Note that progress will not be estimated during the time a deployment is paused. Defaults to 600s. replicas <integer> #副本数 Number of desired pods. This is a pointer to distinguish between explicit zero and not specified. Defaults to 1. revisionHistoryLimit <integer> #保留的历史版本,默认是10 The number of old ReplicaSets to retain to allow rollback. This is a pointer to distinguish between explicit zero and not specified. Defaults to 10. selector <Object> -required- #标签选择器,选择它关联的pod Label selector for pods. Existing ReplicaSets whose pods are selected by this will be the ones affected by this deployment. It must match the pod template's labels. strategy <Object> #更新策略 The deployment strategy to use to replace existing pods with new ones. template <Object> -required- #定义的pod模板 Template describes the pods that will be created.
查看Deployment下的spec.strategy字段
[root@k8s-master1 ~]# kubectl explain deployment.spec.strategy KIND: Deployment VERSION: apps/v1 RESOURCE: strategy <Object> DESCRIPTION: The deployment strategy to use to replace existing pods with new ones. DeploymentStrategy describes how to replace existing pods with new ones. FIELDS: rollingUpdate <Object> Rolling update config params. Present only if DeploymentStrategyType = RollingUpdate. type <string> Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. #支持两种更新,Recreate和RollingUpdate #Recreate是重建式更新,删除一个更新一个 #RollingUpdate滚动更新,定义滚动更新方式,也就是pod能多几个,少几个
查看Deployment下的spec.strategy.rollingUpdate字段
[root@k8s-master1 ~]# kubectl explain deployment.spec.strategy.rollingUpdate KIND: Deployment VERSION: apps/v1 RESOURCE: rollingUpdate <Object> DESCRIPTION: Rolling update config params. Present only if DeploymentStrategyType = RollingUpdate. Spec to control the desired behavior of rolling update. FIELDS: maxSurge <string> #更新的过程当中最多允许超出的指定的目标副本数有几个;它有两种取值方式,第一种直接给定数量,第二种根据百分比,百分比表示原本是5个,最多可以超出20%,那就允许多一个,最多可以超过40%,那就允许多两个 # maxSurage=1,replicas=5,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有5+1个POD The maximum number of pods that can be scheduled above the desired number of pods. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). This can not be 0 if MaxUnavailable is 0. Absolute number is calculated from percentage by rounding up. Defaults to 25%. Example: when this is set to 30%, the new ReplicaSet can be scaled up immediately when the rolling update starts, such that the total number of old and new pods do not exceed 130% of desired pods. Once old pods have been killed, new ReplicaSet can be scaled up further, ensuring that total number of pods running at any time during the update is at most 130% of desired pods. maxUnavailable <string> #最多允许几个不可用假设有5个副本,最多一个不可用,就表示最少有4个可用
#例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态 The maximum number of pods that can be unavailable during the update. Value can be an absolute number (ex: 5) or a percentage of desired pods (ex: 10%). Absolute number is calculated from percentage by rounding down. This can not be 0 if MaxSurge is 0. Defaults to 25%. Example: when this is set to 30%, the old ReplicaSet can be scaled down to 70% of desired pods immediately when the rolling update starts. Once new pods are ready, old ReplicaSet can be scaled down further, followed by scaling up the new ReplicaSet, ensuring that the total number of pods available at all times during the update is at least 70% of desired pods.
2. 创建Deployment
[root@k8s-master1 deployment]# vim deploy-demo.yaml You have new mail in /var/spool/mail/root [root@k8s-master1 deployment]# cat deploy-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-v1 spec: replicas: 2 selector: matchLabels: app: myapp version: v1 template: metadata: labels: app: myapp version: v1 spec: containers: - name: myapp image: janakiramm/myapp:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 80
可以看出,除了控制器类型和名称不同外,它与之前ReplicaSet控制器示例中的内容几乎没有什么不同。在集群中创建它,了解它的工作方式
[root@k8s-master1 deployment]# kubectl apply -f deploy-demo.yaml deployment.apps/myapp-v1 created [root@k8s-master1 deployment]# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE myapp-v1 2/2 2 2 12s [root@k8s-master1 deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-v1-67fd9fc9c8 2 2 2 17s [root@k8s-master1 deployment]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-v1-67fd9fc9c8-dmxrx 1/1 Running 0 22s 10.244.36.120 k8s-node1 <none> <none> myapp-v1-67fd9fc9c8-f6bps 1/1 Running 0 23s 10.244.36.121 k8s-node1 <none> <none>
可以看到创建的deployment对象myapp-v1及其相关的信息,其中UP-TO-DATE字段表示已经达到期望状态的pod副本数量,AVAILABLE 则表示当前处于可用状态的应用程序的数量。
Deployment控制器会自动创建相关的ReplicaSet控制器资源,其中DESIRED字段显示应用程序的所需副本数,这些副本数是在创建时定义的;CURRENT字段 显示当前正在运行多少个副本;READY字段显示用户可以使用多少个应用程序副本。pod资源对象名称以ReplicaSet控制器的名称为前缀,后跟5位随机数字符组成。
由此印证了Deployment借助于ReplicaSet管理pod资源的机制,于是,其大部分管理操作与ReplicaSet相同。但是Deployment有ReplicaSet所不具有的功能,即自动滚动更新机制。
3. 更新策略
ReplicaSet控制器的应用更新需要手动分成多步并以特定的次序进行,过程比较繁杂且容易出错,而Deployment却只需要由用户指定在pod模板中要改动的内容,余下的步骤可交由其自动完成。同样,更新应用程序的规模也只需要修改期望的副本数量,余下的事情交由Deployment控制器即可。
Deployment控制器详细信息中包含了其更新策略的相关配置信息。如控制器myapp-v1控制资源的详细信息中的StrategyType,RollingUpdateStrategy字段等
[root@k8s-master1 deployment]# kubectl describe deployments myapp-v1 Name: myapp-v1 Namespace: default CreationTimestamp: Wed, 07 Sep 2022 21:30:22 +0800 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=myapp,version=v1 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: app=myapp version=v1 Containers: myapp: Image: janakiramm/myapp:v1 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: myapp-v1-67fd9fc9c8 (2/2 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 20m deployment-controller Scaled up replica set myapp-v1-67fd9fc9c8 to 2
Deployment控制器支持两种更新策略:滚动更新(rolling update)和重新创建(recreate),默认为滚动更新。
重新创建更新,即首先删除现有的pod对象,然后由控制器基于新模板重新创建出新版本的资源对象。通常,只应该在应用的新旧版本不兼容时运行时才会使用recreate策略,因为它会导致应用替换期间暂时不可用,好处在于它不存在中间状态,用户访问到要么是应用的新版本,要么是旧版本。
滚动更新时默认的更新策略,它在删除一部分旧版本pod资源的同时,补充创建一部分新版本的pod对象进行应用升级,其优势是升级期间,容器中应用提供服务不会中断,但要求应用程序能够应对新旧版本同时工作的情形,例如新旧版本兼容同一个数据库方案等。不过,更新操作期间,不同客户端得到的响应内容可能会来自不同版本的应用。
Deployment控制器的滚动更新操作并非在同一个ReplicaSet控制器对象下删除并创建pod资源,而是将他们分别置于两个不同的控制器之下,旧控制器的pod对象数量不断减少的同时,新控制器的pod对象数量不断增加,直到旧控制器不再拥有pod对象,而新控制器的副本数量完全符合期望值为止。如下图所示:
rs v1控制三个pod,删除一个pod,在rs v2上重新建立一个,依次类推,直到全部都是由rs v2控制,如果rs v2有问题,还可以回滚,Deployment是建构在rs之上的,多个rs组成一个Deployment,但是只有一个rs处于活跃状态。
滚动更新时,应用升级期间还要确保可用pod数量不低于某阈值以确保可以持续处理客户端的服务请求,变动的方式和pod对象的数量范围将通过maxSurge和maxUnavailable这两个字段定义。
maxSurge:
升级过程中存在的总pod对象数量最多可超出期望值的个数,其值可以是整数,也可以是一个期望值的百分比。
maxUnavailable: [0%, 100%] 向下取整,比如10个副本,5%的话==0.5个,但计算按照0个;
例如:maxSurage=1,replicas=5,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有5+1个POD。
maxUnavaible:
升级过程中正常可用的pod副本数(包括新旧版本)最多不能低于期望数值的个数,其值可以是整数,也可以是一个期望值的百分比。默认值为1。
maxSurge: [0%, 100%] 向上取整,比如10个副本,5%的话==0.5个,但计算按照1个;
例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态,至少要有两个pod对象处于正常的提供服务状态。
注:maxSurge和maxUnavailable 值不可同时为0,否则pod对象的副本数量在符合用户期望的数量后无法做出合理的变动以进行滚动更新操作。
总结:
maxSurge:和期望的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。
maxUnavailable:和期望的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑。
4. 升级Deployment
修改pod模板相关配置参数便能完成deployment控制器资源的更新。由于是声明式配置,因此对deployment控制器资源的修改尤其适合使用apply和patch命令进行;当然,如果仅是修改容器镜像,使用“set image“命令更为容易。
使用“”镜像文件修改pod模板中的myapp容器,启动deployment控制器的滚动更新过程:
[root@k8s-master1 deployment]# kubectl set image deployments myapp-v1 myapp=janakiramm/myapp:v2 deployment.apps/myapp-v1 image updated
查看更新过程:pending表示正在进行调度,ContainerCreating表示正在创建一个pod,running表示运行一个pod,running起来一个pod之后再Terminating(停掉)一个pod,以此类推,直到所有pod完成滚动升级。
[root@k8s-master1 ~]# kubectl get pods -l app=myapp -w NAME READY STATUS RESTARTS AGE myapp-v1-67fd9fc9c8-dmxrx 1/1 Running 0 69m myapp-v1-67fd9fc9c8-f6bps 1/1 Running 0 69m myapp-v1-75fb478d6c-dg4vj 0/1 Pending 0 0s myapp-v1-75fb478d6c-dg4vj 0/1 Pending 0 0s myapp-v1-75fb478d6c-dg4vj 0/1 ContainerCreating 0 0s myapp-v1-75fb478d6c-dg4vj 0/1 ContainerCreating 0 1s myapp-v1-75fb478d6c-dg4vj 1/1 Running 0 2s myapp-v1-67fd9fc9c8-dmxrx 1/1 Terminating 0 69m myapp-v1-75fb478d6c-z8rh9 0/1 Pending 0 0s myapp-v1-75fb478d6c-z8rh9 0/1 Pending 0 0s myapp-v1-75fb478d6c-z8rh9 0/1 ContainerCreating 0 1s myapp-v1-67fd9fc9c8-dmxrx 1/1 Terminating 0 69m myapp-v1-67fd9fc9c8-dmxrx 0/1 Terminating 0 69m myapp-v1-75fb478d6c-z8rh9 0/1 ContainerCreating 0 2s myapp-v1-75fb478d6c-z8rh9 1/1 Running 0 3s myapp-v1-67fd9fc9c8-f6bps 1/1 Terminating 0 69m myapp-v1-67fd9fc9c8-f6bps 1/1 Terminating 0 69m myapp-v1-67fd9fc9c8-f6bps 0/1 Terminating 0 69m myapp-v1-67fd9fc9c8-f6bps 0/1 Terminating 0 69m myapp-v1-67fd9fc9c8-f6bps 0/1 Terminating 0 69m myapp-v1-67fd9fc9c8-dmxrx 0/1 Terminating 0 69m myapp-v1-67fd9fc9c8-dmxrx 0/1 Terminating 0 69m
滚动更新时,myapp-v1控制器会创建一个新的ReplicaSet控制器对象来管控新版本的pod对象,升级完成后,旧版本的ReplicaSet会保留在历史记录中,但其此前管控的pod对象会被删除。
[root@k8s-master1 deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-v1-67fd9fc9c8 0 0 0 75m myapp-v1-75fb478d6c 2 2 2 5m52s
myapp-v1控制器管控的pod资源对象也将随之更新为以新版本ReplicaSet名称为前缀的pod副本。
[root@k8s-master1 deployment]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-v1-75fb478d6c-dg4vj 1/1 Running 0 8m39s 10.244.36.122 k8s-node1 <none> <none> myapp-v1-75fb478d6c-z8rh9 1/1 Running 0 8m37s 10.244.169.144 k8s-node2 <none> <none>
查看myapp-v1这个控制器的历史版本
[root@k8s-master1 deployment]# kubectl rollout history deployment myapp-v1 deployment.apps/myapp-v1 REVISION CHANGE-CAUSE 1 <none> 2 <none>
5. 金丝雀发布
Deployment控制器还支持自定义控制更新过程中的滚动节奏,如“暂停”或“继续”更新操作,尤其是借助maxSurge和maxUnavailable属性还能实现更为精巧的过程控制。比如,待第一批新的pod资源创建完成后立即执行暂停更新过程,此时,仅存在一小部分新版本的应用,主体部分还是旧的版本。然后,再根据用户特征精心筛选出小部分用户的请求到新版本的pod应用,并持续观察其是否能稳定地按期望的方式运行。确定没有问题后再继续完成余下的pod资源的滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布。
如何在kubernetes上使用Deployment控制器实现金丝雀部署?
为了尽可能地降低对现有系统及其容量的影响,金丝雀发布过程通常建议采用“先添加,再删除,且可用pod资源对象总数不低于期望值”的方式进行。首次,添加的pod对象数量取决于其接入的第一批请求的规则及单个pod的承载能力,视具体需求而定,为了能够简单的说明问题,接下来采用首批添加1个pod资源的方式。将Deployment控制器的maxSurge属性值设置为1,并将maxUnavailable属性值设置为0:
[root@k8s-master1 deployment]# kubectl patch deployments myapp-v1 -p '{"spec": {"strategy": {"rollingUpdate": {"maxSurge": 1, "maxUnavailable": 0}}}}' deployment.apps/myapp-v1 patched
接下来,启动myapp-v1控制器更新过程,在修改相应容器的镜像版本后立即暂停更新进度,它会在启动第一批新版本pod对象的创建操作之后转为暂停状态。需要注意的是,之所以能在第一批更新启动后就暂停,有赖于maxReadySeconds属性设置的时长,因此用户要在更新命令启动后的此时长指定的时间范围内启动暂停操作。
[root@k8s-master1 deployment]# kubectl set image deployments myapp-v1 myapp=ikubernetes/myapp:v2 && kubectl rollout pause deployments myapp-v1 deployment.apps/myapp-v1 image updated deployment.apps/myapp-v1 paused
通过其状态查看命令可以看到,在创建完一个新版本的pod资源后,滚动更新操作“暂停”
[root@k8s-master1 deployment]# kubectl rollout status deployments myapp-v1 Waiting for deployment "myapp-v1" rollout to finish: 1 out of 3 new replicas have been updated...
监控到其更新过程中pod对象的变动过程,创建了第一个新版本pod对象后,暂停。
[root@k8s-master1 ~]# kubectl get pods -w NAME READY STATUS RESTARTS AGE myapp-v1-67fd9fc9c8-5v7hz 1/1 Running 1 22h myapp-v1-67fd9fc9c8-wnhbl 1/1 Running 0 10m myapp-v1-67fd9fc9c8-x72zr 1/1 Running 0 10m myapp-v1-6c5b58485f-56txr 0/1 Pending 0 0s myapp-v1-6c5b58485f-56txr 0/1 Pending 0 0s myapp-v1-6c5b58485f-56txr 0/1 ContainerCreating 0 1s myapp-v1-6c5b58485f-56txr 0/1 ContainerCreating 0 4s myapp-v1-6c5b58485f-56txr 1/1 Running 0 6s
[root@k8s-master1 ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-v1-67fd9fc9c8-5v7hz 1/1 Running 1 22h 10.244.36.66 k8s-node1 <none> <none> myapp-v1-67fd9fc9c8-wnhbl 1/1 Running 0 15m 10.244.36.68 k8s-node1 <none> <none> myapp-v1-67fd9fc9c8-x72zr 1/1 Running 0 15m 10.244.36.69 k8s-node1 <none> <none> myapp-v1-6c5b58485f-56txr 1/1 Running 0 4m10s 10.244.169.146 k8s-node2 <none> <none>
查看到当前有4个pod对象,旧版本的ReplicaSet控制下的所有pod副本仍然正常运行,新版的ReplicaSet也包含了一个pod对象,但最多不超过期望值1个,myapp-v1原有的期望值是3,因此总数不超过4个。此时,通过Service或Ingress资源及相关路由策略等设定,即可将一部分用户的流量引入到这些pod之上进行发布验证。运行一段时间后,如果确认没有问题,即可使用“kubectl rollout resume”命令继续此前的滚动更新过程。
[root@k8s-master1 deployment]# kubectl rollout resume deployments myapp-v1 deployment.apps/myapp-v1 resumed
通过其状态查看命令,可以看到滚动更新完成。
[root@k8s-master1 deployment]# kubectl rollout status deployments myapp-v1 Waiting for deployment "myapp-v1" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment spec update to be observed... Waiting for deployment spec update to be observed... Waiting for deployment "myapp-v1" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "myapp-v1" rollout to finish: 1 out of 3 new replicas have been updated... Waiting for deployment "myapp-v1" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "myapp-v1" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "myapp-v1" rollout to finish: 2 out of 3 new replicas have been updated... Waiting for deployment "myapp-v1" rollout to finish: 1 old replicas are pending termination... Waiting for deployment "myapp-v1" rollout to finish: 1 old replicas are pending termination... deployment "myapp-v1" successfully rolled out
监控到在其更新过程中pod对象的变化过程,在myapp-v1-6c5b58485f-56txr这个pod运行后,有一段时间处于暂停状态,继续更新后,开始删除旧版本的pod对象,再创建新的pod对象,直至达到客户期望的状态。
[root@k8s-master1 ~]# kubectl get pods -w NAME READY STATUS RESTARTS AGE myapp-v1-67fd9fc9c8-5v7hz 1/1 Running 1 22h myapp-v1-67fd9fc9c8-wnhbl 1/1 Running 0 10m myapp-v1-67fd9fc9c8-x72zr 1/1 Running 0 10m myapp-v1-6c5b58485f-56txr 0/1 Pending 0 0s myapp-v1-6c5b58485f-56txr 0/1 Pending 0 0s myapp-v1-6c5b58485f-56txr 0/1 ContainerCreating 0 1s myapp-v1-6c5b58485f-56txr 0/1 ContainerCreating 0 4s myapp-v1-6c5b58485f-56txr 1/1 Running 0 6s myapp-v1-67fd9fc9c8-wnhbl 1/1 Terminating 0 21m myapp-v1-6c5b58485f-czcgg 0/1 Pending 0 0s myapp-v1-6c5b58485f-czcgg 0/1 Pending 0 0s myapp-v1-6c5b58485f-czcgg 0/1 ContainerCreating 0 0s myapp-v1-67fd9fc9c8-wnhbl 1/1 Terminating 0 21m myapp-v1-67fd9fc9c8-wnhbl 0/1 Terminating 0 21m myapp-v1-6c5b58485f-czcgg 0/1 ContainerCreating 0 5s myapp-v1-6c5b58485f-czcgg 1/1 Running 0 8s myapp-v1-67fd9fc9c8-x72zr 1/1 Terminating 0 21m myapp-v1-6c5b58485f-fjqc9 0/1 Pending 0 0s myapp-v1-6c5b58485f-fjqc9 0/1 Pending 0 0s myapp-v1-6c5b58485f-fjqc9 0/1 ContainerCreating 0 0s myapp-v1-67fd9fc9c8-x72zr 1/1 Terminating 0 21m myapp-v1-6c5b58485f-fjqc9 0/1 ContainerCreating 0 3s myapp-v1-67fd9fc9c8-x72zr 0/1 Terminating 0 21m myapp-v1-6c5b58485f-fjqc9 1/1 Running 0 5s myapp-v1-67fd9fc9c8-5v7hz 1/1 Terminating 1 22h myapp-v1-67fd9fc9c8-wnhbl 0/1 Terminating 0 21m myapp-v1-67fd9fc9c8-wnhbl 0/1 Terminating 0 21m myapp-v1-67fd9fc9c8-5v7hz 1/1 Terminating 1 22h myapp-v1-67fd9fc9c8-5v7hz 0/1 Terminating 1 22h myapp-v1-67fd9fc9c8-5v7hz 0/1 Terminating 1 22h myapp-v1-67fd9fc9c8-5v7hz 0/1 Terminating 1 22h myapp-v1-67fd9fc9c8-x72zr 0/1 Terminating 0 21m myapp-v1-67fd9fc9c8-x72zr 0/1 Terminating 0 21m
此后,可通过myapp-v1控制器及其ReplicaSet和pod对象的相关信息了解其结果状态。
[root@k8s-master1 deployment]# kubectl get deployments -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR myapp-v1 3/3 3 3 24h myapp ikubernetes/myapp:v2 app=myapp,version=v1 [root@k8s-master1 deployment]# kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR myapp-v1-67fd9fc9c8 0 0 0 24h myapp janakiramm/myapp:v1 app=myapp,pod-template-hash=67fd9fc9c8,version=v1 myapp-v1-6c5b58485f 3 3 3 17m myapp ikubernetes/myapp:v2 app=myapp,pod-template-hash=6c5b58485f,version=v1 myapp-v1-75fb478d6c 0 0 0 23h myapp janakiramm/myapp:v2 app=myapp,pod-template-hash=75fb478d6c,version=v1 [root@k8s-master1 deployment]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-v1-6c5b58485f-56txr 1/1 Running 0 17m 10.244.169.146 k8s-node2 <none> <none> myapp-v1-6c5b58485f-czcgg 1/1 Running 0 7m1s 10.244.36.72 k8s-node1 <none> <none> myapp-v1-6c5b58485f-fjqc9 1/1 Running 0 6m53s 10.244.36.70 k8s-node1 <none> <none>
6. 回滚Deployment控制器下的应用发布
若因为各种原因导致滚动更新无法正常进行,如镜像获取失败等,则应该将应用回滚到之前的版本,或者回滚到由用户指定的历史记录中的版本。Deployment控制器回滚操作可使用“kubectl rollout undo”命令完成。如:将myapp-v1控制器回滚至此前的版本:
[root@k8s-master1 deployment]# kubectl rollout undo deployments myapp-v1 deployment.apps/myapp-v1 rolled back You have new mail in /var/spool/mail/root [root@k8s-master1 deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-v1-67fd9fc9c8 2 2 2 88m myapp-v1-75fb478d6c 0 0 0 19m
若要恢复到指定的版本,可在“kubectl rollout undo” 命令上使用“--to-revision”选项指定revision号码即可回滚到历史特定版本。例如,查看myapp-v1包含如下的revision历史记录:
[root@k8s-master1 deployment]# kubectl rollout history deployment myapp-v1 deployment.apps/myapp-v1 REVISION CHANGE-CAUSE 2 <none> 3 <none>
若要回滚到号码为2的revision记录,可使用如下命令即可完成
[root@k8s-master1 deployment]# kubectl rollout undo deployments myapp-v1 --to-revision=2 deployment.apps/myapp-v1 rolled back You have new mail in /var/spool/mail/root [root@k8s-master1 deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-v1-67fd9fc9c8 1 1 1 95m myapp-v1-75fb478d6c 2 2 1 26m [root@k8s-master1 deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-v1-67fd9fc9c8 0 0 0 96m myapp-v1-75fb478d6c 2 2 2 26m [root@k8s-master1 deployment]# kubectl rollout history deployment myapp-v1 deployment.apps/myapp-v1 REVISION CHANGE-CAUSE 3 <none> 4 <none>
回滚过程中,其revision记录中的信息会发生变动,回滚操作会被当做一次滚动更新追加进历史记录中,而被回滚的条目则会被删除。需要注意的是,如果此前的滚动更新过程处于“暂停”状态,那么回滚操作就需要先将pod模板的版本改回之前的版本,然后“继续”更新,否则,其将一直处于暂停状态而无法回滚。
7. 扩容和缩容
通过修改.spec.replicas字段即可修改deployment控制器中pod资源的副本数量,它将实时作用于控制器并直接生效。Deployment控制器是声明式配置,replicas属性的值可直接修改资源配置文件,然后使用“kubectl apply”进行应用,也可以使用“kubectl edit” 对其进行实时修改。
另外,“kubectl scale”是专用于扩展某些控制器类型的应用规模命令,包括Deployment和Job等。
如:直接修改replicas数量,如下,变成3
[root@k8s-master1 deployment]# vim deploy-demo.yaml You have new mail in /var/spool/mail/root [root@k8s-master1 deployment]# cat deploy-demo.yaml apiVersion: apps/v1 kind: Deployment metadata: name: myapp-v1 spec: replicas: 3 selector: matchLabels: app: myapp version: v1 template: metadata: labels: app: myapp version: v1 spec: containers: - name: myapp image: janakiramm/myapp:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 80 [root@k8s-master1 deployment]# kubectl apply -f deploy-demo.yaml deployment.apps/myapp-v1 configured
查看扩容过程中pod对象的变动过程:先创建2个pod(myapp-v1-75fb478d6c-qh8qj和myapp-v1-67fd9fc9c8-5v7hz), 再删除一个pod(myapp-v1-75fb478d6c-qh8qj),再创建一个pod(myapp-v1-67fd9fc9c8-gjp75),在删除一个pod(myapp-v1-75fb478d6c-ns2s4 ),在创建一个pod(myapp-v1-67fd9fc9c8-sldxk),再删除一个pod(myapp-v1-75fb478d6c-s26s4 ),完成了三个新pod的创建。
[root@k8s-master1 ~]# kubectl get pods -l app=myapp -w NAME READY STATUS RESTARTS AGE myapp-v1-75fb478d6c-ns2s4 1/1 Running 0 9m47s myapp-v1-75fb478d6c-s26s4 1/1 Running 0 9m45s myapp-v1-75fb478d6c-qh8qj 0/1 Pending 0 0s myapp-v1-67fd9fc9c8-5v7hz 0/1 Pending 0 0s myapp-v1-75fb478d6c-qh8qj 0/1 Pending 0 0s myapp-v1-67fd9fc9c8-5v7hz 0/1 Pending 0 0s myapp-v1-75fb478d6c-qh8qj 0/1 ContainerCreating 0 0s myapp-v1-67fd9fc9c8-5v7hz 0/1 ContainerCreating 0 1s myapp-v1-75fb478d6c-qh8qj 0/1 ContainerCreating 0 3s myapp-v1-67fd9fc9c8-5v7hz 0/1 ContainerCreating 0 3s myapp-v1-67fd9fc9c8-5v7hz 1/1 Running 0 4s myapp-v1-75fb478d6c-qh8qj 1/1 Running 0 4s myapp-v1-75fb478d6c-qh8qj 1/1 Terminating 0 4s myapp-v1-67fd9fc9c8-gjp75 0/1 Pending 0 0s myapp-v1-67fd9fc9c8-gjp75 0/1 Pending 0 0s myapp-v1-67fd9fc9c8-gjp75 0/1 ContainerCreating 0 0s myapp-v1-67fd9fc9c8-gjp75 0/1 ContainerCreating 0 2s myapp-v1-67fd9fc9c8-gjp75 1/1 Running 0 2s myapp-v1-75fb478d6c-ns2s4 1/1 Terminating 0 9m57s myapp-v1-67fd9fc9c8-sldxk 0/1 Pending 0 0s myapp-v1-67fd9fc9c8-sldxk 0/1 Pending 0 0s myapp-v1-67fd9fc9c8-sldxk 0/1 ContainerCreating 0 1s myapp-v1-75fb478d6c-qh8qj 1/1 Terminating 0 7s myapp-v1-75fb478d6c-ns2s4 1/1 Terminating 0 9m58s myapp-v1-67fd9fc9c8-sldxk 0/1 ContainerCreating 0 2s myapp-v1-75fb478d6c-qh8qj 0/1 Terminating 0 9s myapp-v1-75fb478d6c-ns2s4 0/1 Terminating 0 10m myapp-v1-67fd9fc9c8-sldxk 1/1 Running 0 3s myapp-v1-75fb478d6c-s26s4 1/1 Terminating 0 9m58s myapp-v1-75fb478d6c-s26s4 1/1 Terminating 0 9m58s myapp-v1-75fb478d6c-s26s4 0/1 Terminating 0 10m myapp-v1-75fb478d6c-s26s4 0/1 Terminating 0 10m myapp-v1-75fb478d6c-s26s4 0/1 Terminating 0 10m myapp-v1-75fb478d6c-qh8qj 0/1 Terminating 0 20s myapp-v1-75fb478d6c-qh8qj 0/1 Terminating 0 20s myapp-v1-75fb478d6c-ns2s4 0/1 Terminating 0 10m myapp-v1-75fb478d6c-ns2s4 0/1 Terminating 0 10m
查看deployment控制器信息
[root@k8s-master1 deployment]# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE myapp-v1 3/3 3 3 107m You have new mail in /var/spool/mail/root [root@k8s-master1 deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-v1-67fd9fc9c8 3 3 3 107m myapp-v1-75fb478d6c 0 0 0 37m [root@k8s-master1 deployment]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-v1-67fd9fc9c8-5v7hz 1/1 Running 0 89s 10.244.36.127 k8s-node1 <none> <none> myapp-v1-67fd9fc9c8-gjp75 1/1 Running 0 85s 10.244.36.65 k8s-node1 <none> <none> myapp-v1-67fd9fc9c8-sldxk 1/1 Running 0 83s 10.244.36.67 k8s-node1 <none> <none>
上面可以看到pod副本数变成了3个。
查看myapp-v1这个控制器的详细信息:
[root@k8s-master1 deployment]# kubectl describe deployments myapp-v1 Name: myapp-v1 Namespace: default CreationTimestamp: Wed, 07 Sep 2022 21:30:22 +0800 Labels: <none> Annotations: deployment.kubernetes.io/revision: 5 Selector: app=myapp,version=v1 Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=myapp version=v1 Containers: myapp: Image: janakiramm/myapp:v1 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: myapp-v1-67fd9fc9c8 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 29m (x2 over 56m) deployment-controller Scaled up replica set myapp-v1-75fb478d6c to 1 Normal ScalingReplicaSet 29m (x2 over 56m) deployment-controller Scaled down replica set myapp-v1-67fd9fc9c8 to 1 Normal ScalingReplicaSet 29m (x2 over 56m) deployment-controller Scaled up replica set myapp-v1-75fb478d6c to 2 Normal ScalingReplicaSet 29m (x2 over 56m) deployment-controller Scaled down replica set myapp-v1-67fd9fc9c8 to 0 Normal ScalingReplicaSet 20m (x2 over 37m) deployment-controller Scaled up replica set myapp-v1-67fd9fc9c8 to 1 Normal ScalingReplicaSet 20m deployment-controller Scaled up replica set myapp-v1-75fb478d6c to 3 Normal ScalingReplicaSet 19m (x3 over 125m) deployment-controller Scaled up replica set myapp-v1-67fd9fc9c8 to 2 Normal ScalingReplicaSet 19m (x2 over 37m) deployment-controller Scaled down replica set myapp-v1-75fb478d6c to 1 Normal ScalingReplicaSet 19m (x2 over 19m) deployment-controller (combined from similar events): Scaled up replica set myapp-v1-67fd9fc9c8 to 3 Normal ScalingReplicaSet 19m (x2 over 37m) deployment-controller Scaled down replica set myapp-v1-75fb478d6c to 0
缩容同理,修改replicas值。
[root@k8s-master1 deployment]# kubectl scale deployment myapp-v1 --replicas=1 deployment.apps/myapp-v1 scaled You have new mail in /var/spool/mail/root [root@k8s-master1 deployment]# kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE myapp-v1 1/1 1 1 129m [root@k8s-master1 deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE myapp-v1-67fd9fc9c8 1 1 1 129m myapp-v1-75fb478d6c 0 0 0 59m [root@k8s-master1 deployment]# kubectl get pods NAME READY STATUS RESTARTS AGE myapp-v1-67fd9fc9c8-5v7hz 1/1 Running 0 24m
监控到的缩容过程中pod对象的变动过程如下:
[root@k8s-master1 ~]# kubectl get pods -l app=myapp -w NAME READY STATUS RESTARTS AGE myapp-v1-67fd9fc9c8-5v7hz 1/1 Running 0 23m myapp-v1-67fd9fc9c8-gjp75 1/1 Running 0 23m myapp-v1-67fd9fc9c8-sldxk 1/1 Running 0 23m myapp-v1-67fd9fc9c8-sldxk 1/1 Terminating 0 23m myapp-v1-67fd9fc9c8-gjp75 1/1 Terminating 0 23m myapp-v1-67fd9fc9c8-sldxk 1/1 Terminating 0 23m myapp-v1-67fd9fc9c8-gjp75 1/1 Terminating 0 23m myapp-v1-67fd9fc9c8-sldxk 0/1 Terminating 0 23m myapp-v1-67fd9fc9c8-gjp75 0/1 Terminating 0 23m myapp-v1-67fd9fc9c8-sldxk 0/1 Terminating 0 23m myapp-v1-67fd9fc9c8-sldxk 0/1 Terminating 0 23m myapp-v1-67fd9fc9c8-gjp75 0/1 Terminating 0 23m myapp-v1-67fd9fc9c8-gjp75 0/1 Terminating 0 23m