本专栏文章持续更新,新增内容使用蓝色表示。

一、容器运行时演进:从 Docker 到 Containerd

1.1 容器运行时的发展历程

关于"K8s 在 1.20 之后就不再支持 Docker"的说法不完全准确。实际情况是 Kubernetes 不再直接内置对 Docker 的支持,但用户仍然可以通过 CRI(容器运行时接口)来管理 Docker 容器。

主要基于两个重要原因:

生态兼容性考量:Docker 商业化后与开源生态的兼容性考虑;

维护成本优化:官方维护 dockershim 适配器的成本较高。

1.2 当前容器运行时方案

继续使用 Docker

可以通过第三方适配器如 cri-dockerd,它实现了 CRI 接口,将 Kubernetes 的指令翻译成 Docker API 调用。

直接使用 Containerd

在 K8s 1.24 之后,更推荐直接使用 containerd,优势如下

  • 架构简洁:containerd 是 Docker 的底层运行时,去除中间层提升效率

  • 原生支持:containerd 原生实现 CRI 接口,无需额外适配器

  • 符合标准:更贴近云原生生态系统标准

  • 资源消耗:更少的资源占用,更高的性能表现

二、Kubernetes 集群搭建过程

首先要规划节点数量,比较推荐准备至少3个控制节点和2个工作节点以保证高可用。

然后对所有节点进行统一处理:安装容器运行时(如containerd)、关闭Swap、加载内核模块。并且安装kubeadm、kubelet和kubectl。

初始化控制平面,在第一个Master节点上使用kubeadm init命令去初始化集群,然后配置kubectl。

完成之后需要安装网络插件,比如Calico、flannel等,以保证正常的通信。

最后让节点使用kubeadm join命令加入集群,验证状态。

为什么必须关闭 Swap?

性能层面的考量

  • 交换操作涉及磁盘 I/O,速度比内存慢几个数量级

  • 启用 Swap 可能导致性能"抖动"现象,影响容器运行稳定性

  • 容器环境对 I/O 性能要求极高,Swap 会显著降低整体性能

资源管理的影响

  • 调度器基于物理内存进行决策,Swap 会干扰调度准确性

  • 破坏 Pod 驱逐机制,可能导致 OOM Killer 误杀重要进程

  • 掩盖内存泄漏问题,增加故障排查难度

特殊场景的处理方案

对于确实需要 Swap 的应用场景:

# 修改 kubelet 配置
--fail-swap-on=false

# 优化内核参数
echo 'vm.swappiness=1' >> /etc/sysctl.conf
echo 'vm.min_free_kbytes=总内存的2-3%' >> /etc/sysctl.conf
sysctl -p

可参考链接:

Tuning Linux Swap for Kubernetes: A Deep Dive | Kubernetes

Kubernetes 1.28:在 Linux 上使用 swap 的 Beta 支持 |Kubernetes

网络插件的重要性

kubeadm init 后必须立即部署网络插件的原因:

  • Pod 网络通信:为 Pod 提供唯一的 IP 地址和网络连通性

  • 服务发现:支持 Service 网络和 DNS 解析

  • 网络策略:实现网络安全控制策略

  • 跨节点通信:确保不同节点上的 Pod 可以互相通信

三、Kubernetes 网络架构

3.1 网络模型与 CNI 机制

Kubernetes 通过扁平化网络模型和 CNI 为 Pod 提供网络服务:

核心网络特性

  • 每个 Pod 拥有唯一的 IP 地址

  • Pod 间无需 NAT 即可直接通信

  • 通过 CNI 插件实现具体网络功能

  • 支持网络策略和访问控制

3.2 主流网络插件对比

3.2.1 Flannel

技术原理:创建 Overlay 网络,通过 VXLAN 或 host-gw 实现跨节点通信

核心优势:对底层网络无特殊要求,部署简单快捷

适用场景:快速部署、网络环境复杂的场景

性能特点:有一定的封包开销,但稳定性较好

3.2.2 Calico

技术原理:基于 BGP 协议的直接路由,无封包开销

核心优势:性能接近物理网络,支持强大的网络策略

适用场景:对性能和安全性要求高的生产环境

扩展能力:支持大规模集群部署

3.3 网络通信机制详解

3.3.1 同一节点 Pod 通信

CNI 插件创建虚拟网桥(如 cni0),连接节点上的所有 Pod,类似物理交换机的工作方式。

br-netfilter 的关键作用
确保经过网桥的数据包也能被 iptables 规则过滤,这是 Service 网络正常工作的基础。

3.3.2 跨节点 Pod 通信的两种模式

Overlay 网络(Flannel)

Pod A → 封包(VXLAN)→ 节点网络 → 解包 → Pod B
    封装开销         透明传输       解封装

直接路由(Calico)

Pod A → 路由表 → 物理网络 → 路由表 → Pod B
    BGP学习路由      直接传输    BGP发布路由

3.4 Calico 与 CRD

Calico 大量使用 CRD 实现高级网络功能:

  • NetworkPolicy:定义精细的 Pod 间访问控制规则

  • GlobalNetworkPolicy:集群级别的网络安全策略

  • IPPool:IP 地址池的动态管理

  • BGPConfiguration:BGP 路由协议的详细配置

