容器开放接口
Kubernetes 作为云原生应用的基础调度平台,相当于云原生的操作系统,为了便于系统的扩展,kubernetes 中开放了以下接口,可以分别对接不同的后端,实现自己的业务逻辑:
- 容器运行时接口(CRI):提供计算资源
- 容器网络接口(CNI):提供网络资源
- 容器存储接口(CSI):提供存储资源
以上三种资源相当于一个分布式操作系统的最基础的几种资源类型,而 kubernetes 是将它们粘在一起的纽带。
容器开放接口
Kubernetes 作为云原生应用的基础调度平台,相当于云原生的操作系统,为了便于系统的扩展,kubernetes 中开放了以下接口,可以分别对接不同的后端,实现自己的业务逻辑:
以上三种资源相当于一个分布式操作系统的最基础的几种资源类型,而 kubernetes 是将它们粘在一起的纽带。
CRI
CRI 是一个插件接口,使 kubelet 能够使用各种容器运行时,无需重新编译集群组件。
CRI 是 kubelet 和容器运行时之间通信的主要协议。CRI 定义了 grpc 协议,用于集群组件 kubelet 与 容器运行时之间的通信。 当通过 grpc 连接到容器运行时,kubelet 充当客户端。运行时和镜像服务端点必须在容器运行时中可用。
k8s v1.24之前的 kubernetes 版本集成了 Docker Engine 的一个组件,名为 dockershim 。在v1.24之后会被移除,需要替换其他的运行时。
几种 kubernetes 常见的容器运行时:
在 Linux 上, CGroup 用于限制分配给进程的资源。
kubelet 和运行时都需要对接控制组来强制执行为 Pod 和容器管理资源,如CPU和Memory。如果要对接控制组,kubelet和容器运行时需要使用一个cgroup驱动。并且 kubelet 和 容器运行时需要使用相同的 cgroup 驱动和相同的配置。
cgroupfs 驱动是 kubelet 中默认的cgroup驱动。当使用 cgroupfs 驱动时,kubelet 和容器运行时将直接对接 cgroup 文件系统来配置 cgroup。
当 systemd 是初始化系统时, 不推荐使用 cgroupfs 驱动,因为 systemd 期望系统上只有一个 cgroup 管理器。因此,如果使用 cgroup v2,则应该使用 systemd cgroup 驱动取代 cgroupfs。
当某个 Linux 系统发行版使用 systemd 作为初始化系统时,初始化进程会生成并使用一个 root 控制组(cgroup),并充当 cgroup 管理器。
当机器上有两个不同的 cgroup 管理器时,会对资源出现两个视图。如将 kublet 和 容器运行时配置为 cgroupfs,但为剩余的进程使用 systemd 的那些节点会在资源压力增大时不稳定。
配置文件: /etc/containerd/config.toml
在 Linux 上,containerd 的默认 CRI 套接字是 /run/containerd/containerd.sock。
Container Storage Interface (CSI)。在 kubernetes V1.13 版本中升级为 GA 。
CSI 为容器编排系统(如 kubernetes)定义标准接口,以将任意存储系统暴露给它们的容器工作负载。
CSI 卷类型是一种 out-tree 的 CSI 卷插件,用于 Pod 与同一节点上运行的外部 CSI 卷驱动程序交互。 部署 CSI 兼容卷驱动后,用户可以使用 csi 作为卷类型来挂载驱动提供的存储。
CSI 卷可以在 Pod中以三种方式使用:
CSI 持久卷具有以下字段可供用户指定:
Out-of-Tree 卷插件包括容器存储接口CSI。它们使存储供应商创建自定义存储插件,而无需将插件源码添加到 kubernetes 代码仓库。
CSI 允许独立于 Kubernetes 代码库开发卷插件,并作为扩展部署(安装)在 Kubernetes 集群上。
以前所有的卷插件都是树内的。“树内”插件是与 Kubernetes 的核心组件一同构建、链接、编译和交付的。这意味着向 Kubernetes 添加新的存储系统(卷插件)需要将 代码合并到 kubernetes 核心代码库中。
通过为 CSI 创建插件 StorageClass 来支持动态配置的 CSI Storage 插件启用自动创建/删除。
例如,以下允许通过名为 com.example.team/csi-driver 的 CSI Volume Plugin 动态创建 fast-storage 的 Volume。
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: fast-storage
provisioner: com.example.team/csi-driver
parameters:
type: pd-ssd
要触发动态配置,需要创建一个 PersistentVolumeClaim 对象。例如,下面的 pvc 可以使用上面的 storageClass 触发动态配置。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-request-for-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: fast-storage
当动态创建 Volume 时,通过 CreateVolume 调用,将参数 type: pd-ssd 传递给 CSI 插件 com.example.team/csi-driver。 作为响应,外部 volume 插件会创建一个新的 Volume,然后自动创建一个 pv 对象来对应前面的 PVC。 然后,kubernetes 会将新的 PersistentVolume 对象绑定到 pvc,使其可以使用。
Container Network Interface(CNI)是k8s网络插件的基础。
Container Network Interface(CNI)是k8s网络插件的基础。基本思想是:Container Runtime 在创建容器时,先创建好 Network Namespace,然后再调用 CNI 插件为这个 net ns 配置网络, 其后再启动容器内的进程。
CNI插件包括两部分:
K8s Pod 中的其他容器都是 Pod 所属 pause 容器的网络,创建过程为:
DHCP 插件是最主要的 IPAM 插件之一,用来通过DHCP方式给容器分配 IP 地址。
host-local 是常见的 CNI IPAM 插件,用来给 container 分配 IP 地址。
Flannel 通过给每台宿主机分配一个子网的方式为容器提供虚拟网络,使用 UDP 封装IP 包来创建 overlay 网络,借助 etcd 维护网络的分配情况。
Calico 是一个基于 BGP 的纯三层的数据中心网络方案,不需要 Overlay。
Calico 在每个计算节点利用 Linux Kernel 实现了一个高效的 VRouter 负责数据转发,而每个 vRoute 通过 BGP 协议负责把自己上运行的 workload 的路由信息像整个 Calico 网络内传播,大规模下可以通过指定的 BGP route reflector 来完成。保证最终所有的 workload 之间的数据流量都是通过 IP 路由的方式完成互联的。
Calico 节点组网可以直接利用数据中心的网络结构,不需要额外的 NAT,隧道或者 Overlay Network。
此外,Calico 基于 iptables 提供了丰富的网络Policy。
Cilium 是一个基于 ebpf 和 xdp 的高性能容器网络方案,提供了 CNI 和 CNM 插件。
Cilium
支持封装路由模式和原生路由模式。
默认的路由模式,在部署时将 tunnel 设置为 vxlan 或者 geneve,它们是两种基于 UDP 的网络封装模式。 在这种模式下,所有集群节点使用基于这样的 UDP 封装协议形成的隧道网络。
将 tunnel 设置为 disabled,cilium会将所有不是发往本地另一个端点的数据包交给Linux内核的路由子系统。 如果所有的节点在同一个 L2 网络上,需要添加 auto-direct-node-routes=true,不需要额外的组件辅助。 如果节点不再同一个 L2 网络上,需要 BGP daemon 组件的辅助。