一、背景
1、从开发角度
(1)服务通过容器化部署的方式运行在云环境的Pod中,然而在 Kubernetes 中,Pod 中的服务不能直接通过 client-go
访问 Kubernetes 资源,而是需要通过 Kubernetes API Server 来进行访问。client-go
库实际上是通过与 Kubernetes API Server 的交互来完成对 Kubernetes 资源的操作。
(2)在使用 client-go
时,通常需要提供 Kubernetes API Server 的地址、认证信息(如服务账号的凭证),以及所需的 API 访问权限(通过 RBAC 角色授权)。这些信息将帮助 client-go
库正确地建立与 Kubernetes API Server 的连接,并确保操作的安全性和正确性。
2、从调库角度
(1)在使用 Kubernetes API 客户端——client-go 的过程中,我们通常需要获取 *rest.Config 配置对象来与 Kubernetes API 服务器进行交互。
(2)通常有四种获取 *rest.Config 的方法
-
使用 kubeconfig 文件
-
kubeconfig 文件是一个 YAML 文件,用于指定 Kubernetes 集群的访问凭证、上下文和集群信息等。
-
-
使用 Kubernetes 集群内的 Service Account
-
在 Kubernetes 中,每个 Namespace 都有一个默认的 Service Account。ServiceAccount仅局限它所在的namespace,每个namespace创建时都会自动创建一个default service account。
-
ServiceAccount是给运行在Pod的程序使用的身份认证,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户。
-
创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。
-
-
直接指定 API Server 的地址和认证信息
-
我们可以直接指定 API Server 的地址和认证信息来获取 *rest.Config 对象。直接将api地址和认证token配置到代码中,但实际开发中一般不用。
-
-
从环境变量、默认配置文件等多个来源获取配置信息
-
`genericclioptions.NewConfigFlags()` 方法可以从环境变量、命令行参数、默认配置文件等多个来源中获取 Kubernetes 集群的配置信息,并生成对应的 *rest.Config 对象。
-
二、在pod中调用自定义资源
1、pod绑定服务账号
(1)创建serviceAccount
apiVersion: v1 kind: ServiceAccount metadata:name: test-sanamespace: test |
(2)创建相关的角色/rbac
-
Role 只能用来给某个特定 namespace 中的资源作鉴权,对多 namespace 和集群级的资源或者是非资源类的 API(如 /healthz)使用 ClusterRole
-
ClusterRole用于所有namespace下的资源,例如需要具备操作 CRD(CustomResourceDefinition) 相关权限,CRD 存在于所有 namespace 下
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata:name: my-cluster rules:- apiGroups: [""]resources: ["nodes"]verbs: ["get","list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata:name: my-bind subjects:- kind: ServiceAccountname: test-sanamespace: test roleRef:kind: ClusterRolename: my-clusterapiGroup: rbac.authorization.k8s.io |
(3)在pod中绑定对应的serviceAccount
-
serviceAccount所需要的证书会被mount到 : /var/run/secrets/kubernetes.io/serviceaccount
apiVersion: v1 kind: Pod metadata:name: testpodnamespace: testlabels:app: test spec:containers:- name: appimage: xxxxserviceAccountName: test-sa |
(4)client-go 中调用
config,err := rest.InClusterConfig() if err!=nil {panic(err) } client,err := kubernetes.NewForConfig(config) if err!=nil {panic(err) } |
2、client-go中操作自定义资源
(1)DynamicClient客户端(推荐)
-
DynamicClient客户端是一种动态客户端,可以对任意的Kubernetes资源进行RESTful操作,包括CRD资源。
-
代码示例
func TestDynamicClient(t *testing.T) {config,err := rest.InClusterConfig()if err!=nil {panic(err)}if err != nil {panic(err)}dynamicClient, err := dynamic.NewForConfig(config)if err != nil {panic(err)}gvr := schema.GroupVersionResource{Version: "v1", Resource: "pods"}//用于设置请求的资源组,资源版本,资源名称即命名空间;List函数用于获取Pod列表unstructObj, err := dynamicClient.Resource(gvr).Namespace(corev1.NamespaceDefault).List(context.Background(), metav1.ListOptions{Limit: 500})if err != nil {panic(err)}podList := &corev1.PodList{}//通过runtime的函数将unstructured.UnstructuredList转换为PodListerr = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructObj.UnstructuredContent(), podList)if err != nil {panic(err)}for _, d := range podList.Items {fmt.Printf("NAMESPACE:%v \t NAME:%v \t STATU:%v\n", d.Namespace, d.Name, d.Status.Phase)}
}
-
DynamicClient如何操作CRD资源
-
代码示例:
-
func TestDynamicClient(t *testing.T) {config,err := rest.InClusterConfig()if err!=nil {panic(err)}if err != nil {panic(err)}dynamicClient, err := dynamic.NewForConfig(config)if err != nil {panic(err)}// 定义要操作的 CRD 资源的 Group 和 Versiongroup := "example.com"version := "v1"plural := "foos"// 创建一个自定义资源对象foo := &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": fmt.Sprintf("%s/%s", group, version),"kind": "Foo","metadata": map[string]interface{}{"name": "example-foo",},"spec": map[string]interface{}{"message": "Hello, CRD!",},},}// 指定要操作的资源的 Group、Version 和 Resourceresource := schema.GroupVersionResource{Group: group, Version: version, Resource: plural}// 创建 Foo 资源created, err := dynamicClient.Resource(resource).Namespace("default").Create(context.TODO(), foo, metav1.CreateOptions{})if err != nil {fmt.Printf("Error creating foo: %s\n", err.Error())panic(err)}fmt.Printf("Created foo: %v\n", created) }
-
-
(2)Typed Clients客户端
-
它们是针对 Kubernetes API 中定义的具体资源类型的客户端,如 Pods、Services 等。这些客户端通常是类型安全的,可以享受静态类型语言的一些好处。
-
代码示例
func TestTypedClient(t *testing.T) {config,err := rest.InClusterConfig()if err!=nil {panic(err)}if err != nil {panic(err)}client, err := kubernetes.NewForConfig(config)if err != nil {panic(err)}namespace := "myns"deploy,err := client.AppsV1().Deployments(namespace).Get("test",metav1.GetOptions{})if err != nil {panic(err)}
}
-
CRD 如何使用 Typed Client
-
对于 CRD,如果想通过 Client-Go Typed Client 的方式来操作的话,那么第一步,是得我们先定义 CRD 的 Go 数据结构
-
通过 Kubernetes 的官方工具:Code Generator 来生成可以直接使用的 ClientSet(可以以 Typed Client 和 API Server 交互的 Client)
-
参考
-
Kubernetes CRD 系列(三):Client-Go 的使用_client-go gvk创建资源-CSDN博客
-
Extend the Kubernetes API with CustomResourceDefinition
-
CRDs and Custom Kubernetes Controllers in Rancher 2.0
-
How to generate client codes for Kubernetes Custom Resource Definitions (CRD)
-
-