云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

发布于:2025-06-11 ⋅ 阅读:(23) ⋅ 点赞:(0)

大家好,欢迎来到《云原生核心技术》系列的第七篇!

在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时候在这片土地上播种、耕作了。

那么问题来了,我们该如何把之前用 Docker 打包好的应用(容器)种植到 K8s 这片广袤的土地上呢?直接扔进去吗?

当然不行。K8s 有一套自己的“种植”规则。今天,我们就来学习这套规则里最基本的两个概念:PodDeployment。它们是你在 K8s 世界里打交道最多的两个朋友。


一、 Pod:K8s 世界的“原子单位”,为什么不是直接部署容器?

在 Docker 的世界里,我们操作的最小单位是“容器”。但到了 K8s,你会发现最小的部署单位是一个叫 Pod 的东西。

一个常见的疑问是:为什么 K8s 不直接管理容器,非要引入一个 Pod 的概念呢?

为了回答这个问题,我们先来看一个比喻:

把一个容器想象成一个

那么 Pod 就像一套房子

K8s 分配资源时,不是按“人头”(容器)分的,而是按“户口”(Pod)分的。它可以给一套房子(一个Pod)分配一个独立的 IP 地址、主机名和一套独立的“水电煤气”(网络、存储等资源)。

这套房子里,可以只住一个人(单容器 Pod),这也是最常见的用法。但 K8s 也允许你让多个人(多容器)合租在同一套房子里。

合租的好处是什么?
住在同一屋檐下的人,他们:

  1. 共享同一个“家庭住址”(共享网络命名空间):他们可以用 localhost 直接互相访问,就像家人之间串门一样,不需要出门绕到大街上(外部网络)。这对于需要紧密协作的程序(比如一个业务容器和一个日志收集容器)来说非常高效。
  2. 共享“储藏室”(共享存储卷 Volume):他们可以轻松地共享文件,就像家人共用一个冰箱一样。

总结一下:Pod 是 K8s 调度、管理和资源分配的最小单位。它将一个或多个紧密关联的容器打包在一起,为它们提供共享的存储和网络资源,形成一个内聚的服务单元。

动手:编写并运行你的第一个 Pod

在 K8s 中,我们通常不使用命令行直接创建资源,而是通过编写 YAML 文件来“声明”我们想要的状态。这就像给 K8s 一张建筑蓝图,它会负责照着蓝图施工。

创建一个名为 nginx-pod.yaml 的文件,内容如下:

# nginx-pod.yaml

# API 版本,表明这个对象属于哪个 API 组
apiVersion: v1
# 资源类型,我们正在创建一个 Pod
kind: Pod
# 元数据,包含资源的名称、标签等信息
metadata:
  name: nginx-hello-pod
  labels:
    app: web
# 规格,定义了这个 Pod 的期望状态
spec:
  # Pod 中包含的容器列表
  containers:
  # 第一个容器
  - name: nginx-container
    # 使用的 Docker 镜像
    image: nginx:1.21
    # 容器需要暴露的端口
    ports:
    - containerPort: 80

现在,打开你的终端,使用 kubectl 来应用这个蓝图:

# 确保你的 kubectl 已经连接到 Minikube 或 kind 集群
kubectl apply -f nginx-pod.yaml

执行后,K8s 就会开始创建这个 Pod。我们可以查看它的状态:

kubectl get pods

# 你会看到类似下面的输出:
# NAME              READY   STATUS    RESTARTS   AGE
# nginx-hello-pod   1/1     Running   0          15s

Running 状态表示我们的 Nginx Pod 已经成功运行起来了!


二、 Deployment:应用的“状态维护者”与“智能管家”

我们现在有了一个正在运行的 Pod。但是,如果这个 Pod 因为某些原因(比如程序 Bug、节点故障)挂掉了怎么办?它就真的消失了,没有人会去管它。这在生产环境中是绝对无法接受的。

我们需要一个更高级的“管家”,它能确保我们的应用:

  • 永不宕机:如果一个 Pod 挂了,它能自动创建一个新的来替代。
  • 数量可控:我们可以告诉它,“请确保始终有3个相同的 Pod 在运行”,它就会自动维护这个数量。
  • 轻松更新:当我们想更新应用版本时,它能平滑地、滚动地用新版 Pod 替换旧版 Pod,保证业务不中断。
  • 一键回滚:如果新版本有问题,它能一键回退到上一个稳定版本。

这个智能管家,就是 Deployment

再次使用比喻:

如果 Pod 是一间公寓,那么 Deployment 就是这栋公寓的物业经理

你不会亲自去管理每一间公寓的入住和维修。你只需要告诉物业经理:“我需要这栋楼里始终有50间公寓是租出去并且正常运作的,租户是 Nginx v1.21”。

经理会负责招租(创建 Pod),检查水电(监控 Pod 健康),如果租户跑了(Pod 挂了)就立刻找新租户(创建新 Pod),如果你想升级所有公寓的装修(更新应用版本),经理会一间一间地施工(滚动更新)。

