1 ReplicaSet简介
1.1 ReplicaSet是什么?
ReplicaSet(简称RS)是Pod控制器类型的一种实现,用于确保由其管控的Pod对象副本数在任一时刻都能精确满足期望的数量。Kubernetes中还有一个类似功能的控制器:Replication Controller。ReplicaSet是Replication Controller的下一代副本控制器,目前两者只在标签选择器支持的查找方式有区别,ReplicaSet支持等式查找与集合查找两种方式,Replication Controller只支持等式查找。
实现上kubernetes官方推荐不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployments支持声明式更新,声明式更好相比于命令式更新的好处是不会丢失历史变更。总结起来就是:不要再直接使用ReplicaSet。
1.2 比较ReplicaSet和ReplicationController
ReplicaSet的行为与ReplicationController完全相同,但pod选择器的表达能力更强。虽然ReplicationController的标签选择器只允许包含某个标签的匹配pod,但ReplicaSet的选择器还允许匹配缺少某个标签的pod,或包含特定标签名的pod,不管其值如何。
kubectl命令同时支持ReplicaSet与Replication Controller两种副本控制器,但是kubectl rolling-update只支持Replication Controller类型的副本控制器,也就是说ReplicaSet无法通过kubectl rolling-update命令滚动升级。如果想要使用rolling-update功能的话,kubernetes官方推荐使用Deployments,并且因为Deployments是声明式的而rolling-update是命令式,所以推荐使用rollout命令实现滚动升级(kubectl管理对象的方式大体上分成两种,一种是命令式,另一种是声明式,声明式又细分成命令声明式与对角声明式,三种方式不能混用,所以才有此说)。
另外,举个例子,单个ReplicationController无法将pod与标签env=production和env=devel同时匹配。它只能匹配带有env=devel标签的pod或带有env=devel标签的pod。但是一个ReplicaSet可以匹配两组pod并将它们视为一个大组。
同样,无论ReplicationController的值如何,ReplicationController都无法仅基于标签名的存在来匹配pod,而ReplicaSet则可以。例如,ReplicaSet可匹配所有包含名为env的标签的pod,无论ReplicaSet的实际值是什么(可以理解为env=*)。
1.3 ReplicaSet 怎么管理Pod
ReplicaSet会通过标签选择器(Label-Selector)管理所有带有与选择器匹配的标签的容器。创建Pod时,它会认为所有Pod 是一样的,是无状态的,所以在创建顺序上不会有先后之分。如果使用相同的标签选择器创建另一个ReplicaSet,则之前的ReplicaSet会认为是它创建了这些Pod,会触发控制循环里的逻辑删掉多余的Pod ,新的ReplicSet又会再次创建Pod。双方的当前状态始终不等于期望状态,这就会引发问题,因此确保ReplicaSet标签选择器的唯一性这一点很重要。
如上图所示,ReplicaSet控制器资源启动后会查找集群中匹配其标签选择器的Pod资源对象,当前活动对象的数量与期望的数量不吻合时,多则删除,少则通过Pod模板创建以补足,等Pod资源副本数量符合期望值后即进入下一轮和解循环。
ReplicaSet的副本数量、标签选择器甚至是Pod模板都可以随时按需进行修改,不过仅改动期望的副本数量会对现存的Pod副本产生直接影响。修改标签选择器可能会使得现有的Pod副本的标签变得不再匹配,此时ReplicaSet控制器要做的不过是不再计入它们而已。另外,在创建完成后,ReplicaSet也不会再关注Pod对象中的实际内容,因此Pod模板的改动也只会对后来新建的Pod副本产生影响。
相比较于手动创建和管理Pod资源来说,ReplicaSet能够实现以下功能。
- 确保Pod资源对象的数量精确反映期望值:ReplicaSet需要确保由其控制运行的Pod副本数量精确吻合配置中定义的期望值,否则就会自动补足所缺或终止所余。
- 确保Pod健康运行:探测到由其管控的Pod对象因其所在的工作节点故障而不可用时,自动请求由调度器于其他工作节点创建缺失的Pod副本。
- 弹性伸缩:业务规模因各种原因时常存在明显波动,在波峰或波谷期间,可以通过ReplicaSet控制器动态调整相关Pod资源对象的数量。
此外,在必要时还可以通过HPA(HroizontalPodAutoscaler)控制器实现Pod资源规模的自动伸缩。
2 ReplicaSet使用
2.1 ReplicaSet 的YAML文件定义
下面这个配置文件的模板里罗列了定义ReplicaSet对象的YAML文件内容的主要组成部分:
代码语言:javascript复制apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: some-name
labels:
app: some-App
tier: some-Tier
spec:
replicas: 3 # 告诉k8s需要多少副本
Selector: # 用于匹配Pod的标签选择器
matchLabels:
tier: someTier
template:
metadata:
labels:
app: some-App
tier: someTier
spec: # 与Pod对象的spec定义类似
Containers: ...
Kubernetes里所有的API对象都由四部分组成:
- apiVersion -- 当前使用的Kubernetes的API版本。
- kind -- 你想创建的对象的种类,当前自然是ReplicaSet。
- metadata -- 元数据,用于唯一表示当前的对象,比如name、namespace等。
- spec -- 当前对象的指定配置。
但是ReplicaSet的spec部分的定义看起来与其他对象的spec定义略有不同。上面的示例中有两个spec字段。第一个spec声明的是ReplicaSet的属性--定义有多少个Pod副本(默认将仅部署1个Pod)、匹配Pod标签的选择器等。第二个spec用于Pod里的容器属性等配置。
实际上" .spec.template"里的内容就是声明Pod对象时要定义的各种属性,所以这部分也叫做PodTemplate(Pod模板)。还有一个值得注意的地方是:在.spec.selector中定义的标签选择器必须能够匹配到spec.template.metadata.labels里定义的Pod标签,否则Kubernetes将不允许创建ReplicaSet。
2.2 ReplicaSet使用案例
了解了什么是副本集,以及如何编写副本集的声明文件后,接下来我们动手创建一个副本集。在此示例中,我们将通过replica.yaml文件创建一个具有3个Pod副本的nginx应用。
代码语言:javascript复制# replica.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-replicas
labels:
app: myapp
tier: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: myapp
tier: frontend
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
首先我们运行kubectl create命令使用上面定义的声明文件创建对象。
代码语言:javascript复制$ kubectl create -f replica.yaml replicaset.apps "myapp-replicas" created
接下来通过命令确保副本集创建成功
代码语言:javascript复制$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
myapp-replicas 3 3 3 15s
上面的命令返回显示了myapp-replicas副本集部署了三个副本,三个都是就绪状态。接下来我们再看一下每个Pod副本的运行状态:
代码语言:javascript复制$ kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-replicas-67rkp 1/1 Running 0 33s
myapp-replicas-6kfd8 1/1 Running 0 33s
myapp-replicas-s96sg 1/1 Running 0 33s
所有3个都处于运行状态,重启次数都是0,这意味着目前为止我们的应用程序没有崩溃过。我们还可以使用kubectl describe命令查询副本集对象的详细信息,信息里的Events部分详细显示了ReplicaSet控制器进行过哪些编排动作。
代码语言:javascript复制$ kubectl describe replicaset myapp-replicas
Name: myapp-replicas
Namespace: default
Selector: tier=frontend,tier in (frontend)
Labels: app=myapp
tier=frontend
Annotations:
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=myapp
tier=frontend
Containers:
nginx:
Image: nginx
Port: 80/TCP
Host Port: 0/TCP
Environment:
Mounts:
Volumes:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 12m replicaset-controller Created pod: myapp-replicas-6kfd8
Normal SuccessfulCreate 12m replicaset-controller Created pod: myapp-replicas-67rkp
Normal SuccessfulCreate 12m replicaset-controller Created pod: myapp-replicas-s96sg
2.3 ReplicaSet支持的操作
2.3.1 删除ReplicaSet与它控制下的pod
kubectl delete命令将删除ReplicaSet及其pod。具体的过程是kubectl delete首先将副本的数量调整到0,然后等待kubernetes控制面将pod删除,再后再删除ReplicaSet,kubectl delete可以被中断,重新运行后继续删除处理。
2.3.2 只删除ReplicaSet
只需要运行kubectl delete命令时加上--cascade=false选项,ReplicaSet被删除,其控制的pod不受影响。
2.3.3 从ReplicaSet隔离pod
更改pod标签,使其无法与ReplicaSet标签选择器匹配就可以将pod从ReplicaSet隔离出来,这时pod副本个数变少,ReplicaSet自动补足。
2.3.4 ReplicaSet扩缩容
只需简单的更新ReplicaSet spec中的.spec.replicas值就可实现。
2.3.5 ReplicaSet水平自动扩缩容器
通过HPA控制ReplicaSet根据负荷如cpu使用情况自动扩缩容。HPA spec如下:
代码语言:javascript复制apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: frontend-scaler
spec:
scaleTargetRef:
kind: ReplicaSet
name: frontend
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 50
创建HPA对象:
代码语言:javascript复制kubectl create -f https://k8s.io/examples/controllers/hpa-rs.yaml
以上根据CPU使用情况,在3到10之间动态的调整副本数量。
参考链接
kubernetes之ReplicaSet_五星上炕的博客-CSDN博客_replicaset
ReplicaSet_喝醉酒的小白的博客-CSDN博客_replicaset
k8s-Pod控制器之ReplicaSet
ReplicaSet
ReplicaSet - 浪漫De刺猬 - 博客园
详解Kubernetes控制器之副本集ReplicaSet - 知乎
4.3 使用ReplicaSet而不是ReplicationController - 知乎
K8S之ReplicaSet详解_Jeremy_Lee123的博客-CSDN博客_k8s replicaset
ReplicaSet | Kubernetes
ReplicaSet · Kubernetes指南