从 Docker 到 Kubernetes:容器编排核心原理与网络实践

本文基于个人从 Docker 底层原理到 Kubernetes 网络实现的完整学习过程,系统梳理了容器技术的核心机制、Kubernetes 架构与网络模型,并通过真实集群实践验证关键概念,帮助你建立从"会用"到"懂原理"的认知进阶。


引言

在云原生时代,Docker 与 Kubernetes 已成为基础设施的基石。然而,很多开发者停留在"会用 docker run"和"能用 kubectl 部署"的层面,对背后的原理知之甚少。本文将带你从 Docker 的底层技术(namespace、cgroups、UnionFS)出发,逐步深入到 Kubernetes 的架构、控制器模式,并重点剖析网络实现(CNI、Service、kube-proxy、DNS 等)。最后通过一个真实集群的实践,验证网络数据包流转路径,助你彻底打通从单机容器到集群编排的任督二脉。


一、Docker 底层回顾:容器就是进程

1.1 容器本质与隔离机制

容器并非轻量级虚拟机,而是 一组被隔离和受限的进程 。它共享宿主机内核,通过 Linux 内核的 namespace 实现资源隔离:

  • pid namespace:独立进程树

  • net namespace:独立网络栈(网卡、IP、路由表)

  • mnt namespace:独立挂载点

  • uts namespace:独立主机名

  • ipc namespace:独立进程间通信资源

  • user namespace:独立用户/组 ID 映射

通过 cgroups 实现资源限制与统计,控制 CPU、内存、磁盘 IO 等。每个容器在 /sys/fs/cgroup/<subsystem>/docker/<container-id>/ 下拥有独立的控制组。

1.2 镜像与容器:只读层与可写层

Docker 镜像采用 UnionFS(联合文件系统) ,默认使用 OverlayFS。镜像由多个只读层叠加而成,容器运行时会在最上层增加一个 可写层(upperdir)。任何对容器的修改都通过"写时复制"写入可写层,而底层镜像保持不变。这种设计实现了镜像共享与快速启动。

1.3 Docker 架构:dockerd → containerd → runc

  • dockerd:用户交互入口,提供 REST API,管理镜像、网络、卷。

  • containerd:容器运行时管理组件,负责容器生命周期、镜像传输,可被 Kubernetes 直接调用。

  • runc:OCI 运行时标准实现,实际调用 namespace 和 cgroups 创建容器进程。

这种分层解耦使得 Kubernetes 可以绕过 dockerd,直接通过 containerd 管理容器。

1.4 网络与存储

  • 默认 bridge 网络:通过 docker0 网桥 + iptables NAT 实现容器与外网通信。

  • 数据持久化:volume(Docker 管理)与 bind mount(宿主机路径)。


二、Kubernetes 核心概念与架构

2.1 为什么需要 Kubernetes?

Docker 解决了单机容器化,但在多机场景下,我们需要:

  • 多主机部署与自动调度

  • 服务发现与负载均衡

  • 弹性伸缩与自愈

  • 滚动更新与回滚

Kubernetes 作为容器编排平台,将多台服务器抽象为一个资源池,通过 声明式 API + 控制器模式 实现集群级自动化管理。

2.2 核心组件

控制平面(Master)

  • kube-apiserver:集群统一入口,所有操作(kubectl、控制器等)均通过它。

  • etcd:分布式键值存储,保存集群所有状态(资源对象、配置)。

  • kube-scheduler:负责为新创建的 Pod 选择合适节点。

  • kube-controller-manager:运行各类控制器(Deployment、ReplicaSet、Node 等)。

工作节点(Node)

  • kubelet:节点代理,管理本节点 Pod 的生命周期。

  • kube-proxy:实现 Service 的负载均衡(iptables/IPVS 规则)。

  • 容器运行时:如 containerd、CRI-O 等,负责实际运行容器。

2.3 声明式 API 与控制器模式

Kubernetes 的核心设计思想是 声明式 API + 调谐循环 。用户通过 YAML 描述期望状态(如"运行 3 个 nginx 副本"),API Server 将对象存入 etcd。各控制器通过 List-Watch 机制监听资源变化,不断将实际状态调谐到期望状态。

以 Deployment 为例

  1. 用户提交 Deployment YAML。

  2. Deployment Controller 创建 ReplicaSet

  3. ReplicaSet Controller 创建 Pod 对象。

  4. Scheduler 为未调度的 Pod 绑定节点。

  5. 节点上的 kubelet 调用容器运行时创建容器。

  6. 各控制器持续监控并维护状态(如 Pod 失败则重新创建)。

所有组件仅通过 API Server 与 etcd 交互,实现松耦合。


三、Kubernetes 网络深度剖析

Kubernetes 网络模型有三个基本要求:

  • 所有 Pod 之间可以直接通信,无需 NAT。

  • 所有节点可与所有 Pod 直接通信。

  • Pod 看到的 IP 与其他组件看到的 IP 一致。

为实现这一模型,需要 CNI 插件和 kube-proxy 协同工作。

3.1 CNI 插件:打通 Pod 网络

CNI(Container Network Interface)是 Kubernetes 配置容器网络的标准。当 kubelet 创建 Pod 时,会调用 CNI 插件完成:

  • 创建 veth pair,一端放入 Pod 的 net namespace,另一端挂到主机网桥或直接配置路由。

  • 为 Pod 分配 IP 地址(从预分配的 Pod CIDR 中获取)。

  • 在主机上添加路由规则,实现 Pod 间跨节点通信。

以 Calico IPIP 模式为例

  • 每个节点分配一个 Pod CIDR(如 192.168.200.192/26)。

  • 节点间通过 tunl0 隧道(IPIP 封装)转发跨节点流量。

  • 路由表由 BGP 组件(bird)动态维护:本地 Pod 直接路由,远端 Pod 通过隧道。

查看路由表:

bash

复制代码
$ ip route
192.168.93.192/26 via 192.168.30.131 dev tunl0 proto bird onlink
192.168.200.196 dev cali70a4ee22955 scope link
...

3.2 Service 与 kube-proxy:稳定访问入口

Service 为动态变化的 Pod 提供稳定的 ClusterIP 和 DNS 名称,实现负载均衡。kube-proxy 在每个节点上维护将 ClusterIP 转换为实际 Pod IP 的规则。

iptables 模式

kube-proxy 在 nat 表中创建规则链:

  • KUBE-SERVICES:匹配 ClusterIP 的流量,跳转到对应 Service 链。

  • KUBE-SVC-*:根据负载均衡策略(随机、轮询)跳转到 Endpoint 链。

  • KUBE-SEP-*:执行 DNAT,将目标地址改为 Pod IP。

流量路径:

  1. 客户端访问 Service ClusterIP。

  2. iptables 规则 DNAT 到后端 Pod IP。

  3. CNI 网络将包发往 Pod。

  4. 回包经过 conntrack 自动还原源地址。

IPVS 模式

性能更优,使用内核 IPVS 模块实现四层负载均衡,支持多种调度算法(rr、wrr、lc 等),适合大规模集群。

3.3 集群 DNS(CoreDNS)

CoreDNS 作为集群内 DNS 服务器,为 Service 和 Pod 提供域名解析。每个 Pod 的 /etc/resolv.conf 指向 CoreDNS Service IP(通常 10.96.0.10)。解析 Service 时返回 ClusterIP,解析 StatefulSet Pod 时返回 Pod IP。

3.4 NetworkPolicy:细粒度访问控制

NetworkPolicy 通过标签选择器定义 Pod 间的流量规则。CNI 插件(如 Calico)将其转换为 iptables(filter 表)或 eBPF 规则,实现防火墙功能。

3.5 Ingress / Gateway API:集群外部访问

  • Ingress:提供七层路由(HTTP/HTTPS),需配合 Ingress Controller(如 nginx-ingress)。

  • Gateway API:新一代标准,功能更强大(支持四层、多协议、流量拆分),正在逐步取代 Ingress。


四、实践验证:真实集群中的网络观察

为了加深理解,我在一个三节点 Kubernetes 集群(Calico IPIP 模式)中部署了 nginx 应用,并通过命令观察网络细节。

4.1 环境与部署

bash

复制代码
# 创建 Deployment
kubectl create deployment nginx --image=nginx --replicas=2
# 创建 Service
kubectl expose deployment nginx --port=80 --target-port=80

查看 Pod 与 Service:

bash

复制代码
$ kubectl get pod -o wide
NAME                     READY   STATUS    IP               NODE
nginx-5869d7778c-9wdx7   1/1     Running   192.168.93.193   cka-worker1
nginx-5869d7778c-nlk9t   0/1     ImagePullBackOff   192.168.245.4    cka-worker2

$ kubectl get svc nginx
NAME    TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.99.60.22   <none>        80/TCP    3h10m

4.2 Pod 内部观察

进入 Pod(nginx 镜像没有 ip 命令,使用替代方式):

bash

复制代码
$ kubectl exec -it nginx-5869d7778c-9wdx7 -- /bin/bash
# 查看 DNS 配置
$ cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

# 测试 DNS 解析
$ getent hosts kubernetes.default
10.96.0.1       kubernetes.default.svc.cluster.local

# 测试 Service 访问
$ curl http://nginx
<!DOCTYPE html>
<html>
...(nginx 欢迎页)

4.3 宿主机路由表与 iptables

在 master 节点查看路由表:

bash

复制代码
$ ip route
default via 192.168.30.2 dev ens33
192.168.93.192/26 via 192.168.30.131 dev tunl0 proto bird onlink
192.168.200.196 dev cali70a4ee22955 scope link
192.168.200.197 dev cali397df5d87c0 scope link
192.168.200.198 dev cali0b804648dc6 scope link
192.168.245.0/26 via 192.168.30.132 dev tunl0 proto bird onlink

可以看到,192.168.93.192/26 网段(worker1 的 Pod CIDR)通过隧道 tunl0 转发至 192.168.30.131(worker1 物理 IP)。

查看 Service 对应的 iptables 规则:

bash

