K8s-Client-go:四种客户端
概述
ClientSet、DynamicClient、DiscoveryClient. —> RESTClient —> kubeconfig
其实,前面三种都是依赖于 RESTClient
RESTClient:就是对HTTP Client进行了封装,实现了RESTful风格的API。
ClientSet:在RESTClient之上封装了Resource和Version的管理方法,ClientSet只能访问K8s内置的资源,不能访问CRD资源,它是通过client-gen代码生成器生成的
DynamicClient:比ClientSet多一个支持CRD资源
DiscoveryClient:用于发现kube-apiserver所支持的资源组、资源版本、资源信息(Group、Version、Resource)
kubeconf文件
kubeconf文件存储了集群、用户、命名空间和身份验证等信息。
- clusters:集群信息
- users:K8s机器用户的客户端凭证
- contexts:定义K8s集群,用户信息和命名空间
读取kubeconfig文件配置:
- 文件路径,(rules.ExplicitPath)
- 环境变量,(KUBECONFIG)
位置:/K8s-sig/tools/clientcmd/load.go
RESTClient
RESTClient基于HTTP Request进行封装,实现了RESTFul风格的API,很灵活。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| package main
import ( "context" "flag" "fmt" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" "path/filepath" )
func main() { var kubeconfig *string if home := homedir.HomeDir(); home != "" { kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") } else { kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") } flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { panic(err) }
config.APIPath = "api" config.GroupVersion = &corev1.SchemeGroupVersion config.NegotiatedSerializer = scheme.Codecs
restClient, err := rest.RESTClientFor(config) if err != nil { panic(err) } res := &corev1.PodList{} namespace := "kube-system" err = restClient.Get().Namespace(namespace). Resource("pods"). VersionedParams(&metav1.ListOptions{Limit: 100}, scheme.ParameterCodec). Do(context.TODO()). Into(res) if err != nil { panic(err) } for _, item := range res.Items { fmt.Printf("%v\t %v\t %v\n", item.Namespace, item.Status.Phase, item.Name) }
}
|
ClientSet
基于RESTClinet,封装了对Resource和Version的抽象,通过代码生成器实现对K8s内置资源的管理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package main
import ( "context" "flag" "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" "path/filepath" )
func main() { var kubeconfig *string if home := homedir.HomeDir(); home != "" { kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") } else { kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") } flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { panic(err) } clientset, err := kubernetes.NewForConfig(config) if err != nil { panic(err) } pod, err := clientset.CoreV1().Pods("default").Get(context.TODO(), "", metav1.GetOptions{}) if err != nil { panic(err) } fmt.Println(pod) }
|
DynamicClient
动态客户端,跟ClientSet一样,但是支持了CRD资源。
DynamicClient不是类型安全的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| package main
import ( "context" "flag" "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "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 if home := homedir.HomeDir(); home != "" { kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") } else { kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") } flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { panic(err) } dynamicClient, err := dynamic.NewForConfig(config) if err != nil { panic(err) }
deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"} deploymentName := "ss" replicas := 1 image := "nginx" deploymnet := &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{ "name": deploymentName, }, "spec": map[string]interface{}{ "replicas": replicas, "selector": map[string]interface{}{ "matchLabels": map[string]interface{}{ "app": "demo", }, }, "template": map[string]interface{}{ "metadata": map[string]interface{}{ "labels": map[string]interface{}{ "app": "demo", }, }, "spec": map[string]interface{}{ "containers": []map[string]interface{}{ { "name": "web", "image": image, "ports": []map[string]interface{}{ { "name": "http", "protocol": "TCP", "containerPort": 80, }, }, }, }, }, }, }, }, } create, err := dynamicClient.Resource(deploymentRes).Namespace("default").Create(context.TODO(), deploymnet, metav1.CreateOptions{}) if err != nil { panic(err) } fmt.Println(create) }
|
DiscoveryClient
主要用于发现K8s API Server所支持的资源组、资源版本、资源信息。
DiscoveryClient通过ReESTFulClient请求/api接口,请求数据存放在metav1.APIVersion结构体中,然后通过RESTClient请求/apis接口,请求结果放在metav1.APIGroupList中。
本地缓存默认存放~/.kube/cache和~/.kube/http-cache。缓存可以减轻client-go对K8s API Server的访问。默认每10min与K8s API Server进行同步。
DiscoveryClient 获取,如果缓存中没有,才回去从K8s-API Server获取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| package main
import ( "flag" "fmt" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" "path/filepath" )
func main() { var kubeconfig *string if home := homedir.HomeDir(); home != "" { kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file") } else { kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file") } flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) if err != nil { panic(err) }
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config) if err != nil { panic(err) } apiGroups, APIResourceListSlice, err := discoveryClient.ServerGroupsAndResources() if err != nil { panic(err) } fmt.Printf("APIGroup:\n\n %v\n\n", apiGroups) for _, resourceList := range APIResourceListSlice { version := resourceList.GroupVersion fmt.Printf("%s", version)
groupVersion, err := schema.ParseGroupVersion(version) if err != nil { panic(err) } fmt.Printf("%v", groupVersion)
}
}
|