想打印k8s资源YAML结果搞懂了Client-Side & Server-Side Apply

这篇具有很好参考价值的文章主要介绍了想打印k8s资源YAML结果搞懂了Client-Side & Server-Side Apply。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

由于查看k8s资源YAML时常看到沉长的YAML与手写的格式,相差甚远不利于阅读,经过探索官方文档,才理解什么是Client-Side & Server-Side Apply。

先看一下我用client-go在生成Deployment的YAML格式,核心代码如下:

k8sDeployment, _ := clientSet.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metav1.GetOptions{})
k8sDeployment.Kind = "Deployment"
k8sDeployment.APIVersion = "apps/v1"
k8sDeployment.SetManagedFields(nil)  // 不显示管理字段,至于什么是管理字段? 请继续阅读后面的内容.
runtimeWorkload = k8sDeployment
yamlPrinter := printers.YAMLPrinter{}
buffers := bytes.NewBufferString("")
yamlErr := yamlPrinter.PrintObj(runtimeWorkload, buffers)
YAML := buffers.String()

效果:
想打印k8s资源YAML结果搞懂了Client-Side & Server-Side Apply

之前一直有这样一个困扰,例如这样的一个Pod资源,可以看到像kubectl.kubernetes.io/last-applied-configuration annotationmanagedFields 这两个字段,并不是我们手写YAML中存在的,他们是什么呢?

用一个例子展现:

