提前检测 Kubernetes API 的废弃/移除
我们将介绍一种检测Kubernetes API中的apps/v1beta1 Deployment等部分被弃用/移除的方法。
对于计划将Kubernetes升级到1.16及以上版本的人来说,需要注意的是,在Kubernetes 1.16中,DaemonSet和Deployment的旧API版本(例如extensions/v1beta1, apps/v1beta2)将被移除,这会带来很大的影响。因此,如果您计划迁移到1.16以上的集群,请注意。
背景
背景条件
背景背景
情景
请参考官方文档,了解 Kubernetes 的新版本中特定 Kubernetes API(例如,apps/v1beta1 Deployment)的弃用/移除情况。
在Kubernetes中,有一种机制可以将每个资源的API版本转换为Internal Version -> Storage Version(如果对Internal/Storage Version感兴趣,请参考这些幻灯片等)。因此,在Kubernetes集群中注册的资源已经转换为不推荐使用/移除的API版本,并且可能在升级Kubernetes集群时不会立即出现问题。
考虑到升级后的运用情况,早晚将面临以下三个挑战。
注意:在下文中提到的”Manifest文件”是指用于描述Pod、Deployment、ConfigMap等的YAML文件。这是您使用kubectl create -f或kubectl apply -f命令时所指定的那个文件。
-
- Helm Chart、Manifest文件: 如果继续使用被弃用/移除的API,可能会在Kubernetes集群上添加或更新资源时失败。
Kubernetes集群上的资源: 如果被转换为内部/存储版本,则可能会设置意外的默认值,并导致不期望的行为。
例如,在DaemonSet中,当API版本为extensions/v1beta1时,spec.updateStrategy.type的默认值为OnDelete,但在apps/v1中,默认值已更改为RollingUpdate。
控制器/操作器: 在Kubernetes集群中使用的自定义控制器/操作器有时会创建或访问特定版本的Kubernetes API资源。如果相关的Kubernetes API被移除,可能会出现在操作相关Kubernetes API资源时失败的问题。
基本上,对于除了控制器/操作器之外的CLI工具等用于创建或注册Kubernetes API资源的工具也可以说是同样的情况。
这些问题的棘手之处在于“升级之后,问题并不会立即显现出来,而是在运行中进行某些操作或者多次进行升级后才有可能出现。”
在升级Kubernetes集群之前,需要检测Kubernetes API的废弃/删除,并进行适当的更改。然而当前的Kubernetes并没有官方提供用于此类检测的机制或工具。但是可以通过利用下面介绍的各种工具来检测API的废弃/删除。
检测方法
我会介绍一种用于检测各种API弃用/移除情况的工具。有关安装和使用方法,请参考各工具的官方存储库或相关URL。
Helm 图表/清单文件
结论:使用冥王星。
有几种工具可以用于检测Helm Chart和Manifest文件(YAML)中的API弃用/移除。基本上,我建议使用Pluto,但如果您重视通用性和灵活性,也许使用conftest会更好。
conftest
Open Policy Agentベースのチェックツール。幅広い用途で利用できる。
swade1987/deprek8ionで各Kubernetesバージョンのdeprecation/removal検出ポリシーが提供されてる。(関連記事)
Helm Chartのチェックには対応していない。
helm templateを併用すればチェック可能。
Pluto
Kubernetes API deprecation/removal検出に特化したツール。
Helm Chart(v2/v3)とManifestファイルの両方に対応。
Helm Chartのチェックはhelm templateを利用するため、helm CLIのインストールが必須。
HelmについてはKubernetesクラスタ上のリソースチェックも可能。
CLIバイナリのみで利用可能。
API deprecation/removal情報はハードコーディングされてるため柔軟性は低い。
在Kubernetes集群中的资源(不推荐)
结论:使用Kubent。但是不建议。
在CI/CD流程中自动生成Helm Chart和Manifest文件并直接应用时,需检查由于资源仅位于Kubernetes集群上而必要的情况。
通过使用kubent,您可以在Kubernetes集群上检测到API的弃用和移除。您可以对使用Helm(v2/v3)和kubectl apply注册的资源进行检查。
请注意,需要注意的是无法对使用kubectl create注册的资源进行检查,而不是使用kubectl apply。因此,无法检测到这些资源的API deprecation/removal。
这不仅仅是kubent的限制,而是由于Kubernetes本身的补充。因此,建议您建立基于GitOps等的CI/CD环境,尽量不需要对群集上的资源进行检查,以便执行Helm Chart和Manifest文件的检查。
补充说明:为什么能够检测到”kubectl apply”命令?
在Kubernetes中注册资源时,该资源将被转换为默认的API版本。例如,即使注册了extensions/v1beta1:DaemonSet资源,但如果DaemonSet的默认API版本是apps/v1,那么资源将被转换为apps/v1:DaemonSet并注册。换句话说,在这个时刻,Kubernetes服务器端的etcd中原始的extensions/v1beta1 API版本信息将不再存在。这适用于kubectl create和kubectl apply。
但是在使用kubectl apply命令的情况下,在注册资源的同时,会将注册时的Manifest信息设置为该资源的kubectl.kubernetes.io/last-applied-configuration注释。这个Manifest信息包括注册时的apiVersion等信息,因此即使进行了资源转换到默认API版本的操作,API版本信息仍然会作为注释保留下来。
由于kubent参考了kubectl.kubernetes.io/last-applied-configuration注释,因此可以正确地检测API的弃用和移除。
控制器/操作员
结论:如果使用Go语言和kubernetes/client-go实现,则可以使用yoichiwo7/k8sdepr。(但工具处于wip=WorkInProgress状态)
请提供已经存在的更好的解决办法,或者对于k8sdepr的问题和改进提出建议。
我认为,个人来说,我认为在Kubernetes API的弃用/移除检测方面,Controller/Operator是最困难的。
如果是使用自己开发的Controller/Operator,可以通过在kind(Docker中的Kubernetes)中准备各个Kubernetes版本的集群并运行测试来进行检测。但是我认为在没有相应规模的情况下,准备测试配置会很困难。
另外,如果是安装在Kubernetes上的第三方Controller/Operator,对所有这样的项目都添加这样的测试是不现实的。
因此,使用靜態代碼分析來檢測API的廢棄/移除成為最現實的選擇之一。這樣的工具可以輕鬆地集成到開發和CI中,並且對第三方的Controller/Operator進行檢查也相對容易。由於在我搜索的範圍內沒有找到此類工具,因此我創建了一個用於檢測Go語言Kubernetes API的廢棄/移除的工具(Go Analyzer)並且正在使用中。
通过在Go语言项目中运行工具,可以检测到Kubernetes API是否存在弃用/删除。以下是在对第三方Operator(spotahome/redis-operator v0.5.0)进行API弃用/删除检测的示例结果摘录。
# Kubernetes v1.16.0を対象バージョンとして指定
$ k8sdepr -targetVersion v1.16.0 ./...
/tmp/redis-operator/service/k8s/deployment.go:18:42: apps/v1beta2:Deployment is removed. Migrate to apps/v1:Deployment. {deprecated=v1.9.0, removed=v1.16.0}
...
/tmp/redis-operator/service/k8s/statefulset.go:18:43: apps/v1beta2:StatefulSet is removed. Migrate to apps/v1:StatefulSet. {deprecated=v1.9.0, removed=v1.16.0}
现在的输出已经包含了在哪个Kubernetes版本中被弃用或删除的信息,同时还包括了应该使用的新的Kubernetes API。
注意:
对于未支持Go Module的项目,如spotahome/redis-operator v0.5.0等,请先执行go mod init等操作,然后将其转换为Go Module项目后再运行工具。虽然Go Module的普及率正在增加,但仍有许多项目尚未支持,因此需要注意。
请注意,此处为了流程不被Go语言和kubernetes/client-go实现的Controller/Operator检查之外的情况不提供支持。如果不是用Go语言实现的,需要通过详细搜寻或目视确认来执行检查,或者需要针对该语言实现相应的代码静态分析工具。
重要的是要弥合Go语言和Kubernetes生态系统之间的差距。
顺便提一下,yoichiwo7/k8sdepr是基于以下前提条件和原则创建的。
-
- 主要なController/OperatorはGo言語 + kubernetes/client-goで実装されている
-
- Go言語は静的解析のためのモジュール群が豊富であるため実装が比較的容易
-
- Kubernetes APIのパッケージ構成が体系化されている
基本的にk8s.io/api/配下に各種apiVersionおよびkindが配置されている
由于存在这样的前提条件,对于在Go语言和Kubernetes生态系统之外实现的Controller/Operator,很可能无法适当地进行检测。
存在着一些用于使用Java、Python等语言实现Controller/Operator的项目,但一旦选择了这些项目,就无法享受到Go语言和Kubernetes生态系统的好处,或者为了获得这些好处需要做出独特的努力。我们应该谨慎权衡使用熟悉的语言带来的优势和无法获得好处的劣势。
特别是在考虑长期运营开发Controller/Operator的情况下,这种劣势很可能成为巨大的技术负债。