【问题标题】:kubectl apply vs kubectl create?kubectl apply vs kubectl create?
【发布时间】:2018-05-02 08:01:38
【问题描述】:

我对文档的理解是:

  • kubectl create
    
    在集群中创建新的 k8s 资源
  • kubectl replace
    
    更新实时集群中的资源
  • kubectl apply
    
    如果我想做创建 + 替换 (Reference)

我的问题是

  1. 为什么要在一个集群中执行相同的任务需要三个操作?
  2. 这些操作有哪些用例?
  3. 它们在底层有何不同?

【问题讨论】:

    标签: kubernetes kubectl


    【解决方案1】:

    这是两种不同的方法:

    命令式管理

    kubectl create 就是我们所说的Imperative Management。在这种方法中,您告诉 Kubernetes API 您要创建、替换或删除什么,而不是您希望 K8s 集群世界的样子。

    声明式管理

    kubectl applyDeclarative Management 方法的一部分,即使您apply对象的其他更改。

    您可以在Kubernetes Object Management 文档中阅读有关命令式和声明式管理的更多信息。

    在外行他们做不同的事情。如果资源存在,kubectl create 会报错,kubectl apply 不会报错。

    【讨论】:

    • 那在生产中使用哪一个?
    • @YogeshJilhawar 都是在生产中工作的有效方式。
    • 所以本质上,这就像修改整个对象与部分补丁?
    • 这个答案没有确认kubectl createkubectl apply这两个操作是否有相同的效果。
    • @Nawaz - 他们做不同的事情。如果资源已经存在,kubectl create 将抛出错误。 kubectl apply 不会。不同之处在于 kubectl create 专门说“创建这个东西”,而 kubectl apply 说“做任何必要的事情(创建、更新等)以使其看起来像这样”。
    【解决方案2】:

    在 CI 脚本中运行时,您将无法使用命令式命令,因为如果资源已经存在,create 会引发错误。

    您可以通过使用--dry-run=true-o yaml 选项应用(声明式模式)命令式命令的输出:

    kubectl create whatever --dry-run=true -o yaml | kubectl apply -f -
    

    如果资源已经存在,上面的命令将不会引发错误(并且会在需要时更新资源)。

    这在您无法使用声明性模式的某些情况下非常有用(例如在创建 docker-registry 机密时)。

    【讨论】:

    • 或者,在创建资源之前删除它,使用 --ignore-not-found 标志。这不会引发 AlreadyExists 错误。例如:kubectl delete deployment nginx --ignore-not-found; kubectl create deployment nginx --image=nginx
    • 我敢打赌很多进入这个问题的人实际上是在寻找类似上面的东西。在这一点上它是如此地道,它应该被合并到kubectl
    • --dry-run 已弃用,可以替换为 --dry-run=client
    • TBH,我来这里看看是哪个 kubectl 命令完成了上述操作(因为它显然是您在 CI 场景中所需要的)。
    【解决方案3】:

    这是了解初学者差异的最佳方式。



    参考:https://www.digitalocean.com/community/tutorials/imperative-vs-declarative-kubernetes-management-a-digitalocean-comic


    编辑

    图片中提到的示例有错误。请参考 cmets 以获得更好的理解。

    你也可以参考下面的例子。

    命令式:

    • 拿一个平底锅。
    • 打开炉子。
    • 在锅中加入水、糖、咖啡粉、牛奶
    • 等到准备好咖啡
    • 用杯子盛咖啡。

    声明式:

    • 告诉服务员您需要一杯咖啡。他会为您端上咖啡。

    从 K8s 的角度来看:

    命令式:您必须自己管理不同的资源,如 pod、服务、副本集等。

    声明式: K8 将处理所有资源,您需要指定您的实际需求。

    【讨论】:

    • 在声明方面,它应该是“沸水”或“水壶中的沸水”。如图所示,它仍然读作命令式管理(将水壶装满水 + 加热水壶中的水)。
    • 同意@golem - 在声明方面它应该是:1. 一个装满 1L 水的水壶,2. 插上电源的水壶,水在 100 摄氏度下沸腾。
    • 我有点惊讶有人付出了所有努力来创作那部漫画,然后内容完全错误?!这两个沸水的例子都是必不可少的。另外,为什么一个用水壶,另一个用锅?一个更好的例子:当务之急: - 拿锅 - 装满 1L 水 - 加热到 100 度。声明式: - 一个装有 1L 水 100 度的锅
    • @Matt 检查更新的答案。如果您发现有问题,请随时编辑答案,或者您可以以更具描述性的方式进行编辑。
    【解决方案4】:

    根据我的理解,只是给出一个更直接的答案:

    apply - 对现有对象进行增量更改
    create - 创建一个全新的对象(以前不存在/已删除)


    取自 Kubernetes 网站链接的 DigitalOcean article

    我们在这里使用 apply 而不是 create,以便将来我们可以逐步将更改应用到 Ingress Controller 对象,而不是完全覆盖它们。

    【讨论】:

    • 是吗?就像我们使用 docker-compose 时一样: + 使用 applydocker-compose up -d + 使用 createdocker-compose up -d --build
    • 我认为重要的是要澄清apply 仍然会在对象不存在时创建它。
    • 谢谢你。我只是想知道实际的区别,对声明式与命令式的讲座不感兴趣。
    • @Gi0rgi0s ikr? blah blah blah 命令式,blah blah blah 声明式。请告诉我这些命令的作用...
    【解决方案5】:
    ┌─────────┬───────────────────────┬────────────────────────┐
    │ command │ object does not exist │ object already exists  │
    ├─────────┼───────────────────────┼────────────────────────┤
    │ create  │ create new object     │          ERROR         │ 
    │         │                       │                        │
    │ apply   │ create new object     │ configure object       │
    │         │ (needs complete spec) │ (accepts partial spec) │
    │         │                       │                        │
    │ replace │         ERROR         │ delete object          │
    │         │                       │ create new object      │
    └─────────┴───────────────────────┴────────────────────────┘
    

    【讨论】:

      【解决方案6】:

      这些是命令式命令

      kubectl run = kubectl create deployment

      优点:

      • 简单、易学、易记。
      • 只需一个步骤即可对集群进行更改。

      缺点:

      • 不要与变更审核流程集成。
      • 不要提供与更改相关的审计跟踪。
      • 请勿提供记录来源,除非是实时记录。
      • 不要提供用于创建新对象的模板。

      这些是命令式对象配置

      kubectl create -f your-object-config.yaml

      kubectl delete -f your-object-config.yaml

      kubectl replace -f your-object-config.yaml

      与命令式命令相比的优势:

      • 可以存储在 Git 等源代码控制系统中。
      • 可以与流程集成,例如在推送和审计跟踪之前审查更改。
      • 为创建新对象提供模板。

      与命令式命令相比的缺点:

      • 需要对对象架构有基本的了解。
      • 需要额外的编写 YAML 文件的步骤。

      与声明性对象配置相比的优势:

      • 更简单、更容易理解。
      • Kubernetes 1.5 版本之后更加成熟。

      与声明性对象配置相比的缺点:

      • 最适用于文件,而不是目录。
      • 对活动对象的更新必须反映在配置文件中,否则它们将在下次替换时丢失。

      这些是声明性对象配置

      kubectl diff -f configs/

      kubectl apply -f configs/

      与命令式对象配置相比的优势:

      • 直接对活动对象所做的更改将被保留,即使它们未合并回配置文件。
      • 更好地支持对目录进行操作并自动检测每个对象的操作类型(创建、修补、删除)。

      与命令式对象配置相比的缺点:

      • 当结果出乎意料时,更难调试和理解。
      • 使用差异的部分更新会创建复杂的合并和修补操作。

      【讨论】:

      • 这个答案可以使用更新。 kubectl run 现在创建 pod。
      【解决方案7】:

      official documentation 下面的解释帮助我理解了kubectl apply

      此命令会将您推送的配置版本与之前的版本进行比较,并应用您所做的更改,而不会覆盖对您未指定的属性的任何自动更改。

      另一方面,kubectl create 将创建(应该是不存在的)资源。

      【讨论】:

        【解决方案8】:

        kubectl create 一次可以使用一个对象配置文件。这也称为命令式管理

        kubectl create -f 文件名|url

        kubectl apply 适用于目录及其包含对象配置 yaml 文件的子目录。这也称为声明式管理。可以从目录中提取多个对象配置文件。 kubectl apply -f 目录/

        详情:
        https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/ https://kubernetes.io/docs/tasks/manage-kubernetes-objects/imperative-config/

        【讨论】:

          【解决方案9】:

          我们喜欢 Kubernetes 是因为一旦我们给了他们我们想要的东西,它就会在没有我们任何参与的情况下弄清楚如何实现它。

          “创造”就像玩上帝,把事情掌握在自己手中。当您只想使用 POD 而不关心部署/复制控制器时,这对本地调试很有用。

          “申请”是按规则进行的。 “应用”就像一个主工具,可以帮助您创建和修改,并且不需要您管理 pod。

          【讨论】:

          • 这个答案并不是那么有帮助。这也意味着 create 命令只能用于创建 Pod。该命令可以创建任何资源,例如 ReplicaSet、Deployment、Namespace 等。另外,我认为在命令式创建 Pod 时使用“kubectl run”更为常见。还有一点,Pods 不能用 apply 更新。他们第一个必须被删除。
          猜你喜欢
          • 2018-06-14
          • 2019-03-01
          • 1970-01-01
          • 2018-10-06
          • 1970-01-01
          • 2018-04-24
          • 2021-12-23
          • 1970-01-01
          • 2022-12-27
          相关资源
          最近更新 更多