从 Docker 到 Kubernetes:概念对照与迁移

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 有几个明显问题,需要手动修正:

  1. 镜像名不完整 :image: postgres:16-alpine 没有 registry 前缀,生产环境应补全;
  2. 环境变量直接写死 :密码 validx123 明文暴露在 YAML 里,应拆分到 Secret;
  3. 卷没有转换 :db_data 卷没有生成对应的 PVC,需要手动补充;
  4. 副本数不合理:数据库通常 1 副本即可,但后端/前端应保留多副本;
  5. 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 迁移步骤总结

  1. 用 kompose convert 生成初始 K8s YAML;
  2. 手动调整:拆分 ConfigMap / Secret、补充 PVC、调整副本数;
  3. 本地 minikube / kind 验证;
  4. 逐步灰度:先迁无状态服务(前端、后端),再迁有状态服务(数据库);
  5. 配置 Ingress 统一入口;
  6. 观察日志与监控,确认稳定后切流量。

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 决策建议

问自己三个问题:

  1. 我是否需要多机部署?
  2. 我是否需要自动扩缩容?
  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 管理」升级为「应用打包与发布」,是生产环境的标准做法。

相关推荐
Java的搬运工1 小时前
【无标题】
python·机器学习·docker·fastapi·模型部署·mlops·ai工程化
怪力左手2 小时前
docker+qemu创建镜像
运维·docker·容器
筑梦之路3 小时前
K8S yaml文件部署kafka集群(Kraft模式)——筑梦之路
容器·kafka·kubernetes
极小狐3 小时前
CI 作业里 kubectl 连不上集群?用 Kubernetes Agent 打通部署链路的 7 个步骤
ci/cd·kubernetes·gitlab·devops·k8s部署
站在墙头上4 小时前
ubantu安装docker
docker·容器
guo_wen_qiang4 小时前
云服务器mysql分库分表环境搭建(2库4表)
数据库·mysql·docker
坏脾气的小十七5 小时前
docker基本知识
docker·容器·eureka
小白的码BUG之路5 小时前
Docker -- 基本命令
java·docker·eureka
guo_wen_qiang5 小时前
jenkins流水线参数化配置
运维·docker·容器·jenkins·持续部署