通过 clinet-go 列出 kubernetes 资源,我如何获得种类和 apiversion?

问题描述

当我使用client-go从api获取kubernetes资源,但是在响应中找不到apiversion和kind,apiversion和kind为空。如何获取资源的apiversion和种类?

下面是我的代码

package main

import (
    "flag"
    "k8s.io/client-go/tools/clientcmd"
    "log"
    "k8s.io/client-go/kubernetes"
    Metav1 "k8s.io/apimachinery/pkg/apis/Meta/v1"
    "fmt"
)

var clientset *kubernetes.Clientset

func main()  {
    k8sconfig := flag.String("k8sconfig","./k8sconfig","kubernetes config file path")
    flag.Parse()
    config,err := clientcmd.BuildConfigFromFlags("",*k8sconfig)
    if err != nil {
        log.Println(err)
    }
    clientset,err = kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatalln(err)
    } else {
        fmt.Println("connect k8s success")
    }
    pods,err := clientset.CoreV1().Pods("").List(Metav1.ListOptions{})
    if err != nil {
        log.Println(err.Error())
    }
    for _,pod := range pods.Items{
        fmt.Println("apiversion: ",pod.APIVersion,"kind: ",pod.Kind)
    }   
}

The output:
apiversion:   kind:  
apiversion:   kind:  
apiversion:   kind:  
apiversion:   kind:  
apiversion:   kind:  
apiversion:   kind:  
apiversion:   kind:  
apiversion:   kind:
......
......

解决方法

我认为问题在于您使用 List() API 获取 pod 列表,因此它不是您期望的 pod,并且没有 Kind 字段。

您需要遍历 pod 列表以访问单个 pod:

for _,pod := range pods.Items {
    fmt.Printf("%s %s\n",pod.GetName(),pod.GetCreationTimestamp())
}

Kind 字段是 Pod's Metadata 的一部分,可以使用 pod.ObjectMeta.Kind 访问。

,

您没有得到 APIVersionKind,因为它被代码忽略了。

如果您查看 API 服务器 JSON response,它将类似于以下内容:

{
   "kind":"PodList","apiVersion":"v1","metadata":{
      "resourceVersion":"2397"
   },"items":[
      {
... ... ...

因此响应确实包含 APIVersionKind。但是当响应被解码为 k8s 对象时,here

out,_,err := r.decoder.Decode(r.body,nil,obj)

这里可以看到忽略了第二个输出参数,即 schema.GroupVersionKind

func (c *Something) Decode([]byte,*schema.GroupVersionKind,runtime.Object) (runtime.Object,error) {
    
}

注意:当您使用 client-go(动态客户端除外)进行 API 调用时,您已经知道 APIVersion(即 CoreV1())和 Kind(即List()).