本文个人博客地址:http://www.huweihuang.com/article/source-analysis/client-go-source-analysis/

1. client-go简介

1.1 client-go说明

​ client-go是一个调用kubernetes集群资源对象API的客户端,即通过client-go实现对kubernetes集群中资源对象(包括deployment、service、ingress、replicaSet、pod、namespace、node等)的增删改查等操作。大部分对kubernetes进行前置API封装的二次开发都通过client-go这个第三方包来实现。

​ client-go官方文档:https://github.com/kubernetes/client-go

1.2 示例代码

  1. git clone https://github.com/huweihuang/client-go.git
  2. cd client-go
  3. #保证本地HOME目录有配置kubernetes集群的配置文件
  4. go run client-go.go

client-go.go

  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "time"
  8. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  9. "k8s.io/client-go/kubernetes"
  10. "k8s.io/client-go/tools/clientcmd"
  11. )
  12. func main() {
  13. var kubeconfig *string
  14. if home := homeDir(); home != "" {
  15. kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
  16. } else {
  17. kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
  18. }
  19. flag.Parse()
  20. // uses the current context in kubeconfig
  21. config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
  22. if err != nil {
  23. panic(err.Error())
  24. }
  25. // creates the clientset
  26. clientset, err := kubernetes.NewForConfig(config)
  27. if err != nil {
  28. panic(err.Error())
  29. }
  30. for {
  31. pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})
  32. if err != nil {
  33. panic(err.Error())
  34. }
  35. fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
  36. time.Sleep(10 * time.Second)
  37. }
  38. }
  39. func homeDir() string {
  40. if h := os.Getenv("HOME"); h != "" {
  41. return h
  42. }
  43. return os.Getenv("USERPROFILE") // windows
  44. }

1.3 运行结果

  1. go run client-go.go
  2. There are 9 pods in the cluster
  3. There are 7 pods in the cluster
  4. There are 7 pods in the cluster
  5. There are 7 pods in the cluster
  6. There are 7 pods in the cluster

2. client-go源码分析

client-go源码https://github.com/kubernetes/client-go

client-go源码目录结构

  • The kubernetes package contains the clientset to access Kubernetes API.
  • The discovery package is used to discover APIs supported by a Kubernetes API server.
  • The dynamic package contains a dynamic client that can perform generic operations on arbitrary Kubernetes API objects.
  • The transport package is used to set up auth and start a connection.
  • The tools/cache package is useful for writing controllers.

2.1 kubeconfig

  1. kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")

获取kubernetes配置文件kubeconfig的绝对路径。一般路径为$HOME/.kube/config。该文件主要用来配置本地连接的kubernetes集群。

config内容如下:

  1. apiVersion: v1
  2. clusters:
  3. - cluster:
  4. server: http://<kube-master-ip>:8080
  5. name: k8s
  6. contexts:
  7. - context:
  8. cluster: k8s
  9. namespace: default
  10. user: ""
  11. name: default
  12. current-context: default
  13. kind: Config
  14. preferences: {}
  15. users: []

2.2 rest.config

通过参数(master的url或者kubeconfig路径)和BuildConfigFromFlags方法来获取rest.Config对象,一般是通过参数kubeconfig的路径。

  1. config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)

BuildConfigFromFlags函数源码

k8s.io/client-go/tools/clientcmd/client_config.go

  1. // BuildConfigFromFlags is a helper function that builds configs from a master
  2. // url or a kubeconfig filepath. These are passed in as command line flags for cluster
  3. // components. Warnings should reflect this usage. If neither masterUrl or kubeconfigPath
  4. // are passed in we fallback to inClusterConfig. If inClusterConfig fails, we fallback
  5. // to the default config.
  6. func BuildConfigFromFlags(masterUrl, kubeconfigPath string) (*restclient.Config, error) {
  7. if kubeconfigPath == "" && masterUrl == "" {
  8. glog.Warningf("Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.")
  9. kubeconfig, err := restclient.InClusterConfig()
  10. if err == nil {
  11. return kubeconfig, nil
  12. }
  13. glog.Warning("error creating inClusterConfig, falling back to default config: ", err)
  14. }
  15. return NewNonInteractiveDeferredLoadingClientConfig(
  16. &ClientConfigLoadingRules{ExplicitPath: kubeconfigPath},
  17. &ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterUrl}}).ClientConfig()
  18. }

