最近在使用代码操作VictoriaMetrics Operator的CRD资源的过程中,探究了几种访问CRD资源的方式。下面以VictoriaMetrics Operator的CRD为例介绍。
方式1:使用dynamic client
这种方式最原始,使用dynamic client获取到原始的json数据,可以使用json.Unmarshal
将数据解析到结构体中,也可以 使用runtime.DefaultUnstructuredConverter.FromUnstructured
方法进行解析。
这种方式的好处是简单好理解,缺点就是需要在json层面操作数据,使用json作为实际数据结构和unstructured.Unstructured
之间的转换媒介,性能上面可能会存在一定问题。
代码如下,更多参见这篇文章。
restConfig := &rest.Config{ Host: "https://xxxxx:6443", BearerToken: "xxxx", TLSClientConfig: rest.TLSClientConfig{Insecure: true}, } dynClient, err := dynamic.NewForConfig(restConfig) if err != nil { return } var r = schema.GroupVersionResource{Group: "operator.victoriametrics.com", Version: "v1beta1", Resource: "vmrules"} list, err := dynClient.Resource(r).Namespace("vm").List(context.TODO(), metav1.ListOptions{}) if err != nil { return } rlist := v1beta1.VMRuleList{} /* 也可以直接使用json方式解析到结构体中 data, _ := list.MarshalJSON() if err := json.Unmarshal(data, &rlist); err != nil { return } */ runtime.DefaultUnstructuredConverter.FromUnstructured(list.UnstructuredContent(), &rlist) fmt.Println(rlist)
方式2:使用client-go
一般会采用这种方式。首先需要在restConfig中注册GroupVersion
和scheme
。可以使用kubectl get --raw /apis/operator.victoriametrics.com/v1beta1
来验证该资源的APIPath
是不是"/apis"。scheme
用于注册结构体信息,使用scheme
生成的parameterCodec
来解析数据。
代码如下:
var SchemeGroupVersion = schema.GroupVersion{Group: "operator.victoriametrics.com", Version: "v1beta1"} restConfig := &rest.Config{ Host: "https://xxxx:6443", BearerToken: "xxxx", TLSClientConfig: rest.TLSClientConfig{Insecure: true}, } restConfig.APIPath = "/apis" restConfig.GroupVersion = &SchemeGroupVersion restConfig.NegotiatedSerializer = scheme1.Codecs.WithoutConversion() scheme := runtime.NewScheme() victoriametricsv1beta1.AddToScheme(scheme) parameterCodec := runtime.NewParameterCodec(scheme) if restConfig.UserAgent == "" { restConfig.UserAgent = rest.DefaultKubernetesUserAgent() } c,err := rest.RESTClientFor(restConfig) if nil != err{ panic(err) } rl := &v1beta1.VMRuleList{} err = c.Get(). Namespace("vm"). Resource("vmrules"). VersionedParams(&metav1.ListOptions{},scheme1.ParameterCodec). Do(context.TODO()). Into(rl) fmt.Println(err,rl)
CRD下的watchList
同样由于scheme的问题,当创建watchList的时候不能直接使用原生的cache.NewListWatchFromClient来创建watch和list方法:
func RunRuleInformer(operatorClit *rest.RESTClient, im *SyncMap){ jobInformer := cache.NewSharedIndexInformer( cache.NewListWatchFromClient(operatorClit, vmRuleResource, metav1.NamespaceAll, fields.Everything()), &v1beta1.VMRule{}, 0, cache.Indexers{}) stopCh := make(chan struct{}) jobInformer.AddEventHandler(im) go jobInformer.Run(stopCh) }
可以通过code-generator来生成informer,如
func RunRuleInformer(host,token string, im *SyncMap){ cs := versioned.NewForConfigOrDie(NewRestCfg(host,token)) informer := vmRuleInformer.NewVMRuleInformer(cs,vmRuleNamespace,0, cache.Indexers{}) informer.AddEventHandler(im) stopCh := make(chan struct{}) go informer.Run(stopCh) }