Kubernetes和云原生:从Docker到K8s的知识三明治

我最近在云服务大厂实习,需要补一下 Kubernetes 和云原生的知识。
但问题是,我并不是一开始就懂 K8s。我之前主要用过 Docker,知道可以把一个应用打包成镜像,然后用容器跑起来。比如本地起一个 MySQL、Redis、Nginx,或者把自己的后端服务打成镜像,这些都还比较直观。
可是当容器数量变多之后,问题就来了。
一个容器挂了怎么办?多个容器之间怎么互相访问?服务升级时怎么不停机?数据库这种有数据的服务怎么处理?应用配置变了是不是还要重新打镜像?容器要跑在哪台机器上?机器挂了以后谁来把服务重新拉起来?
如果只有两三个容器,我们还可以用 Shell 脚本、Docker Compose 或者手动命令勉强管理。但如果是一整个项目、多个服务、多台机器、多个环境,这件事就会迅速失控。
Kubernetes 要解决的,就是“容器多了以后怎么管理”的问题。
它不是 Docker 的替代品,而是站在 Docker 这类容器技术之上,帮我们做容器编排、调度、服务发现、扩缩容、配置管理、存储管理和故障恢复。
这篇文章就按“知识三明治”的方式来补:先用 Docker 的直觉理解 K8s,再逐个解释核心组件,最后看一下它在云原生里的位置。
一、从 Docker 到 Kubernetes:为什么需要 K8s
Docker 解决的是“怎么把应用和运行环境打包起来”。
比如一个 Java 应用原来需要 JDK、配置文件、启动脚本、依赖包。不同机器环境不一样,很容易出现“我本地能跑,你服务器跑不了”的问题。Docker 把这些东西打进镜像里,容器启动后环境基本一致,这就方便很多。
但 Docker 更偏向管理单个容器,或者少量容器。
假设现在有一个简单系统:
- 一个前端服务
- 一个后端 API 服务
- 一个 MySQL 数据库
- 一个 Redis 缓存
- 一个 Nginx 网关
用 Docker 跑起来不难。但继续往下想:
- 后端 API 要不要多跑几个副本?
- 某个副本挂了,谁负责重新启动?
- Redis 的地址变了,后端配置怎么更新?
- MySQL 数据不能丢,容器重启后数据放哪里?
- Nginx 怎么把外部请求转发到正确服务?
- 服务升级时怎么做到用户无感?
- 这些容器到底应该跑在哪台机器上?
这些问题单靠手写脚本也能做一部分,但很快会变得复杂。
于是 Kubernetes 出场了。
可以先把它理解成:Kubernetes 是一个容器管理平台,它负责在一组机器上管理一堆容器,让它们按照我们声明的方式运行。
二、Kubernetes 的基本直觉:我想要什么状态
Kubernetes 里很重要的一个思想叫“声明式”。
你不是一步一步告诉它:先创建这个容器,再启动那个容器,再检查一下,再挂了重启。
你更多是在告诉它:
我希望这个应用一直有 3 个副本,使用 nginx:1.25 这个镜像,对外暴露 80 端口。
然后 Kubernetes 会不断检查当前状态和你想要的状态是否一致。如果少了一个副本,它就补一个;如果某个 Pod 挂了,它就重新创建;如果你把副本数从 3 改成 5,它就再扩两个。
这个过程可以理解为:
flowchart LR
A[你写配置
期望状态] --> B[Kubernetes 接收配置]
B --> C[检查当前状态]
C --> D{是否一致}
D -->|一致| E[保持运行]
D -->|不一致| F[创建 / 删除 / 更新资源]
F --> C
这就是 K8s 的核心直觉:你描述目标状态,它负责尽量把现实状态调整过去。
三、Node:K8s 里的机器
Node 是 Kubernetes 里的节点,可以是一台物理机,也可以是一台虚拟机。
如果你之前用 Docker,大概率是在自己电脑或者一台服务器上跑容器。而 Kubernetes 通常管理的是多台机器。每台机器就是一个 Node。
这些 Node 合在一起,就是一个 Kubernetes 集群。
可以先这样理解:
- Node:一台能跑容器的机器。
- Cluster:很多 Node 组成的集群。
- Kubernetes:负责管理整个集群。
在云厂环境里,Node 很可能就是云服务器 ECS、CVM、EC2 这类虚拟机。你不一定直接登录每台机器,但你的应用最终还是会被调度到某些 Node 上运行。
四、Pod:K8s 不是直接管理容器
学 Kubernetes 第一个容易卡住的概念就是 Pod。
我们直觉上会以为:Docker 里跑的是容器,那 K8s 应该也是直接管理容器。
但实际上,Kubernetes 最小的调度单位不是容器,而是 Pod。
Pod 可以理解为“容器外面的一层壳”,它给容器提供一个运行环境。一个 Pod 里可以有一个容器,也可以有多个容器。它们可以共享网络、存储和一些运行时配置。
大部分情况下,一个 Pod 里只跑一个主业务容器。比如:
- 一个后端服务 Pod,里面跑一个 Java 容器。
- 一个 Nginx Pod,里面跑一个 Nginx 容器。
- 一个 Redis Pod,里面跑一个 Redis 容器。
那什么时候一个 Pod 里会有多个容器?
通常是这些容器关系非常紧密,必须一起工作。比如主业务容器旁边加一个日志采集容器,或者加一个代理容器。这种模式常叫 sidecar。
先不要被这些高级用法绕进去。入门时记住一句话就够了:
Pod 是 Kubernetes 管理应用实例的最小单位,容器通常运行在 Pod 里面。
五、Pod IP:为什么直接访问 Pod 不靠谱
每个 Pod 创建后,Kubernetes 会给它分配一个集群内部 IP。Pod 之间可以通过这个 IP 通信。
比如后端应用要访问数据库,理论上可以直接访问数据库 Pod 的 IP。
但这会有一个问题:Pod 不是稳定的。
Pod 很容易被创建、销毁和重建:
- 容器崩了,Pod 可能被重建。
- Node 挂了,Pod 可能被调度到别的 Node。
- 应用升级了,旧 Pod 会被新 Pod 替换。
- 手动扩缩容时,Pod 数量会变化。
Pod 一重建,IP 可能就变了。
如果应用程序写死数据库 Pod 的 IP,那数据库 Pod 一换,应用就找不到数据库了。
所以不能让应用直接依赖 Pod IP。
这就引出了 Service。
六、Service:给一组 Pod 一个稳定入口
Service 是 Kubernetes 里非常重要的对象。
它解决的问题是:Pod IP 不稳定,但服务访问需要一个稳定入口。
比如数据库可能有一个 Pod,也可能有多个 Pod。无论背后的 Pod 怎么变,应用都希望用一个固定地址访问数据库。
Service 就像一个中间层:
- 前面给调用方一个稳定地址。
- 后面自动转发到健康的 Pod。
可以把它类比成反向代理或者负载均衡器。
flowchart LR
A[应用 Pod] --> B[数据库 Service
稳定入口]
B --> C[数据库 Pod 1]
B --> D[数据库 Pod 2]
B --> E[数据库 Pod 3]
即使数据库 Pod 1 挂了,被新的 Pod 替换了,Service 的地址也不变。应用继续访问 Service,Service 再把请求转发到可用的 Pod。
这里顺手补一下正向代理和反向代理。
正向代理代理的是客户端。比如科学上网时,客户端先把请求发给代理服务器,代理服务器再帮你去访问目标网站。目标网站看到的是代理服务器,不一定知道真实客户端是谁。
反向代理代理的是服务端。比如 Nginx 后面有多台服务器,用户只访问 Nginx,Nginx 再把请求转发给某一台后端服务器。用户不知道后面真实服务器是谁。
Service 更像反向代理:调用方不需要知道后面具体有哪些 Pod,只需要访问 Service。
七、内部服务和外部服务
不是所有服务都应该暴露给外部用户。
比如:
- 数据库
- Redis 缓存
- 消息队列
- 内部管理服务
这些通常只需要在集群内部访问,不应该直接暴露到公网。
而下面这些服务可能需要对外暴露:
- 前端页面
- 后端 API
- 网关服务
- 对外开放的平台接口
所以可以先分成两类:
- 内部服务:只在集群内部访问。
- 外部服务:需要让用户或外部系统访问。
Service 有几种常见类型:
- ClusterIP:默认类型,只能在集群内部访问。
- NodePort:在 Node 上开放一个端口,通过
NodeIP:端口访问。 - LoadBalancer:通常对接云厂的负载均衡器,给服务分配外部入口。
- ExternalName:把服务映射到一个外部域名。
刚入门时,重点理解 ClusterIP 和 NodePort 就够了。
ClusterIP 就像“内网地址”,只在集群里用。NodePort 就像在机器上开了一个端口,比如你以前访问 localhost:8080,本质上也是通过 IP 和端口访问服务。
但生产环境一般不会让用户记 IP 和端口,而是使用域名。
这就轮到 Ingress 了。
八、Ingress:用域名和路径访问服务
Service 能解决服务入口问题,但如果要对外提供正式访问,通常还需要域名、路径转发、HTTPS 证书等能力。
Ingress 就是用来管理外部访问规则的。
比如:
www.example.com访问前端服务。api.example.com/user访问用户服务。api.example.com/order访问订单服务。
Ingress 可以根据域名和路径,把请求转发到不同的 Service。
flowchart TD
U[用户浏览器] --> I[Ingress
统一入口]
I -->|/user| S1[user-service]
I -->|/order| S2[order-service]
S1 --> P1[用户服务 Pod]
S2 --> P2[订单服务 Pod]
需要注意的是,Ingress 本身更像一份规则,真正执行转发的通常是 Ingress Controller,比如 Nginx Ingress Controller,或者云厂自己的网关组件。
入门时可以这样记:
- Pod:真正跑应用的地方。
- Service:给 Pod 一个稳定入口。
- Ingress:把外部域名和路径转到 Service。
九、ConfigMap:配置不要写死在镜像里
以前我们写应用时,数据库地址、Redis 地址、端口号、开关配置,可能会写在配置文件或环境变量里。
如果这些配置直接打进镜像,就会很麻烦。
比如数据库地址变了,难道还要重新改代码、重新构建镜像、重新部署吗?这对线上服务很不友好。
Kubernetes 提供了 ConfigMap,用来管理普通配置。
它的作用是:把配置从镜像里拿出来,交给运行环境管理。
比如同一个后端镜像,可以在开发环境连接开发数据库,在测试环境连接测试数据库,在生产环境连接生产数据库。镜像不变,只是注入的 ConfigMap 不同。
可以这样理解:
- 镜像负责“程序是什么”。
- ConfigMap 负责“程序运行时用什么配置”。
这样应用和配置就解耦了。
十、Secret:敏感信息不要放 ConfigMap
ConfigMap 适合放普通配置,但不适合放密码、Token、证书这类敏感信息。
所以 Kubernetes 提供了 Secret。
Secret 用来保存敏感配置,比如:
- 数据库用户名和密码
- API Token
- TLS 证书
- 私钥片段
不过这里有个坑:Kubernetes Secret 默认只是 Base64 编码,不等于加密。
Base64 很容易解码,网上随便找个工具就能还原。所以 Secret 不是“绝对安全保险箱”,还需要配合权限控制、访问审计、密钥管理系统等手段。
入门时先记住:
- 普通配置放 ConfigMap。
- 敏感配置放 Secret。
- Secret 默认 Base64 不是加密,不要误以为万事大吉。
真是一层套一层。
十一、Volume:Pod 重启后数据怎么办
Pod 是不稳定的。它可能被删除、重建、迁移。
如果 Pod 里跑的是无状态应用,比如普通后端 API,那问题不大。这个 Pod 挂了,重新拉一个就行。
但如果 Pod 里跑的是数据库,事情就复杂了。
数据库最重要的是数据。如果 Pod 一重启,数据就没了,那肯定不行。
Kubernetes 提供 Volume 来解决这个问题。
Volume 可以把一块存储挂载到 Pod 里。这样数据不完全跟着容器生命周期走,而是放在外部存储或节点存储上。
在云环境里,这个存储可能是:
- 云硬盘
- NAS
- 对象存储
- 分布式存储
- 本地磁盘目录
入门时可以先把 Volume 理解成:给 Pod 挂一块“不会因为容器重启就马上消失”的存储。
后面还会遇到 PV、PVC、StorageClass,它们是更完整的持久化存储管理方式。初学不用急着一次吃完。
十二、Deployment:管理应用副本和更新
如果一个服务只有一个 Pod,那么这个 Pod 挂了,服务就不可用了。
为了高可用,我们通常会让同一个服务跑多个副本。
比如后端 API 跑 3 个 Pod:
flowchart LR
S[api-service] --> P1[api Pod 1]
S --> P2[api Pod 2]
S --> P3[api Pod 3]
但问题是:谁来保证一直有 3 个 Pod?谁来处理 Pod 挂了以后补一个?谁来做版本升级?
Deployment 就是用来管理这些事情的。
它主要负责:
- 定义应用有多少个副本。
- 某个 Pod 挂了以后自动补齐。
- 应用升级时做滚动更新。
- 新版本有问题时支持回滚。
比如你声明一个 Deployment:副本数是 3。Kubernetes 就会努力保证集群里一直有 3 个对应的 Pod。
如果其中一个 Pod 挂了,它会再创建一个新的 Pod。
这就叫副本控制。
滚动更新是什么
滚动更新可以理解为:不要一下子把旧版本全部停掉,而是一批一批替换。
比如原来有 3 个旧版本 Pod,现在要升级到新版本。Kubernetes 可以先启动 1 个新版本 Pod,确认它能正常接流量,再逐步替换剩下的旧版本 Pod。
这样用户不容易感知到服务中断。
这就是所谓的平滑升级。
十三、ReplicaSet:Deployment 和 Pod 中间的一层
当你创建 Deployment 后,Kubernetes 通常不会直接由 Deployment 管 Pod,而是中间还有一层 ReplicaSet。
关系大概是:
flowchart TD
D[Deployment
定义版本和副本策略] --> R[ReplicaSet
维护副本数量]
R --> P1[Pod 1]
R --> P2[Pod 2]
R --> P3[Pod 3]
ReplicaSet 的作用是维护某一批 Pod 的副本数量。
平时我们一般不直接操作 ReplicaSet,而是操作 Deployment。你可以把 ReplicaSet 理解成 Deployment 背后自动创建和管理的“副本控制器”。
在命令里看到类似 nginx-deployment-6d6565499c-xrkv9 这种 Pod 名字时,中间那段通常就和 ReplicaSet 有关。
十四、StatefulSet:有状态应用不能简单复制
Deployment 很适合管理无状态应用,比如普通 API 服务、前端服务、计算服务。
什么叫无状态?
简单说:这个 Pod 挂了,换一个新的也没关系。因为关键数据不在它本地,或者它可以从数据库、缓存、对象存储里重新拿到。
但数据库、消息队列、部分缓存、搜索引擎这类服务就不一样。它们有自己的数据、身份、顺序和存储需求。
这种就叫有状态应用。
有状态应用不能简单地“复制 3 个一模一样的 Pod”就完事。因为每个副本可能有不同数据,或者需要固定身份,比如:
mysql-0mysql-1mysql-2
它们之间可能有主从关系、同步关系、选主关系。
StatefulSet 就是 Kubernetes 用来管理有状态应用的对象。
它和 Deployment 有点像,也能管理副本数量,但它额外强调:
- 每个 Pod 有稳定名字。
- 每个 Pod 有稳定网络标识。
- 每个 Pod 可以绑定自己的持久化存储。
- 创建、删除、更新通常有固定顺序。
不过要注意:不是所有数据库都适合直接放进 Kubernetes 里。
有些有状态服务部署和维护很复杂,生产环境里也常常会使用云数据库、独立数据库集群,或者专门的 Operator 来管理,而不是自己手写一个 StatefulSet 就完事。
所以入门理解到这里就够:
- 无状态应用通常用 Deployment。
- 有状态应用可以用 StatefulSet。
- 数据库这类服务要格外小心,不要以为多起几个 Pod 就高可用了。
十五、Kubernetes 架构:Master-Worker
Kubernetes 是典型的 Master-Worker 架构。
- Master Node:负责管理整个集群。
- Worker Node:负责真正运行应用。
现在很多文档会把 Master Node 称为 Control Plane,也就是控制平面。为了入门好理解,先叫 Master 也没问题。
整体结构可以这样看:
flowchart TD
U[用户 / kubectl] --> A[kube-apiserver]
subgraph Master[Master Node / Control Plane]
A --> S[Scheduler]
A --> C[Controller Manager]
A --> E[etcd]
A --> CCM[Cloud Controller Manager]
end
subgraph W1[Worker Node 1]
K1[kubelet]
P1[kube-proxy]
R1[container runtime]
Pod1[Pod]
end
subgraph W2[Worker Node 2]
K2[kubelet]
P2[kube-proxy]
R2[container runtime]
Pod2[Pod]
end
A --> K1
A --> K2
R1 --> Pod1
R2 --> Pod2
下面拆开看。
十六、Worker Node 上有什么
Worker Node 是真正跑业务应用的机器。
每个 Worker Node 上通常有三个重要组件:
- container runtime
- kubelet
- kube-proxy
container runtime
container runtime 是容器运行时。
它负责拉取镜像、创建容器、启动容器、停止容器。
以前大家经常听 Docker,现在 Kubernetes 里也可能使用 containerd、CRI-O 等运行时。对入门来说,可以先理解为:container runtime 就是负责真正把容器跑起来的东西。
kubelet
kubelet 是每个 Node 上非常关键的组件。
它负责管理当前节点上的 Pod。
Master 告诉这个 Node:“你这里应该跑某个 Pod。”然后 kubelet 就会调用容器运行时,把对应容器拉起来,并持续汇报状态。
可以理解为:kubelet 是 Node 上的管家。
它会关心:
- Pod 有没有启动成功。
- 容器是否还活着。
- 当前节点资源状态如何。
- 要不要向 apiserver 汇报最新状态。
kube-proxy
kube-proxy 负责网络代理和负载均衡相关工作。
前面说 Service 会把请求转发到后端 Pod。那这件事在每个节点上就离不开 kube-proxy 这类组件的参与。
你可以先简单理解为:kube-proxy 帮 Service 把流量导到正确的 Pod。
十七、Master Node 上有什么
Master Node 负责管理整个集群。
它上面有几个核心组件。
kube-apiserver
kube-apiserver 是 Kubernetes 的入口。
无论你用 kubectl 创建 Deployment,还是其他组件要读取集群状态,基本都要经过 apiserver。
它负责:
- 提供 Kubernetes API。
- 接收用户请求。
- 做认证、授权和准入控制。
- 把资源状态写入 etcd。
- 让其他组件通过它协作。
可以把 apiserver 理解成 Kubernetes 集群的大门和中转站。
Scheduler
Scheduler 是调度器。
当你创建一个新的 Pod 时,它一开始还不知道该跑在哪个 Node 上。Scheduler 会根据节点资源、调度规则、亲和性、污点容忍等条件,决定把 Pod 放到哪台机器上。
入门理解可以简单一点:Scheduler 负责给 Pod 挑机器。
Controller Manager
Controller Manager 是控制器管理器。
它负责各种控制循环。
比如你声明一个 Deployment 要 3 个副本,但现在只有 2 个,控制器就会发现“不一致”,然后创建新的 Pod 让它恢复到 3 个。
Node 挂了、Pod 少了、资源状态不对,这些都需要控制器不断检查和修正。
所以可以理解为:Controller Manager 负责让现实状态接近期望状态。
etcd
etcd 是一个高可用键值存储系统。
Kubernetes 会把集群状态存在 etcd 里,比如有哪些 Node、有哪些 Pod、有哪些 Service、当前配置是什么。
注意:etcd 存的是 Kubernetes 集群状态,不是你的业务数据。
你的 MySQL 数据、用户订单、文件内容,不应该存在 etcd 里。
Cloud Controller Manager
Cloud Controller Manager 是 Kubernetes 和云厂基础设施之间的连接层。
比如在云上创建 LoadBalancer、挂载云盘、识别云服务器节点,这些都需要和云平台 API 交互。
不同云厂有不同实现,但 Kubernetes 尽量提供统一抽象。
对云厂实习来说,这个组件挺有意义,因为它说明:Kubernetes 并不是孤立运行的,它会和云服务器、负载均衡、云硬盘、网络等云产品发生关系。
十八、kubectl:和 Kubernetes 对话的命令行
kubectl 是 Kubernetes 的命令行工具。
你可以通过 kubectl 和 apiserver 交互,比如:
kubectl get nodes
kubectl get pods
kubectl get services
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl exec -it <pod-name> -- /bin/bash
如果你刚开始学,不用一口气背所有命令。先掌握几个最常用的:
kubectl get:查看资源列表。kubectl describe:查看资源详细信息和事件。kubectl logs:查看 Pod 日志。kubectl exec:进入 Pod 内部执行命令。kubectl apply -f:根据 YAML 文件创建或更新资源。kubectl delete -f:根据 YAML 文件删除资源。
这些命令就是你排查问题的入口。
十九、YAML:把命令变成配置文件
刚开始可以用命令创建资源,比如:
kubectl create deployment nginx-deployment --image=nginx
但命令不方便长期维护。更推荐把资源写成 YAML 文件。
比如一个简单 Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
这里先看几个关键字段:
apiVersion:使用哪个 API 版本。kind:资源类型,比如 Deployment、Service。metadata.name:资源名称。spec.replicas:副本数量。selector.matchLabels:Deployment 用什么标签选择 Pod。template:Pod 模板,描述要创建什么样的 Pod。containers.image:容器镜像。
应用配置:
kubectl apply -f nginx-deployment.yaml
查看 Pod:
kubectl get pods -o wide
这里的 -o wide 可以看到更多信息,比如 Pod IP、所在 Node。
如果把 replicas: 3 改成 replicas: 2,再执行 apply,Kubernetes 就会把副本数调整成 2。
这就是声明式配置的好处:配置文件就是你希望集群变成的样子。
二十、用 Service 把 nginx 暴露出去
前面的 Deployment 创建了 3 个 nginx Pod,但它们的 IP 是集群内部 IP,外部访问不了,而且 Pod IP 也不稳定。
这时可以创建 Service。
一个简单 Service:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
这个 Service 会选择带有 app: nginx 标签的 Pod,把请求转发到它们的 80 端口。
但这个 Service 默认是 ClusterIP 类型,只能集群内部访问。
如果想通过 Node 的 IP 和端口访问,可以改成 NodePort:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30080
应用之后:
kubectl apply -f nginx-service.yaml
kubectl get services
kubectl get nodes -o wide
然后就可以尝试访问:
http://NodeIP:30080
这里的 30080 就是暴露在 Node 上的端口。NodePort 默认端口范围通常是 30000-32767。
这个例子把前面的概念串起来了:
flowchart LR
U[浏览器访问
NodeIP:30080] --> S[NodePort Service]
S --> P1[nginx Pod 1]
S --> P2[nginx Pod 2]
S --> P3[nginx Pod 3]
D[Deployment] --> P1
D --> P2
D --> P3
这时候你就能看到 K8s 的基本链路:
Deployment 创建和管理 Pod,Service 选择这些 Pod 并提供访问入口。
二十一、Namespace:给资源分空间
Namespace 是命名空间,用来把 Kubernetes 资源分组。
可以理解为在一个集群里划分多个空间,不同项目、团队或环境可以放在不同 Namespace 里。
比如:
dev:开发环境test:测试环境prod:生产环境monitoring:监控组件portainer:可视化管理工具
命令里经常会看到 -n 参数:
kubectl get pods -n default
kubectl apply -n portainer -f portainer.yaml
这里的 -n 就是指定 Namespace。
Namespace 的意义是隔离和分组,但它不是虚拟机,也不是强安全边界。入门阶段先理解为“资源分目录”就行。
二十二、minikube、K3s 和云厂集群
如果只是本地学习,可以用 minikube 或 K3s。
minikube 是一个轻量级 Kubernetes 发行版,可以在本地启动一个单节点集群,适合入门学习。
常见命令:
minikube start
kubectl get nodes
如果国内拉镜像慢,可以指定镜像源或版本:
minikube start --image-mirror-country='cn' --kubernetes-version=v1.23.9
K3s 是一个轻量级 Kubernetes,适合资源有限的环境,也常用于边缘计算、开发测试、小集群。
如果你用 Multipass 创建几台 Ubuntu 虚拟机,可以用 K3s 搭一个简单 Master-Worker 集群。
但如果是在云厂实习,你接触的更多可能是托管 Kubernetes:
- 腾讯云 TKE
- 阿里云 ACK
- AWS EKS
- Google GKE
- Azure AKS
它们本质上也是 Kubernetes,只是云厂帮你托管了很多集群管理工作,比如控制面、节点池、负载均衡、云盘、网络插件、监控日志集成等。
所以本地学习 minikube / K3s 是为了理解原理;到云厂看托管 K8s,是看这些原理如何产品化。
二十三、把所有概念串成一张图
到这里,核心概念可以串起来了:
flowchart TD
A[Docker 镜像] --> B[Pod
运行容器]
C[Deployment
管理副本和更新] --> B
D[Service
稳定访问入口] --> B
E[Ingress
域名 / 路径转发] --> D
F[ConfigMap
普通配置] --> B
G[Secret
敏感配置] --> B
H[Volume
持久化存储] --> B
I[Node
运行 Pod 的机器] --> B
如果再放进集群架构里,就是:
flowchart LR
U[用户 / kubectl] --> M[Master Node
管理集群]
M --> W1[Worker Node 1]
M --> W2[Worker Node 2]
W1 --> P1[Pod]
W2 --> P2[Pod]
S[Service] --> P1
S --> P2
I[Ingress] --> S
这两张图基本覆盖了入门阶段最重要的关系。
二十四、用 Docker 使用经验类比 K8s
如果你只用过 Docker,可以这样类比:
- Docker 里你关心
docker run,K8s 里你更多关心kubectl apply -f yaml。 - Docker 里你直接跑容器,K8s 里容器通常跑在 Pod 里。
- Docker 里容器挂了可能手动重启,K8s 里 Deployment 会帮你补副本。
- Docker 里端口映射用
-p 8080:80,K8s 里常用 Service / NodePort / Ingress 暴露服务。 - Docker 里配置可能用环境变量,K8s 里可以用 ConfigMap / Secret 管理配置。
- Docker 里数据卷用 volume,K8s 里也有 Volume / PVC 这套机制。
- Docker Compose 管一组容器,K8s 管一组机器上的一组应用。
这个类比不完全严谨,但足够帮入门者建立第一层直觉。
二十五、实习时先掌握哪些就够用
如果刚开始补 K8s,不建议一上来就钻 CNI、CSI、CRI、etcd 高可用、iptables、IPVS、Operator、Service Mesh。
先把下面这些搞清楚:
- Node 是机器。
- Pod 是最小调度单位,容器跑在 Pod 里。
- Pod IP 不稳定,所以需要 Service。
- Service 给一组 Pod 提供稳定入口。
- Ingress 负责外部域名和路径转发。
- ConfigMap 放普通配置,Secret 放敏感配置。
- Volume 解决 Pod 重启后的数据问题。
- Deployment 管理副本、滚动更新和回滚。
- StatefulSet 用来管理有状态应用。
- Master 管集群,Worker 跑应用。
- kubectl 是和集群交互的命令行。
- YAML 是声明资源期望状态的配置文件。
掌握这些之后,再看云厂里的容器服务、节点池、负载均衡、日志服务、监控告警,就不会完全懵了。
结语:K8s 先别学成玄学
Kubernetes 的生态很大,大到很容易让初学者误以为它是一门玄学。
但刚入门时,不要急着背所有名词。先从 Docker 的问题出发:一个容器好管理,很多容器、多台机器、多个服务、多个环境就不好管理了。
Kubernetes 解决的就是这些复杂性:
- 它用 Pod 包住容器。
- 用 Deployment 管应用副本。
- 用 Service 解决访问入口不稳定。
- 用 Ingress 管外部流量。
- 用 ConfigMap 和 Secret 管配置。
- 用 Volume 管数据。
- 用 Master-Worker 架构管理整个集群。
所以第一阶段不需要装作很懂。只要能把这条线讲清楚:
Docker 让应用容器化,Kubernetes 负责在一组机器上管理这些容器,让它们能被调度、访问、扩缩、更新和恢复。
这就已经是一个很好的开始了。
OfferPilot:把AI Agent面试准备变成一次真实诊断
CS336 语言模型从零构建知识地图:一张图拆开 Stanford LLM 训练课