docker&kubernets篇(二十四)

replication controller设计解读

Kubernetes中第二个重要的概念就是replication controller,它决定了一个pod有多少同时运行的副本,并保证这些副本的期望状态与当前状态一致。所以,如果创建了一个pod,并且在希望该pod是持续运行的应用时[即仅适用于重启策略(RestartPolicy)为Always的pod],一般都推荐同时给pod创建一个replication controller,让这个controller一直守护pod,直到pod被删除。replication controller在设计上依然体现出了“旁路控制”的思想,在Kubernetes中并没有像Cloud Foundry那样设置一个专门的健康检查组件,而是为每个pod“外挂”了一个控制器进程,从而避免了健康检查组件成为性能瓶颈;即使这个控制器进程失效,容器依然可以正常运行,pod和容器无需知道这个控制器,也不会把这个控制器作为依赖(容器运行依赖于健康检查组件,并随之形成的三角依赖关系曾是Cloud Foundry v2中的一个重大问题,也是Cloud Foundry v3重点改进的内容,有兴趣的读者可以自行了解)。
可以看到,在上述过程中,pod的状态可以说是replication controller进行上述控制的唯一依据。所以,有必要先了解一下Kubernetes中的pod的状态和转移过程。

  1. pod的状态转换在Kubernetes中,pod的状态值(podStatus)的数量和定义是系统严格保留和规定的,如表所示。

在这里插入图片描述而上述pod的状态转换与pod的重启策略则是紧密相关的,它的转移过程如下所示。pod处于Running状态,总共包含1个容器,容器退出,这时发生的操作如下。
❏ 若容器正常退出,向系统输出信息为completion(完成)的事件对象,否则输出failure事件;
❏ 若RestartPolicy是Always,重启退出的容器,pod仍处于Running状态;
❏ 若RestartPolicy是OnFailure,若容器正常退出,pod变成Succeeded状态,若异常退出则进行重启并处于Running状态;
❏ 若RestartPolicy是Never,容器正常退出pod变成Succeeded状态,否则变为Failed状态。

pod处于Running状态,总共包含2个容器,其中1个容器异常退出,这时发生的操作如下。
❏ 向系统输出信息为failure(错误)的事件对象(event);
❏ 若RestartPolicy是Always,重启异常退出的容器,pod仍处于Running状态;
❏ 若RestartPolicy是OnFailure,重启异常退出的容器,pod仍处于Running状态;
❏ 若RestartPolicy是Never, pod变成Failed状态。

pod处于Running状态,总共包含2个容器,容器1已经异常退出,并且系统已经按照上述第二种情况完成处理,当容器2也退出时(不论是否异常退出),这时发生的操作如下。
❏ 向系统输出信息为failure(错误)的事件对象(event);
❏ 若RestartPolicy是Always,重启退出的容器,pod仍处于Running状态;
❏ 若RestartPolicy是OnFailure,重启退出的容器,pod仍处于Running状态;
❏ 若RestartPolicy是Never, pod变成Failed状态。

pod处于Running状态,容器内存溢出,这时发生的操作如下。
❏ pod内容器异常退出;
❏ 向系统输出信息为failure(错误)的事件对象(event);
❏ 若RestartPolicy是Always,重启退出的容器,pod仍处于Running状态;
❏ 若RestartPolicy是OnFailure,重启退出的容器,pod仍处于Running状态;
❏ 若RestartPolicy是Never, pod变成Failed状态。

pod处于Running状态,此时pod所在的主机磁盘发生故障,这时发生的操作如下。
❏ pod内所有容器都被杀死;
❏ 向系统输出信息为failure(错误)的事件对象(event);
❏ pod变成Failed状态;
❏ 如果pod被一个replication controller控制,则将在其他工作节点上重新创建一个新的pod。

pod处于Running状态,它的工作节点与集群断开。
❏ node controller等待一个超时时间;
❏ node controller标记该工作节点上所有pod均处于failed状态;
❏ 被replication controller控制的pod将在其他工作节点上重新被创建运行。

