Kubernetes 基础:一切皆为对象
把 Pod、Deployment 和 Service 大白话化,搞懂 Kubernetes 的底层设计哲学与 YAML 规范。
如果你去读官方文档,它会告诉你 Kubernetes 是一个“容器编排和管理的开源系统”。
但从工程一线和排障的视角来看,Kubernetes 其实就是一个极其庞大的分布式 KV 数据库(etcd),加上一群不知疲倦的对账机器人(Controllers)。
你在 YAML 里写的,就是你想存在数据库里的数据。机器人看到数据变了,就会拼命去把现实世界的服务器环境改造成你写死在数据库里的样子。
理解了这个运作逻辑,我们再来看它最核心的“四大件”。
核心基建四大件
Kubernetes 里面有无数个对象(Object/Resource),但真正在一线每天被高频操作的,其实是这四个兄弟。
1. Pod:你以为的容器,其实是豆荚
Docker 时代,大家都是操作单体容器。为什么 Kubernetes 突然搞出个 Pod?
Pod 不是容器,而是跑在同一台物理机/虚拟机上的一组容器。 想象成一个豌豆荚(Pod),里面可以有多个豆子(Container)。它们天生共享网络(同一个 IP)、共享进程空间(可以互相发信号)、共享存储卷。
为什么这么设计?因为微服务时代,你的主应用程序(比如 Java 服务)往往需要一个极其紧密的帮手(比如收集日志用的 Filebeat、负责劫持流量用的 Envoy)。这种主从伴生关系,不适合拆在两台机器上跑。把它们捆绑成一个 Pod 调度,是最完美的解决方式。
2. Deployment:兜底的工头
你很少会直接手写一个 Pod 然后 apply 进去。因为直接起跑的裸 Pod 一旦节点宕机,由于没人负责重新在其他健康节点上拉起它,它就随风消散了。
Deployment 是负责管理可用性的包工头。
你在 Deployment 里写一句 replicas: 3,它内部的 ReplicaSet 就会死盯着全服寻找这个标签的 Pod。
一旦发现死了 1 个变成 2 个,它立马调度出 1 个新的凑齐 3 个。
一旦你更新了镜像版本,它会小心翼翼地删一个旧的,建一个新的(滚动更新),不让业务受到中断的剧烈打击。
3. Service:稳定的入口门牌号
在 Kubernetes 里,Pod 是会不停死掉和重建的“耗材”。每次新建必然被分配一个新 IP。这就导致:你绝对不能用 Pod IP 来配置应用之前的互相调用和访问。
Service 就是给这堆随时会死的耗材套上一个永远不变的门牌号和内部 DNS 域名。
流量打到了 Service 的虚拟 IP 上,它在底层基于底层的 iptables/IPVS 将网络包轮询(Round Robin)负载均衡丢给背后活着的(并且通过探测就绪的)目标 Pod。
4. Namespace:逻辑房间
随着业务复杂度提高,你的集群会慢慢变成有 500 个微服务的庞然大物。 Namespace 像是一个文件夹,把相关联的资源框在一个个命名空间里。
平时你可以用它来区分部门(ns-qa、ns-frontend、ns-data)。但这仅仅是名字上的软隔离,如果不在底层配极度复杂的 NetworkPolicy 和 RBAC 策略,不同 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,就说明系统启动完正常运转了。”
错了!由于那套**对账机器人(Controllers)**的设计模式,系统只告诉你这笔账成功登记到 etcd 数据库了,不代表干活干完了。
真正的微观现实可能惨不忍睹:它可能因为配错物理节点打不出标签导致一直 Pending,可能因为你拼错了镜像仓库字母一直疯狂重试拉取并抛出 ImagePullBackOff,还可能因为没满足探针要求无限次原地死循环 CrashLoopBackOff 重启。
这就要求你:任何变配单落地之后,不是关闭终端去吃午饭,而是立刻跟上验收指令:
# 查看所有状态
kubectl get deploy,pods -n demo
# 如果不对劲,去找犯罪现场看它的描述(最重要的 Debug 命令没有之一)
kubectl describe pod <pod-name> -n demo
接受系统会不断重试和失败。Kubernetes 逼迫你从第一天起,就把描述目标作为手段,把收集诊断证据当成习惯。