在旧版本的kubernetes中,只有ReplicationController对象,它的主要作用是确保Pod以指定的副本数运行,即如果有容器异常退出,会自动创建新的Pod来替换;而异常多出来的容器会被自动回收。可以说,通过ReplicationController,kubernetes实现了集群的高可用性。
在新版本的kubernetes中,建议使用ReplicaSet(简称为RS)来替代ReplicationController;ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的selector(ReplicationController 仅支持等式)。
1、ReplicaSet的创建
ReplicaSet也是kubernetes的对象,创建方式与Pod类似。通过yaml或json描述文件来定义一个ReplicaSet对象,一个典型的RS描述文件如下:
# rs-demo.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
release: cannary
template:
metadata:
name: myapp-pod
labels:
app: myapp
release: cannary
environment: qa
spec:
containers:
- name: myapp-container
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
下面简要解释一下上述RS描述文件中的关键点:
- kind:指定新建的对象类型。
- spec.replicas:指定受此RS管理的Pod需要运行的副本数。
- spec.selector:指定需要管理的Pod的label。这儿将spec.selector设置为app: myapp和release: cannary,意味着所有包含label为app: myapp和release: cannary的Pod都将被这个RS管理。
- template:用于定义Pod,包括Pod的名字,Pod拥有的label以及Pod中运行的应用。
通过kubectl create
创建此RS,可看到分别在node02和node03节点创建了pod,并且pod也打上了app=myapp,environment=qa,release=cannary标签
$ kubectl create -f rs-demo.yaml
replicaset.apps/myapp created
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
myapp-s8wh7 1/1 Running 0 84m 10.244.1.3 node02 <none>
myapp-vl4xs 1/1 Running 0 88m 10.244.2.2 node03 <none>
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-s8wh7 1/1 Running 0 81s app=myapp,environment=qa,release=cannary
myapp-vl4xs 1/1 Running 0 5m36s app=myapp,environment=qa,release=cannary
当使用kubectl delete
删除其中一个pod后,会立即重新创建一个新的pod,以确保pod以指定的副本数运行
$ kubectl delete pods myapp-qgf2b
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-bzzql 0/1 ContainerCreating 0 1s
myapp-qgf2b 1/1 Terminating 0 39s
myapp-vl4xs 1/1 Running 0 141m
2、ReplicaSet的删除
使用kubectl delete
命令可以删除RS以及它管理的Pod。在Kubernetes删除RS前,会将RS的replica调整为0,等待所有的Pod被删除后,在执行RS对象的删除。
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp 2 2 2 146m
$ kubectl delete rs myapp
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-bzzql 0/1 Terminating 0 6m4s
myapp-vl4xs 0/1 Terminating 0 147m
如果希望仅仅删除RS对象(保留Pod),请使用kubectl delete命令时添加--cascade=false选项。
3、ReplicaSet的伸缩与更新
通过修改spec.replicas的值可以实时修改RS运行的Pod数量。这儿将rs-demo.yaml的replica修改为5,可见pod动态扩容为5个副本。
$ kubectl edit rs myapp
...
spec:
replicas: 5
selector:
matchLabels:
app: myapp
release: cannary
...
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-9w2mz 1/1 Running 0 2s
myapp-b9flt 1/1 Running 0 4m44s
myapp-fjts8 1/1 Running 0 4m44s
myapp-rqsvp 1/1 Running 0 2s
myapp-xcc92 1/1 Running 0 2s
动态更新pod容器的镜像版本为v2,但只有新创建的pod副本才会更新为新的镜像版本,旧的pod副本还是使用原来的镜像版本运行。
$ kubectl edit rs myapp
...
spec:
containers:
- image: ikubernetes/myapp:v2
imagePullPolicy: IfNotPresent
name: myapp-container
...
$ kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
myapp 5 5 5 10m myapp-container ikubernetes/myapp:v2 app=myapp,release=cannary
这样,我们就需要手动去删除旧的pod副本,很显然,这样在实际的生产中是不适用的,庆幸的是,kubernetes为我们提供了Deployment对象来来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如 ReplicaSet 不支持 rolling-update 但 Deployment 支持),并且Deployment还支持版本记录、回滚、暂停升级等高级特性。