容器编排:这次怎么落地的

容器编排相关的坑,多半出在边界条件上。

这次做容器化改造,从 Docker Swarm 迁移到 Kubernetes,也学到了不少。

Docker Swarm 的简单之处

Swarm 是 Docker 自带的容器编排工具,上手很快。

部署 Swarm 集群

# 初始化 Swarm 集群
docker swarm init

# 添加工作节点
docker swarm join --token <token> <manager-ip>:2377

# 查看集群状态
docker node ls

定义服务

# docker-compose.yml
version: '3'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    deploy:
      replicas: 3
    networks:
      - myapp-network

  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - myapp-network

networks:
  myapp-network:
    driver: overlay

volumes:
  db-data:

部署应用

docker stack deploy -c docker-compose.yml myapp

就这么简单,应用就跑起来了。

什么时候需要 Kubernetes

Swarm 用着挺好,但有几个问题开始暴露:

功能限制:不支持滚动更新的高级策略、不支持复杂的调度策略

生态问题:Swarm 的生态不如 Kubernetes,很多工具只支持 K8s

团队技能:团队里更多人熟悉 K8s

监控运维:K8s 的监控生态更完善

Kubernetes 基础

Pod:最小部署单元

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: web
    image: nginx:latest
    ports:
    - containerPort: 80

Deployment:管理副本

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web
        image: nginx:latest
        ports:
        - containerPort: 80

Service:稳定的访问入口

apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
  type: ClusterIP

配置管理

ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  database.url: "postgres://db:5432/mydb"
  cache.ttl: "3600"

使用:

env:
- name: DATABASE_URL
  valueFrom:
    configMapKeyRef:
      name: app-config
      key: database.url

Secret

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  password: c3VwcmV0LXNljcmV0

实战中的对比

升级更新

Swarm

docker service update --image myapp:v2 myapp

K8s

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 1

K8s 的滚动更新更可控。

健康检查

K8s

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  template:
    spec:
      containers:
      - name: web
        livenessProbe:
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5

Swarm 的健康检查功能不如 K8s 完善。

踩过的坑

坑一:资源限制没配好

K8s 集群一开始没配置资源限制,结果一个容器吃光了机器资源,其他 Pod 没法调度。

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: app
    resources:
      requests:
        memory: "128Mi"
        cpu: "100m"
      limits:
        memory: "256Mi"
        cpu: "200m"

解决:为所有 Pod 配置资源限制和请求。

坑二:网络模式选错了

一开始用了 HostNetwork,结果端口冲突。

apiVersion: v1
kind: Pod
spec:
  hostNetwork: true  # 不要随便用

解决:使用 ClusterIP 或 NodePort,避免 HostNetwork。

坑三:PersistentVolume 配置问题

存储卷配置出错了,Pod 一直处于 Pending 状态。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-storage
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard

解决:先检查 StorageClass,确保存储类可用。

什么时候不该用 Kubernetes

Kubernetes 不是银弹,有些场景用了反而增加复杂度。

不适合用的场景

  • 容器数量少(<10)
  • 不需要复杂的调度策略
  • 团队没有 K8s 经验
  • 对运维成本敏感

写在最后

容器编排这东西,Swarm 简单,Kubernetes 功能强大但复杂。

对于小团队,Swarm 可能就够用。对于大团队,K8s 的功能确实有价值。

选型之前先评估:项目规模、团队能力、运维复杂度。不是最先进的就好用,而是最合适的。


这次从 Swarm 迁移到 K8s 花了一个月,中间遇到过网络问题、存储问题、调度问题。但迁移完成后,K8s 的功能确实强大,特别是自动扩缩容、滚动更新这些功能,运维效率提升明显。

版权声明: 本文首发于 指尖魔法屋-容器编排:这次怎么落地的https://blog.thinkmoon.cn/post/56-container-orchestration-swarm-kubernetes-practice/) 转载或引用必须申明原指尖魔法屋来源及源地址!