细说kubernetes - 为啥是pod?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了细说kubernetes - 为啥是pod?相关的知识,希望对你有一定的参考价值。

参考技术A

k8s作为现在最火的容器编排调度平台,好用我也就不必多说了。当我们初识k8s的时候一个新的概念就到了我们眼前,那就是pod。我们在使用了之后也就渐渐的接受了pod这个东西,但是你有没有想过,为什么是pod?k8s为什么会有这样的设计?今天我们就来细细说说这个pod

首先我们来回忆看看k8s的架构图是什么样子的

从架构图中我们可以看到,整个k8s的设计架构有以下几个要点:

当然其他组件都非常重要,这个我们以后再说,我们今天就来看看主角“pod”

一开始用的时候我就好奇为什么k8s要弄出一个pod,因为我们一开始使用的是docker,操作的是docker容器,构建的也是docker镜像,为什么不直接调度docker容器就好了,这样粒度不是更加细致,调度也会更加方便吗?
我们在使用k8s之前也使用过docker-compose,从另一个角度说,这也是一种容器的管理,看起来也挺好的。
下面我们就来说说pod

从上面的图你大概可以感受到pod在k8s中其实是一个什么样的角色。
我们如果使用虚拟机,那么上面就会有一系列的服务这些服务可能会有一些依赖,而这样的依赖就好像在服务器中运行的一个个进程组,往往其中也有着相关的依赖,而pod中的容器也是一样的道理,其中也会有类似这样的依赖,为了更好的描述和管理这样的依赖,于是就有了pod。
其实这样的理念往往可以类比出很多这样的设计。

一定会有这样的关系吗?我的感觉是,在现代技术服务的开发的过程中,这样的关系是不可避免的。我下面来举几个例子。

我们知道 java 的 web 应用往往需要部署在tomcat这样的容器之中,在 springboot 还没有出现以前,需要自己启动一个 tomcat 容器,然后将需要部署的应用打包部署到容器中去。

在以前你可能会想着,将 javaweb 打包一个war,然后编写一个 dockerfile 将 war 包cp到 tomcat 中的 webapp 目录中。但是这样带来的就是每次更新发布的时候,镜像会很大,因为每次构建都会有一个基础的tomcat镜像。

而在k8s使用的时候,会有的设计的是,将tomcat作为一个不变的镜像(它也不应该改变)而把 war 包作为另外一个容器,而这样个容器同时挂载同一个目录,将 webapp 挂载的目录与 war包挂载的目录相同来达到目的,然后将他们放到同一个 pod 中。

类似的操作还有: https://kubernetes.io/zh/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/ 里面说的就是前端静态页面和 nginx 的关系。

下面引用官网设计理念中的一句话:“ 比如你运行一个操作系统发行版的软件仓库,一个Nginx容器用来发布软件,另一个容器专门用来从源仓库做同步,这两个容器的镜像不太可能是一个团队开发的,但是他们一块儿工作才能提供一个微服务;这种情况下,不同的团队各自开发构建自己的容器镜像,在部署的时候组合成一个微服务对外提供服务。

在使用 docker 部署项目的时候会遇到一个问题就是日志持久化的问题,因为 docker 容器如果被删除的话,其中的文件也会被删除,那么我们的日志文件同时也会被删除,也就是说我们必须要将日志持久化。

最常见的方式是,将日志存储的目录挂载到宿主机上,这样容器被删除的时候日志不会被删除。
而在k8s中常见的日志处理架构是怎么样的呢?

https://kubernetes.io/zh/docs/concepts/cluster-administration/logging/

使用的是 sidecar,这个是什么呢?其实就是一个辅助性质的容器,同时与主容器放在同一个 pod 中,读取主容器挂载出来的日志目录。其实后续还可以做更多的操作,比如日志发送es等等。

总之我们可以看到,在一个pod中的容器关系是非常密切的,他们可以拥有同一个目录,甚至可以拥有同一个网络,可以拥有相互的服务,这样的关系我听过的名词叫做“超亲密关系”。就类似一对夫妻之间的关系了。

因为在现在的多说应用中,已经几乎做不到一个人顶天立地了,总是会有各种各样的依赖,依赖一些组件,依赖一些工具,依赖一些网络服务等等,一个进程组有很多的进程互相帮助来最终实现功能一样。

这样的关系太过常见,于是k8s就将它设计为了pod。

如果你已经对docker的实现比较熟悉,其实pod的实现并不复杂。(如果对docker实现不熟悉可以翻看之前的博客)
其实pod是一个逻辑上的概念,其实pod做的事情很简单:

其实k8s做的就是初始化一个infra的容器(这是一个很小的容器),利用这个容器去抢先占用需要使用的 Namespace ,然后在将用户指定的容器加载进来,同时使用的就是相同的 Namespace 了。(如果有 InitContainer 会优先按顺序初始化它,图上就不做说明了)

这样共享网络应该是没有问题了,那么要共享Volume也很简单。pod 只需要将 Volume 目录挂载到宿主机,让内部的容器挂载这个目录就可以了。

再来说说pod还有哪些功能,这些功能也是k8s为什么设计pod的原因之一

通过Probe:LivenessProbe或者ReadinessProbe,可以探测应用是否处于健康状态,如果不健康做出相关的反应。
这就好比k8s可以定期的帮你监控、维持一整个应用的健康。
其实在我们看来,很多时候服务挂了,需要重启,需要做高可用,那么nginx呢?tomcat呢?也是一样的。所以pod的健康能保证整个服务的全部健康使用。

我们可以通过给Pod增加kubernetes.io/ingress-bandwidth和kubernetes.io/egress-bandwidth这两个annotation来限制Pod的网络带宽。
为什么我提到了这个功能呢?因为在实际的业务开发过程中经常会使用一些网络插件,这些网络插件在流量的控制上非常有用,有的时候我们会根据网络流量来做一系列的操作,用户的突然增长导致的流量剧增是否要扩容等等...而这样的监控和限制对于pod来说无疑会更加方便,而不需要管pod内部的容器的流量。

重启的策略,这个也算是一个功能吧

官网:一个Pod(就像一群鲸鱼,或者一个豌豆夹)。

我觉得 Pod 更证明了一种设计模式“组合”,在有的时候会,组合的合理,就会方便很多东西,比如设计了一堆组件,组合在一起;ps画图的时候方块更圆组合在一起,就可以一起多复制几个组合。

当然我们在认识到为什么要这样设计 Pod 的同时需要意识到,我们应该将什么样的容器组合放置在同一个 Pod 之中才比较合适。遵循一定的“容器设计模式”进行编排,调度的时候才会更加得心应手。

以上是关于细说kubernetes - 为啥是pod?的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes学习总结—— Kubernetes Pod 资源管理 和 Pod 服务质量

Kubernetes_14_静态Pod网关apiserver底层都是restful接口

Kubernetes_14_静态Pod网关apiserver底层都是restful接口

为啥内存使用量大于我在 Kubernetes 的节点中设置的?

为啥我的主机路径持久卷可以从所有 pod 访问?

如何运行多进程Docker容器