第 4 篇 · 容器与 Kubernetes:云原生的核心引擎
本篇覆盖全景图的 第 ④ 层:容器与编排(CaaS),是云原生的核心。
上一篇我们看到,虚拟机仍带完整操作系统、启动慢。容器用更轻的"进程级隔离"解决了这个问题;
但当容器数量成千上万、跨多台机器时,如何调度、故障自愈、服务发现、弹性伸缩?这就需要 容器编排,而 Kubernetes(K8s)是这个领域的事实标准。本篇把容器原理、Docker、容器运行时、Kubernetes 架构与核心对象讲透。
文章目录
一、容器到底是什么:从原理说起
1. 容器不是"轻量虚拟机"
很多人以为容器是"精简版虚拟机",这是误解。正确的理解是:
容器本质上是宿主机上的一个普通进程,但被 Linux 内核的 Namespace 和 Cgroups 技术加上了"边界",让它看起来像一台独立的机器。
- 虚拟机的隔离由 Hypervisor 实现,要虚拟出完整硬件、跑独立 Guest OS;
- 容器的隔离由 Linux 内核实现,所有容器共享宿主机内核,没有独立的操作系统。
容器的实现依赖三大内核技术:Namespace(隔离"看得到什么")、Cgroups(限制"用得了多少")、联合文件系统(提供"独立的文件")。
2. Namespace:让容器"看到"独立的世界
Namespace(命名空间)通过内核技术,让容器中的进程只能看到自己这一份系统资源,从而实现"隔离"。
每次你运行一个容器,Docker 就会为它创建一组 Namespace:
| Namespace | 隔离的资源 | 作用 |
|---|---|---|
| PID | 进程编号 | 容器内进程从 1 开始编号,看不到宿主机和其他容器的进程 |
| NET | 网络设备/协议栈 | 容器有独立的网卡、IP、端口、路由表 |
| MNT | 挂载点(文件系统) | 容器看到独立的目录树 |
| UTS | 主机名/域名 | 容器有自己的 hostname |
| IPC | 进程间通信 | 容器内的信号量、消息队列隔离 |
| USER | 用户/用户组 | 容器内 root 可映射为宿主机普通用户 |
| Cgroup | Cgroup 根目录 | 容器看到的资源视图隔离 |
对比:
docker run --pid=host nginx会让容器共享宿主机 PID Namespace,它就能看到宿主机所有进程——这反过来说明了 PID Namespace 的隔离作用。
3. Cgroups:限制容器"能用多少"资源
Namespace 解决"隔离",但容器内进程仍可能吃光所有 CPU/内存。Cgroups(Control Groups)负责限制一组进程能使用的资源上限。
Cgroups 可以限制:
- CPU:占用比例(cpu.shares)、CPU 核数(cpuset)、配额(cpu.cfs_quota_us);
- 内存:内存使用上限(memory.limit_in_bytes),超了会触发 OOM 被杀;
- 磁盘 I/O:读写带宽、IOPS;
- 设备访问:允许使用哪些设备。
一句话:Namespace 管"隔离",Cgroups 管"限额"。
例如docker run --cpus=1 --memory=512m nginx就是在配置 Cgroups。
4. 联合文件系统与 rootfs:容器的"独立文件"
容器要有自己的文件系统(/bin、/etc、应用文件等),这就是 rootfs(根文件系统)。
- rootfs 是容器启动时挂载的根目录,它不包含操作系统内核,只包含文件和目录(内核共享宿主机的)。
- rootfs 通过 联合文件系统(UnionFS) 实现,采用分层结构:
常见联合文件系统:Overlay2(Docker 默认)、AUFS、Device Mapper、Btrfs。
分层的好处:多个容器可以共享只读的基础镜像层,各自只加一层可读写层,节省磁盘、启动快。
5. 容器 vs 虚拟机(再强调一次)
| 对比 | 虚拟机 | 容器 |
|---|---|---|
| 隔离技术 | Hypervisor(KVM/ESXi) | Namespace + Cgroups |
| 是否共享内核 | 否(独立 Guest OS) | 是(共享宿主机内核) |
| 隔离强度 | 强(硬件级) | 较弱(进程级) |
| 启动速度 | 分钟级 | 秒级/毫秒级 |
| 镜像大小 | 几 GB | 几 MB~几百 MB |
| 单机数量 | 几十 | 上千 |
| 跨平台 | 一般 | 一次构建、到处运行 |
二、Docker:容器的"打包与运行"平台
1. Docker 架构
Docker 是一个 C/S 架构的平台:
- Docker Client(CLI):用户输入命令的地方;
- Docker Daemon(dockerd):守护进程,监听 API、管理镜像、容器、网络、卷;
- containerd:从 Docker 中剥离出来的容器管理组件,负责镜像传输、容器生命周期(但不直接创建容器);
- runc:OCI 参考实现,真正调用 Namespace/Cgroups 把容器跑起来。
2. 镜像与容器
- 镜像(Image):容器的"只读模板",打包了应用和运行环境(rootfs + 配置)。镜像分层、只读、可复用。
- 容器(Container):镜像的一个运行实例。关系类似"类与对象"、“程序与进程”。
镜像名格式:[仓库地址/]名称:标签,如 nginx:1.25、registry.cn-hangzhou.aliyuncs.com/xxx/app:v1。
3. Dockerfile:用代码构建镜像
Dockerfile 是一个文本文件,用一条条指令描述如何构建镜像。 它是实现"基础设施即代码"的关键。
| 指令 | 作用 |
|---|---|
FROM | 指定基础镜像(如 FROM openjdk:17) |
WORKDIR | 设置工作目录 |
COPY / ADD | 把文件复制进镜像 |
RUN | 构建时执行命令(如装依赖) |
ENV | 设置环境变量 |
EXPOSE | 声明容器端口 |
CMD | 容器启动时默认执行的命令(可被覆盖) |
ENTRYPOINT | 容器启动时固定执行的入口 |
示例(一个 Java 应用):
FROM openjdk:17-jre-slim
WORKDIR /app
COPY target/demo.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
# 构建镜像
docker build -t demo:v1 .
# 运行容器(-d 后台,-p 端口映射)
docker run -d -p 8080:8080 --name mydemo demo:v1
# 查看 / 进入 / 停止 / 删除
docker ps ; docker exec -it mydemo sh ; docker stop mydemo ; docker rm mydemo
4. 容器网络
Docker 单主机默认有几种网络模式:
| 模式 | 说明 |
|---|---|
| bridge(默认) | 容器连到虚拟网桥 docker0,通过 NAT 与外界通信,容器间可互通 |
| host | 容器直接用宿主机网络,无网络隔离,性能最高 |
| none | 只有 lo 回环,无网络,需自己配置 |
| container | 复用另一个容器的网络栈 |
单主机网络够用,但跨主机的容器如何互通?这是 K8s + CNI 网络插件要解决的(见后文)。
5. 数据卷(Volume)
容器的可读写层在容器删除后会丢失。要持久化数据,需要数据卷:
- Volume:由 Docker 管理的独立存储,挂载进容器;
- Bind Mount:挂载宿主机指定目录;
- 容器内数据(如数据库文件)应放到卷里,避免容器重建丢数据。
6. 容器运行时与 OCI 标准
- OCI(开放容器倡议):定义了容器的两大标准——镜像规范(镜像长什么样)和运行时规范(容器怎么运行)。
- 底层运行时:runc(最常用);
- 高层运行时(负责镜像、网络、存储):containerd、CRI-O(RedHat 主推,专用于 K8s)。
演进:早期 Docker 是"大而全"的单体;后来 containerd 被剥离并捐赠给社区,成为云原生的标准运行时。K8s 通过 CRI(容器运行时接口) 调用 containerd 或 CRI-O,现代 K8s 已经不依赖完整的 Docker。
三、为什么需要容器编排
当你只有几个容器,手动 docker run 没问题。但在生产环境,问题接踵而至:
- 容器挂了,谁来自动重启?
- 一台机器宕了,上面的容器怎么办?
- 流量大了,谁来自动扩容到 100 个副本,过后再缩?
- 容器分散在几十台机器上,怎么让它们互相找到、怎么把流量负载均衡过去?
- 怎么滚动更新而不中断业务?出问题怎么一键回滚?
这些问题靠人工或脚本无法解决,需要一个"集群操作系统"统一管理,这就是容器编排(Orchestration)。
编排领域曾经有三大方案(同类竞争):
| 方案 | 特点 | 现状 |
|---|---|---|
| Kubernetes(K8s) | Google 开源,功能强大、生态繁荣 | 事实标准,胜出 |
| Docker Swarm | Docker 原生,简单、轻量 | 小众,适合小规模 |
| Apache Mesos | 早期大数据/混合调度强 | 已基本退出主流 |
K8s 源自 Google 内部使用了十余年的 Borg 系统,2014 年开源,2015 年由 CNCF 托管。
四、★ Kubernetes:集群的"操作系统"
1. Kubernetes 是什么
Kubernetes(K8s,8 代表中间的 8 个字母)是一个开源的容器编排平台,负责在多台机器组成的集群上自动部署、调度、扩缩、管理容器化应用。
它提供的核心能力:
- 服务发现与负载均衡:给容器一个统一入口,自动分发流量;
- 自动装箱(调度):根据资源需求把容器放到合适的节点;
- 自愈(Self-healing):容器挂了自动重启,节点坏了重新调度;
- 自动扩缩容(HPA):按 CPU/内存/自定义指标自动增减副本;
- 滚动更新与回滚:逐步替换旧版本,可一键回退;
- 密钥与配置管理:ConfigMap、Secret,不用重新打包镜像;
- 存储编排:自动挂载本地存储、云盘、NFS 等。
2. 集群架构:Master 与 Node
控制平面组件:
- kube-apiserver:所有组件都通过它交互(其他组件不直接互相通信),是集群的"网关",负责认证、鉴权;
- etcd:高可用键值数据库,集群的唯一数据源,存所有 Pod、Service、配置等状态(生产环境通常 3/5 个节点做冗余);
- kube-scheduler:监听待调度 Pod,根据资源/亲和性/污点等选择最合适的节点;
- kube-controller-manager:运行一系列控制器(节点控制器、副本控制器、端点控制器等),不断把"实际状态"向"期望状态"靠拢;
- cloud-controller-manager:与云厂商交互(创建云盘、负载均衡器)。
工作节点组件:
- kubelet:每个节点上的代理,接收 Pod 定义、调用运行时创建容器、健康检查、汇报状态;
- kube-proxy:维护节点上的网络规则,实现 Service 的负载均衡和访问;
- 容器运行时:containerd / CRI-O,负责真正跑容器。
3. 核心对象:Pod 是最小调度单位
K8s 不直接管理"容器",而是管理 Pod:
- Pod:K8s 中最小的部署和调度单元,一个 Pod 里通常有一个主容器(也可有多个紧密配合的 Sidecar 容器),它们共享网络和存储(同一 IP、同一网络命名空间)。
- Pod 是"用完即弃"的,故障重建后 IP 会变,所以不能直接依赖 Pod IP。
4. 声明式 API:YAML 与"期望状态"
K8s 的核心哲学是声明式(Declarative):
- 你不需要一步步告诉它"怎么干"(命令式),只需用 YAML 描述"我想要什么状态"(如"我要 3 个 nginx 副本");
- 控制器持续工作,让实际状态 = 期望状态。这就是"自愈"的来源。
一个 Deployment 示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 3 # 期望 3 个副本
selector:
matchLabels:
app: nginx
template: # Pod 模板
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
# 应用 / 查看 / 删除
kubectl apply -f deploy.yaml
kubectl get pods -o wide
kubectl describe pod <pod>
kubectl delete -f deploy.yaml
5. 常用工作负载对象
| 对象 | 作用 |
|---|---|
| Pod | 最小单元,一个或多个容器 |
| Deployment | 管理无状态应用的多副本,支持滚动更新、回滚(最常用) |
| ReplicaSet | 维持指定副本数(通常由 Deployment 管理,不直接用) |
| StatefulSet | 管理有状态应用(数据库、消息队列),提供稳定的网络标识和持久化存储 |
| DaemonSet | 每个节点跑一个 Pod(日志采集、监控代理、网络插件) |
| Job / CronJob | 一次性任务 / 定时任务 |
6. 配置与密钥
| 对象 | 作用 |
|---|---|
| ConfigMap | 存放非敏感配置(如配置文件、环境变量),可挂载或注入 |
| Secret | 存放敏感信息(密码、证书、镜像拉取凭证),以 Base64 编码 |
好处:配置和镜像分离,换配置不用重新构建镜像。
7. ★ 服务发现与网络:Service、DNS、Ingress
因为 Pod IP 会变、且有多个副本,K8s 用 Service 提供稳定的访问入口:
- Service:为一组 Pod 提供固定的虚拟 IP(ClusterIP)和 DNS 名称,并自动负载均衡到后端健康的 Pod。即使 Pod 重建,Service 不变。
- Label / Selector:Service 通过标签(Label)找到它要代理的 Pod。
- DNS(CoreDNS):集群内置 DNS,服务之间直接用服务名访问(如
http://user-service:8080)。
Service 的几种类型:
| 类型 | 说明 |
|---|---|
| ClusterIP(默认) | 集群内部访问的虚拟 IP |
| NodePort | 在每个节点上开放一个端口(30000-32767),可从外部访问 |
| LoadBalancer | 对接云厂商负载均衡器,提供公网入口(云上标准) |
| ExternalName | 映射到外部域名 |
Ingress:
- Service 工作在四层(TCP),而 Ingress 工作在七层(HTTP/HTTPS),可以基于域名、路径把流量路由到不同 Service,并提供 SSL 终止;
- 需要 Ingress 控制器(如 Nginx Ingress、Traefik)。
CNI:跨主机容器网络
K8s 自身不规定容器怎么联网,而是通过 CNI(容器网络接口) 插件实现跨主机 Pod 互通。常见 CNI(同类):
- Flannel:简单(常用 VXLAN 覆盖网络),适合入门;
- Calico:基于 BGP、支持网络策略(NetworkPolicy),性能与安全强,生产主流;
- Cilium:基于 eBPF,高性能、可观测性强,是新兴热门;
- 云厂商方案:AWS VPC CNI、阿里云 Terway。
网络策略(NetworkPolicy)相当于容器间的"防火墙规则",类比物理网络的防火墙 / 安全组。
8. 存储:PV、PVC、StorageClass
容器有状态数据需要持久化,K8s 用一套抽象对接各种存储:
- PV(PersistentVolume):集群中的一块实际存储(如一块云盘、一个 NFS 目录);
- PVC(PersistentVolumeClaim):用户对存储的"申请"(要 10GB、读写模式),无需关心底层细节;
- StorageClass:定义"动态供给"模板,PVC 提交时自动创建 PV(对接云盘/Ceph),无需管理员手动建;
- CSI(容器存储接口):存储插件标准,让 K8s 能接入各种存储(类似网络的 CNI)。
对比记忆:CNI 管网络、CSI 管存储、CRI 管容器运行时——K8s 用这三大接口 + 插件实现"可插拔"。
9. 调度、自愈与弹性
- 调度:Scheduler 监听新 Pod,根据资源请求(requests/limits)、节点选择器、亲和性(Affinity)、污点容忍(Taints/Tolerations)选择节点;
- 自愈:kubelet 做**探针(Probe)**健康检查:
- livenessProbe(存活探针,失败重启容器);
- readinessProbe(就绪探针,失败则从 Service 摘除流量);
- startupProbe(启动探针,保护慢启动应用);
- HPA(水平自动扩缩):根据 CPU/内存/自定义指标自动增减 Pod 副本数;
- 滚动更新:Deployment 逐步创建新 Pod、删除旧 Pod,全程业务不中断;
kubectl rollout undo可回滚。
10. 一个请求的完整链路(串起来)
五、Helm、Operator:K8s 的"包管理"与"自动化运维"
1. Helm:K8s 的包管理器
裸写一堆 YAML 部署复杂应用(如 MySQL、Redis 集群)很繁琐。Helm 把一组 YAML 模板打包成 Chart,可参数化、版本化、一键安装/升级,类似 Linux 的 apt/yum。
- Chart:应用模板包;Release:Chart 的一次安装实例;
- 常用:
helm install、helm upgrade、helm rollback。
2. CRD 与 Operator
- CRD(自定义资源定义):允许你在 K8s 原生对象之外定义新的资源类型(如
MySQLCluster); - Operator = CRD + 自定义控制器,把人类运维专家的知识(部署、备份、故障恢复、扩容)编码成软件,实现复杂有状态应用的自动化运维。
- 例如:PostgreSQL Operator 能自动建主从、自动备份、故障切换。
同类工具:Kustomize(K8s 原生的模板化方案,无模板语法)。
六、K8s 与虚拟化、云的关系(定位)
- K8s 节点可以是物理机(裸金属 K8s),也可以是 OpenStack/公有云上的虚拟机(云上托管 K8s,如阿里云 ACK、AWS EKS、华为 CCE);
- 定位:KVM/ESXi 虚拟化的是"资源",K8s 编排的是"应用(容器)";前者是 IaaS,后者是 CaaS。
七、本篇总结
核心记忆点:
- 容器三大内核技术:Namespace(隔离)、Cgroups(限额)、UnionFS(分层文件);
- 容器本质:带边界的普通进程,共享宿主机内核;
- Docker 架构:CLI → dockerd → containerd → runc;
- 标准:OCI(镜像/运行时),运行时 containerd / CRI-O;
- K8s 架构:Master(apiserver/etcd/scheduler/controller)+ Node(kubelet/kube-proxy/运行时);
- K8s 核心:Pod、Deployment、Service、Ingress、ConfigMap、PV/PVC;
- 三大接口:CRI(容器)、CNI(网络)、CSI(存储);
- 上层:Helm(包管理)、CRD/Operator(自动化运维);
- 编排同类:K8s(胜出)/ Swarm / Mesos。
下一篇:有了 K8s 这个"底座",如何围绕它构建完整的云原生应用?
我们讲 微服务、服务网格、DevOps/CI-CD、GitOps、基础设施即代码、可观测性(监控/日志/链路追踪)、Serverless,并梳理主流云厂商服务地图和学习路线,完成整个知识体系的最后一块拼图。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/qq_65272847/article/details/169166204




