pod设计原理

  容器的本质实际上是一个进程,是一个视图被隔离,资源受限的进程。

  容器的设计本身是一种“单进程”模型,指的是容器的生命周期等同于 PID=1 的进程(容器应用进程)的生命周期,由于容器的应用等于进程,所以只能去管理 PID=1 的这个进程,其他再起来的进程其实是一个托管状态。 所以说服务应用进程本身就具有“进程管理”的能力。

  如果把应用改成了 systemd,或者在容器里面运行了一个 systemd,将会导致另外一个问题:使得管理容器,不再是管理应用本身了,而等于是管理 systemd,这里的问题就非常明显了。比如这个容器里面 run 的程序或者进程是 systemd,那么接下来,这个应用是不是退出了?是不是 fail 了?是不是出现异常失败了?实际上是没办法直接知道的,因为容器管理的是 systemd。这就是为什么在容器里面运行一个复杂程序往往比较困难的一个原因。

 

  Pod 实际是 kubernetes 项目抽象出来的一个可以类比为进程组的概念。

  Pod 是 Kubernetes 分配资源的一个单位,因为里面的容器要共享某些资源,所以 Pod 也是 Kubernetes 的原子调度单位。

  Pod 里面的容器是“超亲密关系”。正常来说,有一种关系叫做亲密关系,这个亲密关系是一定可以通过调度来解决的。

  Pod 的设计要解决的核心问题所在:容器之间原本是被 Linux Namespace 和 cgroups 隔开的,所以现在实际要解决的是怎么去打破这个隔离,然后共享某些事情和某些信息。具体的解法分为两个部分:网络和存储。

  共享网络:

    在每个 Pod 里,额外起一个 Infra container 小容器来共享整个 Pod 的  Network Namespace。其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。

    由于需要有一个相当于说中间的容器存在,所以整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 是无关的。这也是为什么在 Kubernetes 里面,它是允许去单独更新 Pod 里的某一个镜像的,即:做这个操作,整个 Pod 不会重建,也不会重启,这是非常重要的一个设计。

  共享存储:

    把 volume 变成了 Pod level。所有同属于一个 Pod 的容器,共享所有的 volume。

  

  InitContainer

    Init Container 会比用户容器先启动,并且严格按照定义顺序来依次执行。

  容器设计模式:Sidecar

    在 Pod 里面,可以定义一些专门的容器,来执行主业务容器所需要的一些辅助工作。

    优势在于其实将辅助功能从业务容器解耦,能够独立发布 Sidecar 容器,并且可以重用

  典型应用:

    1. 业务容器将日志写在一个 Volume 里面,而由于 Volume 在 Pod 里面是被共享的,所以日志容器 —— 即 Sidecar 容器一定可以通过共享该 Volume,直接把日志文件读出来,然后存到远程存储里面,或者转发到另外一个例子。现在业界常用的 Fluentd 日志进程或日志组件,基本上都是这样的工作方式。

    2. 代理容器 Proxy,使用单独的Proxy,用来处理对接外部的服务集群,它对外暴露出来只有一个 IP 地址就可以了。所以接下来,业务容器主要访问 Proxy,然后由 Proxy 去连接这些服务集群,这里的关键在于 Pod 里面多个容器是通过 localhost 直接通信的,因为它们同属于一个 network Namespace,网络视图都一样,所以它们俩通信 localhost,并没有性能损耗。

    3. 适配器容器 Adapter,有个 API 的一个格式是 A,但是现在有一个外部系统要去访问我的业务容器,它只知道的一种格式是 API B ,所以要做一个工作,就是把业务容器怎么想办法改掉,要去改业务代码。但实际上,你可以通过一个 Adapter 帮你来做这层转换。

 
posted @ 2023-10-29 20:20  花都八达鸟  阅读(52)  评论(0)    收藏  举报