ReplicationController
复制控制器 确保在任何时候都运行指定数量的 Pod 副本。换句话说,复制控制器确保 Pod 或一组同构 Pod 始终处于启动和可用状态。
复制控制器的工作方式
如果 Pod 数量过多,复制控制器会终止多余的 Pod。如果 Pod 数量过少,复制控制器会启动更多 Pod。与手动创建的 Pod 不同,复制控制器维护的 Pod 在发生故障、删除或终止时会自动替换。例如,您的 Pod 在内核升级等破坏性维护后会在节点上重新创建。因此,即使您的应用程序只需要一个 Pod,也应该使用复制控制器。复制控制器类似于进程主管,但它不是在单个节点上监督单个进程,而是监督跨多个节点的多个 Pod。
复制控制器在讨论中通常缩写为“rc”,并在 kubectl 命令中作为快捷方式使用。
一个简单的用例是创建一个复制控制器对象来可靠地运行一个 Pod 实例,无限期地运行。更复杂的用例是运行多个相同副本的复制服务,例如 Web 服务器。
运行示例复制控制器
此示例复制控制器配置运行三个 nginx Web 服务器的副本。
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
通过下载示例文件并运行此命令来运行示例作业
kubectl apply -f https://k8s.io/examples/controllers/replication.yaml
输出类似于此
replicationcontroller/nginx created
使用此命令检查复制控制器的状态
kubectl describe replicationcontrollers/nginx
输出类似于此
Name: nginx
Namespace: default
Selector: app=nginx
Labels: app=nginx
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 0 Running / 3 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- ---- ------ -------
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-qrm3m
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-3ntk0
20s 20s 1 {replication-controller } Normal SuccessfulCreate Created pod: nginx-4ok8v
这里创建了三个 Pod,但还没有一个正在运行,可能是因为正在拉取镜像。稍后,相同的命令可能会显示
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
要以机器可读的格式列出属于复制控制器的所有 Pod,可以使用如下命令
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
输出类似于此
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
这里,选择器与复制控制器的选择器相同(在 kubectl describe 输出中可以看到),并且在 replication.yaml 中以不同的形式显示。--output=jsonpath 选项指定一个表达式,其中包含返回列表中每个 Pod 的名称。
编写复制控制器清单
与所有其他 Kubernetes 配置一样,复制控制器需要 apiVersion、kind 和 metadata 字段。
当控制平面为复制控制器创建新的 Pod 时,复制控制器的 .metadata.name 是 Pod 命名的基础之一。复制控制器的名称必须是有效的 DNS 子域名 值,但这可能会对 Pod 主机名产生意想不到的结果。为了获得最佳兼容性,名称应遵循更严格的 DNS 标签 规则。
有关使用配置文件的一般信息,请参阅 对象管理。
复制控制器还需要一个 .spec 部分。
Pod 模板
.spec.template 是 .spec 的唯一必需字段。
.spec.template 是一个 Pod 模板。它具有与 Pod 相同的模式,只是它嵌套且没有 apiVersion 或 kind。
除了 Pod 的必需字段外,复制控制器中的 Pod 模板必须指定适当的标签和适当的重启策略。对于标签,请确保不要与其他控制器重叠。请参阅 Pod 选择器。
仅允许 .spec.template.spec.restartPolicy 等于 Always,如果未指定,则为默认值。
对于本地容器重启,复制控制器委托给节点上的代理,例如 Kubelet。
复制控制器上的标签
复制控制器本身可以具有标签(.metadata.labels)。通常,您会将这些标签设置为与 .spec.template.metadata.labels 相同;如果未指定 .metadata.labels,则默认设置为 .spec.template.metadata.labels。但是,它们允许不同,并且 .metadata.labels 不会影响复制控制器的行为。
Pod 选择器
.spec.selector 字段是一个 标签选择器。复制控制器管理所有标签与选择器匹配的 Pod。它不区分它创建或删除的 Pod 与其他人或进程创建或删除的 Pod。这允许复制控制器被替换而不会影响正在运行的 Pod。
如果指定,.spec.template.metadata.labels 必须等于 .spec.selector,否则将被 API 拒绝。如果未指定 .spec.selector,则默认设置为 .spec.template.metadata.labels。
您通常不应该创建任何标签与此选择器匹配的 Pod,无论是直接的、使用另一个复制控制器,还是使用另一个控制器,例如 Job。如果您这样做,复制控制器会认为它创建了其他 Pod。Kubernetes 不会阻止您这样做。
如果您最终有多个具有重叠选择器的控制器,则必须自行管理删除(请参阅 下面)。
多个副本
可以通过将 .spec.replicas 设置为所需的并发运行 Pod 数量来指定应并发运行多少个 Pod。在任何时候运行的数量可能会更高或更低,例如,如果副本刚刚增加或减少,或者如果 Pod 被优雅地关闭,并且替换品提前启动。
如果未指定 .spec.replicas,则默认值为 1。
使用复制控制器
删除复制控制器及其 Pod
要删除复制控制器及其所有 Pod,请使用 kubectl delete。Kubectl 会将复制控制器缩放为零并等待删除每个 Pod,然后才删除复制控制器本身。如果此 kubectl 命令被中断,可以重新启动它。
在使用 REST API 或 客户端库 时,需要显式执行这些步骤(将副本缩放为 0,等待 Pod 删除,然后删除复制控制器)。
仅删除复制控制器
您可以删除复制控制器而不影响其任何 Pod。
使用 kubectl,将 --cascade=orphan 选项指定给 kubectl delete。
在使用 REST API 或 客户端库 时,可以删除复制控制器对象。
一旦原始对象被删除,您就可以创建一个新的复制控制器来替换它。只要新的 .spec.selector 与旧的相同,新的控制器就会采用旧的 Pod。但是,它不会努力使现有的 Pod 与新的不同 Pod 模板匹配。要以受控方式更新 Pod 到新的规范,请使用 滚动更新。
将 Pod 与复制控制器隔离
可以通过更改 Pod 的标签来将 Pod 从复制控制器的目标集中移除。可以使用此技术将 Pod 从服务中移除以进行调试和数据恢复。以这种方式移除的 Pod 将自动替换(假设副本数也未更改)。
常见用法模式
重新调度
如上所述,无论您是有一个想要保持运行的 Pod,还是有 1000 个 Pod,复制控制器都会确保存在指定数量的 Pod,即使在节点故障或 Pod 终止的情况下(例如,由于另一个控制代理的操作)。
伸缩
复制控制器可以通过更新 `replicas` 字段来手动或通过自动伸缩控制代理来增加或减少副本数量。
滚动更新
复制控制器旨在通过逐个替换 Pod 来促进服务的滚动更新。
如 #1353 中所述,推荐的方法是创建一个具有 1 个副本的新复制控制器,逐个伸缩新的 (+1) 和旧的 (-1) 控制器,然后在旧控制器达到 0 个副本后删除它。 无论发生意外故障,这都能可预测地更新 Pod 集合。
理想情况下,滚动更新控制器应该考虑到应用程序的就绪状态,并确保在任何给定时间都有足够数量的 Pod 正常提供服务。
这两个复制控制器需要创建具有至少一个区分性标签的 Pod,例如 Pod 的主要容器的镜像标签,因为通常是镜像更新驱动滚动更新。
多个发布轨道
除了在滚动更新进行时运行多个应用程序版本外,使用多个发布轨道运行多个版本一段时间,甚至持续运行也是很常见的。 这些轨道将通过标签进行区分。
例如,服务可能针对所有具有 tier in (frontend), environment in (prod) 的 Pod。 现在假设你有 10 个复制的 Pod 构成这个层级。 但是你希望能够“金丝雀”发布这个组件的新版本。 你可以设置一个 `replicas` 设置为 9 的复制控制器,用于大部分副本,标签为 tier=frontend, environment=prod, track=stable,以及另一个 `replicas` 设置为 1 的复制控制器,用于金丝雀,标签为 tier=frontend, environment=prod, track=canary。 现在该服务涵盖了金丝雀和非金丝雀 Pod。 但是你可以单独操作复制控制器来测试事物,监控结果等。
使用复制控制器与服务
多个复制控制器可以位于单个服务之后,例如,一些流量去到旧版本,一些流量去到新版本。
复制控制器永远不会自行终止,但它预计不会像服务一样长期存在。 服务可能由多个复制控制器控制的 Pod 组成,并且预计在服务的生命周期内可能会创建和销毁许多复制控制器(例如,执行服务的 Pod 更新)。 服务本身及其客户端都不应该意识到维护服务 Pod 的复制控制器。
编写复制程序的程序
由复制控制器创建的 Pod 旨在具有可替代性和语义上的相同性,尽管它们的配置可能会随着时间的推移而异构。 这非常适合复制的无状态服务器,但复制控制器也可以用于维护经过主选举、分片和工作池应用程序的可用性。 此类应用程序应使用动态工作分配机制,例如 RabbitMQ 工作队列,而不是静态/一次性自定义每个 Pod 的配置,这被认为是一种反模式。 任何执行的 Pod 自定义,例如资源垂直自动调整大小(例如,cpu 或内存),应由另一个在线控制器进程执行,类似于复制控制器本身。
复制控制器的职责
复制控制器确保所需的 Pod 数量与其标签选择器匹配并且正在运行。 目前,只有终止的 Pod 从其计数中排除。 在未来,就绪状态和其他来自系统的信息可能会被考虑在内,我们可能会添加更多关于替换策略的控制,并计划发出事件,外部客户端可以使用这些事件来实现任意复杂的替换和/或缩减策略。
复制控制器永远受到这种狭窄职责的约束。 它本身不会执行就绪或存活探测。 与其执行自动伸缩,不如由外部自动伸缩器控制它(如 #492 中所述),这将更改其 replicas 字段。 我们不会向复制控制器添加调度策略(例如,扩散)。 它也不应该验证受控的 Pod 是否与当前指定的模板匹配,因为这会妨碍自动调整大小和其他自动化流程。 类似地,完成期限、排序依赖关系、配置扩展和其他功能属于其他地方。 我们甚至计划将批量 Pod 创建机制分解出来 (#170)。
复制控制器旨在成为一个可组合的构建块原语。 我们预计未来将基于它和其他互补原语构建更高级别的 API 和/或工具,以方便用户使用。 当前 kubectl 支持的“宏”操作(run、scale)是对此的初步示例。 例如,我们可以想象 Asgard 管理复制控制器、自动伸缩器、服务、调度策略、金丝雀等。
API 对象
复制控制器是 Kubernetes REST API 中的顶级资源。 可以在以下位置找到有关 API 对象的更多详细信息:复制控制器 API 对象。
复制控制器的替代方案
ReplicaSet
ReplicaSet 是下一代复制控制器,支持新的 基于集合的标签选择器。 它主要由 Deployment 用作编排 Pod 创建、删除和更新的机制。 请注意,我们建议使用 Deployment 而不是直接使用 Replica Set,除非你需要自定义更新编排或根本不需要更新。
Deployment(推荐)
Deployment 是一个更高级别的 API 对象,它更新其底层的 Replica Set 及其 Pod。 如果你需要滚动更新功能,建议使用 Deployment,因为它们是声明式的、服务器端的,并且具有其他功能。
裸 Pod
与用户直接创建 Pod 的情况不同,复制控制器会替换因任何原因(例如节点故障或破坏性节点维护,例如内核升级)而被删除或终止的 Pod。 因此,我们建议即使你的应用程序只需要一个 Pod,也使用复制控制器。 类似于进程主管,它监视多个节点上的多个 Pod,而不是单个节点上的单个进程。 复制控制器将本地容器重启委托给节点上的某个代理,例如 kubelet。
Job
对于预计自行终止的 Pod(即批处理作业),请使用 Job 代替复制控制器。
DaemonSet
对于提供机器级功能的 Pod(例如机器监控或机器日志记录),请使用 DaemonSet 代替复制控制器。 这些 Pod 的生命周期与机器的生命周期相关联:Pod 需要在其他 Pod 开始运行之前在机器上运行,并且在机器准备好重新启动/关闭时可以安全地终止。
接下来
- 了解 Pods。
- 了解 Deployment,它是复制控制器的替代品。
ReplicationController是 Kubernetes REST API 的一部分。 阅读 ReplicationController 对象定义以了解复制控制器的 API。