前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >client-go实现简易K8S资源管理

client-go实现简易K8S资源管理

原创
作者头像
ikun999
发布于 2025-04-27 13:08:42
发布于 2025-04-27 13:08:42
2860
举报

前提:

client-go介绍:

client-go是Kubernetes的官方Go语言客户端库,它封装了与K8s API Server交互的RESTful API,使得开发者能够方便地使用Go语言编写的程序来管理K8s集群中的资源。这些资源包括但不限于Pods、Services、Deployments、Namespaces等。client-go提供了多种客户端实现,如ClientSet、DynamicClient、DiscoveryClient等,每种客户端都有其特定的用途和优势。

安装必要的依赖库:

在终端输入:

go get k8s.io/client-go@v0.26.0

go get k8s.io/api@v0.26.0

go get k8s.io/apimachinery@v0.26.0

Client客户端:

RESTClient:RESTClient是最基础的,相当于的底层基础结构,可以直接通过 是RESTClient提供的RESTful方法如Get(),Put(),Post(),Delete()进行交互

  • 同时支持Json 和 protobuf
  • 支持所有原生资源和CRDs
  • 但是,一般而言,为了更为优雅的处理,需要进一步封装,通过Clientset封装RESTClient,然后再对外提供接口和服务

Clientset:Clientset是调用Kubernetes资源对象最常用的client,可以操作所有的资源对象,包含RESTClient。需要指定Group、指定Version,然后根据Resource获取(主要学习该客户端)

DynamicClient:可以访问内置资源和自定义资源,拿到的内容是Object类型,按实际情况去做强制转换

DiscoveryClient:DiscoveryClient是发现客户端,主要用于发现Kubernetes API Server所支持的资源组、资源版本、资源信息。

kubernetes的Group、Version、Resource等概念

Group:资源组,k8s种分两种,有组名资源组和无组名资源组,例 :deployment就有组名,pod没有组名

Version:版本,这个比较好理解,在k8s中有三种版本,内部测试版(Alpha),正式发布版(Stable),经过测试的相对稳定版(Beta)

Resource:资源,在k8s中很重要的概念,常见的pod、service、deployment这些都是资源,并且k8s为资源准备了8种操作:create、delete、deletecollection、get、list、patch、update、watch,每一种资源都支持其中的一部分,这在每个资源的API文档中可以看到。

环境准备

一台装有k8s的1.18.8版本的linux虚拟机(对应的k8s使用对应的client-go 例:k8s v 1.18.8-client-go v 0.18.0)

Go语言环境以及IDE:Goland2025.1

----了解了这些知识之后,接下来就可以开始实战了(●ˇ∀ˇ●)

使用RESTClient实现对k8s资源进行简易操作:

基础步骤:

1.确定要操作的资源类型(例如Pod),去官网文档查询对应API的path,以及数据结构

2.加载k8s配置文件(和kubeconfig完全相同)

3.通过配置文件,生成配置对象,并通过API对对象进行设置

4.创建RESTClient实例

5.调用RESTClient实例的方法向kubernetes的API Server发起请求

实战:

1.进入官网找到对应资源的路径以及数据结构如下

主要看GET路径以及响应返回值
主要看GET路径以及响应返回值

2.编写代码如下:

代码语言:go
AI代码解释
复制
package main

import (
	"context"
	"flag"
	"fmt"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/homedir"
	"path/filepath"
)

func main() {
	var kubeconfig *string

	if home := homedir.HomeDir(); home != "" {
		//不输入就需要把配置文件导入本地,例如:C:\Users\用户名\.kube\文件名
		//输入则为绝对路径,可以自行更改
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "admin.conf"), "(optional) absolute path to the kubeconfig file")
	} else {
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}
	//上面也可以这么写,一行搞定
	//kubeconfigPath := flag.String("kubeconfig", "kubeconfig的绝对路径", "Path to the kubeconfig file")
	//还可以直接远程调用虚拟机的config文件(不推荐,只能在测试环境使用)
	/*
	config := &rest.Config{
	        Host:        "https://196.168.221.101:6443", // API Server 地址
	        BearerToken: "your-token-here",              // 从 ServiceAccount 或用户获取
	        TLSClientConfig: rest.TLSClientConfig{
	            Insecure: true, // 跳过证书验证(仅测试环境!)
	        },
	    }
	再使用获取到的config去构建client实例
	 */
	flag.Parse()
	//从本地中加载kubeconfig
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	//如果kubeconfig加载失败就退出
	if err != nil {
		fmt.Println("kubeconfig加载失败")
		panic(err.Error())
	}
	//参考:GET /api/v1/namespaces/{namespace}/pods
	config.APIPath = "/api"
	//pod的group为空字符串
	config.GroupVersion = &corev1.SchemeGroupVersion
	//指定序列化工具
	config.NegotiatedSerializer = scheme.Codecs

	//根据配置信息构建restClient实例
	restClient, err := rest.RESTClientFor(config)

	if err != nil {
		fmt.Println("实例构造失败")
		panic(err.Error())
	}

	//保存pod,这是根据官网对应的返回值得到的返回类型“PodList”
	result := &corev1.PodList{}

	//指向namespace
	namespace := "kube-system"
	//设置请求参数并且发起请求
	//GET请求
	err = restClient.Get().
		Namespace(namespace). //指定namespace
		Resource("pods").     //查找pods
		//指定大小限制和序列化工具
		VersionedParams(&metav1.ListOptions{Limit: 100}, scheme.ParameterCodec).
		Do(context.TODO()). //请求
		Into(result)        //结果存入result
	if err != nil {
		fmt.Println("请求失败")
		panic(err.Error())
	}
	//打印表头
	fmt.Printf("namespace\t status\t\t name\n")

	for _, pod := range result.Items {
		fmt.Printf("%v\t %v\t %v\n",
			pod.Namespace, pod.Status.Phase, pod.Name)
	}
}

