TL;DR
- Docker 打包容器,K8s 编排集群,两者互补非替代;
- 核心对象对照:Pod ≈ 容器组、Deployment ≈ 服务更新;
- 迁移路径 :
kompose转换 → 手动调整 → 本地验证; - 配置升级:环境变量 → ConfigMap / Secret;
- 何时用 K8s:多机、需弹性与自愈时才值得引入。
1. 引言
很多开发者从 Docker 起步,用 docker-compose 在单机上把服务编排得井井有条。但当服务数量增长、需要多机部署、或者要应对流量波动时,Docker 本身的能力就到顶了------这时候 Kubernetes(K8s)就会进入视野。
但一个常见的误区是:K8s 是 Docker 的替代品吗? 答案是否定的。Docker 解决的是「如何打包和运行容器」,而 K8s 解决的是「如何在大规模集群中编排和管理容器」。两者是不同层次的问题。
本文沿用前面章节的 ValidX demo(一个包含前端、后端、数据库的典型 Web 应用),分别用 Docker Compose 和 Kubernetes 部署同一套应用,逐项对照核心概念,并给出从 compose 迁移到 K8s 的实操路径。
2. 前置准备
阅读本文前,建议先掌握以下基础:
- 01 Docker 基础:镜像、容器、Dockerfile 的基本操作;
- 05 Docker Compose:多容器编排、服务依赖、网络与卷;
- 14 容器网络与存储:理解容器间通信与数据持久化的原理。
本地环境建议准备:
- Docker Desktop(已内置 Kubernetes,可直接启用);
- 或安装 minikube / kind 作为本地 K8s 集群;
kubectl命令行工具;kompose(用于转换 compose 文件)。
3. 核心对象对照:从 compose 到 K8s
在开始迁移之前,先建立一张「翻译表」。compose 里的每个概念,几乎都能在 K8s 里找到对应物,但不是一一对应,理解这一点是迁移的关键。
3.1 Pod ≈ 容器组
compose 中最小的部署单元是「服务」(service),一个 service 通常对应一个容器。而在 K8s 中,最小的调度单元是 Pod。
Pod 与容器最大的区别在于:一个 Pod 可以包含多个容器,这些容器共享同一个网络命名空间(即共享 IP 和端口)、共享存储卷。典型场景是「边车模式」(sidecar):主容器跑业务逻辑,边车容器负责日志采集、流量代理等辅助功能。
坑位提醒 :Pod 内多个容器共享网络,意味着它们通过
localhost就能互相访问,但端口不能冲突。这与 compose 中服务通过服务名互相访问的模型不同。
3.2 Deployment ≈ 服务更新
compose 中,服务更新通常需要 docker-compose up -d --build 重建容器。而 K8s 中,你几乎不会直接操作 Pod,而是通过 Deployment 来声明「我想要多少个副本、用什么镜像、如何更新」。
Deployment 负责:
- 维持期望的副本数(ReplicaSet 机制);
- 滚动更新(Rolling Update),逐步替换旧版本 Pod;
- 回滚到历史版本;
- 自愈:Pod 挂了自动重建。
3.3 Service ≈ 网络
compose 会自动创建一个内部网络,服务之间通过服务名互相发现。K8s 中,Pod 的 IP 是临时 的(重建就变),所以需要 Service 来提供稳定的访问入口。
Service 有三种常见类型:
- ClusterIP:集群内部访问,类似 compose 的内部网络;
- NodePort:暴露到宿主机端口,适合本地调试;
- LoadBalancer:对接云厂商负载均衡器,适合生产。
3.4 Ingress ≈ 反向代理
compose 中,如果你需要按域名或路径路由流量,通常要手动加一个 Nginx 容器做反向代理。K8s 中,这个需求由 Ingress 承担。
Ingress 是集群入口的「路由规则」,它把外部请求按 host 或 path 转发到不同的 Service。Ingress Controller(如 Nginx Ingress)才是真正干活的反向代理。
4. 同一套 ValidX demo:compose 与 K8s 逐项对照
为了直观理解差异,我们用同一套 ValidX demo 分别部署。ValidX 包含三个组件:
validx-frontend:前端(Nginx 托管静态资源);validx-backend:后端 API(Node.js);validx-db:PostgreSQL 数据库。
4.1 Docker Compose 部署
先看 compose 文件:
yaml
version: "3.8"
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: validx
POSTGRES_PASSWORD: validx123
POSTGRES_DB: validx
volumes:
- db_data:/var/lib/postgresql/data
ports:
- "5432:5432"
backend:
build: ./backend
environment:
DATABASE_URL: postgres://validx:validx123@db:5432/validx
depends_on:
- db
ports:
- "3000:3000"
frontend:
build: ./frontend
ports:
- "8080:80"
depends_on:
- backend
volumes:
db_data:
启动方式:
bash
docker-compose up -d
这里有几个关键点:
- 服务名
db、backend就是网络内的 DNS 名,backend通过db:5432访问数据库; - 数据卷
db_data保证数据库重启不丢数据; - 端口映射把容器端口暴露到宿主机。
4.2 Kubernetes 部署
同样的应用,在 K8s 中需要多个 YAML 文件(或一个多文档 YAML)。我们逐个写。
Deployment:数据库
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: validx-db
spec:
replicas: 1
selector:
matchLabels:
app: validx-db
template:
metadata:
labels:
app: validx-db
spec:
containers:
- name: postgres
image: postgres:16-alpine
env:
- name: POSTGRES_USER
value: validx
- name: POSTGRES_PASSWORD
value: validx123
- name: POSTGRES_DB
value: validx
volumeMounts:
- name: db-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: db-storage
persistentVolumeClaim:
claimName: validx-db-pvc
Service:数据库
yaml
apiVersion: v1
kind: Service
metadata:
name: validx-db
spec:
selector:
app: validx-db
ports:
- port: 5432
targetPort: 5432
Deployment + Service:后端
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: validx-backend
spec:
replicas: 2
selector:
matchLabels:
app: validx-backend
template:
metadata:
labels:
app: validx-backend
spec:
containers:
- name: backend
image: validx-backend:latest
imagePullPolicy: IfNotPresent
env:
- name: DATABASE_URL
value: postgres://validx:validx123@validx-db:5432/validx
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: validx-backend
spec:
selector:
app: validx-backend
ports:
- port: 3000
targetPort: 3000
Deployment + Service:前端
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: validx-frontend
spec:
replicas: 2
selector:
matchLabels:
app: validx-frontend
template:
metadata:
labels:
app: validx-frontend
spec:
containers:
- name: frontend
image: validx-frontend:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: validx-frontend
spec:
selector:
app: validx-frontend
ports:
- port: 80
targetPort: 80
Ingress:统一入口
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: validx-ingress
spec:
rules:
- host: validx.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: validx-frontend
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: validx-backend
port:
number: 3000
应用方式:
bash
kubectl apply -f validx-k8s.yaml
4.3 逐项对照表
| 维度 | Docker Compose | Kubernetes |
|---|---|---|
| 最小部署单元 | 服务(单容器) | Pod(可多容器) |
| 副本与扩缩容 | 手动 --scale |
Deployment + 副本数声明 |
| 服务发现 | 服务名 + 内部 DNS | Service(ClusterIP) |
| 外部访问 | 端口映射 ports |
NodePort / LoadBalancer / Ingress |
| 配置注入 | environment |
ConfigMap / Secret |
| 数据持久化 | 命名卷 / bind mount | PersistentVolumeClaim |
| 更新策略 | 重建容器 | 滚动更新 + 回滚 |
| 自愈能力 | 无(挂了要手动拉起) | 自动重建、自动重启 |
5. 配置与机密:ConfigMap / Secret vs 环境变量
compose 中,配置通常直接写在 environment 里,或者用 .env 文件。这在单机场景没问题,但在 K8s 中,配置与镜像分离是核心设计理念------镜像应该是不可变的,配置应该由外部注入。
5.1 ConfigMap:非敏感配置
ConfigMap 用于存放非敏感的配置项,比如数据库地址、日志级别、功能开关。
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: validx-config
data:
DATABASE_URL: postgres://validx:validx123@validx-db:5432/validx
LOG_LEVEL: info
在 Deployment 中引用:
yaml
envFrom:
- configMapRef:
name: validx-config
5.2 Secret:敏感信息
密码、密钥、Token 等敏感信息应该放在 Secret 中。Secret 的值需要 Base64 编码:
bash
echo -n "validx123" | base64
# 输出:dmFsaWR4MTIz
yaml
apiVersion: v1
kind: Secret
metadata:
name: validx-secret
type: Opaque
data:
DB_PASSWORD: dmFsaWR4MTIz
在 Deployment 中引用:
yaml
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: validx-secret
key: DB_PASSWORD
注意:Secret 只是 Base64 编码,不是加密。生产环境应配合云厂商的密钥管理服务(如 AWS Secrets Manager、Vault)使用。
5.3 迁移建议
从 compose 迁移时,建议把 .env 中的配置拆成两类:
- 非敏感 → ConfigMap;
- 敏感 → Secret。
这样既保持了配置的集中管理,又避免了敏感信息泄露到镜像或代码仓库。
6. 从 compose 迁移到 K8s 的实操路径
6.1 使用 kompose 自动转换
6.1.1 迁移实战:从 compose 到 K8s 的完整调整
下面用一个完整的例子,演示 kompose convert 之后如何手动调整生成的 YAML。我们以第 4 节的 ValidX demo 为例,先看 kompose 生成的原始文件,再逐项调整。
第一步:kompose 生成的原始文件(调整前)
bash
kompose convert -f docker-compose.yml
# 生成:validx-db-deployment.yaml、validx-backend-deployment.yaml、validx-frontend-deployment.yaml 等
以数据库 Deployment 为例,kompose 生成的原始内容大致如下:
yaml
# validx-db-deployment.yaml(kompose 自动生成,调整前)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yml
kompose.version: 1.34.0 (HEAD)
labels:
io.kompose.service: db
name: db
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: db
template:
metadata:
annotations:
kompose.cmd: kompose convert -f docker-compose.yml
kompose.version: 1.34.0 (HEAD)
labels:
io.kompose.service: db
spec:
containers:
- env:
- name: POSTGRES_DB
value: validx
- name: POSTGRES_PASSWORD
value: validx123
- name: POSTGRES_USER
value: validx
image: postgres:16-alpine
name: db
ports:
- containerPort: 5432
hostPort: 5432
protocol: TCP
resources: {}
restartPolicy: Always
第二步:手动调整(调整后)
kompose 生成的 YAML 有几个明显问题,需要手动修正:
- 镜像名不完整 :
image: postgres:16-alpine没有 registry 前缀,生产环境应补全; - 环境变量直接写死 :密码
validx123明文暴露在 YAML 里,应拆分到 Secret; - 卷没有转换 :
db_data卷没有生成对应的 PVC,需要手动补充; - 副本数不合理:数据库通常 1 副本即可,但后端/前端应保留多副本;
hostPort冗余 :kompose会把ports映射成hostPort,这在 K8s 中通常不需要,应去掉。
调整后的数据库 Deployment:
yaml
# validx-db-deployment.yaml(手动调整后)
apiVersion: apps/v1
kind: Deployment
metadata:
name: validx-db
labels:
app: validx-db
spec:
replicas: 1
selector:
matchLabels:
app: validx-db
template:
metadata:
labels:
app: validx-db
spec:
containers:
- name: postgres
image: registry.example.com/postgres:16-alpine
imagePullPolicy: IfNotPresent
env:
- name: POSTGRES_USER
value: validx
- name: POSTGRES_DB
value: validx
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: validx-secret
key: DB_PASSWORD
ports:
- containerPort: 5432
volumeMounts:
- name: db-storage
mountPath: /var/lib/postgresql/data
volumes:
- name: db-storage
persistentVolumeClaim:
claimName: validx-db-pvc
第三步:补充 PVC(调整前没有,调整后新增)
kompose 不会自动为 compose 的命名卷生成 PVC,需要手动补充:
yaml
# validx-db-pvc.yaml(手动新增)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: validx-db-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
第四步:拆分 ConfigMap / Secret(调整前环境变量写死,调整后外部注入)
把非敏感配置放进 ConfigMap,敏感信息放进 Secret:
yaml
# validx-config.yaml(手动新增)
apiVersion: v1
kind: ConfigMap
metadata:
name: validx-config
data:
DATABASE_URL: postgres://validx:validx123@validx-db:5432/validx
LOG_LEVEL: info
yaml
# validx-secret.yaml(手动新增)
apiVersion: v1
kind: Secret
metadata:
name: validx-secret
type: Opaque
data:
DB_PASSWORD: dmFsaWR4MTIz
第五步:调整副本数(调整前 1 副本,调整后按需扩缩)
kompose 默认给每个服务生成 replicas: 1。对于无状态的前端和后端,建议调大副本数以提升可用性:
yaml
# validx-backend-deployment.yaml(调整副本数)
spec:
replicas: 3 # 从 1 调整为 3
yaml
# validx-frontend-deployment.yaml(调整副本数)
spec:
replicas: 3 # 从 1 调整为 3
调整前后对比总结
| 调整项 | kompose 生成(调整前) | 手动调整后 |
|---|---|---|
| 镜像名 | postgres:16-alpine(无 registry) |
registry.example.com/postgres:16-alpine |
| 密码 | 明文写在 env 里 |
移到 Secret,用 secretKeyRef 引用 |
| 数据卷 | 无 PVC | 补充 validx-db-pvc |
| 副本数 | 全部 replicas: 1 |
后端/前端调为 3,数据库保持 1 |
| 端口 | hostPort: 5432 |
去掉 hostPort,仅保留 containerPort |
| 配置 | 全部写死在 YAML | 非敏感进 ConfigMap,敏感进 Secret |
小结 :
kompose能帮你快速生成骨架,但生产可用的 YAML 必须手动调整。核心原则是:镜像不可变、配置外部注入、敏感信息加密、有状态服务补 PVC、无状态服务按需扩副本。
kompose 可以把 compose 文件转换成 K8s YAML,是迁移的起点:
bash
# 安装 kompose(macOS)
brew install kompose
# 转换
kompose convert -f docker-compose.yml
# 会生成 deployment、service 等 YAML 文件
转换结果通常需要手动调整,但能省去大量重复劳动。转换后重点检查:
- 镜像名是否完整(是否带了 registry 地址);
- 卷是否转换成了 PVC;
- 环境变量是否合理拆分到 ConfigMap / Secret。
6.2 本地验证:minikube / kind
转换完成后,先在本地集群验证:
minikube:
bash
minikube start
kubectl apply -f validx-k8s.yaml
minikube service validx-frontend
kind:
bash
kind create cluster
kubectl apply -f validx-k8s.yaml
kubectl port-forward svc/validx-frontend 8080:80
本地验证通过后,再考虑上生产集群。
6.3 迁移步骤总结
- 用
kompose convert生成初始 K8s YAML; - 手动调整:拆分 ConfigMap / Secret、补充 PVC、调整副本数;
- 本地 minikube / kind 验证;
- 逐步灰度:先迁无状态服务(前端、后端),再迁有状态服务(数据库);
- 配置 Ingress 统一入口;
- 观察日志与监控,确认稳定后切流量。
7. 什么时候需要 K8s
K8s 功能强大,但不是所有场景都需要。盲目引入会带来不必要的复杂度。
7.1 单机 vs 多机
| 场景 | 推荐方案 |
|---|---|
| 单机、服务少、个人项目 | Docker Compose 足够 |
| 单机、服务多、需要自愈 | 可考虑 Docker Swarm 或单节点 K8s |
| 多机、需要扩缩容 | K8s |
| 多机、需要滚动更新与回滚 | K8s |
| 大规模、多团队、复杂调度 | K8s(几乎是唯一选择) |
7.2 自建 vs 托管
- 自建 K8s:用 kubeadm 或二进制方式搭建,适合学习、有运维团队、对成本敏感的场景。但运维负担重:etcd 备份、证书轮换、节点升级都要自己管。
- 托管 K8s:云厂商的托管服务(如 AWS EKS、Google GKE、阿里云 ACK),控制面由云厂商管理,你只管节点和应用。适合大多数生产场景,省心但贵。
7.3 决策建议
问自己三个问题:
- 我是否需要多机部署?
- 我是否需要自动扩缩容?
- 我是否有运维能力支撑 K8s 的复杂度?
如果三个答案都是「否」,继续用 Docker Compose 就好。如果有一个「是」,可以考虑引入 K8s。
8. 常见坑位总结
8.1 K8s 不是 Docker 的替代品
这是最大的认知误区。Docker 是容器运行时,K8s 是容器编排平台。K8s 底层仍然依赖容器运行时(如 containerd、CRI-O)来跑容器。两者是互补关系,不是替代关系。
8.2 Pod 内多容器共享网络
Pod 内多个容器共享同一个 IP 和端口空间,通过 localhost 通信。这意味着:
- 端口不能冲突;
- 不能通过 Pod 名访问 Pod 内的其他容器(要用
localhost); - 共享存储卷时要注意文件锁和并发写。
8.3 latest 标签在 K8s 中的坑
compose 中,image: myapp:latest 配合 --build 能拿到最新镜像。但在 K8s 中:
imagePullPolicy默认对latest是Always,每次都会拉取,可能导致意外更新;- 生产环境强烈建议使用带版本号的不可变标签 (如
v1.2.3或 commit SHA),配合imagePullPolicy: IfNotPresent; - 回滚时,固定标签才能精确定位到某个版本。
yaml
# 推荐:固定版本 + 不强制拉取
image: registry.example.com/validx-backend:v1.2.3
imagePullPolicy: IfNotPresent
8.4 其他常见坑
- PVC 与节点绑定:有状态服务的 PVC 可能绑定到特定节点,迁移节点时要小心;
- Service 选择器写错 :
selector必须与 Pod 的labels完全匹配,否则流量不通; - 资源限制缺失 :不设置
resources.limits,某个 Pod 可能吃光节点资源; - 探针缺失 :不配置
readinessProbe,流量可能打到还没就绪的 Pod。
9. 总结
从 Docker Compose 到 Kubernetes,不是「换一个工具」,而是换一种思维:
- compose 面向「单机上的多容器编排」,K8s 面向「集群上的大规模调度」;
- 核心对象可以对照:Pod ≈ 容器组、Deployment ≈ 服务更新、Service ≈ 网络、Ingress ≈ 反向代理;
- 配置管理从「环境变量」升级为「ConfigMap / Secret」;
- 迁移路径:
kompose转换 → 手动调整 → minikube / kind 本地验证 → 灰度上线。
K8s 很强大,但也很复杂。先想清楚是否需要,再决定是否引入。如果只是单机小项目,Docker Compose 依然是最高效的选择;当你的应用需要多机、需要弹性、需要自愈时,K8s 才会真正发挥价值。
下一步可以继续学习:K8s 的存储抽象(PV / PVC)、Helm 包管理
10. K8s 存储抽象:PV / PVC 详解
前面第 6 节我们手动补充了 validx-db-pvc,但只停留在「能用」的层面。这一节深入讲清楚 PV、PVC、StorageClass 和 StatefulSet 之间的关系,仍然以 ValidX 的 PostgreSQL 为例。
10.1 PV 与 PVC 的关系
- PV(PersistentVolume):集群层面的存储资源,由管理员预先创建,或由 StorageClass 动态供给。它描述「这块存储有多大、什么访问模式、挂在哪个节点」。
- PVC(PersistentVolumeClaim) :应用层面的「存储申请」,由 Pod 的
volumeMounts引用。PVC 声明「我要 5Gi、ReadWriteOnce」,K8s 会把它绑定到一个满足条件的 PV。
一句话理解:PV 是「硬盘」,PVC 是「申请单」。Pod 不直接接触 PV,只通过 PVC 间接使用存储。
以 ValidX 数据库为例,我们之前手动写的 PVC:
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: validx-db-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
它会被绑定到一个 PV。如果集群里没有现成的 PV,就需要 StorageClass 来动态创建。
10.2 StorageClass 动态供给
手动创建 PV 很麻烦,生产环境几乎都用 StorageClass 动态供给 :PVC 声明 storageClassName,K8s 自动调用云厂商的存储插件创建 PV 并绑定。
yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: standard
provisioner: kubernetes.io/aws-ebs # 云厂商的存储插件
parameters:
type: gp3
reclaimPolicy: Delete # 删除 PVC 时是否删除 PV
PVC 指定 storageClassName: standard 即可动态申请:
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: validx-db-pvc
spec:
storageClassName: standard
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
坑位提醒 :
reclaimPolicy决定 PVC 删除后 PV 的去留。Delete会连底层存储一起删,Retain则保留数据但需要手动清理。生产环境对数据库这类有状态服务,务必想清楚策略。
10.3 StatefulSet 与 Deployment 的差异
Deployment 适合无状态服务(前端、后端),Pod 可以随意重建、扩缩容,数据不依赖某个 Pod 的身份。但数据库这类有状态服务 ,每个副本需要稳定的标识和独立的存储 ,这就轮到 StatefulSet。
| 维度 | Deployment | StatefulSet |
|---|---|---|
| Pod 命名 | 随机后缀(如 validx-backend-abc12) |
有序编号(如 validx-db-0、validx-db-1) |
| 存储 | 所有副本共享一个 PVC 或各自独立 | 每个副本绑定独立 PVC (volumeClaimTemplates) |
| 启动/销毁顺序 | 无序、可并行 | 有序(0 先启动,n-1 先销毁) |
| 适用场景 | 无状态服务 | 数据库、消息队列等有状态服务 |
StatefulSet 用 volumeClaimTemplates 为每个副本自动生成独立 PVC:
yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: validx-db
spec:
serviceName: validx-db
replicas: 1
selector:
matchLabels:
app: validx-db
template:
metadata:
labels:
app: validx-db
spec:
containers:
- name: postgres
image: postgres:16-alpine
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: validx-secret
key: DB_PASSWORD
volumeMounts:
- name: db-storage
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: db-storage
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 5Gi
小结 :单副本的 ValidX 数据库用 Deployment + 手动 PVC 也能跑,但一旦要多副本、主从复制、每个副本独立存储 ,就必须升级为 StatefulSet +
volumeClaimTemplates。
11. Helm 包管理入门
第 4 节我们手动写了 6 个 YAML 文件,第 6 节又手动调整了一堆。当服务一多,YAML 文件的管理就成了噩梦。Helm 就是来解决这个问题的。
11.1 Helm 解决什么问题
- 打包 :把一组相关的 K8s 资源(Deployment、Service、ConfigMap、Secret、PVC、Ingress)打包成一个 Chart;
- 参数化 :通过
values.yaml把镜像版本、副本数、域名等可变项抽出来,一处修改、处处生效; - 版本管理 :
helm upgrade/helm rollback支持一键升级和回滚,比手动kubectl apply更可控; - 复用 :同一套 Chart 可以部署到开发、测试、生产多个环境,只需换不同的
values.yaml。
11.2 用 Helm Chart 封装 ValidX demo
一个 Chart 的标准目录结构:
text
validx/
├── Chart.yaml # Chart 元信息(名称、版本)
├── values.yaml # 默认配置(镜像、副本数、域名等)
└── templates/
├── deployment.yaml # 模板:Deployment
├── service.yaml # 模板:Service
├── configmap.yaml # 模板:ConfigMap
├── secret.yaml # 模板:Secret
├── pvc.yaml # 模板:PVC
└── ingress.yaml # 模板:Ingress
Chart.yaml:
yaml
apiVersion: v2
name: validx
description: ValidX demo application
version: 0.1.0
values.yaml(把可变项全部抽出来):
yaml
replicaCount:
backend: 3
frontend: 3
db: 1
image:
repository: registry.example.com
tag: v1.2.3
pullPolicy: IfNotPresent
db:
storage: 5Gi
storageClass: standard
ingress:
host: validx.local
secret:
dbPassword: dmFsaWR4MTIz
templates/deployment.yaml (模板语法,用 {``{ .Values.xxx }} 引用 values):
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-backend
labels:
app: validx-backend
spec:
replicas: {{ .Values.replicaCount.backend }}
selector:
matchLabels:
app: validx-backend
template:
metadata:
labels:
app: validx-backend
spec:
containers:
- name: backend
image: "{{ .Values.image.repository }}/validx-backend:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: DATABASE_URL
valueFrom:
configMapKeyRef:
name: {{ .Release.Name }}-config
key: DATABASE_URL
templates/pvc.yaml(数据库存储,引用 values 中的存储配置):
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Release.Name }}-db-pvc
spec:
storageClassName: {{ .Values.db.storageClass }}
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.db.storage }}
templates/secret.yaml (敏感信息,用 b64enc 模板函数编码):
yaml
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-secret
type: Opaque
data:
DB_PASSWORD: {{ .Values.secret.dbPassword | b64enc }}
11.3 helm install 与 kubectl apply 对比
| 维度 | kubectl apply |
helm install |
|---|---|---|
| 文件管理 | 手动维护多个 YAML,改一处要同步多处 | 一个 Chart 打包所有资源,values.yaml 统一参数 |
| 环境切换 | 每个环境一套 YAML,容易漂移 | 同一 Chart + 不同 values.yaml,一处改全局生效 |
| 升级回滚 | 手动 apply,无版本概念 |
helm upgrade / helm rollback 一键完成 |
| 复用性 | 复制粘贴,难维护 | Chart 可发布到仓库,团队共享 |
| 学习成本 | 低 | 需掌握模板语法({``{ .Values }}、{``{ .Release }}) |
安装与升级:
bash
# 安装
helm install validx ./validx
# 升级(改 values.yaml 后)
helm upgrade validx ./validx
# 回滚到上一个版本
helm rollback validx 1
小结 :
kubectl apply适合小项目、快速验证;一旦服务变多、需要多环境部署和版本管理,Helm 是更优解。它把「YAML 管理」升级为「应用打包与发布」,是生产环境的标准做法。