您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何進行k8s-client-go源碼剖析,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
Plain Text
1
[root@normal11 k8s-client-go]# tree . -L 1
2
.
3
├── CHANGELOG.md
4
├── code-of-conduct.md
5
├── CONTRIBUTING.md
6
├── discovery
7
├── dynamic
8
├── examples
9
├── Godeps
10
├── go.mod
11
├── go.sum
12
├── informers
13
├── INSTALL.md
14
├── kubernetes
15
├── kubernetes_test
16
├── LICENSE
17
├── listers
18
├── metadata
19
├── OWNERS
20
├── pkg
21
├── plugin
22
├── README.md
23
├── rest
24
├── restmapper
25
├── scale
26
├── SECURITY_CONTACTS
27
├── testing
28
├── third_party
29
├── tools
30
├── transport
31
└── util
32
33
client-go代碼庫已經集成到了Kubernetes源碼中,所以書本中展示的內容是在Kubernetes源碼中源碼結構,而這里展示的是Client-go代碼庫中原始的內容,所以多了一些源碼之外的內容,例如README、example、go.mod等。下面講一下各個目錄的作用,內容引自書本:
編輯
刪除
下圖是一個簡單的總結,其中ClientSet、DynamicClient、DiscoveryClient都是基于RESTClient封裝的。
最基礎的客戶端,對HTTP Request進行了封裝,實現了RESTFul風格的API。
案例代碼:
Plain Text
1
package main
2
3
import (
4
"fmt"
5
6
corev1 "k8s.io/api/core/v1"
7
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8
"k8s.io/client-go/kubernetes/scheme"
9
"k8s.io/client-go/rest"
10
"k8s.io/client-go/tools/clientcmd"
11
)
12
13
func main() {
14
config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
15
if err != nil {
16
panic(err.Error())
17
}
18
19
config.APIPath = "api"
20
config.GroupVersion = &corev1.SchemeGroupVersion
21
config.NegotiatedSerializer = scheme.Codecs
22
23
restClient, err := rest.RESTClientFor(config)
24
if err != nil {
25
panic(err.Error())
26
}
27
28
result := &corev1.NodeList{}
29
err = restClient.Get().Namespace("").Resource("nodes").VersionedParams(&metav1.ListOptions{Limit: 100}, scheme.ParameterCodec).Do().Into(result)
30
if err != nil {
31
panic(err)
32
}
33
34
for _, d := range result.Items {
35
fmt.Printf("Node Name %v \n", d.Name)
36
}
37
}
38
39
預期運行結果將會打印K8S集群中的node
對RESTClient進行了對象分類方式的封裝,可以實例化特定資源的客戶端,
以Resource和Version的方式暴露。例如實例化一個只操作appsv1版本的Deploy客戶端,
ClientSet可以認為是一系列資源的集合客戶端。缺點是不能直接訪問CRD。
通過client-gen代碼生成器生成帶有CRD資源的ClientSet后可以訪問CRD資源。(未測試)
案例代碼:
Plain Text
1
package main
2
3
import (
4
apiv1 "k8s.io/api/core/v1"
5
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
6
"k8s.io/client-go/kubernetes"
7
"k8s.io/client-go/tools/clientcmd"
8
)
9
10
func main() {
11
config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
12
if err != nil {
13
panic(err)
14
}
15
clientset, err := kubernetes.NewForConfig(config)
16
if err != nil {
17
panic(err)
18
}
19
20
podClient := clientset.CoreV1().Pods(apiv1.NamespaceDefault)
21
22
list, err := podClient.List(metav1.ListOptions{Limit: 500})
23
if err != nil {
24
panic(err)
25
}
26
for _, d := range list.Items {
27
if d.Name == "" {
28
}
29
// fmt.Printf("NAME:%v \t NAME:%v \t STATUS: %+v\n ", d.Namespace, d.Name, d.Status)
30
}
31
32
//請求namespace為default下的deploy
33
deploymentClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault)
34
deployList, err2 := deploymentClient.List(metav1.ListOptions{Limit: 500})
35
if err2 != nil {
36
panic(err2)
37
}
38
for _, d := range deployList.Items {
39
if d.Name == "" {
40
41
}
42
// fmt.Printf("NAME:%v \t NAME:%v \t STATUS: %+v\n ", d.Namespace, d.Name, d.Status)
43
}
44
45
// 請求ds資源 todo 有興趣可以嘗試下
46
// clientset.AppsV1().DaemonSets()
47
48
}
49
50
代碼中分別打印了獲取到K8S集群中的500個Pod和500個deploy,目前打印語句是注釋了,如果要看效果需要先刪掉注釋。
案例代碼中還留了一個小內容,請求獲取daemonset資源,感興趣的可以試一試。
這是一種動態客戶端,對K8S任意資源進行操作,包括CRD。
請求返回的結果是map[string]interface{}
代碼案例:
Plain Text
1
package main
2
3
import (
4
"fmt"
5
6
apiv1 "k8s.io/api/core/v1"
7
corev1 "k8s.io/api/core/v1"
8
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9
"k8s.io/apimachinery/pkg/runtime"
10
"k8s.io/apimachinery/pkg/runtime/schema"
11
"k8s.io/client-go/dynamic"
12
"k8s.io/client-go/tools/clientcmd"
13
)
14
15
func main() {
16
config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
17
if err != nil {
18
panic(err)
19
}
20
21
dymaicClient, err := dynamic.NewForConfig(config)
22
checkErr(err)
23
//map[string]interface{}
24
25
//TODO 獲取CRD資源 這里是獲取了TIDB的CRD資源
26
// gvr := schema.GroupVersionResource{Version: "v1alpha1", Resource: "tidbclusters", Group: "pingcap.com"}
27
// unstructObj, err := dymaicClient.Resource(gvr).Namespace("tidb-cluster").List(metav1.ListOptions{Limit: 500})
28
// checkErr(err)
29
// fmt.Println(unstructObj)
30
31
gvr := schema.GroupVersionResource{Version: "v1", Resource: "pods"}
32
unstructObj, err := dymaicClient.Resource(gvr).Namespace(apiv1.NamespaceDefault).List(metav1.ListOptions{Limit: 500})
33
checkErr(err)
34
// fmt.Println(unstructObj)
35
podList := &corev1.PodList{}
36
err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructObj.UnstructuredContent(), podList)
37
checkErr(err)
38
for _, d := range podList.Items {
39
fmt.Printf("NAME:%v \t NAME:%v \t STATUS: %+v\n ", d.Namespace, d.Name, d.Status)
40
}
41
42
}
43
44
func checkErr(err error) {
45
if err != nil {
46
panic(err)
47
}
48
}
49
50
這個案例是打印了namespace為default下的500個pod,同樣的,在案例中也有一個todo,獲取CRD資源,感興趣的可以嘗試一下。如果K8S集群中沒有TIDB的資源可以自行換成自己想要的CRD資源。
代碼中已經有獲取v1alpha1版本的tidbclusters資源。如果你不知道CRD相關的信息,可以按照下面的步驟來找出對應的信息:
通過kubectl api-resources 獲取到資源的Group和Resource
通過kubectl api-versions 找到對應Group的版本
這樣 資源的GVR(Group、Version、Resource)都有了
這是一種發現客戶端,在前面的客戶端中需要知道資源的Resource和Version才能找到你想要的,
這些信息太多很難全部記住,這個客戶端用于獲取資源組、版本等信息。
前面用到的api-resources和api-versions都是通過discoveryClient客戶端實現的,源碼在Kubernetes源碼庫中 pkg/kubectl/cmd/apiresources/apiresources.gopkg/kubectl/cmd/apiresources/apiversions.go
Plain Text
1
// RunAPIResources does the work
2
func (o *APIResourceOptions) RunAPIResources(cmd *cobra.Command, f cmdutil.Factory) error {
3
w := printers.GetNewTabWriter(o.Out)
4
defer w.Flush()
5
6
//拿到一個DiscoveryClient客戶端
7
discoveryclient, err := f.ToDiscoveryClient()
8
if err != nil {
9
return err
10
}
11
12
13
Plain Text
1
// RunAPIVersions does the work
2
func (o *APIVersionsOptions) RunAPIVersions() error {
3
// Always request fresh data from the server
4
o.discoveryClient.Invalidate()
5
6
//通過discoveryClient獲取group相關信息
7
groupList, err := o.discoveryClient.ServerGroups()
8
if err != nil {
9
return fmt.Errorf("couldn't get available api versions from server: %v", err)
10
}
案例代碼:
獲取集群中的GVR
Plain Text
1
package main
2
3
import (
4
"fmt"
5
"k8s.io/apimachinery/pkg/runtime/schema"
6
"k8s.io/client-go/discovery"
7
"k8s.io/client-go/tools/clientcmd"
8
)
9
10
func main() {
11
config, err := clientcmd.BuildConfigFromFlags("","/root/.kube/config")
12
if err != nil {
13
panic(err.Error())
14
}
15
16
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
17
if err != nil {
18
panic(err.Error())
19
}
20
21
_, APIResourceList, err := discoveryClient.ServerGroupsAndResources()
22
if err != nil {
23
panic(err.Error())
24
}
25
for _, list := range APIResourceList {
26
gv, err := schema.ParseGroupVersion(list.GroupVersion)
27
if err != nil {
28
panic(err.Error())
29
}
30
for _, resource := range list.APIResources {
31
fmt.Printf("name: %v, group: %v, version %v\n", resource.Name, gv.Group, gv.Version)
32
}
33
}
34
}
預期效果:打印集群中的GVR
Plain Text
1
[root@normal11 discoveryclient]# go run main.go
2
name: bindings, group: , version v1
3
name: componentstatuses, group: , version v1
4
name: configmaps, group: , version v1
5
name: endpoints, group: , version v1
6
...
DiscoveryClient在請求到數據之后會緩存到本地,默認存儲位置是~/.kube/cache和~/.kube/http-cache,默認是每10分鐘會和API Server同步一次。關于如何進行k8s-client-go源碼剖析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。