Kubernetes中的Pod的到底是什么?


【编者的话】本文介绍了Kubernetes Pod的基本概念及其在容器应用和Kubernetes部署中的作用。作者通过实例演示,具体地阐述了Pod的本质和作用,并给出了Pod使用的一些建议。

【烧脑式Kubernetes实战训练营】本次培训理论结合实践,主要包括:Kubernetes架构和资源调度原理、Kubernetes DNS与服务发现、基于Kubernetes和Jenkins的持续部署方案 、Kubernetes网络部署实践、监控、日志、Kubernetes与云原生应用、在CentOS中部署Kubernetes集群、Kubernetes中的容器设计模式、开发Kubernetes原生应用步骤介绍等。

最近看到了伟大的“Amy Codes”(真心希望这是她真名)关于Kubernetes Pod的一条推文:


知道为什么一个Pod中的容器总是配置成一起工作么?因为这是嵌套的容器。

——Amy Codes, 2017.8.21
尽管说的并不是100%的准确(容器并不是这回事,我们后面再讲),但也确实说明Pod是非常神奇的。所以,也值得我们研究一下Pod和容器的真实面目。

Kubernetes的Pods官方文档最权威且详尽地解释了Pod,但是官方文档写的更偏整体性,而且用了很多术语。笔者强烈建议从头到尾阅读官方文档,因为官方文档的解释要比笔者写的更好更准确。这篇博文希望能提供更加接地气的介绍。

容器并不是Linux系统的containers

许多人知道这个事实,但是Linux系统中的“containers”并不是真实存在的。在Linux中,没有叫做“container”(容器)的实体。大家所知道的容器,其实是依托于Linux的两个特性而运行的正常的系统进程,这两个特性是命名空间和cgroups。命名空间提供对于某个进程的一种“视图”,可以将其它命名空间的东西隐藏,从而为该进程提供它自己独立运行的环境。这使得进程之间互相不可见,也不可相互影响:

命名空间包括如下:
  • 主机名
  • 进程ID(PID)
  • 文件系统
  • 网络接口
  • 进程间通信(IPC)


上面提到,运行在一个命名空间的进程不会与其它的进程互相影响,其实也并不完全是这样。一个进程可以使用它所在的物理机的所有资源,所以会挤占其它进程的可用资源。为了限制这样的情况,Linux提供了一种特性叫做cgruops。进程在一个cgroup中运行的情况与在一个命名空间中类似,但是cgroup限制了该进程可用的资源。所谓的“资源”包括CPU、内存、阻塞I/O、网络I/O等。CPU的分配可以以千分之一核为单位,内存的分配可以以字节(bytes)为单位。该进程可以正常运行,但是它只可以使用cgroup允许的CPU能力,如果所使用的内存超出cgroup设置的限制就会内存溢出。

通过Google可以搜索到很多关于命名空间和cgroups的学习资料。笔者建议大家可以先学习一下。以下是几个推荐资料:


需要指出的是,cgroups和每个命名空间类型,是_分开的特性_。上文列出的命名空间的组成部分,某些可能会用到,也有些用不到。你可以只使用cgroups进行隔离,或者使用cgroups和不同命名空间类型的组合(其实仍然是使用命名空间和cgroups,但只是使用根元素)。命名空间和cgroups也可以作用于_一组进程_。用户可以在一个命名空间中运行多个进程。这种情况下,进程可以互相可见,也可以进行交互。用户也可以在一个单独的cgroup中运行多个进程。这种方式会限制这组进程可使用的CPU和内存资源。

组合的组合

在使用Docker运行容器时,Docker会为每个容器创建命名空间和cgroups,所以Docker和容器是一一对应的。这也是开发者对于容器的正常认知。
pic-pods-1.png

容器本质上类似于独立的存储仓。如果容器需要与外界通信,容器就需要存储卷或将端口映射到宿主机。

但是,通过增加命令行参数,你可以用一个单独的命名空间将Docker容器结合起来。首先,我们先为nginx创建一个单独的容器。
$ cat <<EOF >> nginx.conf
> error_log stderr;
> events { worker_connections  1024; }
> http {
>     access_log /dev/stdout combined;
>     server {
>         listen 80 default_server;
>         server_name example.com www.example.com;
>         location / {
>             proxy_pass http://127.0.0.1:2368;
>         }
>     }
> }
> EOF
$ docker run -d --name nginx -v `pwd`/nginx.conf:/etc/nginx/nginx.conf -p 8080:80 nginx 

