目录

Kubernetes-01 入门:从零开始理解容器编排

Kubernetes 入门:从零开始理解容器编排

系列文章面向有 Go 开发经验、了解 Docker 基础的读者。本篇是第一篇,重点讲清楚"是什么"和"为什么"。


目录

  1. 容器化的前世今生
  2. Kubernetes 是什么
  3. K8s 解决了什么问题
  4. K8s 的核心价值
  5. K8s 与 Docker 的关系
  6. K8s 的发展历史
  7. 本地环境搭建
  8. 第一个 K8s 命令
  9. 小结

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

生产中永远使用声明式,原因:

  1. 可以纳入 Git 版本控制(GitOps)
  2. kubectl apply 是幂等的,多次执行效果相同
  3. 配置即代码,方便审查和协作

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                     # 查看所有资源