2.3 clientset

通过*rest.Config参数和NewForConfig方法来获取clientset对象,clientset是多个client的集合,每个client可能包含不同版本的方法调用。

  1. clientset, err := kubernetes.NewForConfig(config)

2.3.1 NewForConfig

NewForConfig函数就是初始化clientset中的每个client。

k8s.io/client-go/kubernetes/clientset.go

  1. // NewForConfig creates a new Clientset for the given config.
  2. func NewForConfig(c *rest.Config) (*Clientset, error) {
  3. configShallowCopy := *c
  4. ...
  5. var cs Clientset
  6. cs.appsV1beta1, err = appsv1beta1.NewForConfig(&configShallowCopy)
  7. ...
  8. cs.coreV1, err = corev1.NewForConfig(&configShallowCopy)
  9. ...
  10. }

2.3.2 clientset的结构体

k8s.io/client-go/kubernetes/clientset.go

  1. // Clientset contains the clients for groups. Each group has exactly one
  2. // version included in a Clientset.
  3. type Clientset struct {
  4. *discovery.DiscoveryClient
  5. admissionregistrationV1alpha1 *admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Client
  6. appsV1beta1 *appsv1beta1.AppsV1beta1Client
  7. appsV1beta2 *appsv1beta2.AppsV1beta2Client
  8. authenticationV1 *authenticationv1.AuthenticationV1Client
  9. authenticationV1beta1 *authenticationv1beta1.AuthenticationV1beta1Client
  10. authorizationV1 *authorizationv1.AuthorizationV1Client
  11. authorizationV1beta1 *authorizationv1beta1.AuthorizationV1beta1Client
  12. autoscalingV1 *autoscalingv1.AutoscalingV1Client
  13. autoscalingV2beta1 *autoscalingv2beta1.AutoscalingV2beta1Client
  14. batchV1 *batchv1.BatchV1Client
  15. batchV1beta1 *batchv1beta1.BatchV1beta1Client
  16. batchV2alpha1 *batchv2alpha1.BatchV2alpha1Client
  17. certificatesV1beta1 *certificatesv1beta1.CertificatesV1beta1Client
  18. coreV1 *corev1.CoreV1Client
  19. extensionsV1beta1 *extensionsv1beta1.ExtensionsV1beta1Client
  20. networkingV1 *networkingv1.NetworkingV1Client
  21. policyV1beta1 *policyv1beta1.PolicyV1beta1Client
  22. rbacV1 *rbacv1.RbacV1Client
  23. rbacV1beta1 *rbacv1beta1.RbacV1beta1Client
  24. rbacV1alpha1 *rbacv1alpha1.RbacV1alpha1Client
  25. schedulingV1alpha1 *schedulingv1alpha1.SchedulingV1alpha1Client
  26. settingsV1alpha1 *settingsv1alpha1.SettingsV1alpha1Client
  27. storageV1beta1 *storagev1beta1.StorageV1beta1Client
  28. storageV1 *storagev1.StorageV1Client
  29. }

2.3.3 clientset.Interface

clientset实现了以下的Interface,因此可以通过调用以下方法获得具体的client。例如:

  1. pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})

clientset的方法集接口

