问题
在开发中遇到一个问题:同事通过operator对集群的资源进行逻辑处理。运维平台需要纳管CRD资源,对CRD资源进行CURD,但是使用常见的RestClient和ClientSet没有现成的可以使用的方法对CRD资源进行管理。
CRD (Custom Resource Definition) 是Kubernetes的一种扩展机制,允许用户自定义Kubernetes API中的资源。在对CRD进行CURD操作时,需要使用Dynamic client,因为client-go的标准client对CRDs无法实现自动代码生成。这就需要我们自定义代码来操作这些资源。
解决方案
package main
import (
"context"
"flag"
"fmt"
"k8s.io/api/autoscaling/v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"path/filepath"
)
func main() {
var kubeconfig *string
// home是家目录,如果能取得家目录的值,就可以用来做默认值
if home := homedir.HomeDir(); home != "" {
// 如果输入了kubeconfig参数,该参数的值就是kubeconfig文件的绝对路径,
// 如果没有输入kubeconfig参数,就用默认路径~/.kube/config
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
// 如果取不到当前用户的家目录,就没办法设置kubeconfig的默认目录了,只能从入参中取
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()
// 从本机加载kubeconfig配置文件,因此第一个参数为空字符串
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
// kubeconfig加载失败就直接退出了
if err != nil {
panic(err.Error())
}
dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// 构建CRD资源的GVR
gvr := schema.GroupVersionResource{Group: "test.com", Version: "v1", Resource: "testrosource"}
// 使用dynamicClient的查询列表方法,查询指定namespace下的所有pod,
// 注意此方法返回的数据结构类型是UnstructuredList
unstructObj, err := dynamicClient.
Resource(gvr).
Namespace("default").List(context.TODO(), metav1.ListOptions{Limit: 100})
if err != nil {
panic(err.Error())
}
// 实例化一个testrosource数据结构,用于接收从unstructObj转换后的结果
testrosourceList := &TestrosourceList{}
// 转换
err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructObj.UnstructuredContent(), testrosourceList)
if err != nil {
panic(err.Error())
}
for _, d := range testrosourceList.Items {
fmt.Printf("%v\t %v\n",
d.Spec.Name,
d.Spec.Namespace,
)
}
}
注意:在上述代码中,我们使用了”context.TODO("作为一个临时的上下文传递给方法。在实际的代码中,你应该使用真正的上下文,而不是这个临时值。请注意,由于你正在操作的是自定义资源,所以你需要知道这个资源的API版本(例如"test.com/v1") ,资源类型 (例如"testrosource") 以及你希望在其中执行操作的命名空间。你也需要创建一个包含你要创建或修改的资源的状态的unstructured.Unstructured实例。
这只是一个基本的示例,你可能需要根据你的CRD的实际结构和需要进行相应的调整~
主要思路:对K8S原生资源,直接使用RestClient和ClientSet即可,但是自定义的CRD资源需要将资源转化成Unstructured后进行处理