K8s-kubectl(变更对比策略和拓展命令)
K8s-kubectl(变更对比策略和拓展命令)
基于1.25
什么是变更对比策略
kuebctl apply 通过JSON/YAML,标准输入输出获取K8s集群进行配置更新
Kubectl edit 实时编辑K8s资源对象
kubectl patch 提供更新资源对象
kubectl diff 本地文件和实时资源对比
所以存在了不同的对比策略场景:
- 变更对比逻辑在哪进行(服务端还是客户端)
- 针对什么资源对象可以进行变更对象
- 使用说明变更对比算法
服务端应用和客户端应用
服务端应用
通过声明式的方法,kuebctl 发送完整的对象描述去创建和更新对象。
kubectl提供了俩个命令参数实现支持服务端:
- server-side:服务端应用的开关,当设置为true时,开启并使用服务端应用
- force-conflicts:冲突解决策略,当设置为true;会强制应用变更
kubectl apply 和kubectl diff 都支持启用服务端应用
kubectl patch 值提供服务端应用的变更方式
客户端应用
与服务端不同,客户端在处理变更和冲突逻辑之后,把处理后的变更发送给服务端
- kubectl apply 和 kubectl diff 默认使用客户端应用更新策略
- kubectl edit 和 kubectl annotation 值提供客户端更新策略
- 获取变更配置:kubectl把用户提供的变更内容转换为runtime.Object对象后,会进一步将改对象编码为JSON格式的字节数组,作为待变更配置
- 获取服务端对象:kubectl请求kube-apisever获取最新服务端对象
- 计算变更内容:kubectl内部有一个专门计算变更的Patcher工具,会比形成完整的变更差异
- 应用变更内容:kubectl计算之后的作为参数,使用Patch进行kube-apiserver请求变更
- 使用客户端变更,可以减少kube-apiserver压力
- 如果多个来源同一时间请求变更,可能失败,kubectl实现了失败检测重试机制
- 如果失败的原因是变更冲突,才进入重试(最大重试次数5)
- 第一次重试,先从kube-apiserver获取最新资源
- 第2-5次,为了减少频繁获取,退避1s重试
策略对比器和JSON对比器
kubectl支持提供了策略对比器(strategicpatch)和JSON对比器(jsonmerepatch)俩种
策略对比器
除了常规的字段对比,策略对比还支持使用对应的内置资源来对应OpenAPI资源类型提供的Schema信息进行对比,还可以进行更复杂的指令策略(Directive)对比
在实际中,常用的指令策略-retainKeys
- 描述在变更时需要整体保留/替换字段
JSON对比器
无法从kube-apiserver中获取自定义资源的对象的OpenAPI,在K8s源码中也无法为每个用户自定义资源对象特定的资源实现类。
实现对比:
先把用户自定义的资源对象转换为JSON格式,然后递归便利对比JSON对象的各个字段,找到全部变更内容
JSON无法实现高级对比,但是JSON支持注入预检查(PreconditionFunc)实现拓展对比
双路合并和三路合并
k8s对比分三类:新增字段、修改字段、删除字段
双路合并(2-way-Merge):基于变更配置和当前配置 来计算变更
- kubectl edit|kubectl taint|kubectl cordon 等
三路合并(3-way-Merge):当前配置(服务端获取的完整的资源对象配置)、变更配置(由用户提供的、待生效的资源配置)、最后应用配置(用户提供的、已生效的最新资源配置)
最后的应用配置通过读取配置的annotation的
kubectl.kubernetes.io/last-applied-configuration
注解内容来获取在更新成功后,变更配置会被写入``kubectl.kubernetes.io/last-applied-configuration`
三路合并流程
- 比较变更配置和当前配置
- 将变更配置中存在、当前配置中不存在的字段作为新增字段
- 将变更配置和当前配置中都存在但值不同的字段作为修改字段
- 忽略当前配置中存在、变更配置中不存在的字段
- 比较变更配置和最后应用配置,将最后应用配置中存在、变更配置中不存在的字段作为删除字段
- 合并第一步的新增字段和修改字段,以及第2步中的删除字段,合并的内容作为变更内容
拓展命令
除了预置的kubectl命令,kubectl还支持插件拓展命令
- 目前kubectl还将以kubectl-为前缀的文件作为拓展命令
- Ref:https://github.com/kubernetes/sample-cli-plugin(实现了kubectl 执行切换到指定namespace)
拓展原理
设计插件,需要循环以下设计原则:
- 无需在kubectl上进行任何安装和配置,符合一定命名规范的二进制文件都可以直接作为插件(设置到/usr/bin/kubectl-educate-dplphins,就可以使用kubectl educate dplphins
- kubectl 所有输入参数都会提供给二进制文件
- 拓展命令执行优先级最低,输入参数先匹配到核心,就会先匹配
拓展命令管理器Krew
Krew上K8s官方提供的拓展命令管理工具,实现对拓展命令的查找、安装、使用和管理
1.更新可用命令 |