欢迎光临
我们一直在努力

云原生进阶之路:Docker 与 Kubernetes 深度解析及容器化应用迁移实战

云原生进阶之路:Docker 与 Kubernetes 深度解析及容器化应用迁移实战

在云原生技术体系中,Docker 与 Kubernetes(简称 K8s) 是两个无法绕开的核心工具。Docker 凭借轻量级容器化能力,彻底改变了应用的打包与分发方式;而 Kubernetes 则解决了大规模容器集群的编排、调度与管理难题,成为云原生时代的事实标准。对于已经基于 Docker 完成应用容器化的团队而言,向 Kubernetes 迁移是实现云原生进阶的必经之路。本文将深入剖析 Docker 与 K8s 的关系,并给出容器化应用迁移到 K8s 的完整思路与实战指南。

一、Docker 与 Kubernetes 的关系:从 “单打独斗” 到 “协同作战”

很多初学者会混淆 Docker 与 K8s 的定位,甚至误以为二者是竞争关系。事实上,二者互补性极强,共同构成了云原生应用的基础设施底座。

1.1 核心定位差异:容器引擎 vs 容器编排平台

特性DockerKubernetes
核心角色 容器运行时与打包工具 容器集群编排与管理平台
核心功能 应用打包成镜像、创建 / 运行容器、本地容器管理 多主机容器调度、服务发现、负载均衡、自愈、扩缩容
适用场景 单机容器测试、开发环境、简单应用部署 大规模集群部署、高可用应用、微服务架构
核心组件 Docker Engine、Docker Compose、Docker Swarm kube-apiserver、kube-scheduler、kube-controller-manager、kubelet、etcd

简单来说:Docker 解决了 “应用如何打包和单机运行” 的问题,而 K8s 解决了 “容器如何在多主机集群中大规模管理” 的问题。

1.2 二者的协作模式:K8s 对 Docker 的 “接管” 与 “增强”

