文章归档

为什么我们需要Pod和Service?

我们知道pod和service是kubernetes中非常核心的两个概念,要了解这两个东西,就需要看看它们解决了什么问题。

Pod要解决的问题是:数据共享和交互

而Service,是解决Naming问题的另一种思路

1. Pod要解决什么问题?

共享是Pod最原始的需求,早在google的borg论文里,我们就能看到类似的场景,例如borg中的alloc通常用来运行多个Job,举例:有两个Job,一个job是web server实例,另一个job是负责日志收集

1.1 数据共享

数据共享是最常见的一个场景,pod中有volume来解决这种问题,所谓volume,其实就是在不同的容器之间共享一块磁盘。docker里可以用 --volume= 等用法

1.2 容器交互

交互是更深一层次的共享

我们知道容器之间是天然隔离的,除非使用特别hack的方法,否则你根本就无法看到另外一个容器里的任何东西,事实上你除了能看到你自己之外根本就不知道别人的存在。

多容器共生是这个问题的原始需求,AB容器是一个服务下的两个模块,相互依赖共存亡,既需要做好容器间的隔离,例如CPU、内存、网络带宽等等,又需要解决模块间交互的问题。前面我们说的数据共享只是容器交互最简单的一种形式,除此之外,我们需要解决的共享需求有:

  1. 网络
  2. 进程体系
  3. 文件系统

docker提供一些方法来解决这些问题,例如容器之间共享网络可以使用如下命令:

docker run --tty -i --net=container:11e9bc1b8f5be ubuntu /bin/bash

不过目前kubernetes似乎仅仅支持共享网络,还不支持进程体系、文件系统之间的共享

1.3 kubernetes的解决方案

从上面我们描述的问题和解决方案里,似乎docker就能够完全胜任,那为什么要需要Pod呢?

docker作为一个定位于纯粹的单机容器引擎,它只需要提供解决这些问题的一些机制就足够了,很符合Unix的设计哲学:机制和策略分离。在这里机制是什么?docker提供的机制就是允许容器之间某些东西是可以相互共享的,docker使用引用计数来管理这种行为。

但是引用计数的问题在于复杂的依赖关系、生命周期管理。这是策略要解决的问题

kubernetes抽象出了基础容器,打平了依赖关系,统一了生命周期:

  • 在pod里,隐藏着一个基础容器,负责创建所有容器所依赖的底层设备
  • 所有容器都是基于基础容器创建的,容器之间不相互依赖,仅仅依赖基础容器
  • 基础容器与所有容器共生,最后被销毁

2. Service要解决什么问题?

Kubernetes中Pod不是一成不变的,它们可以随着时间进行迁移。虽然每个pod都有属于自己的IP地址,但是却不能保证每个Pod的IP地址随着时间的变化依然保持不变。这就导致了一个问题: 如果在Kubernetes集群里,Pod之间相互提供服务,那么该如何找到对方呢?

2.1 Naming

Naming是解决这种问题的一种最直观的思路,给不同的Pod分配一个唯一ID,通过ID来访问Pod所提供的服务。Naming有很多解决方案,传统的方案就是DNS,google的borg自然也有BNS来解决这种问题

DNS怎么解决Pod的Naming问题呢?

  • 首先你得有一个DNS服务器,不管是使用ISP的还是自建的
  • 域名自动注册、状态更新、删除

如果你的Pod有多副本、跨机房容灾,这么做可能还不够,还得考虑怎么做负载均衡:

  • 依赖DNS提供商的高级付费服务,支持一个域名下绑定N个IP,支持区域粒度的负载均衡
  • 自己查询DNS信息,client段做负载均衡。负载均衡的策略和client段不解耦,升级困难,容灾不友好

2.2 kubernetes的解决方案

相对而言,kubernetes比较笨重,但更简单、更易用。kubernetes使用了external Port, portal, 环境变量的方式来解决这个问题

2.2.1 Portal

portal是一个由服务虚拟IP和端口组成的元祖,集群内任意一个节点都可以通过portal来访问服务,portal的原理如下:

在Kubernetes集群中的每个node上都运行着一个proxy模块:kube-proxy,它主要做两件事情:首先在本地节点上监听一个随机端口,并转发该端口上的流量到后端服务,如果pod是多副本的,默认的负载均衡策略是round robin;然后kube-proxy还会创建一系列的iptables规则,通过这些规则,所以本地访问portal的数据包都会被重定向到第一步所创建的随机端口上。

2.2.2 External Port

原理和Portal很类似,就是在所有节点上监听一个固定端口,任何一个pod都可以通过访问其所在node的这个端口来访问服务,同样是由kube-proxy做代理。
说实话这个感觉意义一点都不大

2.2.3 环境变量

当一个pod被创建时,master会自动的为这个pod设置一组环境变量:这个环境变量了包含集群内已有所有服务的Service信息,例如portal等等

POD1_SERVICE_HOST=10.0.0.11
POD1_SERVICE_PORT=6379
POD2_SERVICE_HOST=10.0.0.10
POD2_SERVICE_PORT=6378

因此,新的Pod通过环境变量就能快速的访问到所有服务

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>