---
url: /courses/kubernetes-cluster/01-toolchain-setup/index.md
---
# 第一节 个人电脑上的本地模拟工具链

::: tip 本课目标
理解 Kubernetes 解决的问题、核心工作方式、采用收益与边界；完成 Docker、kind、kubectl 与 Helm 的环境检查或安装，确认个人电脑可以进入下一步 kind 集群实验。最终只提交两张终端截图，不需要另外编写安装报告。
:::

## 1.1 先认识项目：云帆商城是什么

**云帆商城**是贯穿本课程 13 次课的虚构电商业务，用来提供一条稳定的 Kubernetes 运维主线。它不是需要从零开发的完整商城，也不对应真实生产系统；本课程关注的是“怎样为一个包含 Web 与数据库的应用建设可重复、可验证的运行平台”。

课程把它抽象为四部分：

| 组成 | 在业务中的职责 | 后续对应的 Kubernetes 内容 |
| --- | --- | --- |
| 商城 Web 服务 | 展示商品页面并接收访问请求，使用 Nginx 容器代表无状态业务 | Pod、Deployment、滚动更新、健康探测、HPA |
| MariaDB 数据服务 | 保存商品、订单等需要持久化的数据，代表有状态业务 | StatefulSet、PV/PVC、ConfigMap、Secret、Helm |
| 运行配置 | 保存环境参数和数据库连接信息 | ConfigMap 与 Secret |
| 访问入口 | 为变化中的 Web 副本提供稳定地址和流量分发 | Service、DNS、NodePort 或端口转发 |

课程不会实现购物车、支付或订单业务代码。只要 Web 容器能稳定发布、访问和扩缩，MariaDB 能正确使用配置与存储，就足以承载后续运维任务。

### 当前运行方式

在课程开始时，先假设云帆商城运行在一台服务器上：一个 Nginx Web 容器提供页面，一个 MariaDB 实例保存数据，启动、更新和故障恢复主要依赖手工操作。

```mermaid
flowchart LR
  User[浏览器访问] --> Web
  subgraph LocalHost[单台服务器]
    Web[Nginx Web 容器]
    DB[(MariaDB 数据库)]
    Config[环境参数与连接信息]
    Web --> DB
    Config --> Web
    Config --> DB
  end
```

这个初始架构并不“错误”。当访问量较小、只有一个运行实例时，它比 Kubernetes 更简单，也更容易维护。

### 当前方式在规模扩大后会遇到什么问题

这套方式成立的前提是“服务少、实例少、单机资源足够、短暂中断可以接受”。当这些条件开始变化时，下面的问题才会逐渐出现：

| 现状 | 人工处理方式 | 规模扩大后的问题 |
| --- | --- | --- |
| 一个 Web 容器停止 | 登录服务器并重新启动 | 故障发现和恢复依赖人工值守 |
| 访问量突然增加 | 手工启动更多容器 | 副本分散在哪些机器、流量怎样分配都要单独处理 |
| 发布新版本 | 停止旧容器，再启动新容器 | 容易产生中断，失败后的回退步骤不统一 |
| 服务数量增加 | 手工维护端口和地址 | 容器重建后地址可能变化，服务之间难以稳定发现 |
| 多台机器共同运行 | 逐台登录和执行命令 | 环境、参数和操作结果容易不一致 |

这些问题的共同点不是“不会启动容器”，而是：**容器数量增加后，怎样持续保持整个应用系统处于预期状态。**

### 所以需要一种怎样的管理工具

仅仅增加更多启动脚本还不够。云帆商城需要的管理工具至少应该具备以下能力：

1. 接收“Web 服务应该始终有几个副本”这样的目标，而不是只执行一次启动命令。
2. 持续观察容器和节点状态，发现偏差后主动恢复。
3. 把工作负载安排到合适的机器，不再逐台登录操作。
4. 在容器地址变化后，仍然提供稳定的服务入口。
5. 按可控节奏发布新版本，并在失败时回退。
6. 使用可以保存、审查和重复应用的配置描述整个系统。

这些需求共同指向一种“面向期望状态、能够持续协调多个容器和节点”的管理平台，Kubernetes 就是为这类问题设计的。

### Kubernetes 是什么

Kubernetes，简称 **K8s**，是一个用于管理容器化工作负载和服务的开源平台。它把多台机器组织成一个集群，并通过统一 API 管理应用的部署、调度、扩缩容、网络入口、配置和故障恢复。

