Files
kuboard-press/learning/k8s-intermediate/workload/wl-replication-con/index.md
2019-11-11 22:09:04 +08:00

219 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
vssueId: 157
layout: LearningLayout
description: Kubernetes中_ReplicationController确保在任何时候某个Pod的副本数都是指定的数量
meta:
- name: keywords
content: Kubernetes教程,K8S教程,ReplicaSet
---
# 控制器 - ReplicationController
<AdSenseTitle>
> 参考文档: [ReplicationController](https://kubernetes.io/docs/concepts/workloads/controllers/replicationcontroller/)
::: tip
推荐使用 [Deployment](/learning/k8s-intermediate/workload/wl-deployment/)
:::
ReplicationController 确保在任何时候某个 Pod 的副本数都是指定的数量。
[[TOC]]
</AdSenseTitle>
## ReplicationController如何工作
如果存在过多的 PodRelicationCotroller 将终止多余的 Pod如果数量不够则启动新的 Pod。不同于手工创建Pod的做法当Pod失败、被删除或者终止时ReplicationController 将立刻自动创建新的 Pod 作为替代。例如,假设您要升级节点的操作系统内核,此时该节点上的 Pod 将被驱逐或者终止,如果 Pod 是通过 ReplicationController 创建的ReplicationController 将能够自动在其他节点上创建新的Pod以确保集群中该Pod的副本数保持在指定的数字。
ReplicationController 经常被缩写为 `rc`,在 kubectl 命令中也可以使用此缩写,例如 `kubectl get rc`
## 运行一个ReplicationController的例子
下面的 Example YAML文件中运行了一个 nginx 服务的三个副本:
<<< @/.vuepress/public/statics/learning/replicationcontroller/replication.yaml
执行命令创建该 ReplicationController
``` sh
kubectl apply -f https://kuboard.cn/statics/learning/replicationcontroller/replication.yaml
```
执行命令检查刚才创建的 ReplicationController 的状态:
``` sh
kubectl describe replicationcontrollers/nginx
```
输出结果如下所示:
``` {7}
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
```
此时有3个Pod被创建但是都还未进入 Running 状态,因为正在抓取镜像。稍等一会儿,执行同样的命令,此处的结果将变为:
```
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
```
下面的命令可以获取 ReplicationController 的 Pod 列表,并存入到环境变量:
``` sh
pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods
```
输出结果如下所示:
```
nginx-3ntk0 nginx-4ok8v nginx-qrm3m
```
此命令中,使用了与 ReplicationController 中相同的 label selector。
## ReplicationController的定义
与其他 Kubernetes 对象一样ReplicationController 需要以下字段:
* `apiVersion`
* `kind`
* `metadata`
ReplicationController 还需要 `.spec` 字段
### PodTemplate
`.spec.template` 字段是一个 [Pod Template](/learning/k8s-intermediate/workload/pod.html#pod-template),为必填字段,且其中必须定义 `.spec.template.metadata.labels` 字段。请小心该字段不要与其他控制器的 selector 重合,以免这些控制器尝试接管该 Pod。
`.spec.template.spec.restartPolicy` 的默认值为 `Always`
### Pod Selector
`.spec.selector` 字段为一个 [标签选择器](/learning/k8s-intermediate/obj/labels.html#标签选择器),用于识别可以接管哪些 Pod。
在 ReplicationController 中, `.spec.template.metadata.labels` 必须与 `.spec.selector` 匹配,否则将不能成功创建 ReplicationController。
同时,您也要避免通过其他方式创建的 Pod例如手工创建、使用另外一个 ReplicationController 创建、或者使用其他控制器如Job等创建的标签与 ReplicationController 的标签选择器匹配。如果发生这种情况ReplicationController 将认为这个 Pod 是由它创建的。Kubernetes并不能阻止你进行这种明显错误的操作。如果确实发生了这种情况您需要手工删除相关的控制器和Pod。
### Replicas
`.spec.replicas` 字段用于指定同时运行的 Pod 的副本数。ReplicaSet 将创建或者删除由其管理的 Pod以便使副本数与该字段指定的值匹配。
如果不指定,默认值为 1
## 使用ReplicationController
### 删除ReplicationController及其Pod
使用 `kubectl delete` 命令可以删除 ReplicationController 及其 Pod。kubectl 会先将 ReplicationController 伸缩到 0 个副本,待其删除了所有的 Pod 之后,再删除 ReplicationController 对象。如果这个命令中断了,可以重新执行。
当使用 REST API 或者 go 语言客户端代码库时,您需要执行如下步骤:
* 伸缩 ReplicationController 的副本数为 0
* 等待 Pod 被删除
* 删除 ReplicationController
### 仅删除ReplicationController
您可以只删除 ReplicationController而保留其创建的 Pod只需要在 kubectl delete 命令中指定选项 --cascade=false
```sh
kubectl delete --cascade=false rc nginx
```
当使用 REST API 或者 go 语言客户端代码库时,只需要直接删除 ReplicationController 即可。
删除原有的 ReplicationController 之后,您可以在创建新的 ReplicationController 作为替代。只要新 ReplicationController 的 `.spec.selector` 字段与之前相同,则新的 ReplicationController 将接管原 ReplicationController 创建的 Pod。但是此时原 ReplicationController 已经创建的 Pod 的模板将保持不变。如果需要更新所有 Pod 的模板,请参考 [滚动更新](#滚动更新)
### 将Pod从ReplicationController中隔离
通过修改 Pod 的标签,可以将其从 ReplicationController 的管理列表中移除。这个小技巧在如下场景可能非常有用:
* 将 Pod 从 Service 中移除,以便 Debug 或者做数据恢复
* 其他
通过这种方式从 ReplicationController 移除了 Pod 之后ReplicationController 将立刻自动创建一个新的 Pod 以维持其指定的 `replicas` 副本数。
## 使用模式
### Rescheduling
不管您是想要保持 1 个 Pod 副本,还是由 1000 个 Pod 副本需要运行ReplicationController 将确保指定的数量的 Pod 副本一直存在,即使是在节点故障、或者 Pod 被人为删除的情况下。
### Scaling
ReplicationController 使得水平伸缩这件事情变得非常简单,只需要修改 `replicas` 字段即可。可以手工修改该字段,也可以通过一个自动化的控制器修改。
### 滚动更新
ReplicationController 可以用逐个替换 Pod 的方式来滚动更新某个服务,具体的做法是:
* 创建一个新的 ReplicationController 其副本数为 1
* 逐个跟新 Pod
* 将旧的 ReplicationController `replicas` -1
* 将新的 ReplicationController `replicas` +1
* 直到旧的 ReplicationController `replicas` 为 0
* 删除旧的 ReplicationController
理想情况下,滚动更新控制器应该考虑应用程序是否就绪,且确保任何时刻都有足够数量的 Pod 是可用的。
滚动更新过程中的两个 ReplicationController 在创建 Pod 时需要使用至少一个不同的标签例如Pod中主要容器的镜像的 Tag
ReplicationController 的滚动更新可以通过 [kubectl rolling-update](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#rolling-update) 命令实现,具体使用方法可参考 [Perform Rolling Update Using a Replication Controller](https://kubernetes.io/docs/tasks/run-application/rolling-update-replication-controller/)
### 多版本multiple release tracks
在滚动更新的过程中应用程序实际会运行多个版本。实际上在一个更长的时间段内也经常会运行同一个应用程序的不同版本release track通过标签来区分。
例如Service 可能会选中所有带 `tier in (frontend), environment in (prod)` 标签的 Pod 作为其后端 Pod。此时假设您有 10 个 Pod 副本为此 Service 服务。您也许想要通过金丝雀发布的方式发布该组件,此时可以:
* 设置主要 ReplicationController 的 `replicas` 为 9且标签为 `tier=frontend, environment=prod, track=stable`
* 另一个 ReplicationController 的 `replicas` 为 1作为金丝雀测试用途标签为 `tier=frontend, environment=prod, track=canary`
在这种情况下Service将覆盖金丝雀 Pod 以及非金丝雀 Pod。同时您可以通过两个 ReplicationController 将不同的 Pod 区分开,监控金丝雀 Pod 的运行效果,验证测试结果等。
### 同Service一起使用ReplicationController
一个 Service 可以对应多个 ReplicationController例如一部分流量进入旧的版本一部分流量进入新的版本。
ReplicationController 不会自己终止,但是,其生命周期通常比 Service 要短:
* Service 可以映射到由不同 ReplicationController 创建的 Pod 上
* Service 的整个生命周期过程中,通常会有多个 ReplicationController 被创建或者销毁(例如,对 Service 的 Pod 执行滚动更新)
ReplicationController 对 Service 以及 Service 的客户端来说,都是透明不可见的。
## 为Replication编写程序
ReplicationController 创建的 Pod 应该都是可替代的且语义上是完全相同的尽管其配置在不同的时间可能存在差异。ReplicationController 非常适用于无状态应用的管理也可以用来维护主节点选举master-elected、分片的sharded、工作节点池worker-pool类型的应用。此类应用程序应该 使用动态负载分配的机制dynamic work assignment mechanism例如 [RabbitMQ work queues](https://www.rabbitmq.com/tutorials/tutorial-two-python.html),而不是为每一个 Pod 做静态的一次性的配置。
任何对 Pod 定义的修改都应该由另一个控制器或者脚本程序执行,而不是由 ReplicationController 自己执行,例如自动调整 Pod 的资源使用cpu/memory等
## 替代选择
### ReplicaSet
`ReplicaSet` ReplicationController 的替代品请在任何情况下使用 ReplicaSet而不是 ReplicationControllerReplicaSet 主要是用作 [Deployment](/learning/k8s-intermediate/workload/wl-deployment/) 中创建删除更新 Pod 的手段同时我们也推荐始终使用 Deployment 而不是 ReplicaSet除非您需要自定义 Deployment 中的某些行为
### Deployment <Badge type="default">推荐</Badge>
[Deployment](/learning/k8s-intermediate/workload/wl-deployment/) 是一个高阶的 API 对象可以更新其管理的 ReplicaSet Pod是推荐的用法
### Bare Pods
与用户直接创建的 Pod 不同ReplicationController Pod 由于任何原因被删除或终止时例如节点故障或者节点升级将创建新的 Pod 作为其替代不推荐您直接使用 Pod即便您的应用程序只需要一个 Pod 副本请使用 Deployment
### Job
使用 [Job](/learning/k8s-intermediate/workload/wl-job/) 执行批处理任务
### DaemonSet
当您需要提供机器级别的功能时例如监控节点[收集节点上的日志](/learning/k8s-advanced/logs/node.html)使用 [DaemonSet](/learning/k8s-intermediate/workload/wl-daemonset/)