Kubernetes之Pod实现原理

2022年 9月 30日 36.4k 0

Pod 就是最小并且最简单的 Kubernetes 对象

本机关于Pod实现原理的主要知识点汇总
Pod、Service、Volume 和 Namespace 是 Kubernetes 集群中四大基本对象,它们能够表示系统中部署的应用、工作负载、网络和磁盘资源,共同定义了集群的状态。Kubernetes 中很多其他的资源其实只对这些基本的对象进行了组合。

  • Pod -> 集群中的基本单元
  • Service -> 解决如何访问 Pod 里面服务的问题
  • Volume -> 集群中的存储卷
  • Namespace -> 命名空间为集群提供虚拟的隔离作用

Kubernetes集群中四大基本对象
Kubernetes 有许许多多的技术概念,同时对应很多 API 对象,其中最重要的也是最基础的是 Pod 对象。Pod 是在 Kubernetes 集群中运行部署应用或服务的最小单元,它是可以支持多容器的。**Pod 的设计理念是支持多个容器在一个 Pod 中共享网络地址和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务**。

apiVersion: v1
kind: Pod
metadata:
  name: busybox
  labels:
    app: busybox
spec:
  containers:
  restartPolicy: Always
    - name: busybox
      image: busybox
      command:
        - sleep
        - "3600"
      imagePullPolicy: IfNotPresent

1. Pod 的内部结构

Pod 代表着集群中运行的进程:共享网络、共享存储

在同一个 Pod 中,有几个概念特别值得关注,首先就是容器,在 Pod 中其实可以同时运行一个或者多个容器,这些容器能够共享网络存储以及 CPU/内存等资源。

首先,我们需要知道的是,每个 Pod 都有一个特殊的被称为 “根容器” 的 Pause 容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,通过 Pause 容器使工作在对应 Pod 的容器之间可以共享网络共享存储

Pod的内部结构
[1] Pod 共享资源
为什么 Kubernetes 会设计出一个全新的 Pod 概念,并且有这样特殊的结构?主要是因为,使用 Pause 容器作为 Pod 根容器,以它的状态代表整个容器组的状态;其次,Pod 里的多个业务容器共享 Pause 容器的 IP 地址,共享 Pause 容器挂接的 Volume 资源。

  • 共享存储资源

可以为一个 Pod 指定多个共享的 Volume 资源。Pod 中的所有容器都可以访问共享的 volume 资源。Volume 也可以用来持久化 Pod 中的存储资源,以防容器重启后文件丢失。

  • 共享网络资源

每个 Pod 都会被分配一个唯一的 IP 地址。Pod 中的所有容器共享网络空间,包括 IP 地址和端口。Pod 内部的容器可以使用 localhost 互相通信。Pod 中的容器与外界通信时,必须分配共享网络资源,例如使用宿主机的端口映射。

Pod的容器之间可以共享网络、共享存储
[2] veth 设备的特点
一个设备收到协议栈的数据发送请求后,会将数据发送到另一个设备上去

  • veth 和其它的网络设备都一样,一端连接的是内核协议栈
  • veth 设备是成对出现的,另一端两个设备彼此相连
# 物理网卡eth0配置的IP为192.168.1.11
# 而veth0和veth2的IP分别是192.168.2.11和192.168.2.10

+----------------------------------------------------------------+
|                                                                |
|       +------------------------------------------------+       |
|       |             Newwork Protocol Stack             |       |
|       +------------------------------------------------+       |
|              ↑               ↑               ↑                 |
|..............|...............|...............|.................|
|              ↓               ↓               ↓                 |
|        +----------+    +-----------+   +-----------+           |
|        |   eth0   |    |   veth0   |   |   veth2   |           |
|        +----------+    +-----------+   +-----------+           |
|192.168.1.11  ↑               ↑               ↑                 |
|              |               +---------------+                 |
|              |         192.168.2.11     192.168.2.10           |
+--------------|-------------------------------------------------+
               ↓
         Physical Network

2. Pod 的网络通信

集群网络解决方案: Kubernetes + Flannel

Kubernetes 的网络模型假定了所有 Pod 都在一个直接连通的扁平的网络空间中,这在 GCE(Google Compute Engine)里面是现成的网络模型,Kubernetes 假定这个网络已经存在了。而在私有云搭建 Kubernetes 集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的 Docker 容器之间的互相访问先打通,然后才能正常运行 Kubernetes 集群。

  • 同一个 Pod 内多个容器之前通过回环网络(lo - 127.0.0.1)进行通信
  • 各 Pod 之间的通讯,则是通过 Overlay Network 网络进行通信
  • 而 Pod 与 Service 之间的通讯,则是各节点的 iptables 或 lvs 规则

Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个网络规划服务,简单来说,它的功能就是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。而且它还能在这些 IP 地址之间建立一个覆盖的网络(Overlay Network),通过这个覆盖网络,将数据包原封不动地传递给目标容器内。

