目录
- 1、Deployment
- 2、Replication Controller
1、Deployment
只需要在Deployment描述想要的目标状态,Deployment controller就会帮你将pod和replicaset的实际状态改变到您的目标状态。 Deployment
controller将pod和replicaset中的实际状态替换为您在deployment中描述的目标状态
可以定义一个全新的Deployment来创建replicaset或者删除已有的deployment并创建一个新的来替换。
注:不可以手动管理Deployment创建的replica set。
典型的用例如下:
- 使用Deployment来创建ReplicaSet。ReplicaSet在后台创建pod。检查启动状态,看它是成功还是失败。
- 然后,通过更新Deployment的PodTemplateSpec字段来声明Pod的新状态。这会创建一个新的ReplicaSet,Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新的ReplicaSet中。
- 如果当前状态不稳定,回滚到之前的Deployment revision。每次回滚都会更新Deployment的revision。
- 扩容Deployment以满足更高的负载。
- 暂停Deployment来应用PodTemplateSpec的多个修复,然后恢复上线。
- 根据Deployment 的状态判断上线是否hang住了。
- 清除旧的不必要的 ReplicaSet。
创建deployment
下面是一个 Deployment 示例,它创建了一个 ReplicaSet 来启动3个 nginx pod。
下载示例文件并执行命令:
$ kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
-f参数代表引用k8s对象定义文件file的意思
输出结果表明我们希望的repalica数是3(根据deployment中的.spec.replicas配置)当前replica数( .status.replicas)是0,最新的replica数(.status.updatedReplicas)是0,可用的replica数(.status.availableReplicas)是0。
过几秒后再执行get命令,将获得如下输出:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 18s
我们可以看到Deployment已经创建了3个 replica,所有的 replica 都已经是最新的了(包含最新的pod template),可用的(根据Deployment中的.spec.minReadySeconds声明,处于已就绪状态的pod的最少个数)。执行kubectl get rs和kubectl get pods会显示Replica Set(RS)和Pod已创建。
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-2035384211 3 3 0 18s
您可能会注意到 ReplicaSet 的名字总是<Deployment的名字>-<pod template的hash值>。
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-2035384211-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
刚创建的Replica Set将保证总是有3个 nginx 的 pod 存在。
注意: 您必须在 Deployment 中的 selector 指定正确的 pod template label(在该示例中是 app = nginx),不要跟其他的 controller 的 selector 中指定的 pod template label 搞混了(包括 Deployment、Replica Set、Replication Controller 等)。Kubernetes 本身并不会阻止您任意指定 pod template label ,但是如果您真的这么做了,这些 controller 之间会相互打架,并可能导致不正确的行为。
Pod-template-hash label
注:这个label不是用户指定的
注意上面示例输出中的 pod label 里的 pod-template-hash label。当 Deployment 创建或者接管ReplicaSet 时,Deployment controller 会自动为 Pod 添加 pod-template-hash label。这样做的目的是防止 Deployment 的子ReplicaSet 的 pod 名字重复。通过将 ReplicaSet 的PodTemplate 进行哈希散列,使用生成的哈希值作为 label 的值,并添加到 ReplicaSet selector 里、 pod template label 和 ReplicaSet 管理中的 Pod 上。
更新deployment
注:deployment 的 rollout 当且仅当 deployment 的 pod template 中的 label 更新或者镜像更改时被触发。
例如:
我们现在想要让 nginx pod 使用nginx:1.9.1的镜像来代替原来的nginx:1.7.9的镜像。
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated
也可以使用edit来编辑deployment,修改.spec.template.spec.containers[0].image ,将nginx:1.7.9 改写成 nginx:1.9.1。
$ kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited
查看rollout状态
$ kubectl rollout status deployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-deployment" successfully rolled out
Rollout 成功后,get Deployment:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 36s
Label selector更新
通常不建议更新 label selector,建议实现规划好selector
任何情况下,只要您想要执行label selector 更新,请谨慎确认已经预料到所有可能因此导致的后果
- 增添 selector 需要同时在 deployment 的 spec 中更新新的 label ,否则将返回校验错误。—此更改不可覆盖,意味着新的selector 不会选择使用旧的 selector 创建的replicaset 和 Pod,从而导致所有旧版本的replicaset 都被丢弃,并创建新的 replicaset。
- 更新 selector ,即更改 selector key 的当前值,将导致跟增添selector 同样的后果。
- 删除 selector ,即删除deployment selector 中已有的key,不需要对Pod template label 做任何更改,现有的replicaset 也不会成为孤儿。—注:删除的label 仍然存在于现有的 Pod 和 replicaset中。
回退deployment
默认情况,kubernetes会在系统中保存前两次的 deployment 和 rollout历史记录,一边可以随时回退。
注:只要deployment 和 rollout 被触发就会创建一个 revision 。
其他更新,比如扩容 deployment 不会创建revision ,—因此我们可以很方便的手动或者自动扩容。
假设我们在更新 Deployment 的时候犯了一个拼写错误,将镜像的名字写成了nginx:1.91,而正确的名字应该是nginx:1.9.1:
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.91
deployment "nginx-deployment" image updated
Rollout 将会卡住。
$ kubectl rollout status deployments nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
按住 Ctrl-C 停止上面的 rollout 状态监控。
您会看到旧的 replica(nginx-deployment-1564180365 和 nginx-deployment-2035384211)和新的 replica (nginx-deployment-3066724191)数目都是2个。
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1564180365 2 2 0 25s
nginx-deployment-2035384211 0 0 0 36s
nginx-deployment-3066724191 2 2 2 6s
看下创建 Pod,您会看到有两个新的 ReplicaSet 创建的 Pod 处于 ImagePullBackOff 状态,循环拉取镜像。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-1564180365-70iae 1/1 Running 0 25s
nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s
nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
nginx-deployment-3066724191-eocby 0/1 ImagePullBackOff 0 6s
注意,Deployment controller会自动停止坏的 rollout,并停止扩容新的 ReplicaSet。
$ kubectl describe deployment
Name: nginx-deployment
Namespace: default
CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700
Labels: app=nginx
Selector: app=nginx
Replicas: 2 updated | 3 total | 2 available | 2 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 1 max unavailable, 1 max surge
OldReplicaSets: nginx-deployment-1564180365 (2/2 replicas created)
NewReplicaSet: nginx-deployment-3066724191 (2/2 replicas created)
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2
22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0
21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-1564180365 to 2
13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 2
为了修复这个问题,我们需要回退到稳定的 Deployment revision。
检查deployment 升级的历史记录
首先检查 deployment 的 revision
$ kubectl rollout history deployment/nginx-deployment
查看单个revision信息:
$ kubectl rollout history deployment/nginx-deployment --revision=2
回退到历史版本
$ kubectl rollout undo deployment/nginx-deployment
可以使用 --revision 指定到某个历史版本
$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
清理policy
您可以通过设置.spec.revisonHistoryLimit项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment就不允许回退了。
deployment扩容
$ kubectl scale deployment nginx-deployment --replicas 10
假设您的集群中启用了horizontal pod autoscaling,您可以给 Deployment 设置一个 autoscaler,基于当前 Pod的 CPU 利用率选择最少和最多的 Pod 数。
$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
比例扩容:
Rollingupdate deployment(滚动更新)支持同时运行一个应用的多个版本。或者 autoscaler 扩 容 RollingUpdate Deployment 的时候,正在中途的 rollout(进行中或者已经暂停的),为了降低风险,Deployment controller 将会平衡已存在的活动中的 ReplicaSet(有 Pod 的 ReplicaSet)和新加入的 replica。这被称为比例扩容。
例如,您正在运行中含有10个 replica 的 Deployment。maxSurge=3,maxUnavailable=2。
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 10 10 10 10 50s
您更新了一个镜像,而在集群内部无法解析。
$ kubectl set image deploy/nginx-deployment nginx=nginx:sometag
deployment "nginx-deployment" image updated
镜像更新启动了一个包含ReplicaSet nginx-deployment-1989198191的新的rollout,但是它被阻塞了,因为我们上面提到的maxUnavailable。
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 5 5 0 9s
nginx-deployment-618515232 8 8 8 1m
然后发起了一个新的Deployment扩容请求。autoscaler将Deployment的repllica数目增加到了15个。Deployment controller需要判断在哪里增加这5个新的replica。如果我们没有谁用比例扩容,所有的5个replica都会加到一个新的ReplicaSet中。如果使用比例扩容,新添加的replica将传播到所有的ReplicaSet中。大的部分加入replica数最多的ReplicaSet中,小的部分加入到replica数少的ReplciaSet中。0个replica的ReplicaSet不会被扩容。
在我们上面的例子中,3个replica将添加到旧的ReplicaSet中,2个replica将添加到新的ReplicaSet中。rollout进程最终会将所有的replica移动到新的ReplicaSet中,假设新的replica成为健康状态。
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
暂停和恢复deployment
可以在发出一次或多次更新前暂停一个deployment,然后在恢复它。这样您就能多次暂停和恢复 deployment ,在此期间进行一些修复工作,而不会发出不必要的rollout。
暂停deployment
$ kubectl rollout pause deployment/nginx-deployment
更新deployment中的镜像
$ kubectl set image deploy/nginx nginx=nginx:1.9.1
注意新的rollout启动
$ kubectl rollout history deploy/nginx
可以进行任意多次更新,例如更新使用的资源
$ kubectl set resources deployment nginx -c=nginx --limits=cpu=200m,memory=512Mi
Deployment 暂停前的初始状态将继续它的功能,而不会对 Deployment 的更新产生任何影响,只要 Deployment是暂停的。
最后恢复deployment
$ kubectl rollout resume deploy nginx
注:在恢复 deployment 之前无法回退一个已经暂停的 deployment。
deployment的状态
deployment在生命周期中有多种状态。在创建一个新的replicaset 的时候,它可以是progressing 状态,complete 状态,或者fail to progress状态。
进行中的deployment
Kubernetes 将执行过下列任务之一的 deployment 标记为progressing 状态:
- Deployment 正在创建新的replicaset过程中。
- Deployment 正在扩容一个已有的replicaset
- Deployment 正在缩容一个已有的replicaset
- 有新的可用的Pod出现
可以使用kubectl rollout status 命令监控deployment进度
完成deployment
- Kubernetes 将包括以下特征的 deployment 标记为 complete 状态:
- Deployment 最小可用。
- 所有与该deployment 相关的replica 都被更新到了指定的版本,也就是说完成了更新。
- 该deployment中没有旧的Pod存在。
可以用kubectl rollout status命令查看 Deployment 是否完成。如果 rollout 成功完成,kubectl rollout status将返回一个0值的 Exit Code
失败的deployment
您的 Deployment 在尝试部署新的 ReplicaSet 的时候可能卡住,用于也不会完成。这可能是因为以下几个因素引起的:
- 无效的引用
- 不可读的 probe failure
- 镜像拉取错误
- 权限不够
- 范围限制
- 程序运行时配置错误
下面的kubectl命令设置progressDeadlineSeconds 使 controller 在 Deployment 在进度卡住10分钟后报告:
$ kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
"nginx-deployment" patched
当超过截止时间后,Deployment controller 会在 Deployment 的 status.conditions中增加一条DeploymentCondition,它包括如下属性:
- Type=Progressing
- Status=False
- Reason=ProgressDeadlineExceeded
金丝雀deployment
想要使用deployment对部分应用或者服务器发布release,可以创建多个deployment,每个deployment对应一个release,
参照
https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments。
编写deployment spec
在所有kubernetes 配置中,deployment 也需要apiVersion ,kind和metadata这些配置项。
Pod Template
.spec.template 是 .spec中唯一要求的字段。
.spec.template 是 pod template. 它跟 Pod有一模一样的schema,除了它是嵌套的并且不需要apiVersion 和 kind字段。
另外为了划分Pod的范围,Deployment中的pod template必须指定适当的label(不要跟其他controller重复了,参考selector)和适当的重启策略。
.spec.template.spec.restartPolicy 可以设置为 Always , 如果不指定的话这就是默认配置。
Replicas
.spec.replicas 是可以选字段,指定期望的pod数量,默认是1。
Selector
.spec.selector是可选字段,用来指定 label selector ,圈定Deployment管理的pod范围。
在Pod的template跟.spec.template不同或者数量超过了.spec.replicas规定的数量的情况下,Deployment会杀掉label跟selector不同的Pod。
注意: 您不应该再创建其他label跟这个selector匹配的pod,或者通过其他Deployment,或者通过其他Controller,例如ReplicaSet和ReplicationController。否则该Deployment会被把它们当成都是自己创建的。Kubernetes不会阻止您这么做。
如果您有多个controller使用了重复的selector,controller们就会互相打架并导致不正确的行为。
策略
.spec.strategy 指定新的Pod替换旧的Pod的策略。 .spec.strategy.type 可以是"Recreate"或者是 “RollingUpdate”。"RollingUpdate"是默认值。
Recreate Deployment
.spec.strategy.type==Recreate时,在创建出新的Pod之前会先杀掉所有已存在的Pod。
2、Replication Controller
Replication controller工作原理
在用户定义范围内,如果Pod增多,则repolication controller会终止额外的Pod,如果减少,RC会创建新的Pod,始终保持在定义范围。例如:RC会在Pod维护(例如内核升级)后在节点上重新创建新的Pod。
注:
- Replication controller会替换由于某些原因而被删除或者终止的Pod,例如在节点故障或节点中断维护的情况下。因此,即使应用只需要一个Pod,也建议使用replication controller。
- RC跨多个Node节点监视多个Pod。
示例:
replication.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
下载示例文件然后运行:
$ kubectl create -f ./replication.yaml
replicationcontroller "nginx" created
检查ReplicationController状态:
$ kubectl describe replicationcontrollers/nginx
创建了三个pod:
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
列出属于ReplicationController的所有pod:
$ pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
删除replication controller及其Pods
使用kubectl delete命令删除 replication controller机器所有Pods。
当使用REST API或客户端库时,需要明确地执行这些步骤(将副本缩放为0,等待pod删除,然后删除ReplicationController)。
只删除replication controller
在删除replication controller时,可以不影响任何Pod
使用kubectl,为kubectl delete指定-cascade = false选项。
使用REST API或go客户端库时,只需删除ReplicationController对象即可。
原始文件被删除后,你可以创建一个新的ReplicationController来替换它。只要旧的和新.spec.selector 相匹配,那么新的将会采用旧的Pod。
Replication controller隔离Pod
可以通过更改标签来从replication controller的目标集中删除Pod
RC常用方式
- Rescheduling(重新规划)
- 扩展
- 滚动更新
- 多版本跟踪
- 使用ReplicationControllers与关联的Services
API对象
Replication controller是Kubernetes REST API中的顶级资源。
RC替代法
Replicaset
Replicaset 是支持新的set-based 选择器要求的下一代replicationcontroller。它主要用作deployment协调Pod创建、删除和更新。
deployment(推荐)
deployment是一个高级API对象,以类似的方式更新其底层的副本集和它们的Pods kubectl rolling-update。如果您希望使用这种滚动更新功能,建议您进行部署,因为kubectl rolling-update它们是声明式的,服务器端的,并具有其他功能。
Bare pods
与用户直接创建Pods的情况不同,replicationcontroller会替换由于某些原因而被删除或者终止的Pod。例如在节点故障或中断节点维护(例如内核升级)的情况下。因此,即使应用只需要一个pod,我们也建议使用ReplicationController。
参考文档:Kubernetes中文文档