可以把两种管理方式理解为：

* 使用 Docker 时，常见操作是“现在启动这个容器”。
* 使用 Kubernetes 时，常见操作是“我希望这个应用始终有 3 个可用副本，并通过一个稳定入口提供服务”。

后一种描述叫作**期望状态**。Kubernetes 会不断观察实际状态，并通过控制器把实际状态拉回期望状态。

```mermaid
flowchart LR
  Desired[期望状态<br/>3 个 Web 副本] --> API[Kubernetes API]
  API --> Controller[控制器持续比较]
  Actual[实际状态<br/>当前只有 2 个副本] --> Controller
  Controller --> Action[创建 1 个新 Pod]
  Action --> Actual
```

这个过程不是只执行一次的安装脚本，而是持续运行的**控制循环**。例如某个副本异常退出后，控制器会发现“实际 2 个、期望 3 个”的差异，并请求创建替代副本。

::: tip 一句话理解
Kubernetes 不负责把源代码变成应用；它负责让已经容器化的应用按照声明的状态持续运行。
:::

### Kubernetes 具体能做什么

| 能力 | 解决的问题 | 云帆商城中的例子 |
| --- | --- | --- |
| 调度 | 应该把工作负载放到哪台节点 | 根据资源情况为 Web Pod 选择节点 |
| 自愈 | 容器或 Pod 失败后怎样恢复 | 自动创建替代副本 |
| 服务发现与负载均衡 | 地址变化后怎样稳定访问 | 使用 Service 为多个 Web Pod 提供统一入口 |
| 滚动更新与回滚 | 怎样减少发布中断 | 逐步替换 Web 版本，异常时回退 |
| 水平扩缩容 | 访问量变化时怎样调整副本 | 根据指标增加或减少 Web Pod |
| 配置与密钥载体 | 怎样把运行配置与镜像分开 | 使用 ConfigMap 与 Secret 注入配置 |
| 存储编排 | 容器重建后怎样继续使用数据 | 为有状态服务绑定持久卷 |

这些能力带来的主要收益是：

1. **自动化**：把反复登录机器执行的操作转成 API 对象和控制循环。
2. **一致性**：同一份声明式配置可以重复应用和审查。
3. **可恢复性**：控制器能持续发现并修正部分运行偏差。
4. **可扩展性**：应用副本可以在多节点间调度和扩缩。
5. **可观察性基础**：资源状态、事件和变更记录形成统一排错入口。

### 回到最初的问题：云帆商城需要 Kubernetes 吗

现在才能作出判断。云帆商城不是因为“用了 Docker 就必须迁移”，而是因为本课程假设它已经出现以下需求：

* Web 服务需要多个副本，单个实例故障不能让入口完全中断。
* 发布过程需要逐步替换和回滚，不能每次都整体停机。
* Web、数据库、配置和网络入口需要统一描述与验证。
* 后续还要练习服务发现、健康探测、持久化、调度和自动扩缩容。

这些需求与 Kubernetes 的调度、自愈、服务发现、滚动更新和声明式管理能力相匹配，因此本课程选择 Kubernetes 作为统一管理层，再使用 kind 在个人电脑上建立低成本的模拟集群。

::: warning 迁移并不总是收益更大
Kubernetes 会增加集群组件、网络、存储、权限、监控和排错复杂度。只有一个访问量稳定的小应用时，单机 Docker Compose 或托管应用平台可能更简单。Kubernetes 也不会自动修复程序逻辑错误、设计数据库备份、构建镜像或替代完整的监控告警系统。
:::

### 迁移不是把所有内容一次性搬进去

更稳妥的顺序是先迁移无状态 Web 服务，再逐步处理配置、访问入口和自动扩缩容。有状态数据库需要单独验证持久化、备份、恢复、性能和故障切换；如果已有成熟的托管数据库，也可以继续让数据库运行在集群外。

```mermaid
flowchart LR
  A[容器化 Web 服务] --> B[在 Kubernetes 运行 Web]
  B --> C[接入 Service 与健康探测]
  C --> D[验证滚动更新与扩缩容]
  D --> E{数据库是否适合迁移}
  E -->|备份恢复与存储已验证| F[再评估有状态迁移]
  E -->|条件不足| G[继续使用集群外数据库]
```

