ReplicationController
ReplicationController 确保指定数量的 Pod 副本始终在运行。换句话说,ReplicationController 确保一个 Pod 或一组同构 Pod 始终处于启动和可用状态。
ReplicationController 的工作原理
如果 Pod 太多,ReplicationController 会终止多余的 Pod。如果 Pod 太少,ReplicationController 会启动更多 Pod。与手动创建的 Pod 不同,如果 ReplicationController 维护的 Pod 失败、被删除或被终止,它们会被自动替换。例如,在进行内核升级等中断性维护后,您的 Pod 会在节点上重新创建。因此,即使您的应用程序只需要一个 Pod,也应该使用 ReplicationController。ReplicationController 类似于进程管理器,但它不是管理单个节点上的单个进程,而是管理多个节点上的多个 Pod。
在讨论中以及作为 kubectl 命令中的快捷方式,ReplicationController 通常缩写为“rc”。
一个简单的用例是创建一个 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,但还没有一个 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
,如果未指定,则默认为 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。这使得 ReplicationController 可以在不影响正在运行的 Pod 的情况下被替换。
如果指定了 .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 时,请为 kubectl delete
指定 --cascade=orphan
选项。
使用 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 构成了此层。但是您希望能够对该组件的新版本进行“金丝雀”测试。您可以为大部分副本设置一个 replicas
设置为 9 的 ReplicationController,标签为 tier=frontend, environment=prod, track=stable
,并为金丝雀设置另一个 replicas
设置为 1 的 ReplicationController,标签为 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
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。
DaemonSet
对于提供机器级功能的 Pod(例如机器监控或机器日志记录),请使用 DaemonSet
而不是 ReplicationController。这些 Pod 的生命周期与机器的生命周期相关联:在其他 Pod 启动之前,Pod 需要在机器上运行,并且在机器准备好重新启动/关闭时可以安全地终止。
下一步
- 了解 Pod。
- 了解 Deployment,它是 ReplicationController 的替代品。
ReplicationController
是 Kubernetes REST API 的一部分。阅读 ReplicationController 对象定义以了解 ReplicationController 的 API。