k8s.io/client-go/kubernetes/clientset.go

  1. type Interface interface {
  2. Discovery() discovery.DiscoveryInterface
  3. AdmissionregistrationV1alpha1() admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Interface
  4. // Deprecated: please explicitly pick a version if possible.
  5. Admissionregistration() admissionregistrationv1alpha1.AdmissionregistrationV1alpha1Interface
  6. AppsV1beta1() appsv1beta1.AppsV1beta1Interface
  7. AppsV1beta2() appsv1beta2.AppsV1beta2Interface
  8. // Deprecated: please explicitly pick a version if possible.
  9. Apps() appsv1beta2.AppsV1beta2Interface
  10. AuthenticationV1() authenticationv1.AuthenticationV1Interface
  11. // Deprecated: please explicitly pick a version if possible.
  12. Authentication() authenticationv1.AuthenticationV1Interface
  13. AuthenticationV1beta1() authenticationv1beta1.AuthenticationV1beta1Interface
  14. AuthorizationV1() authorizationv1.AuthorizationV1Interface
  15. // Deprecated: please explicitly pick a version if possible.
  16. Authorization() authorizationv1.AuthorizationV1Interface
  17. AuthorizationV1beta1() authorizationv1beta1.AuthorizationV1beta1Interface
  18. AutoscalingV1() autoscalingv1.AutoscalingV1Interface
  19. // Deprecated: please explicitly pick a version if possible.
  20. Autoscaling() autoscalingv1.AutoscalingV1Interface
  21. AutoscalingV2beta1() autoscalingv2beta1.AutoscalingV2beta1Interface
  22. BatchV1() batchv1.BatchV1Interface
  23. // Deprecated: please explicitly pick a version if possible.
  24. Batch() batchv1.BatchV1Interface
  25. BatchV1beta1() batchv1beta1.BatchV1beta1Interface
  26. BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface
  27. CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface
  28. // Deprecated: please explicitly pick a version if possible.
  29. Certificates() certificatesv1beta1.CertificatesV1beta1Interface
  30. CoreV1() corev1.CoreV1Interface
  31. // Deprecated: please explicitly pick a version if possible.
  32. Core() corev1.CoreV1Interface
  33. ExtensionsV1beta1() extensionsv1beta1.ExtensionsV1beta1Interface
  34. // Deprecated: please explicitly pick a version if possible.
  35. Extensions() extensionsv1beta1.ExtensionsV1beta1Interface
  36. NetworkingV1() networkingv1.NetworkingV1Interface
  37. // Deprecated: please explicitly pick a version if possible.
  38. Networking() networkingv1.NetworkingV1Interface
  39. PolicyV1beta1() policyv1beta1.PolicyV1beta1Interface
  40. // Deprecated: please explicitly pick a version if possible.
  41. Policy() policyv1beta1.PolicyV1beta1Interface
  42. RbacV1() rbacv1.RbacV1Interface
  43. // Deprecated: please explicitly pick a version if possible.
  44. Rbac() rbacv1.RbacV1Interface
  45. RbacV1beta1() rbacv1beta1.RbacV1beta1Interface
  46. RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface
  47. SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface
  48. // Deprecated: please explicitly pick a version if possible.
  49. Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface
  50. SettingsV1alpha1() settingsv1alpha1.SettingsV1alpha1Interface
  51. // Deprecated: please explicitly pick a version if possible.
  52. Settings() settingsv1alpha1.SettingsV1alpha1Interface
  53. StorageV1beta1() storagev1beta1.StorageV1beta1Interface
  54. StorageV1() storagev1.StorageV1Interface
  55. // Deprecated: please explicitly pick a version if possible.
  56. Storage() storagev1.StorageV1Interface
  57. }

2.4 CoreV1Client

我们以clientset中的CoreV1Client为例做分析。

通过传入的配置信息rest.Config初始化CoreV1Client对象。

k8s.io/client-go/kubernetes/clientset.go

  1. cs.coreV1, err = corev1.NewForConfig(&configShallowCopy)

2.4.1 corev1.NewForConfig

k8s.io/client-go/kubernetes/typed/core/v1/core_client.go

  1. // NewForConfig creates a new CoreV1Client for the given config.
  2. func NewForConfig(c *rest.Config) (*CoreV1Client, error) {
  3. config := *c
  4. if err := setConfigDefaults(&config); err != nil {
  5. return nil, err
  6. }
  7. client, err := rest.RESTClientFor(&config)
  8. if err != nil {
  9. return nil, err
  10. }
  11. return &CoreV1Client{client}, nil
  12. }

