ReplicaSet

    RepicaSet 是通过一组字段来定义的,包括一个用来识别可获得的 Pod 的集合的选择算符、一个用来标明应该维护的副本个数的数值、一个用来指定应该创建新 Pod 以满足副本个数条件时要使用的 Pod 模板等等。 每个 ReplicaSet 都通过根据需要创建和 删除 Pod 以使得副本个数达到期望值, 进而实现其存在价值。当 ReplicaSet 需要创建新的 Pod 时,会使用所提供的 Pod 模板。

    ReplicaSet 通过 Pod 上的 字段连接到附属 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 部分定义你的应用。

    将此清单保存到 frontend.yaml 中,并将其提交到 Kubernetes 集群, 应该就能创建 yaml 文件所定义的 ReplicaSet 及其管理的 Pod。

    1. kubectl apply -f https://kubernetes.io/examples/controllers/frontend.yaml

    你可以看到当前被部署的 ReplicaSet:

    1. kubectl get rs

    并看到你所创建的前端:

    1. NAME DESIRED CURRENT READY AGE
    2. frontend 3 3 3 6s

    你也可以查看 ReplicaSet 的状态:

    1. kubectl describe rs/frontend

    你会看到类似如下的输出:

    1. Name: frontend
    2. Namespace: default
    3. Selector: tier=frontend
    4. Labels: app=guestbook
    5. tier=frontend
    6. Annotations: kubectl.kubernetes.io/last-applied-configuration:
    7. {"apiVersion":"apps/v1","kind":"ReplicaSet","metadata":{"annotations":{},"labels":{"app":"guestbook","tier":"frontend"},"name":"frontend",...
    8. Replicas: 3 current / 3 desired
    9. Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
    10. Pod Template:
    11. Labels: tier=frontend
    12. Containers:
    13. php-redis:
    14. Image: gcr.io/google_samples/gb-frontend:v3
    15. Port: <none>
    16. Host Port: <none>
    17. Environment: <none>
    18. Mounts: <none>
    19. Events:
    20. Type Reason Age From Message
    21. ---- ------ ---- ---- -------
    22. Normal SuccessfulCreate 117s replicaset-controller Created pod: frontend-wtsmm
    23. Normal SuccessfulCreate 116s replicaset-controller Created pod: frontend-b2zdv
    24. Normal SuccessfulCreate 116s replicaset-controller Created pod: frontend-vcmts

    最后可以查看启动了的 Pods:

    1. kubectl get pods

    你会看到类似如下的 Pod 信息:

    1. NAME READY STATUS RESTARTS AGE
    2. frontend-b2zdv 1/1 Running 0 6m36s
    3. frontend-vcmts 1/1 Running 0 6m36s
    4. frontend-wtsmm 1/1 Running 0 6m36s

    你也可以查看 Pods 的属主引用被设置为前端的 ReplicaSet。 要实现这点,可取回运行中的 Pods 之一的 YAML:

    输出将类似这样,frontend ReplicaSet 的信息被设置在 metadata 的 ownerReferences 字段中:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. creationTimestamp: "2020-02-12T07:06:16Z"
    5. generateName: frontend-
    6. labels:
    7. tier: frontend
    8. name: frontend-b2zdv
    9. namespace: default
    10. ownerReferences:
    11. - apiVersion: apps/v1
    12. blockOwnerDeletion: true
    13. controller: true
    14. name: frontend
    15. uid: f391f6db-bb9b-4c09-ae74-6a1f77f3d5cf
    16. ...

    非模板 Pod 的获得

    尽管你完全可以直接创建裸的 Pods,强烈建议你确保这些裸的 Pods 并不包含可能与你 的某个 ReplicaSet 的选择算符相匹配的标签。原因在于 ReplicaSet 并不仅限于拥有 在其模板中设置的 Pods,它还可以像前面小节中所描述的那样获得其他 Pods。

    pods/pod-rs.yaml ReplicaSet - 图1

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: pod1
    5. labels:
    6. tier: frontend
    7. spec:
    8. containers:
    9. - name: hello1
    10. image: gcr.io/google-samples/hello-app:2.0
    11. ---
    12. apiVersion: v1
    13. kind: Pod
    14. name: pod2
    15. labels:
    16. tier: frontend
    17. spec:
    18. containers:
    19. - name: hello2
    20. image: gcr.io/google-samples/hello-app:1.0

    假定你在 frontend ReplicaSet 已经被部署之后创建 Pods,并且你已经在 ReplicaSet 中设置了其初始的 Pod 副本数以满足其副本计数需要:

    1. kubectl apply -f https://kubernetes.io/examples/pods/pod-rs.yaml

    新的 Pods 会被该 ReplicaSet 获取,并立即被 ReplicaSet 终止,因为 它们的存在会使得 ReplicaSet 中 Pod 个数超出其期望值。

    取回 Pods:

    1. kubectl get pods

    输出显示新的 Pods 或者已经被终止,或者处于终止过程中:

    1. NAME READY STATUS RESTARTS AGE
    2. frontend-b2zdv 1/1 Running 0 10m
    3. frontend-vcmts 1/1 Running 0 10m
    4. frontend-wtsmm 1/1 Running 0 10m
    5. pod1 0/1 Terminating 0 1s
    6. pod2 0/1 Terminating 0 1s

    如果你先行创建 Pods:

    1. kubectl apply -f https://kubernetes.io/examples/pods/pod-rs.yaml

    之后再创建 ReplicaSet:

    1. kubectl apply -f https://kubernetes.io/examples/controllers/frontend.yaml

    你会看到 ReplicaSet 已经获得了该 Pods,并仅根据其规约创建新的 Pods,直到 新的 Pods 和原来的 Pods 的总数达到其预期个数。 这时取回 Pods:

    将会生成下面的输出:

    1. NAME READY STATUS RESTARTS AGE
    2. frontend-hmmj2 1/1 Running 0 9s
    3. pod1 1/1 Running 0 36s
    4. pod2 1/1 Running 0 36s

    采用这种方式,一个 ReplicaSet 中可以包含异质的 Pods 集合。

    与所有其他 Kubernetes API 对象一样,ReplicaSet 也需要 apiVersionkind、和 metadata 字段。 对于 ReplicaSets 而言,其 kind 始终是 ReplicaSet。 在 Kubernetes 1.9 中,ReplicaSet 上的 API 版本 apps/v1 是其当前版本,且被 默认启用。API 版本 apps/v1beta2 已被废弃。 参考 frontend.yaml 示例的第一行。

    ReplicaSet 对象的名称必须是合法的 。

    ReplicaSet 也需要 .spec 部分。

    .spec.template 是一个, 要求设置标签。在 frontend.yaml 示例中,我们指定了标签 。 注意不要将标签与其他控制器的选择算符重叠,否则那些控制器会尝试收养此 Pod。

    对于模板的重启策略 字段,.spec.template.spec.restartPolicy,唯一允许的取值是 Always,这也是默认值.

    Pod 选择算符

    .spec.selector 字段是一个。 如前文中所讨论的,这些是用来标识要被获取的 Pods 的标签。在签名的 frontend.yaml 示例中,选择算符为:

    1. matchLabels:
    2. tier: frontend

    在 ReplicaSet 中,.spec.template.metadata.labels 的值必须与 spec.selector 值 相匹配,否则该配置会被 API 拒绝。

    Replicas

    你可以通过设置 .spec.replicas 来指定要同时运行的 Pod 个数。 ReplicaSet 创建、删除 Pods 以与此值匹配。

    如果你没有指定 .spec.replicas, 那么默认值为 1。

    使用 ReplicaSets

    删除 ReplicaSet 和它的 Pod

    要删除 ReplicaSet 和它的所有 Pod,使用 命令。 默认情况下,垃圾收集器 自动删除所有依赖的 Pod。

    当使用 REST API 或 client-go 库时,你必须在删除选项中将 propagationPolicy 设置为 BackgroundForeground。例如:

    1. kubectl proxy --port=8080
    2. curl -X DELETE 'localhost:8080/apis/apps/v1/namespaces/default/replicasets/frontend' \
    3. -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
    4. -H "Content-Type: application/json"

    你可以只删除 ReplicaSet 而不影响它的 Pod,方法是使用 命令并设置 --cascade=false 选项。

    当使用 REST API 或 client-go 库时,你必须将 propagationPolicy 设置为 Orphan。 例如:

    1. kubectl proxy --port=8080
    2. curl -X DELETE 'localhost:8080/apis/apps/v1/namespaces/default/replicasets/frontend' \
    3. -d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
    4. -H "Content-Type: application/json"

    一旦删除了原来的 ReplicaSet,就可以创建一个新的来替换它。 由于新旧 ReplicaSet 的 .spec.selector 是相同的,新的 ReplicaSet 将接管老的 Pod。 但是,它不会努力使现有的 Pod 与新的、不同的 Pod 模板匹配。 若想要以可控的方式更新 Pod 的规约,可以使用 Deployment 资源,因为 ReplicaSet 并不直接支持滚动更新。

    将 Pod 从 ReplicaSet 中隔离

    可以通过改变标签来从 ReplicaSet 的目标集中移除 Pod。 这种技术可以用来从服务中去除 Pod,以便进行排错、数据恢复等。 以这种方式移除的 Pod 将被自动替换(假设副本的数量没有改变)。

    缩放 RepliaSet

    通过更新 .spec.replicas 字段,ReplicaSet 可以被轻松的进行缩放。ReplicaSet 控制器能确保匹配标签选择器的数量的 Pod 是可用的和可操作的。

    ReplicaSet 作为水平的 Pod 自动缩放器目标

    ReplicaSet 也可以作为 的目标。也就是说,ReplicaSet 可以被 HPA 自动缩放。 以下是 HPA 以我们在前一个示例中创建的副本集为目标的示例。

    controllers/hpa-rs.yaml

    1. apiVersion: autoscaling/v1
    2. kind: HorizontalPodAutoscaler
    3. metadata:
    4. name: frontend-scaler
    5. spec:
    6. scaleTargetRef:
    7. kind: ReplicaSet
    8. name: frontend
    9. minReplicas: 3
    10. maxReplicas: 10
    11. targetCPUUtilizationPercentage: 50

    将这个列表保存到 hpa-rs.yaml 并提交到 Kubernetes 集群,就能创建它所定义的 HPA,进而就能根据复制的 Pod 的 CPU 利用率对目标 ReplicaSet进行自动缩放。

    1. kubectl apply -f https://k8s.io/examples/controllers/hpa-rs.yaml

    或者,可以使用 kubectl autoscale 命令完成相同的操作。 (而且它更简单!)

      是一个 可以拥有 ReplicaSet 并使用声明式方式在服务器端完成对 Pods 滚动更新的对象。 尽管 ReplicaSet 可以独立使用,目前它们的主要用途是提供给 Deployment 作为 编排 Pod 创建、删除和更新的一种机制。当使用 Deployment 时,你不必关心 如何管理它所创建的 ReplicaSet,Deployment 拥有并管理其 ReplicaSet。 因此,建议你在需要 ReplicaSet 时使用 Deployment。

      裸 Pod

      与用户直接创建 Pod 的情况不同,ReplicaSet 会替换那些由于某些原因被删除或被终止的 Pod,例如在节点故障或破坏性的节点维护(如内核升级)的情况下。 因为这个原因,我们建议你使用 ReplicaSet,即使应用程序只需要一个 Pod。 想像一下,ReplicaSet 类似于进程监视器,只不过它在多个节点上监视多个 Pod, 而不是在单个节点上监视单个进程。 ReplicaSet 将本地容器重启的任务委托给了节点上的某个代理(例如,Kubelet 或 Docker)去完成。

      Job

      使用 代替ReplicaSet, 可以用于那些期望自行终止的 Pod。

      DaemonSet

      对于管理那些提供主机级别功能(如主机监控和主机日志)的容器, 就要用 而不用 ReplicaSet。 这些 Pod 的寿命与主机寿命有关:这些 Pod 需要先于主机上的其他 Pod 运行, 并且在机器准备重新启动/关闭时安全地终止。