Table of Contents
写在前面 #
前面的文章我们深入介绍了Pod的使用,包括Pod定义,Pod资源管理和服务质量,Pod健康检查,Pod存储管理,Pod调度,当Pod所在的node异常时,Pod无法自动恢复,因此Pod很少单独使用,一般以template的形式嵌套在控制器中使用,下来介绍kubernetes系列教程副本控制器Deployment,ReplicaSet,ReplicationController的使用。
1. 深入学习控制器 #
1.1 控制器概述 #
Pod是kubernetes所有运行应用或部署服务的基础,可以看作是k8s中运行的机器人,应用单独运行在Pod中不具备高级的特性,比如节点故障时Pod无法自动迁移,Pod多副本横向扩展,应用滚动升级RollingUpdate等,因此Pod一般不会单独使用,需要使用控制器来实现。
我们先看一个概念ReplicationController副本控制器,简称RC,副本控制是实现Pod高可用的基础,其通过定义副本的副本数replicas,当运行的Pod数量少于replicas时RC会自动创建Pod,当Pod数量多于replicas时RC会自动删除多余的Pod,确保当前运行的Pod和RC定义的副本数保持一致。
副本控制器包括Deployment,ReplicaSet,ReplicationController,StatefulSet等。其中常用有两个:Deployment和StatefulSet,Deployment用于无状态服务,StatefulSet用于有状态服务,ReplicaSet作为Deployment后端副本控制器,ReplicationController则是旧使用的副本控制器。
为了实现不同的功能,kubernetes中提供多种不同的控制器满足不同的业务场景,可以分为四类:
- Stateless application无状态化应用,如Deployment,ReplicaSet,RC等;
- Stateful application有状态化应用,需要保存数据状态,如数据库,数据库集群;
- Node daemon节点支撑守护,适用于在所有或部分节点运行Daemon,如日志,监控采集;
- Batch批处理任务,非长期运行服务,分为一次性运行Job和计划运行CronJob两种。
本文我们主要介绍无状态服务副本控制器的使用,包括Deployment,ReplicaSet和ReplicationController。
1.2 Deployment #
Deployment是实现无状态应用副本控制器,其通过declarative申明式的方式定义Pod的副本数,Deployment的副本机制是通过ReplicaSet实现,replicas副本的管理通过在ReplicaSet中添加和删除Pod,RollingUpdate通过新建ReplicaSet,然后逐步移除和添加ReplicaSet中的Pod数量,从而实现滚动更新,使用Deployment的场景如下:
- 滚动升级RollingUpdate,后台通过ReplicaSet实现
- 多副本replicas实现,增加副本(高负载)或减少副本(低负载)
- 应用回滚Rollout,版本更新支持回退
1.2.1 Deployment定义 #
\1. 我们定义一个Deployment,副本数为3,Pod以模版Template的形式封装在Deployment中,为了结合之前Pod学习内容,我们增加了resource和健康检查的定义,具体实现参考前面介绍的文章。
1[root@node-1 happylau]# cat deployment-demo.yaml
2apiVersion: apps/v1
3kind: Deployment
4metadata: #Deployment的元数据信息,包含名字,标签
5 name: deployment-nginx-demo
6 labels:
7 app: nginx
8 rc: deployment
9 annotations:
10 kubernetes.io/replicationcontroller: Deployment
11 kubernetes.io/description: "ReplicationController Deployment Demo"
12spec:
13 replicas: 3 #副本数量,包含有3个Pod副本
14 selector: #标签选择器,选择管理包含指定标签的Pod
15 matchLabels:
16 app: nginx
17 rc: deployment
18 template: #如下是Pod的模板定义,没有apiVersion,Kind属性,需包含metadata定义
19 metadata: #Pod的元数据信息,必须包含有labels
20 labels:
21 app: nginx
22 rc: deployment
23 spec: #spec指定容器的属性信息
24 containers:
25 - name: nginx-deployment
26 image: nginx:1.7.9
27 imagePullPolicy: IfNotPresent
28 ports: #容器端口信息
29 - name: http-80-port
30 protocol: TCP
31 containerPort: 80
32 resources: #资源管理,requests请求资源,limits限制资源
33 requests:
34 cpu: 100m
35 memory: 128Mi
36 limits:
37 cpu: 200m
38 memory: 256Mi
39 livenessProbe: #健康检查器livenessProbe,存活检查
40 httpGet:
41 path: /index.html
42 port: 80
43 scheme: HTTP
44 initialDelaySeconds: 3
45 periodSeconds: 5
46 timeoutSeconds: 2
47 readinessProbe: #健康检查器readinessProbe,就绪检查
48 httpGet:
49 path: /index.html
50 port: 80
51 scheme: HTTP
52 initialDelaySeconds: 3
53 periodSeconds: 5
54 timeoutSeconds: 2
Deployment字段说明:
- deployment基本属性,包括apiVersion,Kind,metadata和spec,其中,deployment.metdata指定名称和标签内容,deployment.spec指定部署组的属性信息;
- deployment属性信息包含有replicas,Selector和template,其中replicas指定副本数目,Selector指定管理的Pod标签,template为定义Pod的模板,Deployment通过模板创建Pod;
- deployment.spec.template为Pod定义的模板,和Pod定义不太一样,template中不包含apiVersion和Kind属性,要求必须有metadata,deployment.spec.template.spec为容器的属性信息,其他定义内容和Pod一致。
\2. 生成Deployment,创建时加一个--record参数,会在annotation中记录deployment.kubernetes.io/revision版本
1[root@node-1 happylau]# kubectl apply -f deployment-demo.yaml --record
2deployment.apps/deployment-nginx-demo created
\3. 查看Deployment列表,运行时自动下载镜像,如下已运行了3个副本
1[root@node-1 happylau]# kubectl get deployments deployment-nginx-demo
2NAME READY UP-TO-DATE AVAILABLE AGE
3deployment-nginx-demo 3/3 3 3 2m37s
4
5NAME代表名称,metadata.name字段定义
6READY代表Pod的健康状态,前面值是readiness,后面是liveness
7UP-TO-DATE代表更新,用于滚动升级
8AVAILABLE代表可用
9AGE创建至今运行的时长
\4. 查看Deployment的详情,可以看到Deployment通过一个deployment-nginx-demo-866bb6cf78 replicaset副本控制器控制Pod的副本数量

\5. 查看replicaset的详情信息,通过Events可查看到deployment-nginx-demo-866bb6cf78创建了三个Pod

\6. 查看Pod详情,最终通过Pod定义的模版创建container,资源定义,健康检查等包含在Pod定义的模版中

通过上面的实战演练我们可得知Deployment的副本控制功能是由replicaset实现,replicaset生成Deployment中定义的replicas副本的数量,即创建多个副本,如下图所示:

1.2.2 Deployment扩容 #
当业务比较繁忙时可以通过增加副本数,增加副本数是通过yaml文件中的replicas控制的,当设置了replias后,Deployment控制器会自动根据当前副本数目创建所需的Pod数,这些pod会自动加入到service中实现负载均衡,相反减少副本数,这些pod会自动从service中删除。

\1. 将deployment的副本数扩容至4个,可通过修改yaml文件的replicas个数或者通过scale命令扩展。
1[root@node-1 ~]# kubectl scale --replicas=4 deployment deployment-nginx-demo
2deployment.extensions/deployment-nginx-demo scaled
\2. 查看Deployment副本数量,已增加至4个副本
1[root@node-1 ~]# kubectl get deployments
2NAME READY UP-TO-DATE AVAILABLE AGE
3deployment-nginx-demo 4/4 4 4 77m
\3. 副本的扩容是如何实现的呢?我们查看replicaset的详情信息观察,增加副本的个数是通过replicaset来扩容,通过模版复制新的Pod

\4. 副本缩容
1[root@node-1 ~]# kubectl scale --replicas=2 deployment deployment-nginx-demo
2deployment.extensions/deployment-nginx-demo scaled
3
4[root@node-1 ~]# kubectl get deployments deployment-nginx-demo
5NAME READY UP-TO-DATE AVAILABLE AGE
6deployment-nginx-demo 2/2 2 2 7h41m

