参考:
https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/
ReplicaSet是什么?
ReplicaSet是kubernetes中的一种副本控制器,主要作用是控制由其管理的pod,使pod副本的数量始终维持在预设的个数。Kubernetes中还有一个类似功能的控制器:Replication Controller。ReplicaSet是Replication Controller的下一代副本控制器,目前两者只在标签选择器支持的查找方式有区别,ReplicaSet支持等式查找与集合查找两种方式,Replication Controller只支持等式查找。
kubectl命令同时支持ReplicaSet与Replication Controller两种副本控制器,但是kubectl rolling-update只支持Replication Controller类型的副本控制器,也就是说ReplicaSet无法通过kubectl rolling-update命令滚动升级。如果想要使用rolling-update功能的话,kubernetes官方推荐使用Deployments,并且因为Deployments是声明式的而rolling-update是命令式,所以推荐使用rollout命令实现滚动升级(kubectl管理对象的方式大体上分成两种,一种是命令式,另一种是声明式,声明式又细分成命令声明式与对角声明式,三种方式不能混用,所以才有此说)。
实现上kubernetes官方推荐不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployments支持声明式更新,声明式更好相比于命令式更新的好处是不会丢失历史变更。总结起来就是:不要再直接使用ReplicaSet。
示例
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# this replicas value is default
# modify it according to your case
replicas: 3
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
# If your cluster config does not include a dns service, then to
# instead access environment variables to find service host
# info, comment out the 'value: dns' line above, and uncomment the
# line below.
# value: env
ports:
- containerPort: 80
将以上内容保存在frontend.yaml文件并提供给集群,集群创建ReplicaSet与由它控制的pod:
$ kubectl create -f http://k8s.io/examples/controllers/frontend.yaml
replicaset "frontend" created
$ kubectl describe rs/frontend
Name: frontend
Namespace: default
Selector: tier=frontend,tier in (frontend)
Labels: app=guestbook
tier=frontend
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=guestbook
tier=frontend
Containers:
php-redis:
Image: gcr.io/google_samples/gb-frontend:v3
Port: 80/TCP
Requests:
cpu: 100m
memory: 100Mi
Environment:
GET_HOSTS_FROM: dns
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-qhloh
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-dnjpy
1m 1m 1 {replicaset-controller } Normal SuccessfulCreate Created pod: frontend-9si5l
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
frontend-9si5l 1/1 Running 0 1m
frontend-dnjpy 1/1 Running 0 1m
frontend-qhloh 1/1 Running 0 1m
如何写ReplicaSet spec?
ReplicaSet写法比较简单,需要注意的只有标签选择器。.spec.selector字段定义的标签选择器必需与.spec.template.metadata.labels中定义的标签匹配,也就是标签选择必需能选中它控制下的pod。另外建议.metadata.labels中的值与.spec.template.metadata.labels相同,这样的话有利于通过标签组织管理资源,这一特性非强制,不同的话对ReplicaSet本身没有影响。
用户不应该再通过其它直接、间接的方式创建与上述ReplicaSet标签选择器匹配的pod,否则ReplicaSet会认为是它自己创建了pod并把pod纳入自己管辖。或者在定义其它的副本控制器与,选择器与上述ReplicaSet重叠。以上两种情况都会导致pod的控制权混乱的问题。
ReplicaSet支持的操作
删除ReplicaSet与它控制下的pod
kubectl delete命令将删除ReplicaSet及其pod。具体的过程是kubectl delete首先将副本的数量调整到0,然后等待kubernetes控制面将pod删除,再后再删除ReplicaSet,kubectl delete可以被中断,重新运行后继续删除处理。
只删除ReplicaSet
只需要运行kubectl delete命令时加上–cascade=false选项,ReplicaSet被删除,其控制的pod不受影响。
从ReplicaSet隔离pod
更改pod标签,使其无法与ReplicaSet标签选择器匹配就可以将pod从ReplicaSet隔离出来,这时pod副本个数变少,ReplicaSet自动补足。
ReplicaSet扩缩容
只需简单的更新ReplicaSet spec中的.spec.replicas值就可实现。
ReplicaSet水平自动扩缩容器
通过HPA控制ReplicaSet根据负荷如cpu使用情况自动扩缩容。HPA spec如下:
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: frontend-scaler
spec:
scaleTargetRef:
kind: ReplicaSet
name: frontend
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 50
创建HPA对象:
kubectl create -f https://k8s.io/examples/controllers/hpa-rs.yaml
以上根据CPU使用情况,在3到10之间动态的调整副本数量。