第7章:迈向云原生 - Kubernetes 简介
欢迎来到我们旅程的第二部分!在 Docker 篇中,我们已经能熟练地在单台机器上,使用 Docker 和 Docker Compose 来构建和管理多容器应用。这对于开发和测试来说,已经非常棒了。
但是,当应用需要正式上线,走向生产环境时,新的挑战接踵而至:
- 单点故障:如果我们的应用只运行在一台服务器上,那台服务器宕机了怎么办?整个服务就中断了。
- 弹性伸缩:双十一流量洪峰来了,如何快速地把我们的 Web 服务从1个实例扩展到100个实例?流量回落后,又如何自动缩减,以节约成本?
- 服务更新:发布新版本时,如何做到不中断服务,平滑地将用户流量从旧版本迁移到新版本?
- 健康检查与自愈:如何自动地监控某个应用实例是否"假死",并在它出问题时,自动"杀死"它并重启一个新的来代替?
Docker Compose 无法解决这些问题。它是一个"单机版"的工具,而生产环境需要的是一个 "集群版" 的、能够统一管理成百上千台服务器和容器的"超级大脑"。
这个"超级大脑",就是 Kubernetes (通常简称为 K8s)。
7.1 为什么有了 Docker 还需要 K8s?
如果说 Docker 提供的是标准化的"集装箱"(容器),那么 Kubernetes 就是那个全自动化的"国际航运港口"。
K8s 是一个容器编排 (Container Orchestration) 平台。它的核心工作,就是在一个服务器集群中,自动化地部署、管理、伸缩和维护容器化应用。
它接管了所有繁琐的运维工作,让你只需要关心你的应用本身,而不需要关心它具体运行在哪一台机器上。
场景 | Docker Compose (单机) | Kubernetes (集群) |
---|---|---|
部署规模 | 单台主机 | 成百上千台主机 |
高可用性 | 无,主机宕机则服务中断 | 有,自动在健康的节点上重启失败的容器,实现故障转移 |
负载均衡 | 简单,需要手动配置 | 内置强大的负载均衡和服务发现机制 |
弹性伸缩 | 手动 | 可根据 CPU/内存使用率等指标,自动增加或减少容器实例 |
滚动更新/回滚 | 不支持 | 支持零停机的滚动更新策略,并能一键回滚到旧版本 |
自愈能力 | 无 | 持续监控容器健康状况,自动替换不健康的实例 |
简而言之,Docker 解决了打包和运行 的问题,而 Kubernetes 解决了规模化、自动化和高可用的问题。它们是现代云原生应用开发的黄金搭档。
7.2 K8s 的核心理念:声明式 API 与控制器模式
要理解 K8s 的工作方式,必须理解它的核心设计哲学:声明式 API (Declarative API)。
- 命令式 (Imperative) :你一步步地告诉系统"怎么做 "。比如:"启动一个容器"、"停止那个容器"、"把A的流量切到B"。
docker run
就是典型的命令式。 - 声明式 (Declarative) :你只告诉系统"我想要什么 ",系统会自己想办法达到这个状态。比如,你向 K8s 提交一个配置文件(通常是 YAML 格式),说:"我想要一个运行着
nginx:latest
镜像的应用,并且始终保持3个副本在运行"。
K8s 收到这个"期望状态"后,它内部的控制器 (Controller) 就会开始工作。控制器会不断地将"当前状态 "与你声明的"期望状态"进行比较,如果不一致,它就会采取行动,努力使当前状态趋近于期望状态。
- 例子 :K8s 发现当前只有2个
nginx
副本在运行,而期望是3个。控制器就会立刻找一台合适的机器,启动一个新的nginx
容器。 - 例子 :某个
nginx
容器崩溃了,当前状态变成了2个副本。控制器发现后,又会立刻启动一个新的来补足。
这种"声明式API + 控制器模式"的设计,是 K8s 实现自动化和自愈能力的关键。我们后续与 K8s 的所有交互,都将通过编写 YAML 文件来"声明"我们的意图。
7.3 K8s 架构概览(Master 与 Node)
一个 K8s 集群主要由两类角色的服务器构成:
-
Master 节点 (控制平面 Control Plane)
- 这是整个集群的"大脑"。它负责接收你的指令(YAML文件),做出决策,并将任务分发给工作节点。
- 它包含几个核心组件:
api-server
(接收指令的入口),etcd
(存储集群所有状态的数据库),scheduler
(决定容器该调度到哪个节点),controller-manager
(运行各种控制器)。 - 生产环境中,Master 节点通常有多个,以实现高可用。
-
Node 节点 (工作节点 Worker Nodes)
- 这些是集群中的"工人"。它们是真正负责运行你的应用程序容器(Container)的地方。
- 每个 Node 节点上都运行着两个关键组件:
kubelet
(与 Master 通信,并负责管理本节点上的容器) 和kube-proxy
(负责实现 K8s 的网络功能)。
我们的开发工作,就是与 Master 节点的 api-server
打交道,告诉它我们的"期望状态",然后 Master 会指挥下面的所有 Node 节点去完成实际的工作。
7.4 [实战] 在本地搭建你的第一个 K8s 集群
要在生产环境搭建一个 K8s 集群是相当复杂的。但幸运的是,社区提供了许多优秀的工具,可以让我们在自己的电脑上,一键启动一个功能完备的、用于学习和开发的单节点 K8s 集群。
最主流的两个工具是 Minikube 和 k3d。
- Minikube: 最老牌、最稳定、功能最全面的本地 K8s 工具。它会在你的电脑上启动一个虚拟机(或者使用 Docker 容器),在这个虚拟机里运行一个完整的 K8s 集群。
- k3d: 一个更轻量级的选择,它直接在 Docker 容器中运行 K8s 组件,启动速度更快,资源占用更小。非常适合快速实验。
我们这里以 Minikube 为例,它的体验与真实的 K8s 集群更接近。
1. 安装 Minikube 请访问 Minikube 的官方 GitHub 发布页面下载:github.com/kubernetes/... 根据你的操作系统,下载对应的可执行文件。它只是一个单一的二进制文件,无需安装,你可以把它放到一个在系统 PATH
里的目录。
2. 启动你的本地集群 打开命令行,执行:
bash
minikube start
第一次启动会比较慢,因为它需要下载 K8s 组件的镜像。当看到 Done! kubectl is now configured to use "minikube" cluster...
的提示时,就代表你的本地 K8s 集群已经成功启动并运行了!
Minikube 默认会使用你系统中最合适的驱动(比如 Docker Desktop 自带的 Docker 引擎)。
7.5 kubectl
:你的 K8s 命令行瑞士军刀
我们如何与这个 K8s 集群交互呢?答案是 kubectl
(发音:kube-control)。
kubectl
是 K8s 的官方命令行客户端。它是我们与 K8s api-server
对话的唯一工具。好消息是,Minikube 和 Docker Desktop 在安装时,通常都已经为你自动安装好了 kubectl
。
我们可以用它来检查一下集群的状态:
bash
# 查看集群信息
kubectl cluster-info
# 查看集群中的所有节点 (Node)
# 因为是本地集群,所以应该只会看到一个名为 minikube 的节点
kubectl get nodes
如果这些命令都能成功返回信息,说明你的 kubectl
已经正确配置,并连接上了你的 Minikube 集群。
7.6 本章小结 & 避坑指南
你已经成功地踏入了 Kubernetes 的大门,拥有了属于自己的第一个 K8s 集群。
-
本章回顾:
- 我们明白了 K8s 是为了解决规模化、自动化和高可用 而生的容器编排平台。
- 我们理解了 K8s 的核心理念:声明式 API 和 控制器模式。
- 我们了解了 K8s 的基本架构:Master 节点(大脑) 和 Node 节点(工人)。
- 我们使用 Minikube 在本地搭建了一个单节点 K8s 集群。
- 我们认识了与 K8s 交互的唯一工具:
kubectl
。
-
避坑指南:Minikube 启动失败的常见原因
-
问题1:提示
Exiting due to DRV_NOT_ENOUGH_MEMORY
- 原因:你的电脑分配给 Docker Desktop (或虚拟机) 的内存不足。K8s 是个吃内存的大家伙。
- 解决 :打开 Docker Desktop 的设置 (Settings -> Resources),把内存调大一些,建议至少 4GB 以上。然后执行
minikube delete
清理掉失败的集群,再重新minikube start
。
-
问题2:卡在
Pulling base image ...
-
原因 :国内网络环境访问 Google 的镜像仓库
gcr.io
存在困难。 -
解决 :可以在启动时,通过
--image-mirror-country=cn
或指定国内的镜像仓库地址来加速。bashminikube start --image-mirror-country=cn # 或者 minikube start --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers
-
-
问题3:
kubectl
命令提示The connection to the server localhost:8080 was refused
- 原因 :
kubectl
没有正确地配置到 Minikube 集群。 - 解决 :执行
minikube kubectl -- config view
来查看和确认配置。或者,你可以总是使用minikube kubectl -- <command>
的方式来确保你使用的是 Minikube 自带和配置好的kubectl
,例如minikube kubectl -- get nodes
。
- 原因 :
-
现在,我们的"自动化港口"已经建好,是时候学习如何将我们的"集装箱"部署进去了。下一章,我们将学习 K8s 最核心、最基本的概念:Pod 和 Deployment。