通过上面的操作演练我们可以得知:Deployment的扩容是通过ReplicaSet的模版创建Pod或删除Pod实现,scale是手动扩展实现副本的机制,kubernetes还提供了另外一种副本自动扩容机制horizontalpodautoscalers(Horizontal Pod Autoscaling),即通过定义CPU的利用率实现自动的横向扩展,由于需要依赖于监控组件,后续我们再做介绍。
1.2.3 滚动更新 #
Deployment支持滚动更新,默认创建Deployment后会增加滚动更新的策略,通过逐步替代replicas中的pod实现更新无服务中断(需要结合service),如下图所示:将一个deployment副本数为3的应用更新,先更新10.0.0.6 pod,更新pod应用,替换新的ip,然后加入到service中,以此类推再继续更新其他pod,从而实现滚动更新,不影响服务的升级。

通过类型为:RollingUpdate,每次更新最大的数量maxSurge是replicas总数的25%,最大不可用的数量maxUnavailable为25%,如下是通过kubectl get deployments deployment-nginx-demo -o yaml查看滚动更新相关的策略。
1spec:
2 progressDeadlineSeconds: 600
3 replicas: 3
4 revisionHistoryLimit: 10
5 selector:
6 matchLabels:
7 app: nginx
8 rc: deployment
9 strategy: #strategy定义的是升级的策略,类型为RollingUpdate
10 rollingUpdate:
11 maxSurge: 25%
12 maxUnavailable: 25%
13 type: RollingUpdate
\1. 滚动更新是当pod.template中定义的相关属性变化,如下将镜像更新到1.9.1,通过--record会记录操作命令
1[root@node-1 ~]# kubectl set image deployments deployment-nginx-demo nginx-deployment=nginx:1.9.1 --record
2deployment.extensions/deployment-nginx-demo image updated
\2. 查看滚动升级的状态(由于第一次nginx的镜像写错了,容器下载镜像失败,写成nignx,导致修改后有两次record)
1[root@node-1 happylau]# kubectl rollout status deployment deployment-nginx-demo
2deployment "deployment-nginx-demo" successfully rolled out
3
4查看滚动升级版本,REVSISION代表版本号:
5[root@node-1 happylau]# kubectl rollout history deployment deployment-nginx-demo
6deployment.extensions/deployment-nginx-demo
7REVISION CHANGE-CAUSE
81 <none>
92 kubectl set image deployments deployment-nginx-demo nginx-deployment=nignx:1.9.1 --record=true
103 kubectl set image deployments deployment-nginx-demo nginx-deployment=nignx:1.9.1 --record=true
\3. 观察Deployment的升级过程,新创建一个RS deployment-nginx-demo-65c8c98c7b,逐渐将旧RS中的pod替换,直至旧的RS deployment-nginx-demo-866bb6cf78上的副本数为0.

\4. 查看RS的列表,可以看到新的RS的副本数为2,其他RS副本数为0
1[root@node-1 ~]# kubectl get replicasets
2NAME DESIRED CURRENT READY AGE
3deployment-nginx-demo-65c8c98c7b 2 2 2 21m #新的RS,REVSION为3
4deployment-nginx-demo-6cb65f58c6 0 0 0 22m #镜像写错的RS,REVISON为2
5deployment-nginx-demo-866bb6cf78 0 0 0 40m #旧的RS,对应REVSION为1
\5. 测试版本升级是否成功
1[root@node-1 ~]# kubectl get pods -o wide
2NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
3deployment-nginx-demo-65c8c98c7b-bzql9 1/1 Running 0 25m 10.244.1.58 node-2 <none> <none>
4deployment-nginx-demo-65c8c98c7b-vrjhp 1/1 Running 0 25m 10.244.2.72 node-3 <none> <none>
5[root@node-1 ~]# curl -I http://10.244.2.72
6HTTP/1.1 200 OK
7Server: nginx/1.9.1 #镜像的版本成功更新
8Date: Mon, 28 Oct 2019 15:28:49 GMT
9Content-Type: text/html
10Content-Length: 612
11Last-Modified: Tue, 26 May 2015 15:02:09 GMT
12Connection: keep-alive
13ETag: "55648af1-264"
14Accept-Ranges: bytes
1.2.4 版本回退 #
如果版本不符合预期,kubernetes提供回退的功能,和滚动更新一样,回退的功能Deployment将替换到原始的RS上,即逐步将Pod的副本替换到旧的RS上.
\1. 执行回滚,回退到REVISON版本为1
1[root@node-1 ~]# kubectl rollout undo deployment deployment-nginx-demo --to-revision=1
2deployment.extensions/deployment-nginx-demo rolled back
\2. 查看Deployment的回退状态和历史版本
1[root@node-1 ~]# kubectl rollout status deployment deployment-nginx-demo
2deployment "deployment-nginx-demo" successfully rolled out
3
4[root@node-1 ~]# kubectl rollout history deployment deployment-nginx-demo
5deployment.extensions/deployment-nginx-demo
6REVISION CHANGE-CAUSE
72 kubectl set image deployments deployment-nginx-demo nginx-deployment=nignx:1.9.1 --record=true
83 kubectl set image deployments deployment-nginx-demo nginx-deployment=nignx:1.9.1 --record=true
94 <none>
\3. 查看Deployment的详情,可以看到RS已经会退到原始的RS了

