Deployment和rc的对比
首先RC是Kubernetes的一个核心概念,当我们把应用部署到集群之后,需要保证应用能够持续稳定的运行,RC就是这个保证的关键,主要功能如:
- 确保Pod数量: 它会确保Kubernetes中有指定数量的Pod在运行,如果少于指定数量的Pod,RC就会创建新的,反之这会删除多余的,保证Pod的副本数量不变。
- 确保Pod健康: 当Pod不健康,比如运行出错了,总之无法提供正常服务时,RC也会杀死不健康的Pod,重新创建新的。
- 弹性伸缩: 在业务高峰或者低峰的时候,可以用过RC来动态的调整Pod数量来提供资源的利用率,当然我们也提到过如果使用HPA这种资源对象的话可以做到自动伸缩。
- 滚动升级: 滚动升级是一种平滑的升级方式,通过逐步替换的策略,保证整体系统的稳定性
Deployment同样也是Kubernetes系统的一个核心概念,主要职责和RC一样的都是保证Pod的数量和健康,二者大部分功能都是完全一致的,我们可以看成是一个升级版的RC控制器,Deployment具备的新特性
- RC的全部功能: Deployment具备上面描述的RC的全部功能
- 事件和状态查看: 可以查看Deployment的升级详细进度和状态
- 回滚: 当升级Pod的时候如果出现问题,可以使用回滚操作回滚到之前的任一版本
- 版本记录: 每一次对Deployment的操作,都能够保存下来,这也是保证可以回滚到任一版本的基础
- 暂停和启动: 对于每一次升级都能够随时暂停和启动
对比: Deployment作为新一代的RC,在功能上更为丰富,同时官方也是推荐使用Deployment来管理Pod,比如一些官方组件kube-dns、kube-proxy也都是使用的Deployment来管理的,所以最好使用Deployment来管理Pod。
Deployment 介绍
Deployment拥有多个Replica Set,而一个Replica Set拥有一个或多个Pod。一个Deployment控制多个rs主要是为了支持回滚机制,每当Deployment操作时,Kubernetes会重新生成一个Replica Set并保留,以后有需要的话就可以回滚至之前的状态。
实例: 创建一个Deployment,它创建了一个Replica Set来启动3个nginx pod,yaml文件如下:
nginx-deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$ cat > nginx-deployment.yaml <<EOF
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
labels:
k8s-app: nginx-demo
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
EOF执行创建
1
2$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deploy created执行一下命令查看刚刚创建的Deployment
1
2
3
4
5
6
7
8$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 0/3 3 0 12s
# 再次执行上面命令
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 1/3 3 1 35s可以看到Deployment已经创建了1个Replica Set了,执行下面的命令查看rs和pod
1
2
3
4
5
6
7
8
9
10$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-6dd86d77d 3 3 2 70s
#
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deploy-6dd86d77d-9n9vf 1/1 Running 0 99s app=nginx,pod-template-hash=6dd86d77d
nginx-deploy-6dd86d77d-bhrsk 0/1 ContainerCreating 0 99s app=nginx,pod-template-hash=6dd86d77d
nginx-deploy-6dd86d77d-jdnrh 1/1 Running 0 99s app=nginx,pod-template-hash=6dd86d77d
上面的Deployment的yaml文件中的replicas:3将会保证我们始终有3个POD在运行。
滚动升级
修改之前使用的nginx-deployment.yaml文件中的nginx镜像修改为nginx:1.13.3,然后在spec下面添加滚动升级策略:
nginx-deploments.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
labels:
k8s-app: nginx-demo
spec:
replicas: 3
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.13.3
ports:
- containerPort: 80minReadySeconds:
- 滚动升级时5s后认为该pod就绪
- 如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了
- 如果没有设置该值,在某些极端情况下可能会造成服务不正常运行
rollingUpdate:
- 于replicas为3,则整个升级,pod个数在2-4个之间
maxSurge:
- 升级过程中最多可以比原先设置多出的POD数量
- 例如:maxSurage=1,replicas=3,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有3+1个POD。
maxUnavaible:
- 升级过程中最多有多少个POD处于无法提供服务的状态
- 当maxSurge不为0时,该值也不能为0
- 例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态。
执行创建
1
2$ kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deploy configured查看状态
1
2
3
4
5
6
7
8
9# 使用rollout命令
$ kubectl rollout status deployment/nginx-deploy
Waiting for deployment "nginx-deploy" rollout to finish: 2 out of 3 new replicas have been updated...
# 暂停升级
$ kubectl rollout pause deployment deployment/nginx-deploy
# 继续升级
$ kubectl rollout resume deployment deployment/nginx-deploy
升级结束后,继续查看rs的状态
1 | $ kubectl get rs |
根据AGE我们可以看到离我们最近的当前状态是:3,和我们的yaml文件是一致的,证明升级成功了。用describe命令可以查看升级的全部信息:
1 | $ kubectl describe deploy nginx-deploy |
回滚Deployment
前面已经滚动平滑的升级Deployment,但是如果升级后的POD出了问题该怎么办?我们能够想到的最好最快的方式当然是回退到上一次能够提供正常工作的版本,Deployment就为我们提供了回滚机制。
- 首先,查看Deployment的升级历史:
1
2
3
4
5$ kubectl rollout history deployment nginx-deploy
deployment.extensions/nginx-deploy
REVISION CHANGE-CAUSE
1 <none>
2 <none>
从上面的结果可以看出在执行Deployment升级的时候最好带上record参数,便于我们查看历史版本信息。kubectl apply --filename=nginx-deployment.yaml --record=true
默认情况下,所有通过kubectl xxxx –record都会被kubernetes记录到etcd进行持久化,这无疑会占用资源,最重要的是,时间久了,当你kubectl get rs时,会有成百上千的垃圾RS返回,这对于运维来说维护很不便利,
当我们在上生产时,我们最好通过设置Deployment的.spec.revisionHistoryLimit来限制最大保留的revision number,比如15个版本,回滚的时候一般只会回滚到最近的几个版本就足够了。其实rollout history中记录的revision都和ReplicaSets一一对应。如果手动delete某个ReplicaSet,对应的rollout history就会被删除,也就是还说你无法回滚到这个revison。rollout history和ReplicaSet的对应关系,可以在kubectl describe rs $RSNAME返回的revision字段中得到,这里的revision就对应着rollout history返回的revison。
yaml例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26$ cat nginx-deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
labels:
k8s-app: nginx-demo
spec:
replicas: 3
minReadySeconds: 5
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.13.3
ports:
- containerPort: 80可以使用下面的命令查看单个revison的信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14$ kubectl rollout history deployment nginx-deploy --revision=2
deployment.extensions/nginx-deploy with revision #2
Pod Template:
Labels: app=nginx
pod-template-hash=799d666985
Annotations: kubernetes.io/change-cause: kubectl apply --filename=nginx-deployment.yaml --record=true
Containers:
nginx:
Image: nginx:1.13.3
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>直接回退到当前版本的前一个版本:
1
2
3
4
5
6$ kubectl rollout undo deployment nginx-deploy
deployment.extensions/nginx-deploy rolled back
# 也可以用revision回退到指定的版本
$ kubectl rollout undo deployment nginx-deploy --to-revision=1
deployment.extensions/nginx-deploy rolled back查看Deployment现在的状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 2/3 3 2 56m
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-6dd86d77d 1 1 1 56m
nginx-deploy-799d666985 3 3 1 46m
$ kubectl rollout status deployment/nginx-deploy
Waiting for deployment "nginx-deploy" rollout to finish: 2 of 3 updated replicas are available...
Waiting for deployment "nginx-deploy" rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deploy" successfully rolled out
# 完成后查看
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-6dd86d77d 0 0 0 57m
nginx-deploy-799d666985 3 3 3 47m
Deployment名词解释
1 | apiVersion: apps/v1 # 指定api版本,此值必须在kubectl api-versions中 |