但是,对于当前replication controller实现方法来说,它能够识别的pod重启策略只有Always一种,这是因为当前replication controller的设计目标是保证本身状态为Running且容器一切正常的pod的数量永远跟预设的数目一致。任何时候一个pod中的容器退出或者整个pod变成Failed, replication controller都会固执地重启这个容器或者pod,并使之变成Running状态。即使单独将一个pod的重启策略设置为Never或者OnFailure,后续这个pod关联起来的replication controller也都会忽略这个设置而使用Always策略。如果用户希望在Kubernetes中运行“一次性”任务,比如Map-Reduce的Job或者类似的batch task,可以定义一个Job对象,这将在后续章节中进行介绍。

  1. replication controller的描述文件

前面已经介绍过,replication controller是Kubernetes为解决“如何构造完全同质的pod副本”问题而引入的资源对象。与pod对象类似,Kubernetes使用一份JSON格式的资源配置文件来定义一个replication controller对象。replication controller的资源配置文件主要由3个方面组成:一个用于创建pod的pod模板(pod template)、一个期望副本数和一个用于选择被控制的pod集合的label selector。replication controller将会不断地监测控制的pod集合的数量并与期望的副本数量进行比较,根据实际情况进行创建和删除pod的操作。一份定义replication controller的资源配置文件示例如下所示,该replication controller实例化了两个运行nginx的pod。

apiVersion: v1
kind: ReplicationController
metadata:    
  name: nginx-controller
spec:    
  # 两个副本    
  replicas: 2    
  # 这个replica controller管理包含如下标签的pod    
  selector:      
    name: nginx    
  template:      
    metadata:          
  # 重要!下面的labels属性即被创建的pod的labels,必须与上面的replicaSelector一样          
      labels:              
        name: nginx          
      spec:              
        containers:              
          - name: nginx              
        image: k8stest/nginx:test              
        ports:              
          - containerPort: 80

从上述描述文件中不难看到,replication controller通过使用预定义的pod模板来创建pod,一旦pod创建成功,对模板的任何更改都不会对已经在运行的pod有任何直接的影响。我们推荐replication controller只负责选择指定的pod然后保证这个pod的数量和状态正确,而调整这些已经在运行的pod的CPU、MEM参数等操作应该直接更新pod本身而不是更新replication controller。这依然是旁路控制和解耦的思想。此外,前面已经介绍过,replication controller只能与重启策略为Always的pod进行协作,如果pod模板指定了其他重启策略,那么在创建的时候会提示不支持该策略,比如spec.template.spec.restartPolicy: Unsupported value:“Never”: supported values:Always)。

replication controller对pod的数量和健康状况的监控则是通过副本选择器(replica selector, label selector的一种)来实现的。replica selector定义了replication controller和它所控制的pod之间一种松耦合的关系。这与pod刚好相反,pod与属于它的Docker容器之间体现一种更强的耦合关系。这是一个非常有用的特性,因为可以通过修改pod的labels将一个pod从replication controller的控制集中移除。比如可以将出现了故障的pod从工作集群中移除,然后针对这个pod进行debug、数据恢复等操作。与此同时,replication controller则会自动重启一个新的pod来替换被移除的那个pod。需要注意的是,删除一个replication controller不会影响它所创建的pod,如果想删除一个replication controller所控制的pod,需要将该replication controller的副本数(replicas)字段置为0,这样所有的pod都会被自动删除。

最后,只要满足replica selector的pod都会受到该replication controller的影响,并不仅限于在创建时嵌套在replication controller manifest内的pod。因此,在使用时,用户需要保证任意一个pod只对应一个replication controller。这是因为replication controller没有相应的查重机制,如果一个pod对应了多个replication controller,那么这些replication controller之间会产生冲突。未来,Kubernetes不准备给replication controller赋予更多的职责。Kubernetes的设计者信奉“小而优”的设计哲学,replication controller只要准确、高效地做好以下两点工作就足够了。值得注意的是,Kubernetes现在还引入了一个ReplicaSet的概念,它可以认为是replication controller的扩展,将在后续小节中进行详细介绍。

