Kubernetes-01 入门:从零开始理解容器编排
Kubernetes 入门:从零开始理解容器编排
系列文章面向有 Go 开发经验、了解 Docker 基础的读者。本篇是第一篇,重点讲清楚"是什么"和"为什么"。
目录
1. 容器化的前世今生
1.1 传统部署时代的痛点
想象一下 2010 年以前的软件部署方式:
开发者本地写代码 → 打成 jar/war 包 → 运维在物理机上配置环境 → 手动部署 → 祈祷不出问题
这带来了几个经典问题:
- “在我机器上能跑”:开发环境和生产环境不一致,本地 JDK 1.7、服务器 JDK 1.6,微妙的差异导致各种 bug。
- 资源浪费:一台服务器只跑一个应用,CPU/内存利用率极低,通常不超过 10%。
- 部署慢:手工配置 Nginx、MySQL、JDK 等依赖,一次部署需要几个小时甚至几天。
- 扩容难:流量突增时,需要人工介入买机器、装系统、配置环境,等你搞完,流量高峰早过去了。
1.2 虚拟机时代
VMware 等虚拟机技术缓解了资源浪费问题,一台物理机可以跑多个 VM。但虚拟机本身也很重:
- 每个 VM 需要完整的 OS,几十 GB 磁盘,几分钟启动时间
- Hypervisor 层有性能损耗
- 镜像文件很大,迁移困难
1.3 容器时代的到来
2013 年,Docker 横空出世,带来了一种新的打包和运行方式:
代码 + 依赖 + 配置 → 打成镜像 → 在任何支持 Docker 的机器上运行
Docker 的核心技术:
- namespace:隔离进程、网络、文件系统(Linux 内核特性)
- cgroups:限制 CPU、内存等资源使用
- 联合文件系统(UnionFS):镜像分层,共享层节省空间
容器 vs 虚拟机:
| 对比项 | 虚拟机 | 容器 |
|---|---|---|
| 隔离级别 | 硬件级 | 进程级 |
| 启动时间 | 分钟级 | 秒级甚至毫秒级 |
| 镜像大小 | GB 级 | MB 级 |
| 性能损耗 | 较大 | 接近原生 |
| 密度(同一台机器) | 几十个 | 几百甚至上千个 |
Docker 让"一次构建,到处运行"成为现实。但新的问题随之而来:
当你有几百个容器需要管理,怎么办?
2. Kubernetes 是什么
Kubernetes(发音:koo-ber-neh-tees),简称 K8s(因为 K 和 s 之间有 8 个字母),是一个开源的容器编排(Container Orchestration)平台。
官方定义:
Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.
翻译过来就是:自动化部署、扩缩容和管理容器化应用的系统。
“编排"这个词来自希腊语,原指指挥船员的舵手。K8s 就是你容器世界的"舵手”,告诉容器们:
- 去哪台机器上跑
- 要跑几个副本
- 挂了如何自动恢复
- 流量如何分发
- 怎么滚动升级不中断服务
3. K8s 解决了什么问题
3.1 多容器的调度问题
假设你有 3 台服务器,20 个微服务容器需要部署,每个服务有不同的资源需求。你怎么决定哪个容器跑在哪台机器上?手工排列组合?
K8s 有 Scheduler(调度器),它会自动考虑:
- 每台 Node 的剩余 CPU/内存
- 容器的资源请求(
requests)和限制(limits) - 亲和性/反亲和性规则(某些容器要在同一台机器 / 不能在同一台机器)
- 节点标签和污点
3.2 服务发现与负载均衡
容器的 IP 是动态的,每次重启都会变。你的服务 A 怎么稳定地访问服务 B?
K8s 的 Service 提供稳定的虚拟 IP 和 DNS 名,屏蔽底层 Pod IP 的变化,并自动做负载均衡。
3.3 自动伸缩(Auto Scaling)
流量低谷只需要 2 个实例,高峰需要 20 个。
- HPA(Horizontal Pod Autoscaler):根据 CPU/内存/自定义指标自动扩缩 Pod 数量
- VPA(Vertical Pod Autoscaler):自动调整 Pod 的资源 requests/limits
- CA(Cluster Autoscaler):当节点资源不足时,自动增加节点
3.4 自愈(Self-healing)
Pod 挂了怎么办?K8s 会自动重启它。节点宕机了怎么办?K8s 会把上面的 Pod 调度到其他节点。
Pod 崩溃 → kubelet 检测到 → 自动重启
节点宕机 → Controller Manager 检测到 → 在其他节点重新创建 Pod
容器不健康(健康检查失败)→ 自动重启容器
3.5 滚动升级与回滚
零停机升级:
新版本逐步替换旧版本 Pod
旧: [v1] [v1] [v1] [v1]
中: [v2] [v1] [v1] [v1] ← 新增一个 v2,删掉一个 v1
中: [v2] [v2] [v1] [v1]
后: [v2] [v2] [v2] [v2]
如果新版本有 bug,一条命令回滚:
kubectl rollout undo deployment/my-app
3.6 配置与密钥管理
- ConfigMap:存储非敏感配置,如数据库地址、功能开关
- Secret:存储敏感信息,如密码、Token、TLS 证书
应用和配置解耦,同一个镜像可以在 dev/staging/prod 环境使用不同配置。
4. K8s 的核心价值
用一句话概括:K8s 让你像管理一台超级计算机一样管理一个服务器集群。
你不再需要关心"这个服务跑在哪台机器上",只需要告诉 K8s:
- 我想要运行 什么(哪个镜像)
- 我想要运行 多少(几个副本)
- 我需要 多少资源(CPU/内存)
- 对外暴露 哪个端口
其余的,交给 K8s。
对 Go 开发者的特别价值
Go 天然适合云原生开发:
- K8s 本身就是 Go 写的
- Go 编译出静态二进制,Docker 镜像可以极小(FROM scratch)
- Go 的并发模型适合微服务
- client-go 是操作 K8s API 的官方库
- Operator 模式(扩展 K8s)几乎都用 Go 实现
5. K8s 与 Docker 的关系
很多人刚接触时会困惑:我已经有 Docker 了,为什么还需要 K8s?
Docker 负责单个容器的生命周期,K8s 负责集群中大量容器的编排。
Docker: 我来构建镜像,我来运行单个容器
K8s: 我来决定容器跑在哪,跑几个,怎么对外服务
关系如下:
用户/CI/CD
↓ (构建镜像)
Docker Registry(镜像仓库:Docker Hub / Harbor / ECR)
↓ (拉取镜像)
Kubernetes
├── Node 1: Container Runtime(containerd)→ Container A, B
├── Node 2: Container Runtime(containerd)→ Container C, D
└── Node 3: Container Runtime(containerd)→ Container E, F
容器运行时
有一点需要注意:K8s 1.24 版本之后,移除了对 Docker(dockershim)的直接支持,改用符合 CRI(Container Runtime Interface) 标准的运行时:
- containerd(最主流,Docker 也在用它)
- CRI-O(Red Hat 主导)
- Docker Engine via cri-dockerd(社区维护的适配层)
但这不影响你用 Docker 构建镜像!镜像格式(OCI 标准)是兼容的,K8s 照样能拉取和运行 Docker 构建的镜像。
6. K8s 的发展历史
| 时间 | 事件 |
|---|---|
| 2003 | Google 内部 Borg 系统诞生,管理 Google 内部数以亿计的容器 |
| 2013 | Docker 发布,容器技术走向大众 |
| 2014.06 | Google 开源 Kubernetes(基于 Borg 的经验重新设计) |
| 2015.07 | K8s 1.0 正式发布,Google 将其捐献给 CNCF |
| 2016 | Helm 诞生,K8s 包管理 |
| 2017 | Docker 宣布支持 K8s,K8s 成为容器编排事实标准 |
| 2018 | CNCF 宣布 K8s 毕业,AWS/Azure/GCP 均提供托管 K8s 服务 |
| 2020 | K8s 宣布废弃 Docker 运行时(dockershim) |
| 2022 | K8s 1.24,正式移除 dockershim |
| 2024 | K8s 1.30+,持续演进,AI/GPU 工作负载支持增强 |
7. 本地环境搭建
7.1 安装 kubectl
kubectl 是 K8s 的命令行工具,用于与集群交互。
macOS:
brew install kubectl
# 验证
kubectl version --client
Linux:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
Windows(PowerShell):
winget install -e --id Kubernetes.kubectl
7.2 本地 K8s 集群选择
开发和学习阶段,有几个好用的本地方案:
方案一:minikube(推荐新手)
# macOS
brew install minikube
# 启动(默认使用 Docker 作为 driver)
minikube start
# 启动完成后查看状态
minikube status
方案二:kind(K8s in Docker)
kind 用 Docker 容器模拟 K8s 节点,适合 CI 和需要多节点集群的场景。
# 安装
brew install kind
# 创建单节点集群
kind create cluster --name my-cluster
# 创建多节点集群
cat <<EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
EOF
kind create cluster --config kind-config.yaml
方案三:k3d(轻量级)
brew install k3d
k3d cluster create my-cluster
方案四:Docker Desktop 内置 K8s
如果你已经安装了 Docker Desktop,直接在 Settings → Kubernetes → Enable Kubernetes 即可,最简单。
7.3 验证集群
# 查看集群信息
kubectl cluster-info
# 查看节点
kubectl get nodes
# 输出示例:
# NAME STATUS ROLES AGE VERSION
# minikube Ready control-plane 2m v1.28.3
8. 第一个 K8s 命令
让我们运行一个 Nginx 容器,感受 K8s 的基本操作:
8.1 创建第一个 Pod
# 以命令式方式运行一个 Nginx Pod
kubectl run nginx --image=nginx:alpine
# 查看 Pod 状态
kubectl get pods
# 输出:
# NAME READY STATUS RESTARTS AGE
# nginx 1/1 Running 0 30s
8.2 查看 Pod 详情
kubectl describe pod nginx
输出包含:
- Pod 的 IP 地址
- 所在节点
- 容器状态
- Events(非常重要!排查问题的第一手资料)
8.3 进入容器
kubectl exec -it nginx -- sh
# 进入容器后
ls /usr/share/nginx/html
exit
8.4 端口转发(本地访问)
# 将本地 8080 端口转发到 Pod 的 80 端口
kubectl port-forward pod/nginx 8080:80
# 另开终端测试
curl http://localhost:8080
8.5 查看日志
kubectl logs nginx
# 实时跟踪日志
kubectl logs -f nginx
8.6 删除 Pod
kubectl delete pod nginx
8.7 第一个 YAML 清单(Manifest)
K8s 的生产用法不是命令式的 kubectl run,而是声明式的 YAML 文件。
创建 nginx-pod.yaml:
apiVersion: v1 # API 版本
kind: Pod # 资源类型
metadata:
name: nginx-demo # 资源名称
labels:
app: nginx # 标签,用于选择和过滤
spec:
containers:
- name: nginx # 容器名称
image: nginx:alpine # 镜像
ports:
- containerPort: 80 # 容器暴露的端口(文档性质,不影响实际通信)
resources:
requests: # 调度时保证的资源
cpu: "100m" # 100 毫核(0.1 CPU)
memory: "128Mi"
limits: # 最大可用资源
cpu: "200m"
memory: "256Mi"
应用这个文件:
kubectl apply -f nginx-pod.yaml
# 查看
kubectl get pods
# 删除
kubectl delete -f nginx-pod.yaml
声明式 vs 命令式的区别:
# 命令式(告诉 K8s 怎么做)
kubectl run nginx --image=nginx
# 声明式(告诉 K8s 想要什么状态,K8s 自己去达成)
kubectl apply -f nginx-pod.yaml
生产中永远使用声明式,原因:
- 可以纳入 Git 版本控制(GitOps)
kubectl apply是幂等的,多次执行效果相同- 配置即代码,方便审查和协作
9. 小结
本篇我们学习了:
- 容器化技术的演进背景,为什么需要容器编排
- K8s 是什么:开源容器编排平台
- K8s 解决的核心问题:调度、服务发现、自动伸缩、自愈、滚动升级
- K8s 与 Docker 的关系:一个负责单容器,一个负责集群编排
- 搭建了本地 K8s 环境(minikube/kind/Docker Desktop)
- 运行了第一个 Pod,体验了
kubectl的基础命令 - 了解了 YAML 声明式配置的重要性
常用命令速查
kubectl get pods # 查看所有 Pod
kubectl get pods -n kube-system # 查看系统命名空间的 Pod
kubectl get pods -o wide # 查看更多信息(Node IP 等)
kubectl describe pod <name> # 查看 Pod 详情
kubectl logs <pod-name> # 查看日志
kubectl logs -f <pod-name> # 实时跟踪日志
kubectl exec -it <pod> -- bash # 进入容器
kubectl apply -f <file.yaml> # 应用配置
kubectl delete -f <file.yaml> # 删除资源
kubectl get all # 查看所有资源
xingliuhua