然后,我们再启动一个容器,运行ghost(ghost是一款开源的博客发布平台/软件)。但是这次我们会增加一些额外的参数,使得这个容器与nginx处于同一个namespace中。
$ docker run -d --name ghost --net=container:nginx --ipc=container:nginx --pid=container:nginx --net=container:nginx ghost

现在,我们的nginx容器可以在localhost上直接将请求代理转发给ghost容器。如果你访问http://localhost:8080,你应该可以看到通过nginx代理运行的ghost。上述命令创建了一组容器,这些容器运行在同一组命名空间中。这些命名空间允许Docker的容器互相发现并通信。
pic-pods-2.png

Pods是一种容器

我们已经看到,我们可以将命名空间和cgroups与多个线程结合起来,而这正是Kubernetes Pods的本质。Pods让你可以指定想要运行的容器,而Kubernetes自动地建立相应的命名空间和cgroups。实际上还要复杂一些,因为Kubernets并不使用Docker网络(Kubernetes使用CNI,Container Network Interface,容器网络接口),但是本质是类似的。
pic-pods-3.png

只要我们将容器设置成这种模式,每个进程会“感觉”它运行在同一台机器上。这些容器可以在本机互相通信,也可以共享存储卷(volume)。他们之间甚至可以使用IPC或者互相发送HUP或者TERM这种信号(需要在Kubernetes 1.7,以及Docker>=1.3环境共享PID命名空间)。

现在假设你想运行nginx和confd,使用confd更新nginx配置信息,并在你增加/移除应用服务器时重启nginx。假设你部署了一台etcd服务器,该服务器有后端应用服务器的IP地址。当IP列表变化时,confd会收到通知,生成新的nginx配置,并且会给nginx发HUP信号通知nginx重新加载新配置。
pic-pods-4.png

如果基于Docker做上述工作,你可以将nginx和confd放在同一个容器中。由于Docker只有一个入口点(entrypoint),你需要使用类似supervisord的工具保证两个进程持续运行。这种做法并不理想,因为你得为每个运行的nginx副本运行supervisord。更重要的是,Docker只“知道”supervisord,因为supervisord是Docker的入口点。Docker无法看到每个进程,这意味着维护人员以及所用工具无法通过Docker API获取这些进程的信息。nginx可能已经跪了好久,但是Docker却对此一无所知。
pic-pods-5.png

但是通过Pod,Kubernetes可以管理每个进程,因此对于每个进程的状态都有监控。这样,Kubernetes可以通过API向用户提供进程的状态,而且也可以提供一些服务,例如进程重启或者自动日志记录等。
pic-pods-6.png

将Pods容器作为API

通过上文所述的方式将容器和Pod结合起来,本质上我们可以实现创建容器、将容器加入到Pod中并作为一种“API”供其他人使用。这种API跟正常的Web API不同,更像是一种其它Pods可以使用的抽象API。

以nginx+confd的结合为例。在此示例中,confd对nginx进程一无所知。confd认为自己的工作,就是监控一个etcd中的值,并且向某个进程发送HUP信号或者运行一条命令。confd监控的app并不一定是nginx。这个app可以是任何类型的应用。这种情况下,用户可以使用confd容器镜像和配置,并将confd应用于任何数量的、不同种类的Pods。以这种用法使用的Pods可以称为“侧斗容器”(“侧斗”是像三轮摩托警车的侧边座位那种。译者注),可调用“摩托车的侧斗”镜像。

你也可以想象其它类型的抽象描述。类似istio的全互连服务,可以作为“侧斗”安插到服务中,提供服务路由、遥测、策略加强等服务,而且不需要修改主应用。

你也可以使用多个“侧斗”。你完全可以同时结合confd和istio服务。多种应用可以使用这种方式结合起来,创建更加复杂可靠的系统,同时还能保持每个app相对简单。

希望本文比较清楚地解释了Pods是什么,以及为什么Pods在未来的容器部署中是必不可少的一部分。如果你有兴趣对Kubernetes进行更深入的了解,可以加入Kubernetes Slack。这是最优秀的Kubernetes开发者集中讨论问题的地方。你可以加入#Kubernetes-users聊天室(Slack中叫做channel。译者注),参与Kubernetes各个方面的讨论。

原文链接:What are Kubernetes Pods Anyway?(翻译:孙琪)

==========================================
译者介绍

孙琪,BeeCloud比可网络科技研发工程师,专注于支付技术集成及支付系统架构优化。北京邮电大学硕士毕业,研究方向为IPv6网络标准化,已发布三篇IETF国际标准。

0 个评论

要回复文章请先登录注册