ReplicaSet简称RS,随着Kubernetes的高速发展,官方已经推荐我们使用RS和Deployment来代替RC了,实际上RS和RC的功能基本一致,目前唯一的一个区别就是RC只支持基于等式的selector(env=dev或environment!=qa),但RS还支持基于集合的selector,这对复杂的运维管理就非常方便了。
kubectl命令行工具中关于RC的大部分命令同样适用于我们的RS资源对象。不过我们也很少会去单独使用RS,它主要被Deployment这个更加高层的资源对象使用,除非用户需要自定义升级功能或根本不需要升级Pod,在一般情况下,我们推荐使用Deployment而不直接使用Replica Set。
下面我们简单定义一个ReplicaSet的YAML文件:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-set
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
从这个YAML文件中,我们可以看到其定义了一个Pod标签为app:nginx的Pod的副本数为2。
然后创建一个YAML文件:
# kubectl apply -f rs-myapp.yaml
然后查看ReplicaSet的状态:
[root@master rs]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-set 2 2 2 26s
然后看Pod的状态:
[root@master rs]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-set-n6dxl 1/1 Running 0 2m37s
nginx-set-p2lxb 1/1 Running 0 2m37s
从上面可以看到,我们在YAML文件中定义了Pod template中定义了Pod的名字,但是我们在查看Pod的时候发现其并不是我们定义的Pod名,而是RS的名字加随机字符串。
除了以上,RS还支持水平扩缩和版本更新,对于水平扩缩,我们可以用kubectl scale和kubectl edit来直接修改,也可以修改上面定义的YAML文件再使用kubectl apply来使其生效。
我们使用kubectl edit来修改,使用这个修改会立即生效,如下:
# kubectl edit rs nginx-set
kind: ReplicaSet
....
spec:
replicas: 3
selector:
....
保存退出就会立即生效replicaset.extensions/nginx-set edited。然后我们查看Pod的数量:
replicaset.extensions/nginx-set edited
[root@master rs]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-set-n6dxl 1/1 Running 0 10m
nginx-set-p2lxb 1/1 Running 0 10m
nginx-set-pz2mc 1/1 Running 0 33s
缩容的做法一样。我们也可以对镜像版本进行升级,修改方法同上,我们还是用kubectl edit来修改:
# kubectl edit rs nginx-set
....
spec:
containers:
- image: nginx:1.8
imagePullPolicy: IfNotPresent
如上我们将nginx的版本从1.7.9升级到1.8,我们这时查看RS的信息如下:
[root@master rs]# kubectl get rs nginx-set -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
nginx-set 3 3 3 14m nginx nginx:1.8 app=nginx
我们发现在RS层,nginx的版本已经更新了,但是正在运行的Pod里也已经更新了吗?我们kubectl describe一下pod,如下:
[root@master rs]# kubectl describe pod nginx-set-n6dxl
......
Controlled By: ReplicaSet/nginx-set
Containers:
nginx:
Container ID: docker://68e20a9c102fa4385cf5fc082e9767dc5a6011020bc19a759f3f0a853389f7dc
Image: nginx:1.7.9
......
我们发现Pod的镜像版本还是1.7.9,并没有随着我们更新RS而立即更新Pod。这是因为在RS控制器下,Pod不会自己去创建删除,也就是不会滚动更新,要实现滚动更新就要用Kubernetes的另外一个控制器:Deployment。那么对于RS控制器来说,我们想升级Pod的镜像应该怎么做呢?
我们可以删除Pod,然后通过RS控制器再新创建一个Pod,这时候的Pod版本就会更新,如下:
[root@master rs]# kubectl delete pod nginx-set-n6dxl
pod "nginx-set-n6dxl" deleted
然后我们查看通过RS控制器新创建的Pod的nginx版本信息,如下:
[root@master rs]# kubectl describe pod nginx-set-znlcl
......
Containers:
nginx:
Container ID: docker://2005822f90324cc33478002fcf2bec82d1f1efc5671d688d5913d04e17df6811
Image: nginx:1.8
.......
我们看到nginx的版本已经更新了,其他的Pod版本还是1.7.9。
这种版本更新需要大量的人为干预,这不符合我们期望,所以Kubernetes就推出了另外一个控制器Deployment,它是工作在RS之上的,除了有RS的功能之外,还有滚动更新等功能。
最后我们总结下关于RC/RS的一些特性和作用:
- 大部分情况下,我们可以通过定义一个RC实现的Pod的创建和副本数量的控制
- RC中包含一个完整的Pod定义模块(不包含apiversion和kind)
- RC是通过label selector机制来实现对Pod副本的控制的
- 通过改变RC里面的Pod副本数量,可以实现Pod的扩缩容功能
- 通过改变RC里面的Pod模板中镜像版本,可以实现Pod的滚动升级功能(但是不支持一键回滚,需要用相同的方法去修改镜像地址)