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