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的滾動升級功能(但是不支持一鍵回滾,需要用相同的方法去修改鏡像地址)