\4. 测试nginx的版本
1[root@node-1 ~]# kubectl get pods -o wide
2NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
3deployment-nginx-demo-866bb6cf78-9thtn 1/1 Running 0 3m42s 10.244.1.59 node-2 <none> <none>
4deployment-nginx-demo-866bb6cf78-ws2hx 1/1 Running 0 3m48s 10.244.2.73 node-3 <none> <none>
5
6
7#测试版本
8[root@node-1 ~]# curl -I http://10.244.1.59
9HTTP/1.1 200 OK
10Server: nginx/1.7.9 #回退到1.7.9版本
11Date: Mon, 28 Oct 2019 15:36:07 GMT
12Content-Type: text/html
13Content-Length: 612
14Last-Modified: Tue, 23 Dec 2014 16:25:09 GMT
15Connection: keep-alive
16ETag: "54999765-264"
17Accept-Ranges: bytes
小结:通过上面的操作演练可知,Deployment是通过ReplicaSet实现Pod副本数的管理(扩容或减少副本数),滚动更新是通过新建RS,将Pod从旧的RS逐步更新到新的RS上;相反,回滚版本将会退到指定版本的ReplicaSet上。
1.3 ReplicaSet #
ReplicaSet副本集简称RS,用于实现副本数的控制,通过上面的学习我们可以知道Deployment实际是调用ReplicaSet实现副本的控制,RS不具备滚动升级和回滚的特性,一般推荐使用Deployment,ReplicaSet的定义和Deployment差不多,如下:
\1. 定义ReplicaSet
1[root@node-1 happylau]# cat replicaset-demo.yaml
2apiVersion: extensions/v1beta1
3kind: ReplicaSet
4metadata:
5 name: replicaset-demo
6 labels:
7 controller: replicaset
8 annotations:
9 kubernetes.io/description: "Kubernetes Replication Controller Replication"
10spec:
11 replicas: 3 #副本数
12 selector: #Pod标签选择器
13 matchLabels:
14 controller: replicaset
15 template: #创建Pod的模板
16 metadata:
17 labels:
18 controller: replicaset
19 spec: #容器信息
20 containers:
21 - name: nginx-replicaset-demo
22 image: nginx:1.7.9
23 imagePullPolicy: IfNotPresent
24 ports:
25 - name: http-80-port
26 protocol: TCP
27 containerPort: 80
\2. 创建RS并查看RS列表
1[root@node-1 happylau]# kubectl apply -f replicaset-demo.yaml
2replicaset.extensions/replicaset-demo created
3
4[root@node-1 happylau]# kubectl get replicasets replicaset-demo
5NAME DESIRED CURRENT READY AGE
6replicaset-demo 3 3 3 15s
\3. 扩展副本数至4个
1[root@node-1 happylau]# kubectl scale --replicas=4 replicaset replicaset-demo
2replicaset.extensions/replicaset-demo scaled
3[root@node-1 happylau]# kubectl get replicasets replicaset-demo
4NAME DESIRED CURRENT READY AGE
5replicaset-demo 4 4 4 76s
\4. 减少副本数至2个
1[root@node-1 happylau]# kubectl scale --replicas=2 replicaset replicaset-demo
2replicaset.extensions/replicaset-demo scaled
3[root@node-1 happylau]# kubectl get replicasets replicaset-demo
4NAME DESIRED CURRENT READY AGE
5replicaset-demo 2 2 2 114s
\5. 镜像版本升级,验证得知不具备版本升级的能力
1[root@node-1 happylau]# kubectl set image replicasets replicaset-demo nginx-replicaset-demo=nginx:1.9.1
2replicaset.extensions/replicaset-demo image updated #命令执行成功了

