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文件:

    1. apiVersion: apps/v1
    2. kind: ReplicaSet
    3. metadata:
    4. name: nginx-set
    5. labels:
    6. app: nginx
    7. spec:
    8. replicas: 2
    9. selector:
    10. matchLabels:
    11. app: nginx
    12. template:
    13. metadata:
    14. name: nginx
    15. labels:
    16. app: nginx
    17. spec:
    18. containers:
    19. - name: nginx
    20. image: nginx:1.7.9

    从这个YAML文件中,我们可以看到其定义了一个Pod标签为app:nginx的Pod的副本数为2。

    然后创建一个YAML文件:

    1. # kubectl apply -f rs-myapp.yaml

    然后查看ReplicaSet的状态:

    1. [root@master rs]# kubectl get rs
    2. NAME DESIRED CURRENT READY AGE
    3. nginx-set 2 2 2 26s

    然后看Pod的状态:

    1. [root@master rs]# kubectl get pods
    2. NAME READY STATUS RESTARTS AGE
    3. nginx-set-n6dxl 1/1 Running 0 2m37s
    4. 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来修改,使用这个修改会立即生效,如下:

    1. # kubectl edit rs nginx-set
    2. kind: ReplicaSet
    3. ....
    4. spec:
    5. replicas: 3
    6. selector:
    7. ....

    保存退出就会立即生效replicaset.extensions/nginx-set edited。然后我们查看Pod的数量:

    1. replicaset.extensions/nginx-set edited
    2. [root@master rs]# kubectl get pods
    3. NAME READY STATUS RESTARTS AGE
    4. nginx-set-n6dxl 1/1 Running 0 10m
    5. nginx-set-p2lxb 1/1 Running 0 10m
    6. nginx-set-pz2mc 1/1 Running 0 33s

    缩容的做法一样。我们也可以对镜像版本进行升级,修改方法同上,我们还是用kubectl edit来修改:

    1. # kubectl edit rs nginx-set
    2. ....
    3. spec:
    4. containers:
    5. - image: nginx:1.8
    6. imagePullPolicy: IfNotPresent

    如上我们将nginx的版本从1.7.9升级到1.8,我们这时查看RS的信息如下:

    1. [root@master rs]# kubectl get rs nginx-set -o wide
    2. NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
    3. nginx-set 3 3 3 14m nginx nginx:1.8 app=nginx

    我们发现在RS层,nginx的版本已经更新了,但是正在运行的Pod里也已经更新了吗?我们kubectl describe一下pod,如下:

    1. [root@master rs]# kubectl describe pod nginx-set-n6dxl
    2. ......
    3. Controlled By: ReplicaSet/nginx-set
    4. Containers:
    5. nginx:
    6. Container ID: docker://68e20a9c102fa4385cf5fc082e9767dc5a6011020bc19a759f3f0a853389f7dc
    7. Image: nginx:1.7.9
    8. ......

    我们发现Pod的镜像版本还是1.7.9,并没有随着我们更新RS而立即更新Pod。这是因为在RS控制器下,Pod不会自己去创建删除,也就是不会滚动更新,要实现滚动更新就要用Kubernetes的另外一个控制器:Deployment。那么对于RS控制器来说,我们想升级Pod的镜像应该怎么做呢?
    我们可以删除Pod,然后通过RS控制器再新创建一个Pod,这时候的Pod版本就会更新,如下:

    1. [root@master rs]# kubectl delete pod nginx-set-n6dxl
    2. pod "nginx-set-n6dxl" deleted

    然后我们查看通过RS控制器新创建的Pod的nginx版本信息,如下:

    1. [root@master rs]# kubectl describe pod nginx-set-znlcl
    2. ......
    3. Containers:
    4. nginx:
    5. Container ID: docker://2005822f90324cc33478002fcf2bec82d1f1efc5671d688d5913d04e17df6811
    6. Image: nginx:1.8
    7. .......

    我们看到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的滚动升级功能(但是不支持一键回滚,需要用相同的方法去修改镜像地址)