1. 概述

Kubernetes 是用于容器化应用的编排工具,通过命令行工具 kubectl 与集群进行交互。

本文将通过实际示例讲解 kubectl createkubectl apply 之间的区别,帮助你在不同场景下做出合适的选择。

2. Kubernetes 环境准备

2.1 集群搭建

搭建 Kubernetes 集群有多种方式。对于学习目的,可以使用 Kubeadm 搭建本地多节点集群,或者使用轻量级发行版如 k3skind 快速启动。

如果你希望跳过搭建步骤,可以使用在线实验平台如 KillercodaPlay with Kubernetes

2.2 安装 kubectl

无论使用哪种方式,都需要安装 kubectl 工具。它通过配置文件与 Kubernetes API 通信,虽然不是 Kubernetes 核心组件,但几乎是日常操作必备工具。


3. 声明式 vs 指令式

在比较 createapply 命令之前,我们先来理解 Kubernetes 中对象管理的两种方式:声明式(Declarative)和指令式(Imperative)。

3.1 对象管理简介

Kubernetes 的核心是管理集群中的各种资源对象,如 Pod、Deployment、Service 等。我们可以通过命令创建、更新、删除这些对象。

3.2 指令式操作(Imperative)

指令式操作强调“怎么做”,即通过具体命令直接执行操作。

例如创建一个 Nginx Deployment:

kubectl create deployment nginx --image nginx

也可以通过 YAML 文件创建:

kubectl create -f nginx.yaml

3.3 声明式操作(Declarative)

声明式操作更关注“最终状态”,你只需定义你期望的状态,Kubernetes 会自动处理差异。

例如:

kubectl apply -f deployment.yaml

4. kubectl create 命令详解

kubectl create 是一个典型的指令式命令,适用于创建资源对象。

示例:创建一个 Nginx Deployment

文件 deployment.yaml 内容如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  minReadySeconds: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

执行创建命令:

kubectl create -f deployment.yaml

输出:

deployment.apps/nginx-deployment created

验证 Pod 是否运行:

kubectl get pods

输出示例:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-86dcfdf4c6-zhkw8   1/1     Running   0          88s

4.1 重复创建会报错

如果尝试再次创建相同资源:

kubectl create -f deployment.yaml

会提示错误:

Error from server (AlreadyExists): error when creating "deployment.yaml": deployments.apps "nginx-deployment" already exists

4.2 创建前修改对象

你可以使用 --dry-run--edit 在创建前修改 YAML:

kubectl create -f deployment.yaml -o yaml --dry-run=client > deployment_1.yaml
kubectl create --edit -f deployment_1.yaml

这会打开默认编辑器,让你修改后再创建。

4.3 每次只能执行一个指令式操作

Kubernetes 推荐每次只执行一个指令式操作。例如扩容 Deployment:

kubectl scale --replicas=5 deployment nginx-deployment

也可以修改 YAML 文件并使用 replace 命令更新:

spec:
  replicas: 2
kubectl replace -f deployment_scale.yaml

删除资源:

kubectl delete -f deployment.yaml

4.4 常用选项

  • --dry-run:模拟创建,不真正提交
  • --edit:创建前编辑配置
  • --selector:指定筛选器
  • --save-config:保存配置信息,便于后续使用 apply

5. kubectl apply 命令详解

kubectl apply 是声明式操作的核心命令,更适合长期管理资源状态。

5.1 替换 create 命令

你可以用 apply 替代 create

kubectl apply -f deployment.yaml

效果一样,但行为不同。

5.2 重复 apply 不会报错

再次执行:

kubectl apply -f deployment.yaml

输出:

deployment.apps/nginx-deployment unchanged

如果修改了 YAML 内容,比如更新镜像版本:

kubectl apply -f deployment.yaml

输出:

deployment.apps/nginx-deployment configured

5.3 与对象类型无关

apply 命令不需要指定资源类型,只需提供 YAML 文件即可。Kubernetes 会自动识别 kind 字段。

5.4 记录历史配置

apply 会在资源的 metadata 中添加注解 kubectl.kubernetes.io/last-applied-configuration,记录最后一次应用的配置内容。

查看 last applied 配置:

kubectl apply view-last-applied -f deployment.yaml -o yaml

输出示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  minReadySeconds: 5
  replicas: 3
  ...

5.5 每次变更生成新版本

Kubernetes 会为每次 apply 操作生成新版本。查看 Deployment 的 YAML:

kubectl get deployments.apps nginx-deployment -o yaml

你会看到:

metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      ...
  generation: 2
  resourceVersion: "156401"

这有助于 Kubernetes 比较当前状态与期望状态,实现自动合并。

5.6 从 create 切换到 apply

如果你之前使用 kubectl create 创建资源,但未使用 --save-config,后续使用 apply 时会收到警告:

Warning: resource deployments/nginx-deployment is missing the kubectl.kubernetes.io/last-applied-configuration annotation ...

Kubernetes 会自动补上该注解。

5.7 常用选项

  • --prune:删除不再需要的资源
  • --grace-period:设置资源优雅终止时间

6. create 与 apply 的关键区别总结

特性 kubectl create kubectl apply
类型 指令式 声明式
是否允许重复执行 ❌ 报错 ✅ 无变化或更新
是否自动记录配置 ❌ 需要 --save-config ✅ 自动记录
是否支持自动合并
是否适合持续管理
是否需要指定资源类型

⚠️ 注意:不要在同一个资源上混用 createapply,否则可能引起配置冲突。


7. 总结

  • kubectl create 是指令式命令,适合一次性创建资源。
  • kubectl apply 是声明式命令,适合长期维护资源状态。
  • apply 能自动记录历史配置,支持自动合并,但有时合并逻辑复杂,可能导致意外行为。
  • 如果你希望资源能被后续 apply 管理,创建时请使用 --save-config
  • 选择使用哪种方式取决于你的团队习惯和项目复杂度,但推荐优先使用 apply

建议:除非是脚本中一次性创建资源,否则都应使用 apply
踩坑提醒:混用 createapply 容易导致配置不一致,甚至服务异常。


原始标题:Difference Between kubectl apply and kubectl create