第8章:K8s 核心概念(上)- 工作负载

第8章:K8s 核心概念(上)- 工作负载

我们的 K8s 集群已经就绪,就像一个建好的港口。现在,我们需要学习如何把我们的"集装箱"(容器)运送到这个港口,并让港口按照我们的意愿来管理它们。

在 K8s 的世界里,我们不直接操作单个容器。相反,我们通过操作更高级别的 "工作负载 (Workload)" 资源来管理应用的生命周期。本章,我们将学习两个最核心的工作负载资源:PodDeployment

8.1 Pod:K8s 的原子调度单元

在 Docker 中,最基本的管理单元是容器。但在 K8s 中,情况有所不同。

Pod 是 Kubernetes 中创建和管理的、最小的可部署计算单元

把它想象成一个"豆荚"。一个豆荚(Pod)里,可以包含一个或多个紧密相关的豆子(容器)。

  • 一个 Pod 里有什么?

    • 一个或多个容器 :这些容器共享同一个网络空间(它们可以用 localhost 互相访问)和存储卷(数据卷)。
    • 网络资源:每个 Pod 都会被分配一个集群内唯一的 IP 地址。
    • 存储资源:可以为 Pod 挂载存储卷。
  • 为什么需要 Pod? 为什么不直接管理容器呢?因为有些应用场景,需要多个容器"像一个单元一样"被部署和管理。最经典的例子是"边车模式 (Sidecar)":一个主应用容器,旁边跟着一个专门负责日志收集或网络代理的辅助容器。这两个容器生命周期高度一致,需要被一起调度、一起扩缩容。Pod 完美地解决了这个问题。

  • 黄金法则 : 虽然一个 Pod 可以有多个容器,但在绝大多数情况下(99%) ,我们的实践是"一个 Pod,一个容器"。除非你有非常明确的理由,否则请坚持这个原则,它能让你的应用架构更清晰。

所以,你可以暂时简单地理解为:Pod 就是对 Docker 容器的一层封装。

8.2 ReplicaSet & Deployment:应用的扩缩容与滚动更新

我们很少会直接创建一个孤零零的 Pod。为什么?因为如果这个 Pod 所在的 Node 节点宕机了,这个 Pod 也就消失了,K8s 不会自动重建它。这显然不满足我们对高可用的要求。

我们需要一个更高级别的"老板"来照看我们的 Pod。

  • ReplicaSet (副本集)

    • 职责 :它的唯一职责,就是确保在任何时候,都有指定数量的、一模一样的 Pod 副本在运行。
    • 工作方式:你告诉 ReplicaSet:"我需要3个A应用的Pod副本"。它就会创建3个。如果有一个Pod死掉了,ReplicaSet 会立刻发现,并马上创建一个新的来替代它,始终维持总数为3。
  • Deployment

    • 职责 :这是我们在生产环境中最常用 的工作负载资源。它是一个更高级别的控制器,它管理 ReplicaSet ,并为我们提供了更强大的功能,特别是声明式的应用更新(滚动更新)和回滚

    • 工作方式

      1. 你创建一个 Deployment,在里面定义你应用的期望状态(比如,使用 my-app:1.0 镜像,需要3个副本)。
      2. Deployment 会创建一个 ReplicaSet。
      3. ReplicaSet 再去创建3个 Pod。
      4. 这个关系链是 Deployment -> ReplicaSet -> Pods
    • 为什么需要 Deployment? 想象一下你要发布新版本 my-app:1.1。你只需要修改 Deployment 的定义,把镜像版本从 1.0 改成 1.1。Deployment 就会智能地为你执行一次滚动更新 (Rolling Update):它会创建一个新的、使用新版本镜像的 ReplicaSet,然后一个一个地用新 Pod 替换旧 Pod,直到全部替换完成。整个过程服务不中断,非常平滑。

8.3 [实战] 将我们的 Web 应用部署到 K8s

理论讲完了,让我们把之前在 Docker 篇创建的 my-app 应用,部署到我们的 Minikube 集群中。

第一步:准备 YAML 文件

与 K8s 交互,就是与 YAML 文件打交道。在你的 my-app 项目根目录下,创建一个名为 deployment.yaml 的文件。

yaml 复制代码
# 指定 API 版本
apiVersion: apps/v1
# 指定资源类型为 Deployment
kind: Deployment
# 元数据,描述这个 Deployment
metadata:
  name: my-app-deployment
# 规格,定义期望状态
spec:
  # 期望的 Pod 副本数量
  replicas: 2
  # 选择器,告诉 Deployment 要管理哪些 Pod
  selector:
    matchLabels:
      app: my-app
  # Pod 的模板,定义了要创建的 Pod 长什么样
  template:
    metadata:
      # Pod 自身的标签,必须和上面的 selector 匹配
      labels:
        app: my-app
    spec:
      # 定义 Pod 中的容器
      containers:
      - name: my-app-container
        # 使用哪个镜像
        # 注意:这里需要使用你推送到 Docker Hub 的镜像地址
        # 并且 minikube 可能需要特殊设置才能访问本地镜像
        image: <your-dockerhub-username>/my-app:1.1 
        # 容器监听的端口
        ports:
        - containerPort: 8080