Overlay Network 网络进行通信
数据包原封格式
[1] 不同情况下的网络通信方式

  • 同一个 Pod 内部通讯:
    • 同一个 Pod 共享同一个网络命名空间,共享同一个 Linux 协议栈。
  • 不同 Pod 之间通讯:
    • Pod1 和 Pod2 在同一台 Node 主机,由 docker0 网桥直接转发请求到 Pod2 上面,不经过 Flannel 的转发。
    • Pod1 和 Pod2 不在同一台 Node 主机,Pod 的地址是与 docker0 在同一个网段的,但 docker0 网络与宿主机网卡是两个完全不同的 IP 网段,并且不同的 Node 之间的通讯只能通过宿主机的物理网卡进行。将 Pod 的 IP 地址和所在 Node 的 IP 地址关联起来,通过这个关联让 Pod 可以互相访问。
  • Pod 至 Service 的网络
    • 目前基于性能考虑,全部为 iptables 或 lvs 维护和转发。
  • Pod 到外网
    • Pod 想外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主机网卡完成路由选择之后,iptables 或 lvs 执行 Masquerade,把源 IP 地址更改为宿主机的网卡的 IP 地址,然后向外网服务器发送请求。
  • 外网访问 Pod
    • 通过 Service 服务来向外部提供 Pod 服务。

[2] ETCD 之于 Flannel 提供说明:

  • 存储管理 Flannel 可分配的 IP 地址段资源
  • 监控 ETCD 中每一个 Pod 的实际 IP 地址,并在内存中建立维护 Pod 节点的路由表

ETCD之于Flannel提供说明

3. Pod 的多种类型

Pod 存在多种不同的创建类型来满足不一样的用途

Kubernetes组件工作架构图

  • [1] ReplicationController

ReplicationController 用来确保容器应用的副本数量始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来代替,而如果异常多出现的容器会自动回收。

  • [2] ReplicaSet

在新版本(相对而言的较优方式)的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 来管理 Pod。虽然 ReplicaSet 和 ReplicationController 并没有本质上的不同,只是名字不一样而已,唯一的区别就是 ReplicaSet 支持集合式的 selector,可供标签筛选。
虽然 ReplicaSet 可以独立使用,但一般还是建议使用 Deployment 来自动管理 ReplicaSet 创建的 Pod,这样就无需担心跟其他机制的不兼容问题。比如 ReplicaSet 自身并不支持滚动更新(rolling-update),但是使用 Deployment 来部署就原生支持。

  • [3] Deployment

Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义方法,用来替代以前使用 ReplicationController 来方便且便捷的管理应用。主要的应用场景,包括:滚动升级和回滚应用扩容和缩容暂停和继续

  • [4] HPA

HPA 仅仅适用于 Deployment 和 ReplicaSet,在 V1 版本中仅支持根据 Pod 的 CPU 利用率扩缩容,在新版本中,支持根据内存和用户自定义的 metric 动态扩缩容。

  • [5] StatefulSet

StatefulSet 是为了解决有状态服务的问题,相对于 Deployment 和 ReplicaSet 而已。其主要的使用场景,包括:稳定的持久化存储、稳定的网络标识、有序部署、有序收缩。

  • [6] DaemonSet

DaemonSet 确保全部或者一些 Node 上面运行一个 Pod 副本。当有 Node 加入集群的时候,也会为它们新加一个 Pod。当有 Node 从集群中移除的时候,这些 Pod 也会被回收。删除 DaemonSet 将会删除它所创建的所有 Pod。
使用 DaemonSet 的典型场景就是,在每个节点运行日志收集、运行监控系统、运行集群存储等服务,只要新加进来的节点都需要运行该服务。

  • [7] Job

Job 负责批处理任务,仅执行一次的任务,它保证批处理任务的一个或者多个 Pod 成功结束,才会返回成功。

  • [8] Cront Job

Cront Job 管理是基于时间的 Job,即在给定时间点只运行一次,且周期行的在给定时间点运行特定任务。

相关文章

KubeSphere 部署向量数据库 Milvus 实战指南
探索 Kubernetes 持久化存储之 Longhorn 初窥门径
征服 Docker 镜像访问限制!KubeSphere v3.4.1 成功部署全攻略
那些年在 Terraform 上吃到的糖和踩过的坑
无需 Kubernetes 测试 Kubernetes 网络实现
Kubernetes v1.31 中的移除和主要变更

发布评论