ReplicaSet
ReplicaSet简介
ReplicaSet 的目的是维护一组在任何时候都处于运行状态的 Pod 副本的稳定集合。 因此,它通常用来保证给定数量的、完全相同的 Pod 的可用性。
ReplicaSet 的工作原理
ReplicaSet 是通过一组字段来定义的,包括一个用来识别可获得的 Pod 的集合的选择算符、一个用来标明应该维护的副本个数的数值、一个用来指定应该创建新 Pod 以满足副本个数条件时要使用的 Pod 模板等等。 每个 ReplicaSet 都通过根据需要创建和删除 Pod 以使得副本个数达到期望值, 进而实现其存在价值。当 ReplicaSet 需要创建新的 Pod 时,会使用所提供的 Pod 模板。
ReplicaSet 通过 Pod 上的 metadata.ownerReferences 字段连接到附属 Pod,该字段给出当前对象的属主资源。 ReplicaSet 所获得的 Pod 都在其 ownerReferences 字段中包含了属主 ReplicaSet 的标识信息。正是通过这一连接,ReplicaSet 知道它所维护的 Pod 集合的状态, 并据此计划其操作行为。
ReplicaSet 使用其选择算符来辨识要获得的 Pod 集合。如果某个 Pod 没有 OwnerReference 或者其 OwnerReference 不是一个控制器, 且其匹配到某 ReplicaSet 的选择算符,则该 Pod 立即被此 ReplicaSet 获得。
何时使用 ReplicaSet
ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。 然而,Deployment 是一个更高级的概念,它管理 ReplicaSet,并向 Pod 提供声明式的更新以及许多其他有用的功能。 因此,我们建议使用 Deployment 而不是直接使用 ReplicaSet, 除非你需要自定义更新业务流程或根本不需要更新。
这实际上意味着,你可能永远不需要操作 ReplicaSet 对象:而是使用 Deployment,并在 spec 部分定义你的应用。
编辑yaml文件
cat > frontend.yaml << EOF
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
# 按你的实际情况修改副本数
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: php-redis
#image: gcr.io/google_samples/gb-frontend:v3
# 这里使用ucloud提供的镜像加速功能
image: uhub.service.ucloud.cn/996.icu/gb-frontend:v3
EOF
创建ReplicaSet
kubectl apply -f frontend.yaml
查看ReplicaSet
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
frontend 3 3 0 39s
查看pod
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
frontend-6778b 1/1 Running 0 50s
frontend-dxbtc 1/1 Running 0 50s
frontend-fbwfv 1/1 Running 0 50s
你也可以查看 Pod 的属主引用被设置为前端的 ReplicaSet。 要实现这点,可取回运行中的某个 Pod 的 YAML:
kubectl get pods frontend-6778b -o yaml
输出将类似这样,frontend ReplicaSet 的信息被设置在 metadata 的 ownerReferences 字段中:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2022-10-31T14:20:27Z"
generateName: frontend-
labels:
tier: frontend
name: frontend-6778b
namespace: test
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: frontend
uid: f33c0445-3139-42f7-a0b0-2617b22b57cb
resourceVersion: "3315496"
uid: b3ed0951-8a0a-40e5-b4b1-39ebae12e13e
spec:
containers:
- image: uhub.service.ucloud.cn/996icu/gb-frontend:v3
imagePullPolicy: IfNotPresent
name: php-redis
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-5rl8g
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: ctyun
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
...
非模板 Pod 的获得
尽管你完全可以直接创建裸的 Pod,强烈建议你确保这些裸的 Pod 并不包含可能与你的某个 ReplicaSet 的选择算符相匹配的标签。原因在于 ReplicaSet 并不仅限于拥有在其模板中设置的 Pod,它还可以像前面小节中所描述的那样获得其他 Pod。
编辑yaml文件
cat > pod-rs.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: pod1
labels:
tier: frontend
spec:
containers:
- name: hello1
#image: gcr.io/google-samples/hello-app:2.0
image: uhub.service.ucloud.cn/996.icu/hello-app:2.0
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
labels:
tier: frontend
spec:
containers:
- name: hello2
#image: gcr.io/google-samples/hello-app:1.0
image: uhub.service.ucloud.cn/996.icu/hello-app:1.0
EOF
由于这些 Pod 没有控制器(Controller,或其他对象)作为其属主引用, 并且其标签与 frontend ReplicaSet 的选择算符匹配,它们会立即被该 ReplicaSet 获取。
新的 Pod 会被该 ReplicaSet 获取,并立即被 ReplicaSet 终止, 因为它们的存在会使得 ReplicaSet 中 Pod 个数超出其期望值。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
frontend-6778b 1/1 Running 0 14m
frontend-dxbtc 1/1 Running 0 14m
frontend-fbwfv 1/1 Running 0 14m
pod1 0/1 Terminating 0 6s
pod2 0/1 Terminating 0 6s
删除之前创建的rs和刚才创建的pod
如果先创建pod
kubectl apply -f pod-rs.yaml
然后在创建ReplicaSet
kubectl apply -f frontend.yaml
你会看到 ReplicaSet 已经获得了该 Pod,并仅根据其规约创建新的 Pod, 直到新的 Pod 和原来的 Pod 的总数达到其预期个数
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
frontend-7dcnt 1/1 Running 0 8s
pod1 1/1 Running 0 35s
pod2 1/1 Running 0 35s
采用这种方式,一个 ReplicaSet 中可以包含异质的 Pod 集合。
编写 ReplicaSet 的清单
与所有其他 Kubernetes API 对象一样,ReplicaSet 也需要 apiVersion、kind、和 metadata 字段。 对于 ReplicaSet 而言,其 kind 始终是 ReplicaSet。
ReplicaSet 对象的名称必须是合法的 DNS 子域名。
ReplicaSet 也需要 .spec 部分。
Pod 模板
.spec.template 是一个 Pod 模板, 要求设置标签。在 frontend.yaml 示例中,我们指定了标签 tier: frontend。 注意不要将标签与其他控制器的选择算符重叠,否则那些控制器会尝试收养此 Pod。
对于模板的重启策略 字段,.spec.template.spec.restartPolicy,唯一允许的取值是 Always,这也是默认值。
Pod 选择算符
.spec.selector 字段是一个标签选择算符。 如前文中所讨论的,这些是用来标识要被获取的 Pod 的标签。在签名的 frontend.yaml 示例中,选择算符为:
matchLabels:
tier: frontend
在 ReplicaSet 中,.spec.template.metadata.labels 的值必须与 spec.selector 值相匹配,否则该配置会被 API 拒绝。
:::tip说明
对于设置了相同的 .spec.selector,但 .spec.template.metadata.labels 和 .spec.template.spec 字段不同的两个 ReplicaSet 而言,每个 ReplicaSet 都会忽略被另一个 ReplicaSet 所创建的 Pod。
:::
Replicas
你可以通过设置 .spec.replicas 来指定要同时运行的 Pod 个数。 ReplicaSet 创建、删除 Pod 以与此值匹配。
如果你没有指定 .spec.replicas,那么默认值为 1。
使用 ReplicaSet
删除 ReplicaSet 和它的 Pod
要删除 ReplicaSet 和它的所有 Pod,使用 kubectl delete 命令。 默认情况下,垃圾收集器 自动删除所有依赖的 Pod。
当使用 REST API 或 client-go 库时,你必须在 -d 选项中将 propagationPolicy 设置为 Background 或 Foreground。例如:
kubectl proxy --port=8080
curl -X DELETE 'localhost:8080/apis/apps/v1/namespaces/default/replicasets/frontend' \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"