上面代码实现了使用Restclient客户端对k8s中pods资源进行查看

小总结:

使用RestClient客户端实现查看比较偏底层但是简单易懂,根据官网信息读取配置文件和发送请求,让我对client-go了解的更深刻,为后续使用其他高级客户端打下好的基础

使用ClientSet实现对k8s资源进行增删改查操作:

前提:上面使用RestClient实现获取指定namespace下所有pod的信息这一简单操作,但是还是编写了不少代码,而且各种设置太过繁琐,例如api的path,Version,group还有返回的数据结构,编码解码的工具等等,所以就有了ClientSet来帮助我们简化代码,将这些操作封装起来,话不多说,开始实战!( •̀ ω •́ )y

基础步骤:

1.简单通过源码了解一下Clientset

2.实现简单的增删操作

实战:

1.通过源码简单了解Clientset

代码语言:go
AI代码解释
复制
type Clientset struct {
	*discovery.DiscoveryClient
	admissionregistrationV1      *admissionregistrationv1.AdmissionregistrationV1Client
	admissionregistrationV1beta1 *admissionregistrationv1beta1.AdmissionregistrationV1beta1Client
	appsV1                       *appsv1.AppsV1Client
	appsV1beta1                  *appsv1beta1.AppsV1beta1Client
	appsV1beta2                  *appsv1beta2.AppsV1beta2Client
	...
	batchV1                      *batchv1.BatchV1Client
	...

通过前面的知识结合源码我们可以发现:k8s的Group和Version的每个组合,都对应Clientset数据结构的一个字段(例:batchV1就对应/batch/v1)所以Clientset名副其实,是所以Group和Version组合对象的集合。但是这个组合对象到底是什么呢?那就以appsV1为例,查看其appsv1.AppsV1Client内部结构如下

如图内部只有一个字段restClient所以前面说Clientset包含restClient没问题
如图内部只有一个字段restClient所以前面说Clientset包含restClient没问题

注意上方红框中的Deployments方法返回的是DeploymentInterface接口实现,点击进去查看接口,发现实现了基本的增删改查以及其他接口

代码语言:go
AI代码解释
复制
type DeploymentInterface interface {
	Create(*v1.Deployment) (*v1.Deployment, error)
	Update(*v1.Deployment) (*v1.Deployment, error)
	UpdateStatus(*v1.Deployment) (*v1.Deployment, error)
	Delete(name string, options *metav1.DeleteOptions) error
	DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
	Get(name string, options metav1.GetOptions) (*v1.Deployment, error)
	List(opts metav1.ListOptions) (*v1.DeploymentList, error)
	Watch(opts metav1.ListOptions) (watch.Interface, error)
	Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Deployment, err error)
	GetScale(deploymentName string, options metav1.GetOptions) (*autoscalingv1.Scale, error)
	UpdateScale(deploymentName string, scale *autoscalingv1.Scale) (*autoscalingv1.Scale, error)
	DeploymentExpansion
}

再挑选一个接口看看怎么实现的,打开“deployment.go”,是不是很熟悉?没错和我上面使用RestClient的编码如出一辙

代码语言:go
AI代码解释
复制
func (c *deployments) Create(deployment *v1.Deployment) (result *v1.Deployment, err error) {
	result = &v1.Deployment{}
	err = c.client.Post().
		Namespace(c.ns).
		Resource("deployments").
		Body(deployment).
		Do(context.TODO()).
		Into(result)
	return
}

至此,真相大白!原来Clientset就是把我们使用RestClient操作资源的代码按照Group和Version分类封装起来,这样我们使用只需要调用接口方法即可。接下来实战看看(●'◡'●)

2.简单入手Clientset:

实现对k8s资源简单的增删操作(添加namespace,deployment,service和删除 namespace,deployment,service)

代码如下:

代码比较容易理解,但是有些冗长,我就不在此展示,想看的可以下载下来运行一下,里面都有注解,下面才是重头戏

Clientset-try.zip

3.编写小demo来实现对k8s集群内的pods进行增删改查以及list,watch操作(以nginx为例)

主要流程:

1.读取kubeconfig配置,生成clientset实例。这一步不一定要将config文件下载到本地,可以直接远程访问,代码如下:

