显然,dynamicClient还需要用户自己设置resource资源。其实更多的时候用户只是希望如果要操作pod,那么生成一个podClient;如果要操作service,那么 生成一个serviceClient。ClientSet就是满足用户的这种需要。

ClientSet

ClientSet是多个Client的集合,定义在/pkg/client/clientset_generated/release_1_5/clientset.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset.
//***Fankang***//
//***v1.5中的client***//
type Clientset struct {
*discovery.DiscoveryClient
*v1core.CoreV1Client
*v1beta1apps.AppsV1beta1Client
*v1beta1authentication.AuthenticationV1beta1Client
*v1beta1authorization.AuthorizationV1beta1Client
*v1autoscaling.AutoscalingV1Client
*v1batch.BatchV1Client
*v2alpha1batch.BatchV2alpha1Client
*v1alpha1certificates.CertificatesV1alpha1Client
*v1beta1extensions.ExtensionsV1beta1Client
*v1beta1policy.PolicyV1beta1Client
*v1alpha1rbac.RbacV1alpha1Client
*v1beta1storage.StorageV1beta1Client
}

可以看到ClientSet是按包来组织Client的。

再来看下ClientSet的生成函数。NewForConfig()可以生成一个ClientSet。可以看出,在NewForConfig()中调用了各子client的生成函数,如CoreV1Client通过v1core.NewForConfig(&configShallowCopy)生成,后面的文章将以CoreV1Client为例展示ClientSet的各种操作。

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
// NewForConfig creates a new Clientset for the given config.
func NewForConfig(c *restclient.Config) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var clientset Clientset
var err error
clientset.CoreV1Client, err = v1core.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.AppsV1beta1Client, err = v1beta1apps.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.AuthenticationV1beta1Client, err = v1beta1authentication.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.AuthorizationV1beta1Client, err = v1beta1authorization.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.AutoscalingV1Client, err = v1autoscaling.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.BatchV1Client, err = v1batch.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.BatchV2alpha1Client, err = v2alpha1batch.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.CertificatesV1alpha1Client, err = v1alpha1certificates.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.ExtensionsV1beta1Client, err = v1beta1extensions.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.PolicyV1beta1Client, err = v1beta1policy.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.RbacV1alpha1Client, err = v1alpha1rbac.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.StorageV1beta1Client, err = v1beta1storage.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
clientset.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
if err != nil {
glog.Errorf("failed to create the DiscoveryClient: %v", err)
return nil, err
}
return &clientset, nil
}

ClientSet可以通过Core()方法获取CoreV1Client:

1
2
3
4
5
6
7
//***Core()返回Core***//
func (c *Clientset) Core() v1core.CoreV1Interface {
if c == nil {
return nil
}
return c.CoreV1Client
}

CoreV1Client

CoreV1Client定义在/pkg/client/clientset_generated/release_1_5/typed/core/v1/core_client.go中,可以通过NewForConfig()返回一个CoreV1Client:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// CoreV1Client is used to interact with features provided by the k8s.io/kubernetes/pkg/apimachinery/registered.Group group.
type CoreV1Client struct {
restClient restclient.Interface
}
// NewForConfig creates a new CoreV1Client for the given config.
func NewForConfig(c *restclient.Config) (*CoreV1Client, error) {
config := *c
//***在config上设置上core v1的配置***//
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
//***生成RESTClient***//
client, err := restclient.RESTClientFor(&config)
if err != nil {
return nil, err
}
//***返回CoreV1Client***//
return &CoreV1Client{client}, nil
}

NewForConfig()先通过setConfigDefaults()设置config,然后调用restclient.RESTClientFor()生成RESTClient,最后把RESTClient封装成CoreV1Client并返回。

