范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

整合k8s系列02服务器端应用

  适用版本: Kubernetes v1.22 [stable] 简介
  服务器端应用协助用户、控制器通过声明式配置的方式管理他们的资源。 客户端可以发送完整描述的目标(A fully specified intent), 声明式地创建和/或修改 对象。
  一个完整描述的目标并不是一个完整的对象,仅包括能体现用户意图的字段和值。 该目标(intent)可以用来创建一个新对象, 也可以通过服务器来实现与现有对象的合并。
  系统支持多个应用者(appliers)在同一个对象上开展协作。
  "字段管理(field management)"机制追踪对象字段的变化。 当一个字段值改变时,其所有权从当前管理器(manager)转移到施加变更的管理器。 当尝试将新配置应用到一个对象时,如果字段有不同的值,且由其他管理器管理, 将会引发冲突。 冲突引发警告信号:此操作可能抹掉其他协作者的修改。 冲突可以被刻意忽略,这种情况下,值将会被改写,所有权也会发生转移。
  当你从配置文件中删除一个字段,然后应用这个配置文件, 这将触发服务端应用检查此字段是否还被其他字段管理器拥有。 如果没有,那就从活动对象中删除该字段;如果有,那就重置为默认值。 该规则同样适用于 list 或 map 项目。
  服务器端应用既是原有 kubectl apply 的替代品, 也是控制器发布自身变化的一个简化机制。
  如果你启用了服务器端应用,控制平面就会跟踪被所有新创建对象管理的字段。字段管理
  相对于通过 kubectl 管理的注解 last-applied, 服务器端应用使用了一种更具声明式特点的方法: 它持续的跟踪用户的字段管理,而不仅仅是最后一次的执行状态。 这就意味着,作为服务器端应用的一个副作用, 关于用哪一个字段管理器负责管理对象中的哪个字段的这类信息,都要对外界开放了。
  用户管理字段这件事,在服务器端应用的场景中,意味着用户依赖并期望字段的值不要改变。 最后一次对字段值做出断言的用户将被记录到当前字段管理器。 这可以通过发送 POST、 PUT、 或非应用(non-apply)方式的 PATCH 等命令来修改字段值的方式实现, 或通过把字段放在配置文件中,然后发送到服务器端应用的服务端点的方式实现。 当使用服务器端应用,尝试着去改变一个被其他人管理的字段, 会导致请求被拒绝(在没有设置强制执行时,参见冲突)。
  如果两个或以上的应用者均把同一个字段设置为相同值,他们将共享此字段的所有权。 后续任何改变共享字段值的尝试,不管由那个应用者发起,都会导致冲突。 共享字段的所有者可以放弃字段的所有权,这只需从配置文件中删除该字段即可。
  字段管理的信息存储在 managedFields 字段中,该字段是对象的 metadata 中的一部分。
  服务器端应用创建对象的简单示例如下:apiVersion: v1 kind: ConfigMap metadata:   name: test-cm   namespace: default   labels:     test-label: test   managedFields:   - manager: kubectl     operation: Apply     apiVersion: v1     time: "2010-10-10T0:00:00Z"     fieldsType: FieldsV1     fieldsV1:       f:metadata:         f:labels:           f:test-label: {}       f:data:         f:key: {} data:   key: some value
  上述对象在 metadata.managedFields 中包含了唯一的管理器。 管理器由管理实体自身的基本信息组成,比如操作类型、API 版本、以及它管理的字段。
  Note:  该字段由 API 服务器管理,用户不应该改动它。
  不过,执行 Update 操作修改 metadata.managedFields 也是可实现的。 强烈不鼓励这么做,但当发生如下情况时, 比如 managedFields 进入不一致的状态(显然不应该发生这种情况), 这么做也是一个合理的尝试。
  managedFields 的格式在 API 文档中描述。冲突
  冲突是一种特定的错误状态, 发生在执行 Apply 改变一个字段,而恰巧该字段被其他用户声明过主权时。 这可以防止一个应用者不小心覆盖掉其他用户设置的值。 冲突发生时,应用者有三种办法来解决它:覆盖前值,成为唯一的管理器: 如果打算覆盖该值(或应用者是一个自动化部件,比如控制器), 应用者应该设置查询参数 force 为 true,然后再发送一次请求。 这将强制操作成功,改变字段的值,从所有其他管理器的 managedFields 条目中删除指定字段。不覆盖前值,放弃管理权: 如果应用者不再关注该字段的值, 可以从配置文件中删掉它,再重新发送请求。 这就保持了原值不变,并从 managedFields 的应用者条目中删除该字段。不覆盖前值,成为共享的管理器: 如果应用者仍然关注字段值,并不想覆盖它, 他们可以在配置文件中把字段的值改为和服务器对象一样,再重新发送请求。 这样在不改变字段值的前提下, 就实现了字段管理被应用者和所有声明了管理权的其他的字段管理器共享。管理器
  管理器识别出正在修改对象的工作流程(在冲突时尤其有用), 管理器可以通过修改请求的参数 fieldManager 指定。 虽然 kubectl 默认发往 kubectl 服务端点,但它则请求到应用的服务端点(apply endpoint)。 对于其他的更新,它默认的是从用户代理计算得来。应用和更新
  此特性涉及两类操作,分别是 Apply (内容类型为 application/apply-patch+yaml 的 PATCH 请求) 和 Update (所有修改对象的其他操作)。 这两类操作都会更新字段 managedFields,但行为表现有一点不同。
  Note:
  不管你提交的是 JSON 数据还是 YAML 数据, 都要使用 application/apply-patch+yaml 作为 Content-Type 的值。
  所有的 JSON 文档 都是合法的 YAML。
  例如,在冲突发生的时候,只有 apply 操作失败,而 update 则不会。 此外,apply 操作必须通过提供一个 fieldManager 查询参数来标识自身, 而此查询参数对于 update 操作则是可选的。 最后,当使用 apply 命令时,你不能在应用中的对象中持有 managedFields。
  一个包含多个管理器的对象,示例如下:apiVersion: v1 kind: ConfigMap metadata:   name: test-cm   namespace: default   labels:     test-label: test   managedFields:   - manager: kubectl     operation: Apply     apiVersion: v1     fields:       f:metadata:         f:labels:           f:test-label: {}   - manager: kube-controller-manager     operation: Update     apiVersion: v1     time: "2019-03-30T16:00:00.000Z"     fields:       f:data:         f:key: {} data:   key: new value
  在这个例子中, 第二个操作被管理器 kube-controller-manager 以 Update 的方式运行。 此 update 更改 data 字段的值, 并使得字段管理器被改为 kube-controller-manager。
  如果把 update 操作改为 Apply,那就会因为所有权冲突的原因,导致操作失败。合并策略
  由服务器端应用实现的合并策略,提供了一个总体更稳定的对象生命周期。 服务器端应用试图依据负责管理它们的主体来合并字段,而不是根据值来否决。 这么做是为了多个主体可以更新同一个对象,且不会引起意外的相互干扰。
  当用户发送一个"完整描述的目标"对象到服务器端应用的服务端点, 服务器会将它和活动对象做一次合并,如果两者中有重复定义的值,那就以配置文件的为准。 如果配置文件中的项目集合不是此用户上一次操作项目的超集, 所有缺少的、没有其他应用者管理的项目会被删除。 关于合并时用来做决策的对象规格的更多信息,参见 sigs.k8s.io/structured-merge-diff.
  Kubernetes 1.16 和 1.17 中添加了一些标记, 允许 API 开发人员描述由 list、map、和 structs 支持的合并策略。 这些标记可应用到相应类型的对象,在 Go 文件或在 CRD 的 OpenAPI 的模式中定义:
  Golang 标记
  OpenAPI extension
  可接受的值
  描述
  引入版本
  //+listType
  x-kubernetes-list-type
  atomic/set/map
  适用于 list。set 适用于仅包含标量元素的列表。这些元素必须是不重复的。map 仅适用于包含嵌套类型的列表。列表中的键(参见 listMapKey)不可以重复。atomic 适用于任何类型的列表。如果配置为 atomic,则合并时整个列表会被替换掉。任何时候,只有一个管理器负责管理指定列表。如果配置为 set 或 map,不同的管理器也可以分开管理条目。
  1.16
  //+listMapKey
  x-kubernetes-list-map-keys
  字段名称的列表,例如,["port", "protocol"]
  仅当 +listType=map 时适用。取值为字段名称的列表,这些字段值的组合能够唯一标识列表中的条目。尽管可以存在多个键,listMapKey 是单数的,这是因为键名需要在 Go 类型中各自独立指定。键字段必须是标量。
  1.16
  //+mapType
  x-kubernetes-map-type
  atomic/granular
  适用于 map。 atomic 指 map 只能被单个的管理器整个的替换。 granular 指 map 支持多个管理器各自更新自己的字段。
  1.17
  //+structType
  x-kubernetes-map-type
  atomic/granular
  适用于 structs;否则就像 //+mapType 有相同的用法和 openapi 注释.
  1.17
  若未指定 listType,API 服务器将 patchMergeStrategy=merge 标记解释为 listType=map 并且视对应的 patchMergeKey 标记为 listMapKey 取值。
  atomic 列表类型是递归的。
  这些标记都是用源代码注释的方式给出的,不必作为字段标签(tag)再重复。拓扑变化时的兼容性
  在极少的情况下,CRD 或者内置类型的作者可能希望更改其资源中的某个字段的 拓扑配置,同时又不提升版本号。 通过升级集群或者更新 CRD 来更改类型的拓扑信息与更新现有对象的结果不同。 变更的类型有两种:一种是将字段从 map/set/granular 更改为 atomic, 另一种是做逆向改变。
  当 listType、mapType 或 structType 从 map/set/granular 改为 atomic 时,现有对象的整个列表、映射或结构的属主都会变为这些类型的 元素之一的属主。这意味着,对这些对象的进一步变更会引发冲突。
  当一个列表、映射或结构从 atomic 改为 map/set/granular 之一 时,API 服务器无法推导这些字段的新的属主。因此,当对象的这些字段 再次被更新时不会引发冲突。出于这一原因,不建议将某类型从 atomic 改为 map/set/granular。
  以下面的自定义资源为例:apiVersion: example.com/v1 kind: Foo metadata:   name: foo-sample   managedFields:   - manager: manager-one     operation: Apply     apiVersion: example.com/v1     fields:       f:spec:         f:data: {} spec:   data:     key1: val1     key2: val2
  在 spec.data 从 atomic 改为 granular 之前,manager-one 是 spec.data 字段及其所包含字段(key1 和 key2)的属主。 当对应的 CRD 被更改,使得 spec.data 变为 granular 拓扑时, manager-one 继续拥有顶层字段 spec.data(这意味着其他管理者想 删除名为 data 的映射而不引起冲突是不可能的),但不再拥有 key1 和 key2。因此,其他管理者可以在不引起冲突的情况下更改 或删除这些字段。自定义资源
  默认情况下,服务器端应用把自定义资源看做非结构化数据。 所有的键值(keys)就像 struct 的字段一样被处理, 所有的 list 被认为是原子性的。
  如果自定义资源定义(Custom Resource Definition,CRD)定义了一个 模式, 它包含类似以前"合并策略"章节中定义过的注解, 这些注解将在合并此类型的对象时使用。在控制器中使用服务器端应用
  控制器的开发人员可以把服务器端应用作为简化控制器的更新逻辑的方式。 读-改-写 和/或 patch 的主要区别如下所示:应用的对象必须包含控制器关注的所有字段。对于在控制器没有执行过应用操作之前就已经存在的字段,不能删除。 (控制器在这种用例环境下,依然可以发送一个 PATCH/UPDATE)对象不必事先读取,resourceVersion 不必指定。
  强烈推荐:设置控制器在冲突时强制执行,这是因为冲突发生时,它们没有其他解决方案或措施。转移所有权
  除了通过冲突解决方案提供的并发控制, 服务器端应用提供了一些协作方式来将字段所有权从用户转移到控制器。
  最好通过例子来说明这一点。 让我们来看看,在使用 Horizo ntalPodAutoscaler 资源和与之配套的控制器, 且开启了 Deployment 的自动水平扩展功能之后, 怎么安全的将 replicas 字段的所有权从用户转移到控制器。
  假设用户定义了 Deployment,且 replicas 字段已经设置为期望的值:
  application/ssa/nginx-deployment.yamlapiVersion: apps/v1 kind: Deployment metadata:   name: nginx-deployment   labels:     app: nginx spec:   replicas: 3   selector:     matchLabels:       app: nginx   template:     metadata:       labels:         app: nginx     spec:       containers:       - name: nginx         image: nginx:1.14.2
  并且,用户使用服务器端应用,像这样创建 Deployment:kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment.yaml --server-side
  然后,为 Deployment 启用 HPA,例如:kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10
  现在,用户希望从他们的配置中删除 replicas,所以他们总是和 HPA 控制器冲突。 然而,这里存在一个竟态: 在 HPA 需要调整 replicas 之前会有一个时间窗口, 如果在 HPA 写入字段成为所有者之前,用户删除了replicas, 那 API 服务器就会把 replicas 的值设为 1, 也就是默认值。 这不是用户希望发生的事情,即使是暂时的。
  这里有两个解决方案:(基本操作)把 replicas 留在配置文件中;当 HPA 最终写入那个字段, 系统基于此事件告诉用户:冲突发生了。在这个时间点,可以安全的删除配置文件。(高级操作)然而,如果用户不想等待,比如他们想为合作伙伴保持集群清晰, 那他们就可以执行以下步骤,安全的从配置文件中删除 replicas。
  首先,用户新定义一个只包含 replicas 字段的配置文件:
  application/ssa/nginx-deployment-replicas-only.yamlapiVersion: apps/v1 kind: Deployment metadata:   name: nginx-deployment spec:   replicas: 3
  用户使用名为 handover-to-hpa 的字段管理器,应用此配置文件。kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment-replicas-only.yaml    --server-side --field-manager=handover-to-hpa    --validate=false
  如果应用操作和 HPA 控制器产生冲突,那什么都不做。 冲突表明控制器在更早的流程中已经对字段声明过所有权。
  在此时间点,用户可以从配置文件中删除 replicas 。
  application/ssa/nginx-deployment-no-replicas.yamlapiVersion: apps/v1 kind: Deployment metadata:   name: nginx-deployment   labels:     app: nginx spec:   selector:     matchLabels:       app: nginx   template:     metadata:       labels:         app: nginx     spec:       containers:       - name: nginx         image: nginx:1.14.2
  注意,只要 HPA 控制器为 replicas 设置了一个新值, 该临时字段管理器将不再拥有任何字段,会被自动删除。 这里不需要执行清理工作。在用户之间转移所有权
  通过在配置文件中把一个字段设置为相同的值,用户可以在他们之间转移字段的所有权, 从而共享了字段的所有权。 当用户共享了字段的所有权,任何一个用户可以从他的配置文件中删除该字段, 并应用该变更,从而放弃所有权,并实现了所有权向其他用户的转移。与客户端应用的对比
  由服务器端应用实现的冲突检测和解决方案的一个结果就是, 应用者总是可以在本地状态中得到最新的字段值。 如果得不到最新值,下次执行应用操作时就会发生冲突。 解决冲突三个选项的任意一个都会保证:此应用过的配置文件是服务器上对象字段的最新子集。
  这和客户端应用(Client Side Apply) 不同,如果有其他用户覆盖了此值, 过期的值被留在了应用者本地的配置文件中。 除非用户更新了特定字段,此字段才会准确, 应用者没有途径去了解下一次应用操作是否会覆盖其他用户的修改。
  另一个区别是使用客户端应用的应用者不能改变他们正在使用的 API 版本,但服务器端应用支持这个场景。从客户端应用升级到服务器端应用
  客户端应用方式时,用户使用 kubectl apply 管理资源, 可以通过使用下面标记切换为使用服务器端应用。kubectl apply --server-side [--dry-run=server]
  默认情况下,对象的字段管理从客户端应用方式迁移到 kubectl 触发的服务器端应用时,不会发生冲突。
  Caution:
  保持注解 last-applied-configuration 是最新的。 从注解能推断出字段是由客户端应用管理的。 任何没有被客户端应用管理的字段将引发冲突。
  举例说明,比如你在客户端应用之后, 使用 kubectl scale 去更新 replicas 字段, 可是该字段并没有被客户端应用所拥有, 在执行 kubectl apply --server-side 时就会产生冲突。
  此操作以 kubectl 作为字段管理器来应用到服务器端应用。 作为例外,可以指定一个不同的、非默认字段管理器停止的这种行为,如下面的例子所示。 对于 kubectl 触发的服务器端应用,默认的字段管理器是 kubectl。kubectl apply --server-side --field-manager=my-manager [--dry-run=server] 从服务器端应用降级到客户端应用
  如果你用 kubectl apply --server-side 管理一个资源, 可以直接用 kubectl apply 命令将其降级为客户端应用。
  降级之所以可行,这是因为 kubectl server-side apply 会保存最新的 last-applied-configuration 注解。
  此操作以 kubectl 作为字段管理器应用到服务器端应用。 作为例外,可以指定一个不同的、非默认字段管理器停止这种行为,如下面的例子所示。 对于 kubectl 触发的服务器端应用,默认的字段管理器是 kubectl。kubectl apply --server-side --field-manager=my-manager [--dry-run=server] API 端点
  启用了服务器端应用特性之后, PATCH 服务端点接受额外的内容类型 application/apply-patch+yaml。 服务器端应用的用户就可以把 YAMl 格式的 部分定义对象(partially specified objects)发送到此端点。 当一个配置文件被应用时,它应该包含所有体现你意图的字段。清除 ManagedFields
  可以从对象中剥离所有 managedField, 实现方法是通过使用 MergePatch、 StrategicMergePatch、 JSONPatch、 Update、以及所有的非应用方式的操作来覆盖它。 这可以通过用空条目覆盖 managedFields 字段的方式实现。以下是两个示例:PATCH /api/v1/namespaces/default/configmaps/example-cm Content-Type: application/merge-patch+json Accept: application/json Data: {"metadata":{"managedFields": [{}]}} PATCH /api/v1/namespaces/default/configmaps/example-cm Content-Type: application/json-patch+json Accept: application/json Data: [{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}]
  这一操作将用只包含一个空条目的列表覆写 managedFields, 来实现从对象中整个的去除 managedFields。 注意,只把 managedFields 设置为空列表并不会重置字段。 这么做是有目的的,所以 managedFields 将永远不会被与该字段无关的客户删除。
  在重置操作结合 managedFields 以外其他字段更改的场景中, 将导致 managedFields 首先被重置,其他改变被押后处理。 其结果是,应用者取得了同一个请求中所有字段的所有权。
  Caution:  对于不接受资源对象类型的子资源(sub-resources), 服务器端应用不能正确地跟踪其所有权。 如果你对这样的子资源使用服务器端应用,变更的字段将不会被跟踪。
  参考链接:
  https://kubernetes.io/zh/docs/reference/using-api/server-side-apply/
  顺便祝大家五一假期愉快,也不要忘记提升自己。
  欢迎大家提出不一样的观点,我们一起讨论,
  我是辣个男人,一个运维人。