ReplicaSet小结:通过上面的演示可以知道,RS定义和Deployment类似,能实现副本的控制,扩展和缩减,Deployment是更高层次的副本控制器,ReplicaSet主要为Deployment的副本控制器和滚动更新机制,ReplicaSet本身无法提供滚动更新的能力。
1.4 ReplicationController #
ReplicationController副本控制器简称RC,是kubernetes中最早的副本控制器,RC是ReplicaSet之前的版本,ReplicationController提供副本控制能力,其定义方式和Deployment,ReplicaSet相类似,如下:
\1. 定义ReplicationController
1[root@node-1 happylau]# cat rc-demo.yaml
2apiVersion: v1
3kind: ReplicationController
4metadata:
5 name: rc-demo
6 labels:
7 controller: replicationcontroller
8 annotations:
9 kubernetes.io/description: "Kubernetes Replication Controller Replication"
10spec:
11 replicas: 3
12 selector: #不能使用matchLables字符集模式
13 controller: replicationcontroller
14 template:
15 metadata:
16 labels:
17 controller: replicationcontroller
18 spec:
19 containers:
20 - name: nginx-rc-demo
21 image: nginx:1.7.9
22 imagePullPolicy: IfNotPresent
23 ports:
24 - name: http-80-port
25 protocol: TCP
26 containerPort: 80
\2. 生成RC并查看列表
1[root@node-1 happylau]# kubectl apply -f rc-demo.yaml
2replicationcontroller/rc-demo created
3
4[root@node-1 happylau]# kubectl get replicationcontrollers
5NAME DESIRED CURRENT READY AGE
6rc-demo 3 3 3 103s
7
8#查看详情
9[root@node-1 happylau]# kubectl describe replicationcontrollers rc-demo
10Name: rc-demo
11Namespace: default
12Selector: controller=replicationcontroller
13Labels: controller=replicationcontroller
14Annotations: kubectl.kubernetes.io/last-applied-configuration:
15 {"apiVersion":"v1","kind":"ReplicationController","metadata":{"annotations":{"kubernetes.io/description":"Kubernetes Replication Controlle...
16 kubernetes.io/description: Kubernetes Replication Controller Replication
17Replicas: 3 current / 3 desired
18Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
19Pod Template:
20 Labels: controller=replicationcontroller
21 Containers:
22 nginx-rc-demo:
23 Image: nginx:1.7.9
24 Port: 80/TCP
25 Host Port: 0/TCP
26 Environment: <none>
27 Mounts: <none>
28 Volumes: <none>
29Events:
30 Type Reason Age From Message
31 ---- ------ ---- ---- -------
32 Normal SuccessfulCreate 113s replication-controller Created pod: rc-demo-hm8s9
33 Normal SuccessfulCreate 113s replication-controller Created pod: rc-demo-xnfht
34 Normal SuccessfulCreate 113s replication-controller Created pod: rc-demo-lfhc9
3.副本扩容至4个
1[root@node-1 happylau]# kubectl scale --replicas=4 replicationcontroller rc-demo
2replicationcontroller/rc-demo scaled
3[root@node-1 happylau]# kubectl get replicationcontrollers
4NAME DESIRED CURRENT READY AGE
5rc-demo 4 4 4 3m23s
\4. 副本缩容至2个
1[root@node-1 happylau]# kubectl scale --replicas=2 replicationcontroller rc-demo
2replicationcontroller/rc-demo scaled
3[root@node-1 happylau]# kubectl get replicationcontrollers
4NAME DESIRED CURRENT READY AGE
5rc-demo 2 2 2 3m51s
写在最后 #
本文介绍了kubernetes中三个副本控制器:Deployment,ReplicaSet和ReplicationController,当前使用最广泛的是Deployment,ReplicaSet为Deployment提供滚动更新机制,RC当前是旧版的副本控制器,当前已废弃,推荐使用Deployment控制器,具备副本控制器,扩展副本,缩减副本,滚动升级和回滚等高级能力。
参考文献 #
Deployment:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
ReplicaSet:https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
ReplicationController:[https://kubernetes.io/docs/concepts/workloads/controllers/
『 转载 』该文章来源于网络,侵删。