corev1.NewForConfig方法本质是调用了rest.RESTClientFor(&config)方法创建RESTClient对象,即CoreV1Client的本质就是一个RESTClient对象。

2.4.2 CoreV1Client结构体

以下是CoreV1Client结构体的定义:

k8s.io/client-go/kubernetes/typed/core/v1/core_client.go

  1. // CoreV1Client is used to interact with features provided by the group.
  2. type CoreV1Client struct {
  3. restClient rest.Interface
  4. }

CoreV1Client实现了CoreV1Interface的接口,即以下方法,从而对kubernetes的资源对象进行增删改查的操作。

k8s.io/client-go/kubernetes/typed/core/v1/core_client.go

  1. //CoreV1Client的方法
  2. func (c *CoreV1Client) ComponentStatuses() ComponentStatusInterface {...}
  3. //ConfigMaps
  4. func (c *CoreV1Client) ConfigMaps(namespace string) ConfigMapInterface {...}
  5. //Endpoints
  6. func (c *CoreV1Client) Endpoints(namespace string) EndpointsInterface {...}
  7. func (c *CoreV1Client) Events(namespace string) EventInterface {...}
  8. func (c *CoreV1Client) LimitRanges(namespace string) LimitRangeInterface {...}
  9. //Namespaces
  10. func (c *CoreV1Client) Namespaces() NamespaceInterface {...}
  11. //Nodes
  12. func (c *CoreV1Client) Nodes() NodeInterface {...}
  13. func (c *CoreV1Client) PersistentVolumes() PersistentVolumeInterface {...}
  14. func (c *CoreV1Client) PersistentVolumeClaims(namespace string) PersistentVolumeClaimInterface {...}
  15. //Pods
  16. func (c *CoreV1Client) Pods(namespace string) PodInterface {...}
  17. func (c *CoreV1Client) PodTemplates(namespace string) PodTemplateInterface {...}
  18. //ReplicationControllers
  19. func (c *CoreV1Client) ReplicationControllers(namespace string) ReplicationControllerInterface {...}
  20. func (c *CoreV1Client) ResourceQuotas(namespace string) ResourceQuotaInterface {...}
  21. func (c *CoreV1Client) Secrets(namespace string) SecretInterface {...}
  22. //Services
  23. func (c *CoreV1Client) Services(namespace string) ServiceInterface {...}
  24. func (c *CoreV1Client) ServiceAccounts(namespace string) ServiceAccountInterface {...}

2.4.3 CoreV1Interface

k8s.io/client-go/kubernetes/typed/core/v1/core_client.go

  1. type CoreV1Interface interface {
  2. RESTClient() rest.Interface
  3. ComponentStatusesGetter
  4. ConfigMapsGetter
  5. EndpointsGetter
  6. EventsGetter
  7. LimitRangesGetter
  8. NamespacesGetter
  9. NodesGetter
  10. PersistentVolumesGetter
  11. PersistentVolumeClaimsGetter
  12. PodsGetter
  13. PodTemplatesGetter
  14. ReplicationControllersGetter
  15. ResourceQuotasGetter
  16. SecretsGetter
  17. ServicesGetter
  18. ServiceAccountsGetter
  19. }

CoreV1Interface中包含了各种kubernetes对象的调用接口,例如PodsGetter是对kubernetes中pod对象增删改查操作的接口。ServicesGetter是对service对象的操作的接口。

2.4.4 PodsGetter

以下我们以PodsGetter接口为例分析CoreV1Clientpod对象的增删改查接口调用。

示例中的代码如下:

  1. pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})

CoreV1().Pods()

k8s.io/client-go/kubernetes/typed/core/v1/core_client.go

  1. func (c *CoreV1Client) Pods(namespace string) PodInterface {
  2. return newPods(c, namespace)
  3. }

newPods()