未来,Kubernetes不准备给replication controller赋予更多的职责。Kubernetes的设计者信奉“小而优”的设计哲学,replication controller只要准确、高效地做好以下两点工作就足够了。值得注意的是,Kubernetes现在还引入了一个ReplicaSet的概念,它可以认为是replication controller的扩展,将在后续小节中进行详细介绍。

❏ 维护它所控制的pod的数量。如果需要调整pod的数量,则通过修改它的副本数(replicas)字段来实现。
❏ 在pod模板中定义replication controller所控制的pod的labels,使用replica selector匹配pod集,实现对pod的管理。

replication controller并不负责譬如调度pod、检查pod是否与指定的pod模板匹配等工作,因为这会阻塞replication controller的弹性伸缩和其他自动化操作的进程。

  1. replication controller的典型场景

❏ 重调度。前文提到,不管使用者想运行1个还是1000个pod副本,replication controller都能保证指定数目的pod正常运行。一旦当前的宿主机节点异常崩溃或pod运行终止,Kubernetes就会进行相应pod重调度。
❏ 弹性伸缩。不论是通过手动还是自动弹性伸缩控制代理来修改副本数(replicas)字段,replication controller都能轻松实现pod数量的弹性伸缩。
❏ 滚动更新(灰度发布)。replication controller被设计成通过逐个替换pod的方式来进行副本增删操作,这使得容器的滚动更新会非常简单。
■ 假设服务集群中已经有一个旧的replication controller负责管理旧版本容器的数量,现在需要启动一个新的replication controller,将其初始副本数设置成1,这个replication controller负责管理新版本容器的数量。
■ 逐步将新的replication controller的副本数+1,将旧的replication controller副本数-1,直到旧的replication controller的副本数减为0,然后将旧的replication controller删除。这样就完成了一个replication controller对应的所有pod的更新。
❏ 应用多版本release追踪。在生产环境中一个已经发布的应用程序同时在线多个release版本是一个很普遍的现象。通过replica selector机制,我们能很方便地实现对一个应用的多版本release进行管理。假设需要有10个labels均为tier=frontend, environment=prod的pod,现在希望占用其中一个pod用于测试新功能,可以进行如下操作。

■ 首先,创建一个replication controller,并设置其pod副本数为9,其replia selector为tier=frontend, environment=prod, track=stable。
■ 然后,再创建一个replication controller,并设置其pod副本数为1(作为测试pod),其replia selector为tier=frontend,environment=prod, track=canary。

  1. replication controller的使用示例

前文已经介绍过replication controller的各项定义和设计思路,下面使用以下描述文件来创建一个replication controller。

$ cat redis-controller.json
{
	"apiVersion": "v1",
	"kind": "ReplicationController",
	"metadata": {
		"name": "redis-controller",
		"labels": {
			"name": "redis"
		}
	},
	"spec": {
		"replicas": 1,
		"selector": {
			"name": "redis"
		},
		"template": {
			"metadata": {
				"labels": {
					"name": "redis"
				}
			},
			"spec": {
				"containers": [{
					"name": "redis",
					"image": "k8stest/redis:test",
					"imagePullPolicy": "IfNotPresent",
					"ports": [{
						"containerPort": 6379,
						"hostPort": 6380
					}]
				}]
			}
		}
	}
}

该资源配置文件的kind字段表明定义的是一个replication controller对象,pod的副本数为1, .spec.selector字段定义了一个label selector,表明该replication controller控制所有labels为{“name”: “redis”}的pod。.spec.template对应嵌套的pod模板,表明该pod中有一个名为redis的容器。当然,.spec. template.metadata.labels字段也是必需的,且必须与replicaSelector字段的值匹配。需要注意的是,replication controller一般也会有一组自己的labels属性,在该例子中即最下面一个"labels":{“name”: “redis”},这是一个可选项。

注意 replication controller资源文件中两个labels字段的区别:一个是属于replication controller管理的pod的,一个是属于replication controller自身的,前者是必填项,后者是可选项。

根据上述资源配置文件使用kubectl create命令创建一个replication controller对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yitian_hm

您的支持是我最大鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值