kubernetes 估計會成爲 linux 同樣的存在,client-go 是它的 go sdk,client-go/examples/ 給出了一些用例,可是數量比較少。linux
Resource 的定義不在client-go中,而是在一個名爲 api 的項目中,這個項目中的內容同步自 kubernetes 項目的目錄 staging/src/k8s.io/api,能夠用下面的方式獲取:git
go get k8s.io/api
api的目錄結構以下:github
▾ api/
▸ admission/
▸ admissionregistration/
▸ apps/
▸ authentication/
▸ authorization/
▸ autoscaling/
▸ batch/
▸ certificates/
▸ core/
▸ extensions/
▸ Godeps/
▸ imagepolicy/
▸ networking/
▸ policy/
▸ rbac/
▸ scheduling/
▸ settings/
▸ storage/
▸ vendor/
LICENSE
OWNERS
README.md
client-go是kubernetes官方的項目,go語言實現,使用示例源碼位於: go-code-example/k8sclient。vim
獲取 client-go:api
go get k8s.io/client-go
go get k8s.io/apimachinery
go get k8s.io/api
go get k8s.io/kube-openapi
Clientset 包含 kubernetes 的全部資源的操做句柄,經過」k8s.io/client-go/kubernetes」中NewForConfig()
建立。緩存
建立 Clientset 須要提供一個 rest.Config,Config 能夠用後面提到的 tools/clientcmd 生成,也能夠本身填寫:bash
config := rest.Config{ Host: "https://10.39.0.105:6443", APIPath: "/", Prefix: "", BearerToken: "af8cbdf725efadf8c4", TLSClientConfig: rest.TLSClientConfig{Insecure: true}, }
建立方法很簡單:app
clientset, err := kubernetes.NewForConfig(&config)
Clientset,意如其名,是client 的集合,在client-go/kubernetes/clientset.go中定義。工具
type Clientset struct { *discovery.DiscoveryClient admissionregistrationV1alpha1 *admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Client appsV1beta1 *appsv1beta1.AppsV1beta1Client appsV1beta2 *appsv1beta2.AppsV1beta2Client appsV1 *appsv1.AppsV1Client authenticationV1 *authenticationv1.AuthenticationV1Client authenticationV1beta1 *authenticationv1beta1.AuthenticationV1beta1Client authorizationV1 *authorizationv1.AuthorizationV1Client authorizationV1beta1 *authorizationv1beta1.AuthorizationV1beta1Client autoscalingV1 *autoscalingv1.AutoscalingV1Client autoscalingV2beta1 *autoscalingv2beta1.AutoscalingV2beta1Client batchV1 *batchv1.BatchV1Client batchV1beta1 *batchv1beta1.BatchV1beta1Client batchV2alpha1 *batchv2alpha1.BatchV2alpha1Client certificatesV1beta1 *certificatesv1beta1.CertificatesV1beta1Client coreV1 *corev1.CoreV1Client extensionsV1beta1 *extensionsv1beta1.ExtensionsV1beta1Client networkingV1 *networkingv1.NetworkingV1Client policyV1beta1 *policyv1beta1.PolicyV1beta1Client rbacV1 *rbacv1.RbacV1Client rbacV1beta1 *rbacv1beta1.RbacV1beta1Client rbacV1alpha1 *rbacv1alpha1.RbacV1alpha1Client schedulingV1alpha1 *schedulingv1alpha1.SchedulingV1alpha1Client settingsV1alpha1 *settingsv1alpha1.SettingsV1alpha1Client storageV1beta1 *storagev1beta1.StorageV1beta1Client storageV1 *storagev1.StorageV1Client }
用 Clientset 的方法得到不一樣資源的操做句柄,Clientset有如下的方法可供使用:ui
+Admissionregistration() : admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Interface +AdmissionregistrationV1alpha1() : admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Interface +Apps() : appsv1.AppsV1Interface +AppsV1() : appsv1.AppsV1Interface +AppsV1beta1() : appsv1beta1.AppsV1beta1Interface +AppsV1beta2() : appsv1beta2.AppsV1beta2Interface +Authentication() : authenticationv1.AuthenticationV1Interface +AuthenticationV1() : authenticationv1.AuthenticationV1Interface +AuthenticationV1beta1() : authenticationv1beta1.AuthenticationV1beta1Interface +Authorization() : authorizationv1.AuthorizationV1Interface +AuthorizationV1() : authorizationv1.AuthorizationV1Interface +AuthorizationV1beta1() : authorizationv1beta1.AuthorizationV1beta1Interface +Autoscaling() : autoscalingv1.AutoscalingV1Interface +AutoscalingV1() : autoscalingv1.AutoscalingV1Interface +AutoscalingV2beta1() : autoscalingv2beta1.AutoscalingV2beta1Interface +Batch() : batchv1.BatchV1Interface +BatchV1() : batchv1.BatchV1Interface +BatchV1beta1() : batchv1beta1.BatchV1beta1Interface +BatchV2alpha1() : batchv2alpha1.BatchV2alpha1Interface +Certificates() : certificatesv1beta1.CertificatesV1beta1Interface +CertificatesV1beta1() : certificatesv1beta1.CertificatesV1beta1Interface +Core() : corev1.CoreV1Interface +CoreV1() : corev1.CoreV1Interface +Discovery() : discovery.DiscoveryInterface +Extensions() : extensionsv1beta1.ExtensionsV1beta1Interface +ExtensionsV1beta1() : extensionsv1beta1.ExtensionsV1beta1Interface +Networking() : networkingv1.NetworkingV1Interface +NetworkingV1() : networkingv1.NetworkingV1Interface +Policy() : policyv1beta1.PolicyV1beta1Interface +PolicyV1beta1() : policyv1beta1.PolicyV1beta1Interface +Rbac() : rbacv1.RbacV1Interface +RbacV1() : rbacv1.RbacV1Interface +RbacV1alpha1() : rbacv1alpha1.RbacV1alpha1Interface +RbacV1beta1() : rbacv1beta1.RbacV1beta1Interface +Scheduling() : schedulingv1alpha1.SchedulingV1alpha1Interface +SchedulingV1alpha1() : schedulingv1alpha1.SchedulingV1alpha1Interface +Settings() : settingsv1alpha1.SettingsV1alpha1Interface +SettingsV1alpha1() : settingsv1alpha1.SettingsV1alpha1Interface +Storage() : storagev1.StorageV1Interface +StorageV1() : storagev1.StorageV1Interface +StorageV1beta1() : storagev1beta1.StorageV1beta1Interface
其中Core()和CoreV1()獲取到的corev1.CoreV1Interface,用來操做kubernetes的最基礎的Resrouce。
type CoreV1Interface interface { RESTClient() rest.Interface ComponentStatusesGetter ConfigMapsGetter EndpointsGetter EventsGetter LimitRangesGetter NamespacesGetter NodesGetter PersistentVolumesGetter PersistentVolumeClaimsGetter PodsGetter PodTemplatesGetter ReplicationControllersGetter ResourceQuotasGetter SecretsGetter ServicesGetter ServiceAccountsGetter }
例如查找指定 namespace 中的全部 Pod:
pods, err := clientset.CoreV1().Pods("lijiaocn").List(v1.ListOptions{})
client-go/rest 實現了 RESTClient,RESTClient 的建立方法有兩種。
第一種方式是直接經過 config 建立,這種方式須要在 config 中填入 GroupVersion 信息:
// create restClient from config func CreateCoreRestClient(config *rest.Config) (*rest.RESTClient, error) { config.ContentConfig.GroupVersion = &core_v1.SchemeGroupVersion config.ContentConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} config.APIPath = "/api" restClient, err := rest.RESTClientFor(config) if err != nil { return nil, err } if restClient == nil { return nil, errors.New("restclient1 is nil") } return restClient, nil }
第二種方式是從 Clientset 中獲取,這種方式不須要手動填入 GroupVersion,調用 Clientset 對應的接口便可:
// get restClient from clientset func GetCoreRestClient(config *rest.Config) (rest.Interface, error) { clientset, err := kubernetes.NewForConfig(config) if err != nil { return nil, err } if clientset == nil { return nil, errors.New("clientset is nil") } restClient := clientset.CoreV1().RESTClient() if restClient == nil { return nil, errors.New("restclient is nil") } return restClient, nil }
RESTClient 是鏈式調用,使用方法以下,Do() 方法最後調用:
// /<namespace>/<resource>/<name> // GET https://10.10.173.203/api/v1/namespaces/default/pods?limit=500 // GET https://10.10.173.203/api/v1/namespaces/kube-system/pods?limit=500 // GET https://10.10.173.203/api/v1/namespaces/kube-system/pods/kube-dns-5b54cf547c-jl4r9 result := restClient.Get(). Namespace("kube-system"). Resource("pods"). Name("kube-dns-5b54cf547c-jl4r9"). Do() bytes, err := result.Raw() if err != nil { fmt.Printf("%s: %s\n", err.Error(), bytes) } else { fmt.Printf("%s\n", bytes) }
client-go 提供一套 tools,提供了配置文件加載、實現本地緩存等方法。
tools/clientcmd 中提供了一些輔助工具,例如加載 kubeconfig 文件生成建立 client 是必須的 Config:
home, err := os.UserHomeDir() if err != nil { glog.Fatal(err.Error()) } file, err := filepath.Abs(home + "/.kube/config") if err != nil { glog.Fatal(err.Error()) } config, err := clientcmd.BuildConfigFromFlags("", file) if err != nil { glog.Fatal(err.Error()) return } clientset, err := kubernetes.NewForConfig(config) if err != nil { glog.Fatal(err.Error()) return }
tools/cache 中提供了本地緩存的功能,特別是提供了 informer。
建立 informer 須要提供的 listwatcher 和 handler 都用 cache 中方法建立或在 cache 中定義:
labels := make(map[string]string) selector := fields.SelectorFromSet(labels) listwatch := cache.NewListWatchFromClient(restClient, "endpoints", "", selector)
handler 定義:
handler := cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { fmt.Printf("Add endpoint:\n") if ep, ok := obj.(*core_v1.Endpoints); !ok { fmt.Printf("not endpoints\n") } else { printEndpoint(ep) } }, UpdateFunc: func(oldObj, newObj interface{}) { fmt.Printf("Update endpoint:\n") if epOld, ok := oldObj.(*core_v1.Endpoints); !ok { fmt.Printf("not endpoints\n") } else { printEndpoint(epOld) } if epNew, ok := newObj.(*core_v1.Endpoints); !ok { fmt.Printf("not endpoints\n") } else { printEndpoint(epNew) } }, DeleteFunc: func(obj interface{}) { fmt.Printf("Delete endpoint:\n") if ep, ok := obj.(*core_v1.Endpoints); !ok { fmt.Printf("not endpoint") } else