重要提示:关于镜像 Minikube 运行在一个独立的 Docker 环境中,它默认是无法访问你主机本地 Docker 里的镜像的。你有两个选择:

  1. 推荐 :将你构建好的镜像 push 到 Docker Hub,然后在 YAML 文件里使用完整的 Docker Hub 镜像地址,如 docker.io/<your-username>/my-app:1.1
  2. 开发技巧 :执行 eval $(minikube docker-env) (macOS/Linux) 或 minikube docker-env | Invoke-Expression (PowerShell)。这个命令会将你的命令行环境指向 Minikube 内的 Docker daemon。这样,你再执行 docker build,镜像就会被直接构建到 Minikube 内部,可以直接使用。

第二步:应用你的配置

使用 kubectl apply 命令,将你的"期望状态"提交给 K8s 集群。

bash 复制代码
kubectl apply -f deployment.yaml
  • apply: K8s 的核心命令之一,表示"让集群的状态与这个文件描述的一致"。
  • -f: 指定配置文件的路径。

执行后,如果成功,会提示 deployment.apps/my-app-deployment created

第三步:检查部署状态

bash 复制代码
# 查看 Deployment 的状态
kubectl get deployment my-app-deployment

# 查看 ReplicaSet
kubectl get rs

# 查看 Pods,你应该能看到两个 my-app-deployment-xxx 的 Pod 正在运行
kubectl get pods

你还可以用 describe 命令查看更详细的信息,这在排错时非常有用: kubectl describe deployment my-app-deployment kubectl describe pod <pod_name>

8.4 [实战] 体验"永不宕机"的滚动更新

现在,来体验一下 K8s 最令人兴奋的功能。

体验自愈能力 手动删除一个 Pod,模拟故障:

bash 复制代码
# 找到一个 Pod 的名字,比如 my-app-deployment-xxxx
kubectl delete pod <pod_name>

删除后,你立刻再次执行 kubectl get pods,你会发现 K8s 几乎在瞬间就创建了一个新的 Pod 来替代被删除的那个,replicas 始终保持为2。这就是 ReplicaSet 的功劳。

体验滚动更新

  1. 修改代码并构建新镜像

    • 修改 app.js,比如返回 "Hello, Kubernetes!"。
    • 构建一个新版本的镜像 my-app:1.2,并推送到 Docker Hub (或者构建到 Minikube 内部)。
  2. 更新 Deployment: 有两种方式:

    • 方法一(推荐) :直接修改 deployment.yaml 文件,将 image 的 tag 改为 1.2,然后再次执行 kubectl apply -f deployment.yaml。K8s 会智能地计算出差异并只更新变化的部分。

    • 方法二(命令式)

      bash 复制代码
      kubectl set image deployment/my-app-deployment my-app-container=<your-dockerhub-username>/my-app:1.2
  3. 观察更新过程 : 执行更新后,立刻打开另一个终端,执行 kubectl get pods -w (-w 表示 watch,实时监控变化)。你会看到 K8s 正在:

    • 创建一个新的 Pod (版本1.2)
    • 等新 Pod 启动成功后,删除一个旧的 Pod (版本1.1)
    • 再创建一个新 Pod,再删除一个旧 Pod...
    • 直到所有 Pod 都更新为版本1.2。

整个过程服务不中断。这就是滚动更新的魅力!

体验回滚 如果发现新版本有 Bug 怎么办?一键回滚!

bash 复制代码
# 查看发布历史
kubectl rollout history deployment/my-app-deployment

# 回滚到上一个版本
kubectl rollout undo deployment/my-app-deployment

K8s 会用同样平滑的方式,将应用回滚到之前的稳定版本。

8.5 本章小结

你已经掌握了在 K8s 中部署无状态应用的核心技能。

  • 本章回顾
    • 我们理解了 Pod 是 K8s 中最小的部署单元,通常坚持"一个 Pod 一个容器"的原则。
    • 我们学习了通过 Deployment 来管理应用的副本数量、自愈和滚动更新。
    • 我们掌握了通过编写 YAML 文件来向 K8s 声明我们的应用部署意图。
    • 我们使用 kubectl apply 将应用部署到了 K8s,并用 get, describe, delete 等命令进行了交互。
    • 我们亲身体验了 K8s 强大的自愈能力滚动更新一键回滚功能。

目前,我们的应用虽然已经在 K8s 中运行起来了,但外界还无法访问它。在下一章,我们将学习 K8s 的网络核心------Service,来为我们的应用打开通往世界的大门。

相关推荐
StevenLdh2 小时前
Docker容器化部署简要指南
运维·docker·容器
段振轩3 小时前
Docker数据卷
运维·docker·容器
吃不胖没烦恼3 小时前
Alibaba Cloud Linux 3 +Docker 部署 ThinkPHP6 (宝塔环境)
linux·运维·docker
货拉拉技术5 小时前
货拉拉离线大数据跨云迁移 - 数据迁移篇
大数据·云原生
Ting-yu5 小时前
零基础学Docker(4)--Docker镜像原理
java·docker·容器
绝非小练7 小时前
Podman安装与使用 Mac系统
容器
qq_569384129 小时前
K8S (使用步骤)
云原生·容器·kubernetes
浅拾光º9 小时前
Docker部署的MySQL,如何一键备份Docker中的MySQL?
mysql·docker·容器
麦兜*9 小时前
Spring Boot 项目 Docker 化:从零到一的完整实战指南
数据库·spring boot·redis·后端·spring·缓存·docker