Kubernetes 之 Pod 实现原理
Pod 就是最小并且最简单的 Kubernetes 对象
Pod、Service、Volume 和 Namespace 是 Kubernetes 集群中四大基本对象,它们能够表示系统中部署的应用、工作负载、网络和磁盘资源,共同定义了集群的状态。Kubernetes 中很多其他的资源其实只对这些基本的对象进行了组合。
Pod -> 集群中的基本单元 Service -> 解决如何访问 Pod 里面服务的问题 Volume -> 集群中的存储卷 Namespace -> 命名空间为集群提供虚拟的隔离作用
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
Pod 的内部结构
Pod 代表着集群中运行的进程:共享网络、共享存储
在同一个 Pod 中,有几个概念特别值得关注,首先就是容器,在 Pod 中其实可以同时运行一个或者多个容器,这些容器能够共享网络、存储以及 CPU/内存等资源。
首先,我们需要知道的是,每个 Pod 都有一个特殊的被称为 “根容器” 的 Pause 容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,通过 Pause 容器使工作在对应 Pod 的容器之间可以共享网络、共享存储。
Pod 共享资源
为什么 Kubernetes 会设计出一个全新的 Pod 概念,并且有这样特殊的结构?主要是因为,使用 Pause 容器作为 Pod 根容器,以它的状态代表整个容器组的状态;其次,Pod 里的多个业务容器共享 Pause 容器的 IP 地址,共享 Pause 容器挂接的 Volume 资源。
共享存储资源
可以为一个 Pod 指定多个共享的 Volume 资源。Pod 中的所有容器都可以访问共享的 volume 资源。Volume 也可以用来持久化 Pod 中的存储资源,以防容器重启后文件丢失。
共享网络资源
每个 Pod 都会被分配一个唯一的 IP 地址。Pod 中的所有容器共享网络空间,包括 IP 地址和端口。Pod 内部的容器可以使用 localhost 互相通信。Pod 中的容器与外界通信时,必须分配共享网络资源,例如使用宿主机的端口映射。
veth 设备的特点
一个设备收到协议栈的数据发送请求后,会将数据发送到另一个设备上去
veth 和其它的网络设备都一样,一端连接的是内核协议栈 veth 设备是成对出现的,另一端两个设备彼此相连
# 物理网卡eth0配置的IP为192.168.1.11
# 而veth0和veth1的IP分别是192.168.2.11和192.168.2.10
+----------------------------------------------------------------+
| |
| +------------------------------------------------+ |
| | Newwork Protocol Stack | |
| +------------------------------------------------+ |
| ↑ ↑ ↑ |
|..............|...............|...............|.................|
| ↓ ↓ ↓ |
| +----------+ +-----------+ +-----------+ |
| | eth0 | | veth0 | | veth1 | |
| +----------+ +-----------+ +-----------+ |
|192.168.1.11 ↑ ↑ ↑ |
| | +---------------+ |
| | 192.168.2.11 192.168.2.10 |
+--------------|-------------------------------------------------+
↓
Physical Network
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),通过这个覆盖网络,将数据包原封不动地传递给目标容器内。
不同情况下的网络通信方式
同一个 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 服务。
ETCD 之于 Flannel 提供说明:
存储管理 Flannel 可分配的 IP 地址段资源 监控 ETCD 中每一个 Pod 的实际 IP 地址,并在内存中建立维护 Pod 节点的路由表
Pod 的多种类型
Pod 存在多种不同的创建类型来满足不一样的用途
ReplicationController
ReplicationController 用来确保容器应用的副本数量始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来代替,而如果异常多出现的容器会自动回收。
ReplicaSet
在新版本(相对而言的较优方式)的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 来管理 Pod。虽然 ReplicaSet 和 ReplicationController 并没有本质上的不同,只是名字不一样而已,唯一的区别就是 ReplicaSet 支持集合式的 selector,可供标签筛选。
虽然 ReplicaSet 可以独立使用,但一般还是建议使用 Deployment 来自动管理 ReplicaSet 创建的 Pod,这样就无需担心跟其他机制的不兼容问题。比如 ReplicaSet 自身并不支持滚动更新(rolling-update),但是使用 Deployment 来部署就原生支持。
Deployment
Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义方法,用来替代以前使用 ReplicationController 来方便且便捷的管理应用。主要的应用场景,包括:滚动升级和回滚应用、扩容和缩容、暂停和继续。
HPA
HPA 仅仅适用于 Deployment 和 ReplicaSet,在 V1 版本中仅支持根据 Pod 的 CPU 利用率扩缩容,在新版本中,支持根据内存和用户自定义的 metric 动态扩缩容。
StatefulSet
StatefulSet 是为了解决有状态服务的问题,相对于 Deployment 和 ReplicaSet 而已。其主要的使用场景,包括:稳定的持久化存储、稳定的网络标识、有序部署、有序收缩。
DaemonSet
DaemonSet 确保全部或者一些 Node 上面运行一个 Pod 副本。当有 Node 加入集群的时候,也会为它们新加一个 Pod。当有 Node 从集群中移除的时候,这些 Pod 也会被回收。删除 DaemonSet 将会删除它所创建的所有 Pod。
使用 DaemonSet 的典型场景就是,在每个节点运行日志收集、运行监控系统、运行集群存储等服务,只要新加进来的节点都需要运行该服务。
Job
Job 负责批处理任务,仅执行一次的任务,它保证批处理任务的一个或者多个 Pod 成功结束,才会返回成功。
Cront Job
Cront Job 管理是基于时间的 Job,即在给定时间点只运行一次,且周期行的在给定时间点运行特定任务。
- END -
往期推荐:
Kubernetes Ingress-Nginx 实现蓝绿、灰度发布
订阅,一起成长
K8s生态圈
点在看,K8s一年不出问题 👇