client-go的使用及源码分析

本文个人博客地址: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 示例代码

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

client-go.go

package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	var kubeconfig *string
	if home := 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()
	// uses the current context in kubeconfig
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}
	// creates the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}
	for {
		pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})
		if err != nil {
			panic(err.Error())
		}
		fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
		time.Sleep(10 * time.Second)
	}
}

func homeDir() string {
	if h := os.Getenv("HOME"); h != "" {
		return h
	}
	return os.Getenv("USERPROFILE") // windows
}

1.3 运行结果

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

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

config内容如下:

2.2 rest.config

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

BuildConfigFromFlags函数源码

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

2.3 clientset

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

2.3.1 NewForConfig

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

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

2.3.2 clientset的结构体

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

2.3.3 clientset.Interface

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

clientset的方法集接口

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

2.4 CoreV1Client

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

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

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

2.4.1 corev1.NewForConfig

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

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

2.4.2 CoreV1Client结构体

以下是CoreV1Client结构体的定义:

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

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

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

2.4.3 CoreV1Interface

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

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

2.4.4 PodsGetter

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

示例中的代码如下:

CoreV1().Pods()

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

newPods()

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

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

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

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

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

PodsGetter

PodsGetter继承了PodInterface的接口。

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

Pods().List()

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

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

以上分析了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

2.5.1 rest.RESTClientFor

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

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

2.5.2 NewRESTClient

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

2.5.3 RESTClient结构体

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

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

2.5.4 RESTClient.Interface

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

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

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

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

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

3.1 deployment

3.2 service

3.3 ingress

3.4 replicaSet

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

3.5 pod

3.6 statefulset

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

参考文档:

  • https://github.com/kubernetes/client-go

最后更新于

这有帮助吗?