在 K8s 早期版本中,Docker 是默认的容器运行时(Container Runtime)。K8s 通过 CRI(容器运行时接口) 与 Docker 交互,具体协作流程如下:

  • 镜像管理:用户通过 Dockerfile 构建镜像并推送到镜像仓库,K8s 通过镜像仓库拉取镜像。
  • 容器调度:K8s 的 kube-scheduler 决定容器在哪个节点运行,kubelet 调用 Docker Engine 在节点上创建容器。
  • 容器生命周期管理:K8s 通过控制器(如 Deployment)监控容器状态,当容器故障时,通过 Docker 重启容器;当需要扩缩容时,通过 Docker 创建 / 销毁容器实例。
  • 注意:从 K8s 1.24 版本开始,Docker 不再作为默认容器运行时(因 Docker 不符合 CRI 标准,需通过 cri-dockerd 适配),取而代之的是 containerd(Docker 生态的核心组件,独立后成为 CNCF 毕业项目)。但这并不影响 Docker 镜像的兼容性 ——K8s 依然支持 Docker 构建的镜像格式。

    1.3 Docker Swarm 与 K8s 的对比:为何选择 K8s?

    Docker 官方提供了轻量级编排工具 Docker Swarm,但在功能完整性和生态丰富度上远逊于 K8s。二者核心差异如下:

    特性Docker SwarmKubernetes
    架构复杂度 极简,一键搭建集群 相对复杂,组件丰富
    扩缩容能力 支持基本的服务扩缩容 支持自动扩缩容(HPA),基于指标弹性伸缩
    自愈能力 支持容器重启,节点故障时需手动干预 节点故障自动迁移容器,支持 Pod 健康检查、自动重建
    服务发现与负载均衡 内置 DNS,简单负载均衡 内置 Service 资源,支持 ClusterIP、NodePort、LoadBalancer 多种类型
    滚动更新与回滚 支持基本滚动更新 支持精细化滚动更新策略(如 maxSurge、maxUnavailable),一键回滚
    生态系统 生态薄弱,第三方工具少 生态庞大,支持监控、日志、CI/CD、服务网格等丰富插件

    对于追求稳定性、可扩展性的企业级应用而言,K8s 是容器编排的首选方案;Docker Swarm 仅适用于小型、简单的容器集群场景。

    二、容器化应用迁移到 K8s 的核心思路:从 “单机思维” 到 “集群思维”

    将基于 Docker/Docker Compose 运行的容器化应用迁移到 K8s,核心是转变运维思维—— 从 “管理单个容器” 转变为 “管理集群中的应用资源”。迁移过程并非简单的 “容器平移”,而是需要结合 K8s 的资源模型,对应用进行重新设计与适配。

    2.1 迁移前的准备工作:评估与规划

    在迁移之前,需要完成三项关键准备,避免盲目迁移导致的风险。

    1. 应用容器化成熟度评估
    • 镜像标准化检查:镜像是否基于轻量化基础镜像(如 Alpine)?是否使用多级构建减小镜像体积?是否包含健康检查脚本?
    • 依赖关系梳理:应用是否有外部依赖(如数据库、缓存、消息队列)?依赖服务是否也需要迁移到 K8s,或通过外部服务暴露?
    • 状态性判断:应用是无状态(如 Web 服务、API 服务)还是有状态(如数据库、Redis 集群)?无状态应用迁移难度低,有状态应用需要考虑数据持久化与高可用。
    2. K8s 集群环境准备
    • 集群搭建:根据需求选择自建 K8s 集群(如 kubeadm)或托管 K8s 服务(如 EKS、AKS、GKE)。
    • 网络与存储规划:配置集群网络插件(如 Calico、Flannel),确保 Pod 间通信正常;根据应用需求选择存储类(StorageClass),为有状态应用提供持久化存储(PV/PVC)。
    • 镜像仓库准备:搭建私有镜像仓库(如 Harbor),确保 K8s 集群能拉取应用镜像;配置镜像拉取密钥(ImagePullSecret)。
    3. 迁移工具选型
    • 简单应用:直接手动编写 K8s YAML 配置文件。
    • 复杂应用(如 Docker Compose 部署的多服务应用):使用工具自动转换配置,如 kompose(将 Docker Compose 文件转换为 K8s YAML)。
    • 大规模迁移:使用专业的迁移平台(如 Velero),支持应用的备份、迁移与恢复。

    2.2 核心迁移步骤:适配 K8s 资源模型

    K8s 采用声明式 API 管理应用,所有应用都以 “资源” 的形式存在。迁移的核心是将 Docker/Docker Compose 的配置,映射为 K8s 的核心资源对象。

    步骤 1:将 Docker 容器映射为 K8s Pod

    Pod 是 K8s 最小的部署单元,包含一个或多个紧密关联的容器。Docker 中的单个容器,通常对应 K8s 中的一个单容器 Pod。

    Docker 配置K8s Pod 对应配置示例
    docker run -d –name nginx -p 80:80 nginx:1.25 Pod 的 containers 字段,指定镜像、端口 ```yaml
    apiVersion: v1
    kind: Pod
    metadata:
    name: nginx-pod
    spec:
    containers:
    • name: nginximage: nginx:1.25ports:
      • containerPort: 80

    |

    | `docker run -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0` | Pod 的 `env` 字段,设置环境变量 | ```yaml
    spec:
    containers:
    – name: mysql
    image: mysql:8.0
    env:
    – name: MYSQL_ROOT_PASSWORD
    value: "123456"
    ``` |
    | `docker run -v nginx-data:/usr/share/nginx/html nginx:1.25` | 使用 `volumes` + `volumeMounts`,结合 PVC 实现持久化 | ```yaml
    spec:
    containers:
    – name: nginx
    image: nginx:1.25
    volumeMounts:
    – name: nginx-data
    mountPath: /usr/share/nginx/html
    volumes:
    – name: nginx-data
    persistentVolumeClaim:
    claimName: nginx-pvc
    ``` |

    **关键注意点**:
    – Pod 是**临时性**的,重启后 IP 会变化,**不能直接通过 Pod IP 访问应用**。
    – 必须为 Pod 配置**健康检查**(`livenessProbe`、`readinessProbe`),K8s 通过探针判断应用状态,实现自愈能力。

    #### 步骤 2:使用 Deployment 管理无状态应用
    直接创建 Pod 无法实现应用的扩缩容、滚动更新与自愈。对于**无状态应用**,需要使用 **Deployment** 控制器管理 Pod。

    Deployment 的核心价值是**声明应用的期望状态**,K8s 会自动将实际状态调整为期望状态。例如:
    ```yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx-deployment
    spec:
    replicas: 3 # 期望 3 个 Pod 副本
    selector:
    matchLabels:
    app: nginx
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    – name: nginx
    image: nginx:1.25
    ports:
    – containerPort: 80
    livenessProbe: # 存活探针:检测应用是否运行
    httpGet:
    path: /
    port: 80
    initialDelaySeconds: 10
    periodSeconds: 5
    readinessProbe: # 就绪探针:检测应用是否可提供服务
    httpGet:
    path: /
    port: 80
    initialDelaySeconds: 5
    periodSeconds: 3

    Docker Compose 与 Deployment 的映射关系:

    • replicas 对应 Compose 的 deploy.replicas。
    • 滚动更新策略(strategy.rollingUpdate)对应 Compose 的 deploy.update_config。
    步骤 3:使用 Service 暴露应用服务

    由于 Pod IP 是临时的,K8s 通过 Service 为 Pod 提供固定的访问入口,并实现 Pod 间的负载均衡。

    Service 主要有三种类型,对应不同的访问场景:

    Service 类型适用场景对应 Docker 配置
    ClusterIP 集群内部 Pod 间通信 docker-compose 中的服务名访问
    NodePort 从集群外部通过节点 IP + 端口访问 docker run -p 8080:80
    LoadBalancer 云环境中通过负载均衡器访问 云厂商的 LB 服务

    示例:为 Nginx Deployment 创建 NodePort Service

    yaml

    apiVersion: v1
    kind: Service
    metadata:
    name: nginx-service
    spec:
    type: NodePort
    selector:
    app: nginx # 匹配 Deployment 中的 Pod 标签
    ports:
    – port: 80 # Service 端口
    targetPort: 80 # Pod 端口
    nodePort: 30080 # 节点端口(范围 30000-32767)

    步骤 4:有状态应用迁移:使用 StatefulSet

    对于数据库、Redis 等有状态应用,Deployment 无法满足需求(如固定的网络标识、有序的扩缩容、持久化存储与 Pod 绑定)。此时需要使用 StatefulSet 控制器。

    StatefulSet 的核心特性:

    • 为每个 Pod 分配固定的名称(如 mysql-0、mysql-1),而非随机名称。
    • 为每个 Pod 分配固定的 PVC,数据持久化与 Pod 解耦。
    • 支持有序部署(按 Pod 序号从 0 到 N)和有序删除(从 N 到 0)。

    示例:MySQL StatefulSet 关键配置

    yaml

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
    name: mysql-statefulset
    spec:
    serviceName: mysql-service # 必须指定 Headless Service
    replicas: 2
    selector:
    matchLabels:
    app: mysql
    template:
    metadata:
    labels:
    app: mysql
    spec:
    containers:
    – name: mysql
    image: mysql:8.0
    env:
    – name: MYSQL_ROOT_PASSWORD
    value: "123456"
    volumeMounts:
    – name: mysql-data
    mountPath: /var/lib/mysql
    volumeClaimTemplates: # 自动为每个 Pod 创建 PVC
    – metadata:
    name: mysql-data
    spec:
    accessModes: [ "ReadWriteOnce" ]
    storageClassName: "standard"
    resources:
    requests:
    storage: 10Gi

    步骤 5:使用 ConfigMap 和 Secret 管理配置

    在 Docker 中,应用配置通常通过环境变量或挂载配置文件实现;在 K8s 中,推荐使用 ConfigMap 管理非敏感配置,使用 Secret 管理敏感配置(如密码、密钥),实现 “配置与代码分离”。

    • ConfigMap:存储配置文件、命令行参数等非敏感数据。

      yaml

      apiVersion: v1
      kind: ConfigMap
      metadata:
      name: nginx-config
      data:
      nginx.conf: |
      server {
      listen 80;
      server_name localhost;
      root /usr/share/nginx/html;
      }

      在 Pod 中挂载 ConfigMap:

      yaml

      spec:
      containers:
      – name: nginx
      image: nginx:1.25
      volumeMounts:
      – name: nginx-config-volume
      mountPath: /etc/nginx/conf.d
      volumes:
      – name: nginx-config-volume
      configMap:
      name: nginx-config

    • Secret:存储敏感数据,数据会被 Base64 编码(注意:并非加密,生产环境需结合密钥管理工具)。

      yaml

      apiVersion: v1
      kind: Secret
      metadata:
      name: mysql-secret
      type: Opaque
      data:
      root-password: MTIzNDU2 # Base64 编码的 "123456"

      在 Pod 中引用 Secret:

      yaml

      spec:
      containers:
      – name: mysql
      image: mysql:8.0
      env:
      – name: MYSQL_ROOT_PASSWORD
      valueFrom:
      secretKeyRef:
      name: mysql-secret
      key: root-password

    2.3 迁移后的验证与优化

    应用部署到 K8s 后,需要完成一系列验证与优化,确保应用稳定运行。

    1. 功能验证
    • 检查 Pod 状态:kubectl get pods,确保所有 Pod 处于 Running 状态。
    • 检查服务访问:通过 Service 的 NodePort 或 LoadBalancer 访问应用,验证功能是否正常。
    • 检查日志:kubectl logs <pod-name>,查看应用日志,排查报错信息。
    2. 性能优化
    • 资源限制:为 Pod 设置 resources.requests 和 resources.limits,避免资源争抢。

      yaml

      spec:
      containers:
      – name: nginx
      image: nginx:1.25
      resources:
      requests:
      cpu: 100m
      memory: 128Mi
      limits:
      cpu: 500m
      memory: 256Mi

    • 自动扩缩容:配置 HPA(Horizontal Pod Autoscaler),基于 CPU / 内存使用率或自定义指标自动扩缩容 Pod 数量。 kubectl autoscale deployment nginx-deployment –min=2 –max=5 –cpu-percent=80
    3. 运维自动化
    • CI/CD 集成:将 K8s 应用部署融入 CI/CD 流水线,实现代码提交后自动构建镜像、更新 Deployment。
    • 监控与日志:集成 Prometheus + Grafana 监控 Pod 和集群状态;集成 ELK 或 Loki 收集应用日志。
    • 备份与恢复:使用 Velero 备份 K8s 资源和持久化数据,确保数据安全。

    三、迁移实战案例:将 Docker Compose 部署的 LNMP 应用迁移到 K8s

    以之前 Docker Compose 编排的 LNMP 应用为例,演示迁移到 K8s 的具体步骤。

    3.1 原 Docker Compose 配置回顾

    yaml

    version: '3.8'
    services:
    nginx:
    image: nginx:1.25-alpine
    ports:
    – "80:80"
    volumes:
    – ./nginx.conf:/etc/nginx/conf.d/default.conf
    – ./www:/var/www/html
    depends_on:
    – php
    php:
    image: php:8.2-fpm-alpine
    volumes:
    – ./www:/var/www/html
    mysql:
    image: mysql:8.0
    environment:
    – MYSQL_ROOT_PASSWORD=123456
    – MYSQL_DATABASE=lnmp_demo
    volumes:
    – mysql-data:/var/lib/mysql
    volumes:
    mysql-data:

    3.2 迁移步骤

  • 使用 kompose 转换 Compose 文件

    kompose convert -f docker-compose.yml

    转换后会生成 nginx-deployment.yaml、php-deployment.yaml、mysql-deployment.yaml 等文件。

  • 优化转换后的配置

    • 将 MySQL 的 Deployment 改为 StatefulSet,并添加 volumeClaimTemplates 实现数据持久化。
    • 为 Nginx 和 PHP 创建 ConfigMap,管理配置文件和代码目录。
    • 为每个 Deployment 添加健康检查探针。
    • 创建 Service 暴露服务:Nginx 使用 NodePort Service,PHP 和 MySQL 使用 ClusterIP Service。
  • 部署应用到 K8s

    kubectl apply -f .

  • 验证应用

    # 查看 Pod 状态
    kubectl get pods
    # 查看 Service 端口
    kubectl get svc nginx
    # 访问应用
    curl http://<node-ip>:<node-port>

  • 四、云原生进阶:从 K8s 到完整云原生架构

    迁移到 K8s 只是云原生进阶的第一步,真正的云原生架构还需要结合以下技术:

  • 服务网格(Service Mesh):使用 Istio 等工具管理服务间通信,实现流量治理、熔断、链路追踪。
  • 无服务器架构(Serverless):基于 K8s 部署 Knative,实现应用的按需扩缩容(甚至缩容到零)。
  • GitOps:使用 ArgoCD 等工具实现 “配置即代码”,通过 Git 仓库管理 K8s 资源配置。
  • 五、总结

    Docker 与 Kubernetes 的关系,是 **“基础工具” 与 “上层平台”的关系 ——Docker 为 K8s 提供了标准化的容器镜像和运行时,K8s 则将 Docker 的能力扩展到集群规模。将容器化应用迁移到 K8s,核心是转变思维模式 **,从 “单机容器管理” 转向 “集群资源编排”,并结合 K8s 的核心资源模型(Pod、Deployment、StatefulSet、Service、ConfigMap/Secret)完成应用适配。

    赞(0)
    未经允许不得转载:171主机测评 » 云原生进阶之路:Docker 与 Kubernetes 深度解析及容器化应用迁移实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址