[Kubernetes] Pod 基本原理

Pod 原理

Pod 作为最小调度单位

容器——单进程模型:不是指容器只能运行一个进程(线程,轻量级进程),而是说容器没有管理多个进程的能力。因为容器内PID=1的进程就是容器本身,容器内其他进程都是这个容器进程的子进程,在容器内没有类似 init 进程和 systemd 这样执行进程管理功能的进程。

在操作系统中,应用往往不是以单个进程的形式运行,而是以进程组的形式存在(Linux 中的进程实际上是线程,或者说轻量级进程)。进程组之间的进程相互之间可能会基于 IPC(Inter Process Comunication) 进行通信。这就要求这些进程都运行在同一台宿主机上。

由于容器的单进程模型,进程组之间的各个进程各自需要运行在不同的容器中。假设某个应用进程组中有三个进程。

假设每个容器都需要 1 GB 的内存配额。集群中有两个节点,node-1 有 3 GB,node-2 有 2.5 GB。如果将应用的进程一个个单独调度,那么可能出现同一应用进程组中的各个进程被调度到了不同节点上,或者在设置了亲和性的情况下,出现节点上内存资源不足,可是却已经把部分进程调度到了该节点的状况。

在 Kubernetes 中,不是以容器作为基本调度单位,而是以 Pod 作为调度单位,应用所需要的三个容器一起组成一个 Pod,k8s 以 Pod 作为资源分配以及任务调度的单位,就可以解决上述问题。

这种容器之间的紧密联系,可以称为“超亲密关系”。

容器设计模式

除了上述的调度方面的考虑外,Pod 还有一个重要意义在于容器设计模式。

Pod 的本质是一组共享了某些资源的容器。Pod 中的容器,共享同一个Network Namespace,并且可以声明共享同一个 Volume

类似于:

$ docker run --net=B --volumes-from=B --name=A image-A ...

但是以上述方式启动容器,就注定需要容器 B 比容器 A 先启动。

因此在 kubenetes 中,Pod 的实现需要使用一个中间容器或者说 Infra 容器。在 Kubernetes 创建 Pod 时,首先启动的都是这个容器,其他用户定义的容器通过 Join Network Namesapce 的方式使用 Infra 容器的 Network Namespace,这样就实现了 Pod 内容器共享网络设备。

Infra 容器本身是一个非常特殊的镜像,叫做 k8s.gcr.io/pause,这个进程永远处于“暂停”状态。

后续用户定义的容器通过 Join Network Namespace 实现了:

  • 它们可以直接使用 localhost 进行通信
  • 看到的网络设备就是 Infra 的网络设备
  • 一个 Pod 只有一个 IP 地址,也就是 Pod 的 Network Namespace 对应的 IP 地址
  • Pod 的生命周期只和 Infra 容器相关,和用户容器无关

那么实际上,Pod 的网络通信也是通过 Infra 容器完成的。而 Infra 容器的镜像中几乎什么都没有,那么在开发容器网络插件时,就不能使用其他的安装包,只需要关注如何通过 docker 启动接口配置 Network Namespace 即可

同时,卷的挂载也是一个原理。一个 Volume 对应的宿主机目录对于 Pod 来说就只有一个,Pod 内的容器只需要声明挂载这个 Volume 就可以共享这个 Volume 所对应的宿主机目录。

apiVersion: v1
kind: Pod
metadata:
  name: two-containers
spec:
  restartPolicy: Never
  volumes:
  - name: shared-data
    hostPath:      
      path: /data
  containers:
  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  - name: debian-container
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    command: ["/bin/sh"]
    args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]

例如上述 yaml 文件中,ngnix-container 和 debian-container 两个容器都挂载了宿主机的 /data 文件夹,两个容器实现了数据共享。

所谓容器设计模式就是充分利用 Pod 的原理,合理地设计 Pod 内容器的功能。
比如为了实现 Pod 内的日志收集。那么我们可以将 Pod 里的一个 Volume 挂载到容器内的 /var/log 目录中,同时在 Pod 里运行另一个 sidecar 容器,它也挂载该 Volume,接下来 sidecar 容器只需要将日志文件的内容通过 MongoDB 或者 Elasticsearch 保存起来。

猜你喜欢

转载自www.cnblogs.com/hezhiqiangTS/p/12125496.html