代码语言:go
AI代码解释
复制
config := &rest.Config{
		Host:            "http://192.168.xxx.xxx:8080",        // 代理地址:需要在主节点使用:kubectl proxy --address=0.0.0.0 --port=8080 --accept-hosts='.*'开放端口
		TLSClientConfig: rest.TLSClientConfig{Insecure: true}, // 无需证书
	}

为了简易化我还是下载到本地去访问并且生成clientset对象

代码语言:go
AI代码解释
复制
// 获取k8s集群配置
func getKubernetesClient() (*kubernetes.Clientset, error) {
	var config *rest.Config
	var err error

	// 本地kubeconfig,“HOME”就是指默认路径:C:\Users\用户名\
	kubeconfig := flag.String("kubeconfig", "C:\\Users\\朱杨\\.kube\\admin.conf", "Path to the kubeconfig file")
	config, err = clientcmd.BuildConfigFromFlags("", *kubeconfig)

	if err != nil {
		fmt.Println("kubeconfig loading error", err)
		return nil, err
	}
	return kubernetes.NewForConfig(config)
}

2.创建pods

以nginx为例,代码如下:

代码语言:go
AI代码解释
复制
// 创建Pod以nginx为例
func createPod(client *kubernetes.Clientset, namespace string) error {
	pod := &corev1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "demo-pod",
			Labels: map[string]string{"app": "demo-pod"},
		},
		Spec: corev1.PodSpec{
			Containers: []corev1.Container{
				{
					Name:  "nginx",
					Image: "nginx:alpine",
					Ports: []corev1.ContainerPort{{ContainerPort: 80}},
				},
			},
		},
	}
	_, err := client.CoreV1().Pods(namespace).Create(
		context.Background(),
		pod,
		metav1.CreateOptions{},
	)
	return err
}

先对pod进行元数据配置,然后具体的配置可以查看官方文档

3.删除pod,给定参数namespace以及pod名进行删除

代码语言:go
AI代码解释
复制
// 删除pods
func deletePod(client *kubernetes.Clientset, namespace, name string) error {
	return client.CoreV1().
		Pods(namespace).
		Delete(context.TODO(), name, metav1.DeleteOptions{})
}

4.查询pods,列出所有pods

代码语言:go
AI代码解释
复制
// 查询pods
func getPod(client *kubernetes.Clientset, namespace, name string) (*corev1.Pod, error) {
	pod, err := client.CoreV1().
		Pods(namespace).
		Get(context.TODO(), name, metav1.GetOptions{})
	return pod, err
}

// 列出所有pods(list)
func listPods(client *kubernetes.Clientset, namespace string) (*corev1.PodList, error) {
	return client.CoreV1().
		Pods(namespace).
		List(context.TODO(), metav1.ListOptions{})
}

5.监控pods,使用goroutine运行

代码语言:go
AI代码解释
复制
// 监控pods(watch)
func watchPods(client *kubernetes.Clientset, namespace string) {
	watcher, err := client.CoreV1().Pods(namespace).Watch(
		context.Background(),
		metav1.ListOptions{},
	)
	if err != nil {
		fmt.Println("监控失败!", err)
		panic(err.Error())
	}
	for event := range watcher.ResultChan() {
		pod := event.Object.(*corev1.Pod)
		fmt.Printf("Event: %s, Pod: %s\n", event.Type, pod.Name)
	}
}

6.编写权限配置,使用RBAC鉴权,根据官网示例进行编写

代码语言:yaml
AI代码解释
复制
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-manager
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-manager-binding
subjects:
- kind: ServiceAccount
  name: default
  namespace: default
roleRef:
  kind: Role
  name: pod-manager
  apiGroup: rbac.authorization.k8s.io

7.主函数按照“创建->查询->list->删除->watch”顺序运行函数即可。

注意:如果运行代码结束后忘记删除,第二次运行的时候不要先进行删除操作然后创建,因为删除操作是异步的,当进行删除操作的时候,也在创建了,但是此时并没有完全删除,会导致创建同样的pod从而产生冲突。

至此,已经初步掌握了使用client-go对k8s的内置资源进行管理,但是如果我想管理非内置资源呢?后续会进行学习

总结:

使用client-go中的两种client对k8s的内置资源进行了简易的管理,特别是对clientset的使用理解更深入,对于官方文档的使用也更加熟练,后续还需要对k8s的内部构造进一步的了解,并且尝试去操作deployment资源,而且对于后面的两种client也需要进行基本的了解,加油!!!!(ง •_•)ง

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
LV.2
这个人很懒,什么都没有留下~
目录
  • 前提:
    • 安装必要的依赖库:
    • Client客户端:
    • kubernetes的Group、Version、Resource等概念
    • 环境准备
  • 使用RESTClient实现对k8s资源进行简易操作:
    • 基础步骤:
    • 实战:
    • 小总结:
  • 使用ClientSet实现对k8s资源进行增删改查操作:
    • 实战:
  • 总结:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档