选看视频：[100 秒理解 Kubernetes 的作用](https://www.bilibili.com/video/BV1jrdoYqEAc/)

@[bilibili](BV1jrdoYqEAc)

::: details 看完后回答

1. Kubernetes 管理的是源代码，还是已经容器化的工作负载？
2. 为什么“期望状态”比逐台机器执行命令更适合管理多个副本？
3. 哪一种小型应用场景可能暂时不需要 Kubernetes？
   :::

### 本课为什么先准备工具链

理解采用理由后，再准备本地实验所需的四个工具：

```mermaid
flowchart LR
  Docker[Docker<br/>运行节点容器] --> Kind[kind<br/>创建本地集群]
  Kind --> Cluster[Kubernetes 集群]
  Kubectl[kubectl<br/>调用 Kubernetes API] --> Cluster
  Helm[Helm<br/>包化交付资源] --> Cluster
```

直接创建集群之前，先确认三个条件：

1. Docker Engine 能正常运行容器。
2. kind、kubectl 与 Helm 命令可以执行。
3. CPU、内存、磁盘和虚拟化能力足以运行本地节点。

### 先分清镜像、容器与虚拟机

Docker 不是虚拟机管理器，容器也不是一台缩小的虚拟机。三者的边界如下：

| 概念 | 它是什么 | 本课中的例子 |
| --- | --- | --- |
| 镜像 Image | 只读模板，包含程序和运行所需文件 | `hello-world` 镜像 |
| 容器 Container | 镜像启动后的运行实例，本质上仍是受隔离和限制的进程 | `docker run` 启动的测试容器 |
| 虚拟机 VM | 拥有独立客户操作系统的虚拟计算机 | macOS/Windows 上 Docker Desktop 使用的 Linux 运行环境 |
| kind 节点 | 用容器模拟的一台 Kubernetes 节点 | control-plane 或 worker 节点容器 |

在 Linux 上，Docker Engine 可以直接使用内核提供的 Namespace 和 cgroup 隔离进程。macOS 与 Windows 不能直接运行 Linux 容器，因此 Docker Desktop 会先准备一个轻量 Linux 环境，再在其中运行 Docker Engine。后续命令虽然一致，底层路径并不完全相同。

选看视频：[Docker 概述与核心概念](https://www.bilibili.com/video/BV1biXxYfE8b/)

@[bilibili](BV1biXxYfE8b)

::: details 看完后回答

1. 镜像与容器分别对应“模板”还是“运行实例”？
2. 为什么删除一个容器不会自动删除它使用的镜像？
3. `docker run` 至少需要经过哪些环节才能看到程序输出？
   :::

### kind 解决的不是“安装 Docker”

kind 的全称是 Kubernetes IN Docker。它不会替代 Docker，而是调用 Docker 创建一个或多个节点容器，再在这些节点中启动 Kubernetes 组件。它适合在个人电脑上反复创建、删除和重建实验环境。

这里存在三层容易混淆的运行关系：

```mermaid
flowchart TB
  Host[个人电脑<br/>Docker Desktop 或 Docker Engine]
  Node[kind 节点容器<br/>control-plane / worker]
  Runtime[节点内部的 containerd]
  Pod[Pod 中的业务容器]

  Host --> Node
  Node --> Runtime
  Runtime --> Pod
```

Docker 负责运行 kind 节点容器；节点内部的容器运行时再负责运行 Pod 中的业务容器。因此，“kind 节点容器”和“Pod 业务容器”不在同一层。

| 对比维度 | kind 本地模拟 | 生产集群 |
| --- | --- | --- |
| 运行位置 | 一台个人电脑中的容器 | 多台服务器或云主机 |
| 创建与重建 | 分钟级，可频繁重建 | 需要网络、证书、高可用和变更计划 |
| 主要用途 | 学习、测试和可重复实验 | 承载真实业务 |
| 数据边界 | 受本机和节点容器生命周期影响 | 依赖生产级存储、备份与容灾 |

::: warning 使用边界
kind 可以模拟 Kubernetes 的控制与工作负载机制，但不能代替生产环境。不要把本机端口映射、节点容器存储或单控制平面结果直接当作生产方案。
:::

观察下面的架构动画，辨认宿主机、节点容器与 Kubernetes 组件之间的边界。

## 1.2 预检：用检查结果判断资源档位

标准实验集群使用 1 个控制平面节点和 2 个工作节点；资源接近最低要求时，可以改用 1 个控制平面节点和 1 个工作节点。

先执行与你当前系统对应的命令。

::: tabs#k8s-platform
@tab macOS

```bash
# CPU 逻辑核心数
sysctl -n hw.ncpu

# 物理内存，换算为 GB
sysctl -n hw.memsize | awk '{printf "%.0f GB\n", $1/1024/1024/1024}'

# 根分区可用磁盘
df -h /

# Apple Hypervisor Framework：1 表示可用
sysctl -n kern.hv_support
```

@tab Windows

```powershell
# CPU 逻辑核心数
(Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors

# 物理内存，换算为 GB
[math]::Round(
  (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory / 1GB,
  1
)

# C 盘可用磁盘，换算为 GB
[math]::Round((Get-PSDrive C).Free / 1GB, 1)

# 查看系统与虚拟化要求
systeminfo
```

@tab Linux

```bash
# CPU 逻辑核心数
nproc

# 内存
free -h

# 根分区可用磁盘
df -h /

# KVM 设备存在且可读写时，输出 kvm-ready
test -r /dev/kvm -a -w /dev/kvm && echo kvm-ready || echo check-kvm
```

:::

把命令结果填入下面的问题，点击按钮得到资源档位建议。这里的答案只用于当前页面判断，不作为最终提交内容。

::: danger 不要忽略资源不足
Docker 被系统强制回收、磁盘写满或虚拟化不可用时，后续现象可能表现为节点失联、镜像拉取失败或 Pod 随机重启。反复删除集群不能解决这些根因。
:::

### 提前排除常用端口冲突

后续实验可能把节点端口映射到本机。下面的通用检查命令可以保留到后续课次使用；当前端口被占用并不影响本课工具安装。

::: tabs#k8s-platform
@tab macOS

```bash
lsof -nP -iTCP:80 -sTCP:LISTEN
lsof -nP -iTCP:443 -sTCP:LISTEN
```

@tab Windows

```powershell
Get-NetTCPConnection -State Listen |
  Where-Object LocalPort -In 80, 443 |
  Select-Object LocalAddress, LocalPort, OwningProcess
```

@tab Linux

```bash
ss -lntp '( sport = :80 or sport = :443 )'
```

:::

没有输出表示对应端口当前没有监听进程；有输出时先确认进程用途，不要直接结束未知进程。

## 1.3 实施：按当前系统准备 Docker

统一实验环境已经预装 Docker Desktop。若 `docker info` 能正常返回服务端信息，可以直接进入下一节；若命令不存在或 Docker Engine 没有启动，再参考对应系统的安装方式。

macOS 和 Windows 使用完整产品 **Docker Desktop**，Linux 可以安装 **Docker Engine**。

### Docker Client 与 Docker Engine

在终端输入的 `docker` 是客户端。它把请求发送给 Docker daemon，再由 daemon 管理镜像、网络、存储和容器。

```mermaid
sequenceDiagram
  participant CLI as docker CLI
  participant D as Docker daemon
  participant R as 镜像仓库
  participant C as 容器
  CLI->>D: docker run hello-world
  D->>D: 检查本地镜像
  D->>R: 本地不存在时拉取镜像
  D->>C: 创建并启动容器
  C-->>CLI: 返回程序输出
```

这也解释了两种常见现象：

* `docker --version` 成功，只能证明客户端命令存在。
* `docker info` 同时返回 Client 与 Server 信息，才能证明客户端已经连接到 Docker Engine。

::: tabs#k8s-platform
@tab macOS

使用 Homebrew 安装：

```bash
brew install --cask docker
```

也可以从 Docker 官网下载安装包。安装后启动 Docker Desktop，等待 Docker Engine 进入运行状态。

```bash
docker info
docker version
```

@tab Windows

使用 WinGet 安装：

```powershell
winget install --id Docker.DockerDesktop
```

安装后启动 Docker Desktop，并确认 WSL 2 后端可以正常工作。

```powershell
wsl --version
docker info
docker version
```

@tab Linux

以下命令适用于 Ubuntu；其他发行版应使用 Docker 官方对应发行版的安装说明。

```bash
sudo apt update
sudo apt install -y ca-certificates curl

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

. /etc/os-release
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${UBUNTU_CODENAME:-$VERSION_CODENAME} stable" |
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker

sudo usermod -aG docker "$USER"
```

退出当前登录会话并重新登录，再执行：

```bash
docker info
docker version
```

:::

::: warning Docker 权限边界
Linux 的 `docker` 组可以控制 Docker daemon，通常等同于获得主机高权限。只给确实需要操作 Docker 的账号授予该权限。
:::

仅看到 Docker 图标不能证明容器运行能力。Docker 官方提供了名为 `hello-world` 的最小测试镜像，用它可以同时检查镜像拉取和容器启动链路。阅读 `docker info` 输出后，回答问题并完成验证。

看到 `Hello from Docker!` 表示 Docker 客户端、Docker Engine、镜像拉取与容器启动链路均可工作。

## 1.4 实施：安装 kind、kubectl 与 Helm

三个命令行工具都保留 macOS、Windows 与 Linux 的通用安装方式。包管理器默认安装当前可用版本，本课不要求指定或冻结版本。

### 三个命令都不是 Kubernetes 集群

| 工具 | 主要输入 | 主要输出 | 是否负责长期运行工作负载 |
| --- | --- | --- | --- |
| kind | 节点数量、角色和端口等集群配置 | 一套本地节点容器与 kubeconfig | 否，负责创建和删除本地集群 |
| kubectl | 命令、资源名称或 YAML | Kubernetes API 的查询或变更结果 | 否，它是 API 客户端 |
| Helm | Chart、values 和 release 操作 | 渲染后的 Kubernetes 资源与 release 记录 | 否，它通过 Kubernetes API 交付资源 |

kubectl 连接集群时会读取 kubeconfig。kubeconfig 主要回答三个问题：

* **cluster**：API Server 在哪里，以及如何验证它的证书。
* **user**：用什么凭据发起请求。
* **context**：当前把哪个 user 与哪个 cluster 组合起来，并默认使用哪个 namespace。

当前还没有创建集群，所以本课只能验证 kubectl 客户端。下一课由 kind 生成 kubeconfig 后，`kubectl` 才能真正向 API Server 发起请求。

::: tabs#k8s-platform
@tab macOS

```bash
brew install kind kubectl helm
```

@tab Windows

```powershell
winget install --id Kubernetes.kind
winget install --id Kubernetes.kubectl
winget install --id Helm.Helm
```

@tab Linux

安装 kind：

```bash
KIND_ARCH="$(uname -m)"
case "$KIND_ARCH" in
  x86_64) KIND_ARCH=amd64 ;;
  aarch64|arm64) KIND_ARCH=arm64 ;;
  *) echo "Unsupported architecture: $KIND_ARCH"; exit 1 ;;
esac

curl -Lo kind "https://github.com/kubernetes-sigs/kind/releases/latest/download/kind-linux-${KIND_ARCH}"
chmod +x kind
sudo mv kind /usr/local/bin/kind
```

安装 kubectl：

```bash
KUBECTL_ARCH="$(uname -m)"
case "$KUBECTL_ARCH" in
  x86_64) KUBECTL_ARCH=amd64 ;;
  aarch64|arm64) KUBECTL_ARCH=arm64 ;;
  *) echo "Unsupported architecture: $KUBECTL_ARCH"; exit 1 ;;
esac

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${KUBECTL_ARCH}/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
```

安装 Helm：

```bash
curl -fsSL -o get_helm.sh \
  https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
less get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh
```

:::

kind 用 Docker 容器模拟 Kubernetes 节点；kubectl 通过 kubeconfig 连接 Kubernetes API；Helm 用 Chart 组织复杂应用。当前还没有创建集群，因此 `kubectl cluster-info` 连接失败是正常现象。

观察动画，理解 kind 创建集群时 Docker、kubeadm、CNI 和 kubeconfig 各自出现在哪一步。

::: tip 关键关系
每个 kind 节点都是一个 Docker 容器。下一课会把节点数量、角色和端口映射写入 `kind-config.yaml`，再由 kind 创建本地集群。
:::

### Helm 中的 Chart、values 与 release

Helm 常被称为 Kubernetes 的包管理器，但它管理的不是普通操作系统软件包：

* **Chart** 是一组 Kubernetes 模板和元数据。
* **values** 为模板提供可替换参数。
* **release** 是某个 Chart 使用一组 values 安装到集群后的实例记录。

同一个 Chart 可以用不同 values 创建不同 release。Helm 最终仍然通过 Kubernetes API 创建或更新资源，因此安装 Helm 客户端并不代表集群中已经安装了应用。

选看视频：[Helm 的基本定位（第 34 分 P）](https://www.bilibili.com/video/BV1jrdoYqEAc/?p=34)

@[bilibili p34](BV1jrdoYqEAc)

::: details 看完后回答

1. Chart、values 与 release 分别对应模板、参数还是安装实例？
2. Helm 为什么仍然需要 kubeconfig？
3. `helm version` 成功能否证明集群中已经存在 release？
   :::

## 1.5 验证：确认四个工具都能使用

不要通过桌面图标或安装器的“完成”页面判断结果。终端命令能直接证明 Docker Engine 是否可连接，以及三个客户端是否进入 PATH。

阅读前文中 kubectl 客户端与集群的关系，回答问题后运行整组验收命令。`kubectl version` 默认还会尝试联系集群；尚未创建集群时，应加上 `--client` 参数，只检查本地客户端。

通过标准：

| 检查项 | 通过现象 | 不通过时先检查 |
| --- | --- | --- |
| Docker | `docker info` 同时显示 Client 与 Server 信息 | Docker Desktop 或 daemon 是否运行 |
| kind | `kind version` 返回版本信息 | 安装位置是否在 PATH |
| kubectl | `kubectl version --client` 返回客户端信息 | 命令名、PATH 与安装是否完成 |
| Helm | `helm version` 返回版本信息 | PATH 是否刷新 |

## 1.6 交付：只提交两张截图

本课不要求资源表、版本冻结表、安装报告、命令日志或故障工单。只保留以下两张截图：

1. **Docker 容器验证截图**：终端中同时包含执行的 `docker run --rm hello-world` 命令和 `Hello from Docker!` 成功信息。
2. **工具链验证截图**：同一终端画面中包含 `kind version`、`kubectl version --client`、`helm version` 三条命令及其成功输出。

截图需要包含完整命令和关键结果，不需要截取桌面、个人目录、账号信息、代理地址或其他无关区域。

{{reflection-checkpoint:toolchain-baseline-check}}

## 1.7 排错：从报错类型开始定位

| 现象 | 优先检查 | 常见原因 | 最小修复方向 |
| --- | --- | --- | --- |
| `docker info` 无法连接 | Docker Desktop/daemon 状态 | 服务未启动 | 启动服务后重新检查 |
| Linux 报 Docker socket 权限错误 | `id`、`ls -l /var/run/docker.sock` | 组权限尚未生效 | 确认授权范围并重新登录 |
| 命令不存在 | `command -v` 或 `Get-Command` | PATH 未刷新或安装失败 | 确认安装位置并重开终端 |
| 下载超时 | DNS、代理与下载站连通性 | 网络或代理配置异常 | 先定位网络层，再配置代理 |
| 端口已监听 | 监听进程与用途 | 本机服务占用 | 后续映射时换端口，或确认影响后再停止服务 |
| 资源低于最低要求 | 资源预检答案 | 配置或后台负载不足 | 使用低配档；仍不满足时先释放或扩充资源 |

::: details 挑战任务：编写只读环境检查脚本
脚本可以汇总 CPU、内存、磁盘、虚拟化、工具版本和端口监听状态，但不得自动结束进程、修改系统设置或安装软件。输出应清楚区分“通过、警告、失败”；挑战任务不增加提交物。
:::

## 本章小测

{{assessment:toolchain-setup}}

## 本章小结

完成本课后，你应能够：

* 用自己的话说明 Kubernetes 是什么，以及它为什么采用期望状态和持续控制循环。
* 判断多副本、自动恢复、统一发布等需求何时值得引入 Kubernetes，并说明它增加的复杂度。
* 说明 Docker、kind、kubectl 与 Helm 的依赖关系。
* 根据当前系统检查 CPU、内存、磁盘和虚拟化能力。
* 在预装环境中直接验证 Docker，也能在其他环境中找到对应安装路径。
* 使用 `hello-world` 验证完整容器运行链路。
* 在尚未创建集群时使用 `kubectl version --client` 检查客户端。
* 用两张终端截图证明工具链已经可用。

下一课将编写 `kind-config.yaml`，创建一套可删除、可重建的本地多节点模拟集群。