k8s.io/client-go/kubernetes/typed/core/v1/pod.go

  1. // newPods returns a Pods
  2. func newPods(c *CoreV1Client, namespace string) *pods {
  3. return &pods{
  4. client: c.RESTClient(),
  5. ns: namespace,
  6. }
  7. }

CoreV1().Pods()的方法实际上是调用了newPods()的方法,创建了一个pods对象,pods对象继承了rest.Interface接口,即最终的实现本质是RESTClient的HTTP调用。

k8s.io/client-go/kubernetes/typed/core/v1/pod.go

  1. // pods implements PodInterface
  2. type pods struct {
  3. client rest.Interface
  4. ns string
  5. }

pods对象实现了PodInterface接口。PodInterface定义了pods对象的增删改查等方法。

k8s.io/client-go/kubernetes/typed/core/v1/pod.go

  1. // PodInterface has methods to work with Pod resources.
  2. type PodInterface interface {
  3. Create(*v1.Pod) (*v1.Pod, error)
  4. Update(*v1.Pod) (*v1.Pod, error)
  5. UpdateStatus(*v1.Pod) (*v1.Pod, error)
  6. Delete(name string, options *meta_v1.DeleteOptions) error
  7. DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error
  8. Get(name string, options meta_v1.GetOptions) (*v1.Pod, error)
  9. List(opts meta_v1.ListOptions) (*v1.PodList, error)
  10. Watch(opts meta_v1.ListOptions) (watch.Interface, error)
  11. Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Pod, err error)
  12. PodExpansion
  13. }

PodsGetter

PodsGetter继承了PodInterface的接口。

k8s.io/client-go/kubernetes/typed/core/v1/pod.go

  1. // PodsGetter has a method to return a PodInterface.
  2. // A group's client should implement this interface.
  3. type PodsGetter interface {
  4. Pods(namespace string) PodInterface
  5. }

Pods().List()

pods.List()方法通过RESTClient的HTTP调用来实现对kubernetes的pod资源的获取。

k8s.io/client-go/kubernetes/typed/core/v1/pod.go

  1. // List takes label and field selectors, and returns the list of Pods that match those selectors.
  2. func (c *pods) List(opts meta_v1.ListOptions) (result *v1.PodList, err error) {
  3. result = &v1.PodList{}
  4. err = c.client.Get().
  5. Namespace(c.ns).
  6. Resource("pods").
  7. VersionedParams(&opts, scheme.ParameterCodec).
  8. Do().
  9. Into(result)
  10. return
  11. }

以上分析了clientset.CoreV1().Pods("").List(metav1.ListOptions{})对pod资源获取的过程,最终是调用RESTClient的方法实现。

2.5 RESTClient

以下分析RESTClient的创建过程及作用。

RESTClient对象的创建同样是依赖传入的config信息。

k8s.io/client-go/kubernetes/typed/core/v1/core_client.go

  1. client, err := rest.RESTClientFor(&config)

2.5.1 rest.RESTClientFor

k8s.io/client-go/rest/config.go

  1. // RESTClientFor returns a RESTClient that satisfies the requested attributes on a client Config
  2. // object. Note that a RESTClient may require fields that are optional when initializing a Client.
  3. // A RESTClient created by this method is generic - it expects to operate on an API that follows
  4. // the Kubernetes conventions, but may not be the Kubernetes API.
  5. func RESTClientFor(config *Config) (*RESTClient, error) {
  6. ...
  7. qps := config.QPS
  8. ...
  9. burst := config.Burst
  10. ...
  11. baseURL, versionedAPIPath, err := defaultServerUrlFor(config)
  12. ...
  13. transport, err := TransportFor(config)
  14. ...
  15. var httpClient *http.Client
  16. if transport != http.DefaultTransport {
  17. httpClient = &http.Client{Transport: transport}
  18. if config.Timeout > 0 {
  19. httpClient.Timeout = config.Timeout
  20. }
  21. }
  22. return NewRESTClient(baseURL, versionedAPIPath, config.ContentConfig, qps, burst, config.RateLimiter, httpClient)
  23. }