相比之下,Flannel 基本不使用 CRD,其设计定位更专注于基础网络连通性,这也是两者在架构哲学上的根本差异。

四、CRD

4.1 基础概念

CRD(Custom Resource Definition) 是 Kubernetes 的核心扩展机制,它允许用户自定义资源类型,就像内置的 Pod、Service 一样。

核心组件关系

  • CRD:定义资源结构的模板,包括字段规范和验证规则

  • CR:根据 CRD 模板创建的具体资源配置实例

  • Controller:监听 CR 变化并执行相应运维操作的控制器

4.2 生态价值

平台扩展性:使 Kubernetes 从容器编排平台演进为真正的"云原生操作系统";

统一管理界面:通过统一的 kubectl 工具管理所有自定义资源;

运维自动化:催生 Operator 模式,实现复杂应用的全生命周期管理;

生态集成:为第三方工具提供标准的集成接口。

4.3 应用场景

场景类型 典型实现 核心价值
数据库管理 MySQL Operator, Redis Operator 有状态应用的自动化运维
监控告警 Prometheus ServiceMonitor 声明式监控配置
网络策略 Calico NetworkPolicy 精细化网络访问控制
CI/CD Tekton Pipeline 流水线即代码
备份恢复 Velero Backup 跨云灾备方案

五、Pod

Pod 作为 Kubernetes 的最小调度单元,体现了重要的设计理念:

  • 逻辑分组:Pod 是容器的逻辑组合,代表一个完整的应用实例

  • 共享环境:容器间共享网络、存储和生命周期

  • 调度原子性:Pod 内的容器总是被调度到同一个节点

5.1 Pause 容器的关键作用

Pause 容器,又称 "infra" 容器,是每个 Pod 中第一个启动的容器,为 Pod 提供底层基础设施支持。

  • 命名空间管理:提供共享的 network、IPC、PID 命名空间

  • 资源驻留:保持 Pod 网络和存储资源的持续存在

  • 僵尸进程回收:作为 PID 1 进程回收僵尸进程

Pause 容器在 Pod 中的角色类似于 Linux 系统中的 systemd——它不运行具体应用,而是为其他进程提供稳定的运行环境和生命周期管理

5.2 Pod 生命周期

Pending:已接受请求,等待调度和镜像拉取

ContainerCreating:正在创建容器运行时环境

Running:至少一个主容器正常运行

Succeeded:所有容器成功完成任务并退出

Failed:至少一个容器异常退出

Terminating:正在执行优雅终止流程

5.4 静态 Pod

由 kubelet 直接管理的特殊 Pod 类型:

管理方式:通过节点本地静态配置文件定义

监控机制:API Server 通过镜像 Pod 间接监控状态

命名规范:自动添加节点主机名后缀避免冲突

使用场景:集群核心组件部署,如 etcd、kube-proxy

六、核心组件

6.1 管理工具组件

组件 核心职责 关键特性
kubeadm 集群生命周期管理 init/join/upgrade 命令
kubectl 集群交互命令行工具 声明式资源管理
kubelet 节点代理和容器运行时接口 Pod 生命周期管理
kube-proxy 服务发现和负载均衡 iptables/ipvs 规则管理

6.2 控制平面组件

组件 核心职责 高可用方案
kube-apiserver 统一 API 接口和认证鉴权 多实例负载均衡
etcd 分布式元数据存储 集群化部署
kube-controller-manager 状态协调和故障恢复 领导者选举
kube-scheduler 资源调度决策 多副本部署

6.3 Pod 创建过程

首先,用户通过 kubectl 提交 Pod 配置,kube-apiserver 对其进行验证后,将元数据作为“期望状态”写入 etcd,此时 Pod 状态为 Pending。

接着,kube-scheduler (通过 List-watch 机制)监听到这个未调度的 Pod,通过调度算法为其选择最合适的节点,并将绑定信息通过 kube-apiserver 更新回 etcd。

最后,目标节点上的 kubelet 监听到该 Pod 的绑定事件,调用容器运行时创建容器,并将最终的 Running 状态汇报给 kube-apiserver,由其再次写入 etcd,完成整个流程。

注意

kube-controller-manager 不参与:此流程适用于直接创建单个 Pod(kind: Pod)。当创建 Deployment 等控制器资源时,kube-controller-manager 中的相应控制器才会介入,确保实际的 Pod 副本数与期望值一致。

etcd 是唯一状态源:整个过程中,所有状态的变更都经由 kube-apiserver 持久化到 etcd,确保了集群状态的一致性和可追溯性。

List-Watch 机制:kube-scheduler 和 kubelet 通过监听 kube-apiserver 的事件来触发相应操作,这是一种高效的、声明式的协同工作模式。

6.4 调度策略与节点选择

调度器基于多维度因素进行智能决策:

  • 资源需求匹配:CPU、内存、存储的资源请求和限制

  • 亲和性规则:节点亲和性、Pod 亲和性/反亲和性

  • 污点与容忍度:节点的排斥机制与 Pod 的接受能力

  • 拓扑分布约束:保证工作负载在集群中的合理分布

  • 自定义策略:通过调度器扩展实现业务特定需求


如有问题或建议,欢迎在评论区中留言~

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