kubectl get pods demo -o yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"creationTimestamp":null,"labels":{"run":"demo"},"name":"demo","namespace":"default"},"spec":{"containers":[{"image":"nginx","name":"demo","resources":{}}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always"},"status":{}}
  creationTimestamp: "2022-05-28T07:28:51Z"
  labels:
    run: demo
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:kubectl.kubernetes.io/last-applied-configuration: {}
        f:labels:
          .: {}
          f:run: {}
....

由这两个字段,引出本文的两位主角,Client-Side Apply(以下简称CSA)和Server-Side Apply(以下简称SSA)

  1. kubectl.kubernetes.io/last-applied-configuration是使用kubectl apply进行Client-Side Apply时,由kubectl自行填充的。
  2. managedFields 则是由kubectl apply的增强功能 Server-Side Apply 的引入而添加。

Client-Side Apply

kubectl apply是一种声明示的K8S对象管理方式,是我们最常用的应用部署,升级方式之一。

需要特别指出的是,kubectl apply声明的仅仅是它关心的字段的状态,而不是整个对象的真实状态。apply表达的意思是:此次提交管理的字段应该和apply的配置文件一致,其它字段并不关心。

比如首次部署时,K8S会将replicas值设置为默认1,随后由HPA控制器扩容到合适的副本数。

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  # replicas: 1 不要设置replicas
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        resources: {}

当升级应用时(修改镜像版本),修改配置文件中的image字段,再次执行kubectl apply。此时kubectl apply只会影响镜像版本 ,而不会影响HPA控制器设置的副本数。在这个例子中,replicas字段不是kubectl apply管理的字段,因此更新镜像时不会被删除,避免了每次应用升级时,副本数都会被重置。

在上述例子中,为了能识别出replicas不是kubectl管理的字段,kubectl需要一个标识,用来追踪对象中哪些字段是由kubectl apply管理的,而这个标识就是last-applied-configuration。
该annotation是在kubectl apply时,由kubectl客户端自行填充——每次执行kubectl apply时(未启用SSA),kubectl会将本次apply的配置文件全量的记录在last-applied-configurationannotation中,用于追踪哪些字段由kubectl apply管理。

CSA工作工作机制:

Apply一个资源对象时,如果该对象不存在,则创建它(同时写入last-applied-configuration)。如果对象已经存在,则kubectl需要根据以下三个状态:

  • 当前配置文件所表示的对象在集群中的真实状态。(修改对象前先Get一次)当前apply的配置。以及上次apply的配置。 (在last-applied-configuration里)。
  • 当前apply的配置。
  • 以及上次apply的配置。 (在last-applied-configuration里)

计算patch

通过patch方式进行更新(而不是将配置文件全量的发送到服务端)。patch报文的计算方法如下:

  1. 计算需要被删除的字段。如果字段存在在last-applied-configuration中,但配置文件中没有,将删除它们。
  2. 计算需要修改或添加的字段。如果配置文件中的字段与真实状态不一致,则添加或修改它们。
  3. 对于那些last-applied-configuration中不存在的字段,不要修改它们(例如上述示例中的replicas字段)。

CSA的合并策略

详细的patch计算示例可参考K8S文档中给出的详细示例。

由此可见,last-applied-configuration体现的是一种ownership的关系,表示哪些字段是由kubectl管理,它是kubectl apply时,计算patch报文的依据。

Server-Side Apply

Server-Side Apply 是另一种声明式的对象管理方式,和CSA的作用是基本一致的。SSA始于从1.14开始发布alpha版本,到1.16beta,到1.18beta2,终于在1.22升级为GA。
它协助用户、控制器通过声明式配置的方式管理他们的资源。 客户端可以发送完整描述的目标(A fully specified intent), 声明式地创建和修改对象。

顾名思义,SSA将对象合并的逻辑转移到了服务端(APIServer),客户端只需提交完整的配置文件,剩下的工作交给服务端处理。 在kubectl中使用SSA,只需在kubectl apply时加上--server-side参数即可,例如这样:

kubectl apply --server-side=true -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: test-server-side-apply
data:
  a: "a"
  b: "b"
EOF

部署成功后,查看对象会发现该对象中不再存在之前CSA中的last-applied-configuration,取而代之的是metadata.managedFields。查看上面apply创建的资源:

apiVersion: v1
data:
  a: a
  b: b
kind: ConfigMap
metadata:
  creationTimestamp: "2022-12-04T07:59:24Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        f:a: {}
        f:b: {}
    manager: kubectl
    operation: Apply
    time: "2022-12-04T07:59:24Z"
  name: test-server-side-apply
  namespace: default
  resourceVersion: "1304750"
  uid: d265df3d-b9e9-4d0f-91c2-e654f850d25a

字段管理(field management)机制追踪对象字段的变化。 当一个字段值改变时,其所有权从当前管理器(manager)转移到施加变更的管理器。 当尝试将新配置应用到一个对象时,如果字段有不同的值,且由其他管理器管理, 将会引发冲突。 冲突引发警告信号:此操作可能抹掉其他协作者的修改。 冲突可以被刻意忽略,这种情况下,值将会被改写,所有权也会发生转移。

SSA的合并策略

在介绍SSA的合并策略前,我们先了解一下CSA的合并策略。CSA的合并规则是基于Kubernetes的strategic merge patch方式,不同的字段类型分别有各自不同的合并策略,规则比较复杂。这也导致了CSA容易产生更多的Bug。SSA针对这个问题做了优化,相较于CSA,SSA定义了更加规范和准确的合并规则。 这里抄录文档中的一段表格加以说明:
想打印k8s资源YAML结果搞懂了Client-Side & Server-Side Apply

SSA的优点

简化客户端逻辑,CSA是一个很重的客户端逻辑,里面有复杂的对象合并操作,这意味着apply这项操作和kubectl是深度绑定的,使用其他客户端或者在控制器(Controller)中难以使用apply方式来配置对象。而SSA将这些合并的逻辑转移到了服务端,提供单一的API,客户端实现方式得以简化。这让apply的能力得以整合到client-go中,让应用可以通过client-go来使用apply的能力。

更细粒度的字段所有权管理,减少错误覆盖配置的可能性

相比于last-applied-configuration,SSA使用managedFields来管理每个字段的ownership,这是一种更细粒度的字段管理方式。这使得多个管理者之间能更好的协作,且其自带冲突检测,能很大程度避免错误覆盖配置的发生。

当使用SSA时,dry-run的逻辑也放在服务端执行。相比CSA,服务端dry-run可以真实的经过validating/mutating admission webhooks的校验,从而获取最准确的返回结果。这是CSA无法实现的。

总之CSA和SSA是两种不同实现的声明示管理Kubernetes对象的方式。SSA的出现是为了解决了CSA中存在的一些挑战与问题,如apply逻辑和kubectl深度绑定、strategic merge patch复杂多bug等等。SSA发展至今已是Kubernetes中的一个关键特性,相信其最终的目标将会是完全取代CSA,成为Kubernetes中唯一的apply方式。文章来源地址https://www.toymoban.com/news/detail-437155.html

到了这里,关于想打印k8s资源YAML结果搞懂了Client-Side & Server-Side Apply的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • K8S---yaml文件详解

    目录 一、K8S支持的文件格式 1、yaml和json的主要区别 2、YAML语言格式 二、YAML 1、查看 API 资源版本标签 2、编写资源配置清单 2.1 编写 nginx-test.yaml 资源配置清单 2.2 创建资源对象 2.3 查看创建的pod资源 3、创建service服务对外提供访问并测试 3.1 编写nginx-svc-test.yaml文件 3.2 创建资

    2024年02月12日
    浏览(29)
  • K8S:Yaml文件详解

    目录 一.Yaml文件详解 1.Yaml文件格式 2.YAML 语法格式 二.Yaml文件编写及相关概念 1.查看 api 资源版本标签 2.yaml编写案例 (2)Deployment类型编写nginx服务 (3)k8s集群中的port介绍 (5)快速编写yaml文件 (6)案例:自主式创建service并关联上面的pod (7)Pod yaml文件详解 (8)deploymen

    2024年02月08日
    浏览(37)
  • [ K8S ] yaml文件讲解

    Kubernetes 支持 YAML 和 JSON 格式管理资源对象 JSON 格式:主要用于 api 接口之间消息的传递 YAML 格式:用于配置和管理,YAML 是一种简洁的非标记性语言,内容格式人性化,较易读 YAML 语法格式: ●大小写敏感 ●使用缩进表示层级关系 ●不支持Tab键制表符缩进,只使用空格缩进

    2024年02月13日
    浏览(32)
  • K8S之yaml文件详解

    文章目录 一、概述 二、YAML文件优点 三、YAML与 JSON 和 XML 的关系 四、YAML 文件的结构 五、YAML 在 Kubernetes 中的使用 六、YAML文件模板生成/导出 一、概述  Kubernetes只支持YAML和JSON格式创建资源对象 JSON格式用于接口之间消息的传递,YAML格式用于配置和管理 YAML是专门用来写配置

    2024年02月02日
    浏览(38)
  • K8s中yaml文件详解

    文章目录 目录 一、YAML基础 二、说明 三、使用YAML创建Pod 附上一个具体的yaml解释文件: YAML是专门用来写配置文件的语言,非常简洁和强大,使用比json更方便。它实质上是一种通用的数据串行化格式。 YAML语法规则: 1.1 YAML Maps Map顾名思义指的是字典,即一个Key:Value 的键值

    2024年02月15日
    浏览(41)
  • k8s之YAML文件书写秘笈

                 在kubernetes的江湖里,一直流传YAML的传说,它是Yet Another Markup Language的英文缩写,用来配置k8s里的各类资源.。通常,你可以选择YAML或JSON来完成声明式的配置文件,这种方式便于复用和保存,但命令式的方式有一定的局限性,仅有部分kubernetes资源可以使用命令

    2024年01月18日
    浏览(35)
  • kubernetes(k8s) Yaml 文件详解

    YAML格式 :用于配置和管理,YAML是一种简洁的非标记性语言,内容格式人性化,较易读。 1、查看API 资源版本标签 kubectl api-versions 2、编写资源配置清单 2.3 查看创建的pod资源 kubectl get pods -o wide 3、创建service服务对外提供访问并测试 3.1、编写nginx-svc-test.yaml文件 3.2、创建资源

    2024年02月05日
    浏览(35)
  • k8s-如何快速编写yaml文件(新手)

    但是这个过程并没有在集群中执行,只是把结果通过yaml格式的方式输出出来,包括咱们可把它输出到文件里 场景:适用于部署好的项目,可以把部署好的项目中的yaml文件导出出来,实际效果比较实用

    2024年02月13日
    浏览(28)
  • 云原生(第四篇)-k8s yaml文件

    Kubernetes 支持 YAML 和 JSON 格式管理资源对象 JSON 格式:主要用于 api 接口之间消息的传递 YAML 格式:用于配置和管理,YAML 是一种简洁的非标记性语言,内容格式人性化,较易读 YAML 语法格式: ●大小写敏感 ●使用缩进表示层级关系 ●不支持Tab键制表符缩进,只使用空格缩进

    2024年02月12日
    浏览(33)
  • K8S学习笔记-01(yaml文件编写)

    原创文档编写不易,未经许可请勿转载。文档中有疑问的可以邮件联系我。 邮箱:yinwanit@163.com 记录k8s中yaml文件编写相关内容。 k8s官网文档库:https://kubernetes.io/docs/home/ kubelet 命令参考:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands k8s中yaml文件结尾需以.yml或.yaml结

    2024年02月14日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包