Kubernetes(k8s)解决了 Docker Compose 在生产环境中无法应对的 7 大核心痛点。
✅ 1. 跨主机(多节点)部署
- Compose 痛点 :只能在单台机器上运行,无法利用集群资源。
- k8s 解决 :Pod 可自动调度到任意节点,天然支持多服务器集群。
✅ 2. 真正的负载均衡(内置、自动)
- Compose 痛点 :即使
--scale启动多个容器,没有自动流量分发,需手动加 Nginx。 - k8s 解决 :
Service自动将请求轮询分发到所有健康 Pod,开箱即用。
✅ 3. 自愈能力(Self-healing)
- Compose 痛点 :容器崩溃后,依赖
restart: always重启,但不会重建新容器(如镜像损坏就挂了)。 - k8s 解决 :Pod 挂了 → 自动销毁并创建全新 Pod ,确保副本数始终符合
replicas。
✅ 4. 滚动更新 & 回滚(零停机发布)
- Compose 痛点 :更新镜像需
down + up,服务中断;回滚麻烦。 - k8s 解决 :
kubectl set image deployment/app nginx:v2→ 逐个替换 Pod,零停机kubectl rollout undo→ 一键秒级回滚
✅ 5. 弹性伸缩(自动扩缩容)
- Compose 痛点 :扩缩容需手动执行
--scale,无法根据 CPU/内存自动调整。 - k8s 解决 :
- 手动:
kubectl scale --replicas=5 - 自动:
HorizontalPodAutoscaler(HPA)根据指标自动扩缩
- 手动:
✅ 6. 服务发现与网络稳定性
- Compose 痛点 :服务通过容器名通信,但容器 IP 可变,多实例时 DNS 不做 LB。
- k8s 解决 :
Service提供永久不变的虚拟 IP 和 DNS 名- 流量自动代理到后端动态变化的 Pod,应用完全无感
✅ 7. 有状态应用管理(StatefulSet)
- Compose 痛点 :MySQL、Redis 主从等有状态服务难以管理(数据卷、启动顺序、固定网络标识)。
- k8s 解决 :
StatefulSet提供稳定 Pod 名称、固定存储、有序启停- 配合
Headless Service实现主从发现

docker-compose.yml
javascript
version: '3.8'
services:
# ────────────────────────
# Java 应用服务
# ────────────────────────
app:
image: my-java-app # 你的 Java 镜像(需提前构建或 pull)
container_name: java-app
ports:
- "8080:8080" # 主机:容器端口映射
environment:
# Spring Boot 推荐的环境变量命名(大写 + 下划线)
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: rootpass
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: 6379
depends_on:
mysql:
condition: service_healthy # 等 MySQL 健康后再启动
redis:
condition: service_started # Redis 启动即可(无健康检查)
networks:
- app-network
restart: unless-stopped
# ────────────────────────
# MySQL 8.0 服务
# ────────────────────────
mysql:
image: mysql:8.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: mydb # 自动创建数据库
MYSQL_USER: appuser # 可选:创建普通用户
MYSQL_PASSWORD: apppass
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql # 持久化数据
- ./mysql/conf.d:/etc/mysql/conf.d # 可选:自定义配置(如时区)
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # 初始化脚本(首次启动执行)
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "--password=rootpass"]
interval: 10s
timeout: 5s
retries: 10
networks:
- app-network
restart: unless-stopped
# ────────────────────────
# Redis 7 服务
# ────────────────────────
redis:
image: redis:7-alpine
container_name: redis
ports:
- "6379:6379"
volumes:
- redis_data:/data # 持久化 RDB/AOF
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf # 可选:自定义配置
command: ["redis-server", "/usr/local/etc/redis/redis.conf"] # 使用自定义配置
networks:
- app-network
restart: unless-stopped
# ──────────────────────────
# 数据卷(持久化存储)
# ──────────────────────────
volumes:
mysql_data:
redis_data:
# ──────────────────────────
# 自定义网络(服务间通过服务名 DNS 通信)
# ──────────────────────────
networks:
app-network:
driver: bridge
k8s.yaml
javascript
# ==============================
# 第一部分:Java 应用的 Deployment(负责创建和管理 Pod 副本)
# ==============================
apiVersion: apps/v1 # 使用 apps/v1 API 版本(Deployment 所属的 API 组)
kind: Deployment # 资源类型:Deployment(用于管理无状态应用的副本)
metadata:
name: java-app # Deployment 的名称,在命名空间内必须唯一
spec:
replicas: 1 # 期望运行的 Pod 副本数量(这里只起 1 个)
selector:
matchLabels:
app: java-app # 通过标签选择器,关联由该 Deployment 管理的 Pod
# 必须与 template.metadata.labels 一致!
# 关键:Pod 模板(Template)------ 这是嵌套的核心原因
template: # 定义"如何创建每一个 Pod"的模板
metadata:
labels:
app: java-app # 给每个 Pod 打上标签,必须匹配上面的 selector
# 这样 Service 和 Deployment 才能找到它
spec: # ← 这是 Pod 的 spec!不是 Deployment 的 spec!
# 它描述了容器运行时的具体配置
containers:
- name: app # 容器名称(在一个 Pod 内必须唯一)
image: my-java-app # 镜像名称(需提前推送到镜像仓库或本地存在)
ports:
- containerPort: 8080 # 容器监听的端口(仅声明,不暴露到宿主机)
env: # 环境变量(供应用读取)
- name: SPRING_DATASOURCE_URL
value: "jdbc:mysql://mysql:3306/mydb" # 注意:mysql 是 Service 名称!
- name: SPRING_REDIS_HOST
value: "redis" # redis 是另一个 Service 的名称
---
# ==============================
# 第二部分:Java 应用的 Service(负责网络访问)
# ==============================
apiVersion: v1 # Service 属于 core/v1 API 组,简写为 v1
kind: Service # 资源类型:Service(提供稳定的网络入口)
metadata:
name: java-app # Service 名称(在集群内可通过 DNS 访问:java-app.namespace.svc.cluster.local)
spec:
selector:
app: java-app # 选择带有此标签的 Pod,将流量转发给它们
# 必须与 Deployment 中 Pod 的 labels 一致!
ports:
- protocol: TCP
port: 8080 # Service 监听的端口(其他 Pod 访问 java-app:8080 即可)
targetPort: 8080 # 流量转发到 Pod 的 containerPort(即上面定义的 8080)
type: ClusterIP # 默认类型:仅集群内部可访问
# 其他选项:
# NodePort → 通过宿主机 IP:端口 访问
# LoadBalancer → 云厂商分配公网 IP
如何使用这个 YAML?
javascript
# 1. 保存为 app.yaml
# 2. 应用到集群
kubectl apply -f app.yaml
# 3. 查看状态
kubectl get pods # 看 Pod 是否 Running
kubectl get svc # 看 Service 是否创建成功