setConfigDefaults()定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//***设置coreV1Client的config***//
func setConfigDefaults(config *restclient.Config) error {
gv, err := unversioned.ParseGroupVersion("/v1")
if err != nil {
return err
}
// if /v1 is not enabled, return an error
if !registered.IsEnabledVersion(gv) {
return fmt.Errorf("/v1 is not enabled")
}
config.APIPath = "/api"
if config.UserAgent == "" {
config.UserAgent = restclient.DefaultKubernetesUserAgent()
}
copyGroupVersion := gv
config.GroupVersion = &copyGroupVersion
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
return nil
}

可以看出,setConfigDefaults()把config的APIPath字段设置为”/api”,GroupVersion字段设置为对应的gv。

CoreV1Client定义有Nodes(),Pods(),PersistentVolumes()等方法,以Pods()为例:

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

可以看到Pods中调用了newPods(c, namespace)生成一个pods,pods可以对”pods”资源进行各种操作。

pods

pods定义在/pkg/client/clientset_generated/release_1_5/typed/core/v1/pod.go中:

1
2
3
4
5
6
7
8
9
10
11
12
13
// pods implements PodInterface
type pods struct {
client restclient.Interface
ns string
}
// newPods returns a Pods
func newPods(c *CoreV1Client, namespace string) *pods {
return &pods{
client: c.RESTClient(),
ns: namespace,
}
}

可以看到pods包含一个RESTClient和ns(即namespace)。

再来看下pods的成员方法,这些成员方法都调用了RESTClient:

Create()

1
2
3
4
5
6
7
8
9
10
11
// Create takes the representation of a pod and creates it. Returns the server's representation of the pod, and an error, if there is any.
func (c *pods) Create(pod *v1.Pod) (result *v1.Pod, err error) {
result = &v1.Pod{}
err = c.client.Post().
Namespace(c.ns).
Resource("pods").
Body(pod).
Do().
Into(result)
return
}

Update()

1
2
3
4
5
6
7
8
9
10
11
12
// Update takes the representation of a pod and updates it. Returns the server's representation of the pod, and an error, if there is any.
func (c *pods) Update(pod *v1.Pod) (result *v1.Pod, err error) {
result = &v1.Pod{}
err = c.client.Put().
Namespace(c.ns).
Resource("pods").
Name(pod.Name).
Body(pod).
Do().
Into(result)
return
}

Delete()

1
2
3
4
5
6
7
8
9
10
// Delete takes name of the pod and deletes it. Returns an error if one occurs.
func (c *pods) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("pods").
Name(name).
Body(options).
Do().
Error()
}

Get()

1
2
3
4
5
6
7
8
9
10
11
// Get takes name of the pod, and returns the corresponding pod object, and an error if there is any.
func (c *pods) Get(name string) (result *v1.Pod, err error) {
result = &v1.Pod{}
err = c.client.Get().
Namespace(c.ns).
Resource("pods").
Name(name).
Do().
Into(result)
return
}

List()

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

Watch()

1
2
3
4
5
6
7
8
9
// Watch returns a watch.Interface that watches the requested pods.
func (c *pods) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.client.Get().
Prefix("watch").
Namespace(c.ns).
Resource("pods").
VersionedParams(&opts, api.ParameterCodec).
Watch()
}

Patch()

1
2
3
4
5
6
7
8
9
10
11
12
13
// Patch applies the patch and returns the patched pod.
func (c *pods) Patch(name string, pt api.PatchType, data []byte, subresources ...string) (result *v1.Pod, err error) {
result = &v1.Pod{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("pods").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

例子

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
package main
import (
"flag"
"fmt"
apiv1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
kubeconfig := flag.String("kubeconfig", "/root/.kube/config", "Path to a kube config. Only required if out-of-cluster.")
fmt.Println(kubeconfig)
flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
fmt.Println("error")
}
// 生成clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
fmt.Println("error")
}
// 生成podCLient
podClient := clientset.Core().Pods("")
pods, err := podClient.List(apiv1.ListOptions{})
if err != nil {
fmt.Println("error")
}
for _, pod := range pods.Items {
fmt.Println(pod)
}
}