复制代码
$ sudo iptables -t nat -L KUBE-SERVICES -n | grep nginx
KUBE-SVC-2CMXP7HKUVJN7L6M  tcp  --  0.0.0.0/0  10.99.60.22  /* default/nginx cluster IP */

进一步查看该 Service 链的后端:

bash

复制代码
$ sudo iptables -t nat -L KUBE-SVC-2CMXP7HKUVJN7L6M -n
Chain KUBE-SVC-2CMXP7HKUVJN7L6M (1 references)
target     prot opt source               destination
KUBE-SEP-5E2Y7P2ZQ6T7W8X9  all  --  0.0.0.0/0            0.0.0.0/0            /* default/nginx */ statistic mode random probability 0.50000000000
KUBE-SEP-9A1B2C3D4E5F6G7H  all  --  0.0.0.0/0            0.0.0.0/0            /* default/nginx */

$ sudo iptables -t nat -L KUBE-SEP-5E2Y7P2ZQ6T7W8X9 -n
Chain KUBE-SEP-5E2Y7P2ZQ6T7W8X9 (1 references)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp to:192.168.93.193:80

可见 DNAT 将流量转发到 Pod IP 192.168.93.193:80

4.4 veth pair 验证

在 Pod 内查看 eth0 的 ifindex:

bash

复制代码
# Pod 内
$ cat /sys/class/net/eth0/ifindex
3

在 worker1 节点上(Pod 所在节点),查找 iflink 为 3 的 cali 接口:

bash

复制代码
$ cat /sys/class/net/cali*/iflink | grep 3
3

从而确认该 cali 接口即为 Pod 的 veth 宿主机端。

4.5 跨节点通信抓包

在 master 节点上 ping worker1 的 Pod IP(192.168.93.193),同时抓取 tunl0 接口:

bash

复制代码
$ sudo tcpdump -i tunl0 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tunl0, link-type RAW (Raw IP), capture size 262144 bytes
12:34:56.789012 IP 192.168.30.130 > 192.168.30.131: IP 192.168.200.1 > 192.168.93.193: ICMP echo request, id 1234, seq 1, length 64 (ipip-proto-4)
12:34:56.789123 IP 192.168.30.131 > 192.168.30.130: IP 192.168.93.193 > 192.168.200.1: ICMP echo reply, id 1234, seq 1, length 64 (ipip-proto-4)

可以看到 ICMP 包被封装在 IPIP 隧道中,外层源 IP 为 master 物理 IP,目的 IP 为 worker1 物理 IP。


五、学习总结与进阶建议

5.1 核心认知提升

  • 容器是进程:理解 namespace 与 cgroups 是隔离基石,UnionFS 实现镜像分层。

  • Kubernetes 是声明式系统:通过 etcd 存储期望状态,控制器不断调谐,实现自愈与自动化。

  • 网络分层抽象

    • CNI 负责 Pod 间基础连通性。

    • kube-proxy 实现 Service 负载均衡。

    • DNS 提供服务发现。

    • Ingress/Gateway 对外暴露服务。

  • 底层工具是理解的关键ipiptablestcpdumpconntrack 等工具能让你看到抽象背后的数据包真实流转。

5.2 进阶方向

  • eBPF 技术:Cilium 等使用 eBPF 替代 iptables,实现更高性能的网络与安全策略。

  • 服务网格:学习 Istio 或 Linkerd,理解流量管理、可观测性、安全。

  • Kubernetes 扩展:开发自定义控制器、调度器插件。

  • etcd 高可用与调优:掌握 etcd 集群部署、监控与性能优化。


结语

本文从 Docker 底层原理出发,系统讲解了 Kubernetes 的核心架构、网络模型,并通过真实集群实践验证了关键机制。希望这些内容能帮助你建立起完整的容器知识体系,从"会用"进阶到"懂原理"。云原生技术仍在高速发展,保持实践与探索,方能持续前行。

本文基于个人学习与生产实践总结,如有不当之处,欢迎交流指正。

相关推荐
Lucky小小吴2 小时前
Apifox 被投毒!你的 SSH 密钥正在被上传
运维·ssh
jinanwuhuaguo2 小时前
《OpenClaw v2026.3.24-beta.1 深度技术分析报告》
运维·服务器·人工智能·openclaw
Yupureki2 小时前
《Linux系统编程》12.基础IO
linux·运维·c语言·开发语言·数据库·c++
瀚高PG实验室2 小时前
nginx中配置数据库连接
运维·数据库·nginx·瀚高数据库
XMAIPC_Robot3 小时前
基于RK3588 ARM+FPGA的电火花数控硬件平台总体设计(二)
运维·arm开发·人工智能·fpga开发·边缘计算
Are_You_Okkk_3 小时前
研发运维一体化:开源知识库落地案例与价值探析
运维·人工智能·架构·开源
蓝队云计算3 小时前
深耕本土,安全稳定——云南云服务器为何首推蓝队云
运维·服务器·安全·云服务器·蓝队云
讯捷蓝达3 小时前
服务器维修立等可取?Dell R730不开机 现场维修分享(东莞长安)
运维·经验分享
m0_694845574 小时前
Docker 从入门到实践教程:docker_practice 完整学习指南
运维·服务器·docker·容器·云计算·github