RESTClientFor函数调用了NewRESTClient的初始化函数。

2.5.2 NewRESTClient

k8s.io/client-go/rest/client.go

  1. // NewRESTClient creates a new RESTClient. This client performs generic REST functions
  2. // such as Get, Put, Post, and Delete on specified paths. Codec controls encoding and
  3. // decoding of responses from the server.
  4. func NewRESTClient(baseURL *url.URL, versionedAPIPath string, config ContentConfig, maxQPS float32, maxBurst int, rateLimiter flowcontrol.RateLimiter, client *http.Client) (*RESTClient, error) {
  5. base := *baseURL
  6. ...
  7. serializers, err := createSerializers(config)
  8. ...
  9. return &RESTClient{
  10. base: &base,
  11. versionedAPIPath: versionedAPIPath,
  12. contentConfig: config,
  13. serializers: *serializers,
  14. createBackoffMgr: readExpBackoffConfig,
  15. Throttle: throttle,
  16. Client: client,
  17. }, nil
  18. }

2.5.3 RESTClient结构体

以下介绍RESTClient的结构体定义,RESTClient结构体中包含了http.Client,即本质上RESTClient就是一个http.Client的封装实现。

k8s.io/client-go/rest/client.go

  1. // RESTClient imposes common Kubernetes API conventions on a set of resource paths.
  2. // The baseURL is expected to point to an HTTP or HTTPS path that is the parent
  3. // of one or more resources. The server should return a decodable API resource
  4. // object, or an api.Status object which contains information about the reason for
  5. // any failure.
  6. //
  7. // Most consumers should use client.New() to get a Kubernetes API client.
  8. type RESTClient struct {
  9. // base is the root URL for all invocations of the client
  10. base *url.URL
  11. // versionedAPIPath is a path segment connecting the base URL to the resource root
  12. versionedAPIPath string
  13. // contentConfig is the information used to communicate with the server.
  14. contentConfig ContentConfig
  15. // serializers contain all serializers for underlying content type.
  16. serializers Serializers
  17. // creates BackoffManager that is passed to requests.
  18. createBackoffMgr func() BackoffManager
  19. // TODO extract this into a wrapper interface via the RESTClient interface in kubectl.
  20. Throttle flowcontrol.RateLimiter
  21. // Set specific behavior of the client. If not set http.DefaultClient will be used.
  22. Client *http.Client
  23. }

2.5.4 RESTClient.Interface

RESTClient实现了以下的接口方法:

k8s.io/client-go/rest/client.go

  1. // Interface captures the set of operations for generically interacting with Kubernetes REST apis.
  2. type Interface interface {
  3. GetRateLimiter() flowcontrol.RateLimiter
  4. Verb(verb string) *Request
  5. Post() *Request
  6. Put() *Request
  7. Patch(pt types.PatchType) *Request
  8. Get() *Request
  9. Delete() *Request
  10. APIVersion() schema.GroupVersion
  11. }

在调用HTTP方法(Post(),Put(),Get(),Delete() )时,实际上调用了Verb(verb string)函数。

k8s.io/client-go/rest/client.go

  1. // Verb begins a request with a verb (GET, POST, PUT, DELETE).
  2. //
  3. // Example usage of RESTClient's request building interface:
  4. // c, err := NewRESTClient(...)
  5. // if err != nil { ... }
  6. // resp, err := c.Verb("GET").
  7. // Path("pods").
  8. // SelectorParam("labels", "area=staging").
  9. // Timeout(10*time.Second).
  10. // Do()
  11. // if err != nil { ... }
  12. // list, ok := resp.(*api.PodList)
  13. //
  14. func (c *RESTClient) Verb(verb string) *Request {
  15. backoff := c.createBackoffMgr()
  16. if c.Client == nil {
  17. return NewRequest(nil, verb, c.base, c.versionedAPIPath, c.contentConfig, c.serializers, backoff, c.Throttle)
  18. }
  19. return NewRequest(c.Client, verb, c.base, c.versionedAPIPath, c.contentConfig, c.serializers, backoff, c.Throttle)
  20. }

Verb函数调用了NewRequest方法,最后调用Do()方法实现一个HTTP请求获取Result。

2.6 总结

client-go对kubernetes资源对象的调用,需要先获取kubernetes的配置信息,即$HOME/.kube/config

整个调用的过程如下:

kubeconfig→rest.config→clientset→具体的client(CoreV1Client)→具体的资源对象(pod)→RESTClient→http.Client→HTTP请求的发送及响应

通过clientset中不同的client和client中不同资源对象的方法实现对kubernetes中资源对象的增删改查等操作,常用的client有CoreV1ClientAppsV1beta1ClientExtensionsV1beta1Client等。

3. client-go对k8s资源的调用

创建clientset

  1. //获取kubeconfig
  2. kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
  3. //创建config
  4. config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
  5. //创建clientset
  6. clientset, err := kubernetes.NewForConfig(config)
  7. //具体的资源调用见以下例子

3.1 deployment

  1. //声明deployment对象
  2. var deployment *v1beta1.Deployment
  3. //构造deployment对象
  4. //创建deployment
  5. deployment, err := clientset.AppsV1beta1().Deployments(<namespace>).Create(<deployment>)
  6. //更新deployment
  7. deployment, err := clientset.AppsV1beta1().Deployments(<namespace>).Update(<deployment>)
  8. //删除deployment
  9. err := clientset.AppsV1beta1().Deployments(<namespace>).Delete(<deployment.Name>, &meta_v1.DeleteOptions{})
  10. //查询deployment
  11. deployment, err := clientset.AppsV1beta1().Deployments(<namespace>).Get(<deployment.Name>, meta_v1.GetOptions{})
  12. //列出deployment
  13. deploymentList, err := clientset.AppsV1beta1().Deployments(<namespace>).List(&meta_v1.ListOptions{})
  14. //watch deployment
  15. watchInterface, err := clientset.AppsV1beta1().Deployments(<namespace>).Watch(&meta_v1.ListOptions{})

3.2 service

  1. //声明service对象
  2. var service *v1.Service
  3. //构造service对象
  4. //创建service
  5. service, err := clientset.CoreV1().Services(<namespace>).Create(<service>)
  6. //更新service
  7. service, err := clientset.CoreV1().Services(<namespace>).Update(<service>)
  8. //删除service
  9. err := clientset.CoreV1().Services(<namespace>).Delete(<service.Name>, &meta_v1.DeleteOptions{})
  10. //查询service
  11. service, err := clientset.CoreV1().Services(<namespace>).Get(<service.Name>, meta_v1.GetOptions{})
  12. //列出service
  13. serviceList, err := clientset.CoreV1().Services(<namespace>).List(&meta_v1.ListOptions{})
  14. //watch service
  15. watchInterface, err := clientset.CoreV1().Services(<namespace>).Watch(&meta_v1.ListOptions{})

3.3 ingress

  1. //声明ingress对象
  2. var ingress *v1beta1.Ingress
  3. //构造ingress对象
  4. //创建ingress
  5. ingress, err := clientset.ExtensionsV1beta1().Ingresses(<namespace>).Create(<ingress>)
  6. //更新ingress
  7. ingress, err := clientset.ExtensionsV1beta1().Ingresses(<namespace>).Update(<ingress>)
  8. //删除ingress
  9. err := clientset.ExtensionsV1beta1().Ingresses(<namespace>).Delete(<ingress.Name>, &meta_v1.DeleteOptions{})
  10. //查询ingress
  11. ingress, err := clientset.ExtensionsV1beta1().Ingresses(<namespace>).Get(<ingress.Name>, meta_v1.GetOptions{})
  12. //列出ingress
  13. ingressList, err := clientset.ExtensionsV1beta1().Ingresses(<namespace>).List(&meta_v1.ListOptions{})
  14. //watch ingress
  15. watchInterface, err := clientset.ExtensionsV1beta1().Ingresses(<namespace>).Watch(&meta_v1.ListOptions{})

3.4 replicaSet

  1. //声明replicaSet对象
  2. var replicaSet *v1beta1.ReplicaSet
  3. //构造replicaSet对象
  4. //创建replicaSet
  5. replicaSet, err := clientset.ExtensionsV1beta1().ReplicaSets(<namespace>).Create(<replicaSet>)
  6. //更新replicaSet
  7. replicaSet, err := clientset.ExtensionsV1beta1().ReplicaSets(<namespace>).Update(<replicaSet>)
  8. //删除replicaSet
  9. err := clientset.ExtensionsV1beta1().ReplicaSets(<namespace>).Delete(<replicaSet.Name>, &meta_v1.DeleteOptions{})
  10. //查询replicaSet
  11. replicaSet, err := clientset.ExtensionsV1beta1().ReplicaSets(<namespace>).Get(<replicaSet.Name>, meta_v1.GetOptions{})
  12. //列出replicaSet
  13. replicaSetList, err := clientset.ExtensionsV1beta1().ReplicaSets(<namespace>).List(&meta_v1.ListOptions{})
  14. //watch replicaSet
  15. watchInterface, err := clientset.ExtensionsV1beta1().ReplicaSets(<namespace>).Watch(&meta_v1.ListOptions{})

新版的kubernetes中一般通过deployment来创建replicaSet,再通过replicaSet来控制pod。

3.5 pod

  1. //声明pod对象
  2. var pod *v1.Pod
  3. //创建pod
  4. pod, err := clientset.CoreV1().Pods(<namespace>).Create(<pod>)
  5. //更新pod
  6. pod, err := clientset.CoreV1().Pods(<namespace>).Update(<pod>)
  7. //删除pod
  8. err := clientset.CoreV1().Pods(<namespace>).Delete(<pod.Name>, &meta_v1.DeleteOptions{})
  9. //查询pod
  10. pod, err := clientset.CoreV1().Pods(<namespace>).Get(<pod.Name>, meta_v1.GetOptions{})
  11. //列出pod
  12. podList, err := clientset.CoreV1().Pods(<namespace>).List(&meta_v1.ListOptions{})
  13. //watch pod
  14. watchInterface, err := clientset.CoreV1().Pods(<namespace>).Watch(&meta_v1.ListOptions{})

3.6 statefulset

  1. //声明statefulset对象
  2. var statefulset *v1.StatefulSet
  3. //创建statefulset
  4. statefulset, err := clientset.AppsV1().StatefulSets(<namespace>).Create(<statefulset>)
  5. //更新statefulset
  6. statefulset, err := clientset.AppsV1().StatefulSets(<namespace>).Update(<statefulset>)
  7. //删除statefulset
  8. err := clientset.AppsV1().StatefulSets(<namespace>).Delete(<statefulset.Name>, &meta_v1.DeleteOptions{})
  9. //查询statefulset
  10. statefulset, err := clientset.AppsV1().StatefulSets(<namespace>).Get(<statefulset.Name>, meta_v1.GetOptions{})
  11. //列出statefulset
  12. statefulsetList, err := clientset.AppsV1().StatefulSets(<namespace>).List(&meta_v1.ListOptions{})
  13. //watch statefulset
  14. watchInterface, err := clientset.AppsV1().StatefulSets(<namespace>).Watch(&meta_v1.ListOptions{})

​ 通过以上对kubernetes的资源对象的操作函数可以看出,每个资源对象都有增删改查等方法,基本调用逻辑类似。一般二次开发只需要创建deployment、service、ingress三个资源对象即可,pod对象由deployment包含的replicaSet来控制创建和删除。函数调用的入参一般只有NAMESPACEkubernetesObject两个参数,部分操作有Options的参数。在创建前,需要对资源对象构造数据,可以理解为编辑一个资源对象的yaml文件,然后通过kubectl create -f xxx.yaml来创建对象。

参考文档: