IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。
在第 20 篇中,我们通过 kubectl create deployment 创建了第一个 Nginx 应用,看到了 Pod 被自动创建出来。但那个 Pod 是 Deployment 帮我们"自动生成"的,你没有亲手写过 Pod 的 YAML,也没有直接和 Pod 这个核心对象打过交道。
在 Docker 的世界里,容器是你最常操作的对象------docker run、docker ps、docker stop,都是围绕着容器展开。而在 Kubernetes 中,最小的调度单元不是容器,而是 Pod。这意味着 K8s 不会直接调度一个容器到节点上,而是将 Pod 作为一个整体分配给节点,节点上的 kubelet 再负责启动 Pod 内的容器。这个设计是理解 K8s 和 Docker 本质区别的关键。今天我们就把 Pod 的 YAML 结构、多容器协作原理和常用操作全部拆解清楚。
一、Pod 是什么?为什么比容器"高一级"?
回忆第 19 篇中的 Pod 创建流程:你提交 Deployment → Deployment Controller 创建 ReplicaSet → ReplicaSet Controller 创建 Pod → Scheduler 把 Pod 分配节点 → kubelet 启动容器。在整个链路上,被调度的对象始终是 Pod,不是容器。
Pod 的本质定义 :Pod 是 Kubernetes 中可以创建和管理的最小计算单元 。一个 Pod 可以包含一个或多个容器,这些容器共享网络命名空间(同一个 IP 和端口空间)、共享 IPC 命名空间、可以通过 localhost 互相通信,也可以共享挂载的存储卷。
在 Docker Compose 中,容器之间通过自定义网络和 DNS 解析互相访问,每个容器有独立 IP。而在 K8s 中,同一个 Pod 内的容器共享同一个 IP 和网络命名空间,它们通过 localhost 就能通信------这是 K8s 在 Pod 层面实现紧密耦合服务的关键设计。
用一个简单的对比帮助理解:
Pod 与容器之间的"中间层"设计:你可能会问,为什么不直接调度容器?因为很多真实场景需要多个紧密协作的进程共享网络和存储------比如一个 Web 服务和一个日志采集 Sidecar,它们需要共享文件系统和网络。Pod 为这种需求提供了天然的封装单元,同时在调度、资源管理、生命周期上保持了统一的抽象。这和 Docker Compose 中每个容器独立 IP、通过网络互访的模式有本质区别。
二、Pod YAML 结构详解
前面 18 篇我们写了不少 Compose YAML。K8s YAML 与之相似但结构更统一------所有 K8s 对象都有相同的四段式结构。YAML 的缩进和键名是语法核心,单次操作只需应用一个 YAML 文件,集群内部会按顺序自动协调。
2.1 第一层:元数据和类型声明
以我们贯穿案例的 Flask 应用为例,以下是一个包含 Flask 和 Redis 两个容器的完整 Pod YAML:
bash
apiVersion: v1
kind: Pod
metadata:
name: flask-redis-pod
labels:
app: flask-redis-counter
tier: full-stack
spec:
containers:
- name: flask
image: flask-redis-counter:2.0
ports:
- containerPort: 5000
env:
- name: REDIS_HOST
value: localhost # 重点:共享网络,直接用 localhost
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
每个 K8s YAML 文件都必须包含四个顶级字段,下面逐一拆解。
apiVersion 指定 K8s API 的版本,不同资源对象使用不同的 API 组:核心资源(Pod、Service、Node 等)用 v1;应用类资源(Deployment、StatefulSet)用 apps/v1;批处理资源(Job、CronJob)用 batch/v1。
kind 指定资源对象的类型,这里填 Pod。其他常见类型包括 Deployment、Service、ConfigMap 等,后续文章会逐个接触到。
metadata 包含对象的元数据,其中 name 是必填项(Pod 的唯一标识),labels 是键值对标签(用于 Service 等对象的筛选匹配,第 28 篇会深入用到),namespace 可选(不填默认 default)。
spec 定义期望状态,不同类型的 spec 字段完全不同。Pod 的 spec 中最核心的是 containers 列表。
2.2 containers 字段详解
containers 是 Pod spec 中最重要的字段,它是一个列表,可以包含一个或多个容器。每个容器常用的配置项包括:
command 和 args 的覆盖规则与 Docker 的 CMD/ENTRYPOINT 一致:
三、编写并部署第一个 Pod
理论知识有了,现在动手。
3.1 创建 YAML 文件
创建 flask-redis-pod.yaml,填入上文中的 Pod 定义。确保 Minikube 集群正在运行:
bash
minikube status
# minikube: Running
3.2 部署 Pod
bash
kubectl apply -f flask-redis-pod.yaml
输出:
bash
pod/flask-redis-pod created
3.3 查看 Pod 状态
输出:
bash
NAME READY STATUS RESTARTS AGE
flask-redis-pod 2/2 Running 0 30s
READY 2/2 表示 Pod 中有 2 个容器(Flask 和 Redis),且都已就绪。
3.4 验证内部通信:localhost 互访
第 9 篇我们在 Docker 中验证过自定义网络的 DNS 解析。现在来看看 Pod 内更紧密的通信方式:
bash
# 进入 Flask 容器
kubectl exec -it flask-redis-pod -c flask -- /bin/bash
# 在容器内用 localhost 连接 Redis
redis-cli -h localhost ping
# PONG
同一个 Pod 内的 Flask 和 Redis 容器共享网络命名空间,所以 Flask 可以通过 localhost:6379 访问 Redis,不需要 Service、不需要 DNS 解析。这就是 Pod 设计的精妙之处------紧密耦合的进程可以像一个容器一样交互,但又保持了各自的镜像和部署独立性。-c flask 指定要进入哪个容器,如果 Pod 只有一个容器可以省略。
3.5 访问 Flask 服务
bash
# 端口转发
kubectl port-forward pod/flask-redis-pod 5000:5000
打开另一个终端:
bash
curl http://localhost:5000
# Hello World! I have been seen 1 times.
四、Pod 常用操作
4.1 查看详情
bash
# 查看 Pod 的完整信息,包括事件日志(Events)
kubectl describe pod flask-redis-pod
Events 部分记录了 Pod 从创建到运行的完整过程------调度到哪个节点、拉取镜像是否成功、容器何时启动等,是排查问题的第一手资料。
4.2 查看日志
单容器 Pod 直接指定 Pod 名称即可;多容器 Pod 需要加 -c 指定容器名:
bash
# 查看 Flask 容器的日志
kubectl logs flask-redis-pod -c flask
# 实时跟踪
kubectl logs -f flask-redis-pod -c flask
4.3 在容器内执行命令
bash
# 执行单条命令
kubectl exec flask-redis-pod -c flask -- env | grep REDIS_HOST
# REDIS_HOST=localhost
# 进入交互式 Shell
kubectl exec -it flask-redis-pod -c redis -- redis-cli
# 127.0.0.1:6379> PING
# PONG
4.4 删除 Pod
bash
kubectl delete pod flask-redis-pod
# pod "flask-redis-pod" deleted
kubectl delete 会等待 Pod 优雅终止(默认 30 秒,超时后强制杀死),--grace-period=0 --force 可以立即删除(⚠️ 可能导致数据丢失,仅用于紧急情况)。
五、Pod 与容器的关键区别回顾
通过这一篇的学习,你需要在脑海中将"Docker 容器思维"升级为"Kubernetes Pod 思维":
-
Pod 是 K8s 的最小调度单元,不是容器。Scheduler 分配的是 Pod,kubelet 启动的是 Pod 内的容器。
-
Pod 内容器共享网络命名空间 ,通过
localhost即可互访,不需要像 Docker 那样创建自定义网络。 -
Pod 内容器共享存储卷(我们将在第 34 篇深入),多个容器可以读写同一个目录。
-
Pod 是容器的"命运共同体"------Pod 一旦被删除,其内部所有容器都会被删除。
六、本篇总结
-
Pod 的本质:最小的调度与运行单元,可包含一个或多个共享网络和存储的容器。
-
YAML 四要素 :
apiVersion、kind、metadata、spec是所有 K8s 对象的共同骨架。 -
containers 字段:定义了容器名称、镜像、端口、环境变量等,是 Pod spec 的核心。
-
共享机制 :同一 Pod 内的容器通过
localhost互访,这是与 Docker Compose 网络模型最本质的区别。 -
常用操作 :
apply(部署)、get(查看)、describe(详情+事件)、logs(日志)、exec(进入容器)、delete(删除)。
通过本篇,你已经能亲手编写 Pod YAML、部署多容器 Pod、验证共享网络特性、使用 kubectl 管理 Pod 的完整生命周期。这为下一篇------第 22 篇:Pod 生命周期与重启策略------打好了基础,届时我们将深入 Pod 从创建到终止的完整状态流转,理解 Pending、Running、Succeeded、Failed 背后的含义。
想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !