使用client-go观察CustomResourceDefinitions(CRD)

chr*_*ian 5 go kubernetes

我已经ApiGateway向Kubernetes 添加了一个新的CRD ,我想要关注它的新资源/更改资源.

这适用于简单的Rest Client,如下例所示.

但我想用这些资源来观察k8s.io/client-go/kubernetes.

虽然获取标准资源很简单,例如下面的客户端 - 例子,但我没有得到任何适用于CRD的东西.是否可以通过client-go完成这项工作?

客户端 - 标准资源的示例

import (
    ....
    "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func handleNewServices(clientset *kubernetes.Clientset) {
    for {
        serviceStreamWatcher, err := clientset.CoreV1().Services("").Watch(metav1.ListOptions{})
        if err != nil {
            panic(err.Error())
        }
        //fmt.Printf("%T\n", serviceStreamWatcher)
        for {
            select {
            case event := <-serviceStreamWatcher.ResultChan():
            service := event.Object.(*v1.Service)

            for key, value := range service.Labels {
                fmt.Printf("Key, VAlue: %s %s\n", key, value)
            }
...
Run Code Online (Sandbox Code Playgroud)

RestClient(工作正常)

package main

import (
    "net/http"
    ....

)

func main() {
    for {
        // Url "cw.com" must match the config spec.group in api-gateway-crd.yaml
        // URL "apigateways" must match the config spec.names.plural in api-gateway-crd.yaml
        resp, err := http.Get("http://localhost:8001/apis/cw.com/v1/apigateways?watch=true")
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        decoder := json.NewDecoder(resp.Body)
        for {
            var event v1.ApiGatewayWatchEvent
            if err := decoder.Decode(&event); err == io.EOF {
                break
            } else if err != nil {
                log.Fatal(err)
            }
            log.Printf("Received watch event: %s: %s: \n", event.Type, event.Object.Metadata.Name)

        }
    }

}
Run Code Online (Sandbox Code Playgroud)

CRD

apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: apigateways.cw.com
spec:
  scope: Namespaced
  group: cw.com
  version: v1
  names:
    kind: ApiGateway
    singular: apigateway
    plural: apigateways
Run Code Online (Sandbox Code Playgroud)

Abd*_*hin 9

如果你想想看,client-go知道deployments,services,pods等资源.但它无法识别您的CRD ApiGateway.

所以,client-go不能用作自定义资源的客户端(等待它),除非你让它们可识别client-go!

怎么样?!

您必须为CRD生成自己的客户端.Kubernetes已经有工具来自动生成客户端,你需要指定structsAPI.这被称为code-generation.

这是一个关于代码生成的博客文章史蒂芬SCHIMANSKI(谁是杰出贡献者kubernetes之一).

示例控制器

这是kubernetes自己给出的一个示例控制器示例.该pkg文件夹包含所有APISClient.在main.gocontroller.go包含示例代码来监控CRD,并相应地做一些工作.


Ano*_*usX 5

使用client-go的动态包来操作CRD可能是一个不错的选择。

基本上看例子:

cliSet, err := dynamic.NewForConfig(&rest.Config{})
if err != nil {
    return err
}

cliSet.Resource(schema.GroupVersionResource{
    // replace it with your CRD's corresponding property
    Group:    CRDGroup,
    Version:  CRDVersion,
    Resource: CRDResourceName,
}).Watch(context.Background(), metav1.ListOptions{})
Run Code Online (Sandbox Code Playgroud)

高级手表、告密者示例:

cliSet, err := dynamic.NewForConfig(&rest.Config{})
if err != nil {
    return err
}

fac := dynamicinformer.NewFilteredDynamicSharedInformerFactory(cliSet, 0, metav1.NamespaceAll, nil)
informer := fac.ForResource(schema.GroupVersionResource{
    // replace it with your CRD's corresponding property 
    Group:    CRDGroup,
    Version:  CRDVersion,
    Resource: CRDResourceName,
}).Informer()

informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
    AddFunc: func(obj interface{}) {
        // converting the dynamic object to your CRD struct
        typedObj := obj.(*unstructured.Unstructured)
        bytes, _ := typedObj.MarshalJSON()
        
        var crdObj *crd.CRD
        json.Unmarshal(bytes, &crdObj)
    },
    UpdateFunc: func(oldObj, newObj interface{}) {
        
    },
})
Run Code Online (Sandbox Code Playgroud)