动手:用 Deployment 部署应用

让我们来创建一个 nginx-deployment.yaml 文件,用 Deployment 的方式来部署 Nginx。

# nginx-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  # 期望的 Pod 副本数量
  replicas: 3
  # 选择器,告诉 Deployment 要管理哪些 Pod
  # Deployment 通过这个标签找到它应该管理的 Pod
  selector:
    matchLabels:
      app: nginx-server
  # Pod 模板,这就是 Deployment 创建新 Pod 时使用的“蓝图”
  # 注意,这里的结构和我们上面定义的 Pod YAML 的 spec 部分几乎一样
  template:
    metadata:
      # Pod 的标签,必须和上面的 selector.matchLabels 匹配
      labels:
        app: nginx-server
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80

应用这个 YAML 文件:

kubectl apply -f nginx-deployment.yaml

查看 Deployment 和它创建的 Pods:

kubectl get deployment

# 输出:
# NAME               READY   UP-TO-DATE   AVAILABLE   AGE
# nginx-deployment   3/3     3            3           20s

kubectl get pods

# 输出: (注意,Pod 名称是 Deployment 名称加上随机字符串)
# NAME                                READY   STATUS    RESTARTS   AGE
# nginx-deployment-6b6c47948c-7v9d8   1/1     Running   0          25s
# nginx-deployment-6b6c47948c-8l9f4   1/1     Running   0          25s
# nginx-deployment-6b6c47948c-k5z2x   1/1     Running   0          25s

看!Deployment 严格按照我们的要求 replicas: 3,创建并维护了3个 Nginx Pod。


三、实战演练:见证 Deployment 的“魔法时刻”

现在,让我们亲眼见证 Deployment 作为“智能管家”的神奇能力。

1. 魔法一:故障自愈 (Self-healing)

我们来手动“干掉”一个 Pod,模拟一次故障。

首先,获取 Pod 列表,随便挑一个名字记下来:
kubectl get pods

然后,无情地删除它:

# 将 <your-pod-name> 替换为你复制的 Pod 名称
kubectl delete pod <your-pod-name>

现在,立刻、马上再次查看 Pod 列表,并使用 -w (watch) 参数持续观察变化:

kubectl get pods -w

你会看到一个激动人心的场面:

  1. 你删除的那个 Pod 状态会变为 Terminating(正在终止)。
  2. 几乎在同一时间,一个新的 Pod 会立刻出现,状态从 Pending -> ContainerCreating -> Running
  3. 最终,Pod 的总数依然是3个!

这就是 K8s 的故障自愈能力,由 Deployment 精确执行。

2. 魔法二:滚动更新 (Rolling Update)

我们的应用要发布新版本了,比如把 Nginx 从 1.21 升级到 1.22

直接编辑 nginx-deployment.yaml 文件,将 image: nginx:1.21 修改为 image: nginx:1.22

# ...
    spec:
      containers:
      - name: nginx
        image: nginx:1.22 # <--- 修改这里
        ports:
        - containerPort: 80

保存文件后,再次执行 apply 命令:
kubectl apply -f nginx-deployment.yaml

再次用 -w 观察 Pod 变化:kubectl get pods -w

你会看到 K8s 正在进行“滚动更新”:
它会先创建一个新版本的 Pod,等新 Pod 启动并准备就绪后,再优雅地终止一个旧版本的 Pod。如此循环,直到所有 Pod 都被更新为新版本。整个过程服务不中断!

你可以通过以下命令查看更新状态:
kubectl rollout status deployment/nginx-deployment

3. 魔法三:一键回滚 (Rollback)

糟糕!新版本 1.22 有一个重大 Bug,我们需要紧急回退到上一个版本!

别慌,Deployment 已经为我们记录了历史版本。执行回滚命令即可:

kubectl rollout undo deployment/nginx-deployment

再次观察 Pod 变化 kubectl get pods -w,你会发现 K8s 又开始了一次滚动操作,这次是把 1.22 版本的 Pod 逐个替换回 1.21 版本。危机解除!


总结

今天我们学习了 K8s 中两个最核心、最基础的概念:

  • Pod: K8s 的原子调度单元,是容器的“家”,为内部容器提供共享的网络和存储。
  • Deployment: Pod 的“智能管家”,负责保证 Pod 的数量(副本)、实现故障自愈、并以安全、平滑的方式进行应用更新和回滚。

你现在已经掌握了在 K8s 中部署、更新和维护无状态应用的基本技能。我们已经成功地让应用在集群内部“活起来”并且“活得很好”。

但是,新的问题又来了:现在这些 Nginx 服务都运行在 K8s 集群内部,我们作为外部用户,如何才能访问到它们呢?

别急,这正是我们下一篇文章要解决的问题。在下一篇 《K8s 核心概念白话解读(下)》 中,我们将揭秘 ServiceIngress 这两个负责“对外暴露服务”和“管理流量”的关键角色。敬请期待!