兼融之道自成新境新雷克萨斯ES上海区域上市发布会圆满落幕2021年9月11日晚,以兼融之道自成新境为主题的新雷克萨斯ES上海区域上市发布会在星尚创意空间内隆重举行。发布会现场,历届奥运会冠军得主乐靖宜女士亲临现场为新ES助力,此外雷克萨科技平权潮流平替MGONE誓做燃油车新势力公元2021年9月9日,魔都壹秀秀场,汽车界潮玩品牌带头大哥MG,召开了一场轰动汽车江湖的武林大会,现场各路英雄云集。MG虚拟代言人MGONE机电潮人,作为全真派2021掌门,以最微视网媒暻阁酒店斩获中国酒店星光奖杰出发展潜力高端酒店品牌4月1日,2021AHF亚洲酒店及旅游论坛年会暨第十六届中国酒店星光奖颁奖典礼在上海盛大举行,暻阁酒店凭借独一无二的东方禅意文化品牌基调及稳健的市场表现突出的消费者口碑一举斩获中国Arm推出Armv9架构面向人工智能安全和专用计算的未来3月31日Arm宣布推出Armv9架构,以满足全球对功能日益强大的安全人工智能(AI)和无处不在的专用处理的需求。Armv9立足于Armv8的成功基础,是这十年来最新的Arm架构。神装上阵华硕主板爆款直降装机SHOW即日起至4月15日,华硕在京东特别开启华硕装机SHOW活动,有超多人气主板新品主板单品以及超值板U套装汇聚于此,秒杀不断,特惠不打烊,更有0元入会抽豪礼首购礼金等你来抢。这里不仅有萤石又添新成员智能视频锁DL20VC安全便捷看家放心在智能锁领域,萤石无疑是最受消费者关注的品牌之一了。近日,萤石家族又添新成员,新品智能视频锁DL20VC采用了一握开解锁造型,融入了萤石最为擅长的视觉能力,支持远程通视频话PIR人11代酷睿好战友华硕Z590吹雪体验热榜神作先驱者近日,CDPR正式推出了赛博朋克2077的1。2版本,该版本补丁修复了游戏内的数百项内容,包括修正了多个任务开放世界剧情动画环境和关卡方面的BUG,同时改善了UI稳定性和性能等。可让未来,现在就来!手指管家J81Pro新品发布未来是什么颜色?这一看似无厘头的问题,却包含了人类对未来生活的无垠想象。而我们也能从诸多科幻影视游戏作品以及概念产品中,窥探到创意天才们关于这一命题的解答。在银翼杀手里,未来既包含联想拯救者电竞手机2Pro正式发布,超强散热加持北京时间4月8日晚,联想推出旗下新一代游戏手机产品联想拯救者电竞手机2Pro。本次联想拯救者2Pro的外观设计十分有特色,机器背面有凸起设计,CPU内存等重要硬件都集中在这个区域,不局限国内市场,AWE海信再秀实力,5年后海外市场占比50AWE2021中国家电及消费电子博览会海信成为了明星企业,一举俘获9项艾普兰奖,这些奖项对于海信而言可谓来之不易,不仅象征着海信多年来的技术沉淀,同时也代表着海信的品质深得人心。可首度引入保时捷设计!极米RS系列4K级旗舰投影上市4月27日,国内顶级投影厂商之一的极米科技发布了全新的RS投影新品,其中包括4K家用智能投影极米RSPro2以及便携智能投影极米RSAIR保时捷设计。极米发布RSPro2RSAIR