Kubernetes 基础:一切皆为对象
把 Pod、Deployment 和 Service 大白话化,搞懂 Kubernetes 的底层设计哲学与 YAML 规范。
官方文档会告诉你:Kubernetes 是一个“容器编排和管理的开源系统”。
但从工程和排障视角看,可以先把它理解成一个很大的分布式 KV 数据库(etcd),再加上一组不停对账的控制器(Controllers)。
你在 YAML 里写的,就是希望存在集群里的目标状态。控制器看到数据变了,就会不断尝试把真实环境改成你描述的样子。
理解了这个运作逻辑,我们再来看它最核心的“四大件”。
核心基建四大件
Kubernetes 里面有很多对象(Object/Resource),但入门阶段最常接触的,基本是下面四类。
1. Pod:不是单个容器,而是一组一起调度的容器
Docker 时代,大家更习惯直接操作单个容器。Kubernetes 为什么还要多一层 Pod?
Pod 不是容器,而是跑在同一台物理机/虚拟机上的一组容器。 你可以把它想成一组被绑定在一起的容器。它们共享网络(同一个 IP)、进程空间(可以互相发信号)和存储卷。
为什么这么设计?因为主应用程序(比如 Java 服务)经常需要一个紧密配合的旁路容器,比如收集日志的 Filebeat,或者负责代理流量的 Envoy。这种伴生关系不适合拆到两台机器上跑,放进同一个 Pod 调度会更自然。
2. Deployment:负责维持副本数量
你很少会直接手写一个 Pod 然后 apply 进去。裸 Pod 一旦所在节点宕机,没人负责在其他健康节点上重新拉起它。
Deployment 负责管理可用性和滚动更新。
你在 Deployment 里写 replicas: 3,它内部的 ReplicaSet 就会持续检查匹配标签的 Pod 数量。
一旦发现只剩 2 个,它会调度出 1 个新的补回 3 个。
你更新镜像版本时,它会按滚动更新的方式逐步替换旧 Pod,尽量避免一次性中断业务。
3. Service:稳定的入口门牌号
在 Kubernetes 里,Pod 会被替换和重建。每次新建通常都会拿到新 IP,所以不要用 Pod IP 直接配置应用之间的调用关系。
Service 给一组不断变化的 Pod 提供稳定入口和内部 DNS 名称。
流量打到 Service 的虚拟 IP 后,会通过 iptables/IPVS 等机制转发给背后仍然存活、并且已经就绪的目标 Pod。
4. Namespace:逻辑房间
随着业务复杂度提高,一个集群里可能会有大量服务和配套资源。 Namespace 更像逻辑目录,把相关资源放在同一个作用域里。
平时你可以用它区分团队或环境,比如 ns-qa、ns-frontend、ns-data。但这主要是组织边界,不是强安全边界。没有 RBAC、NetworkPolicy 等策略时,不同 Namespace 里的 Pod 默认仍然可能互相通信。
YAML 不是玄学,是标准结构
不要被很长的 YAML 文件吓住。无论对象多复杂,通常都离不开这几个基本块:
# 1. 我要和内核哪个 API 版本对话
apiVersion: apps/v1
# 2. 我要什么类型的对象
kind: Deployment
# 3. 它的身份证信息(名字、放在哪个文件夹、贴什么标签)
metadata:
name: hello
namespace: demo
# 4. 我想要它长什么样(核心区域)
spec:
replicas: 2
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
面向失败的设计哲学
很多新手会有个错觉:“我敲了 kubectl apply,系统返回 deployment.apps/hello created,就说明应用已经正常跑起来了。”
这其实只说明目标状态已经写进 API,并不代表实际运行已经完成。
真实情况可能还卡在后面:节点标签不匹配导致 Pod 一直 Pending,镜像地址写错导致 ImagePullBackOff,探针不通过导致 CrashLoopBackOff。
所以任何变更落地后,都应该立刻跟上验收指令:
# 查看所有状态
kubectl get deploy,pods -n demo
# 如果不对劲,先看 Pod 的详细描述
kubectl describe pod <pod-name> -n demo
接受系统会不断重试,也会失败。Kubernetes 从第一天起就在训练你:先描述目标,再收集证据。