当前位置: 首页 > article >正文

【云原生开发】如何通过client-go来操作K8S集群

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,云原生开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:云原生开发
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • client-go
    • 一、client-go介绍
      • 1. 什么是client-go?
      • 2. client-go版本的演变
      • 3. client-go客户端分类
      • 4. client-go客户端工具依赖关系
      • 5. 安装client-go
    • 二、使用client-go进行基本操作
      • 2.1 in-cluster配置
      • 2.2 out-of-cluster配置
      • 2.3 client-go 查询列表功能使用
      • 2.4 client-go查询资源详情
      • 2.5 client-go更新资源功能
      • 2.6 client-go删除资源
      • 2.7 client-go创建资源
      • 2.8 client-go使用json串创建资源
    • 三、总结

client-go

一、client-go介绍

1. 什么是client-go?

client-go是Kubernetes官方提供的,用于操作kubernetes资源的Go语言客户端库,通过它,开发者可以非常方便地在Go项目中与Kubernetes集群进行交互,实现对Kubernetes资源以及自定义CRD的增删改查和事件监听等操作。
同时,可以通过client-go实现kubernetes的二次开发。自定义资源开发。

源码:
github下载地址:https://github.com/kubernetes/client-go
在这里插入图片描述

如果是其他语言的客户端工具,可以通过https://github.com/kubernetes-client 来查看
在这里插入图片描述

我们看下client-go几个比较重要的目录
在这里插入图片描述

2. client-go版本的演变

左边是client-go的版本。右边是k8s的版本
在client-go 1.17版本之前,client-go的版本与k8s版本保持一致,1.17之后,client-go的版本多了一个v的tag。是由于go语言的包是带v的版本
在这里插入图片描述
在这里插入图片描述

建议:client-go我们直接用最新版本

3. client-go客户端分类

在这里插入图片描述

restclient: 一般我们不会使用restclient,因为它需要把整个资源的yaml文件或json数据都传过去,显得比较臃肿,一般我们不用这个
discoverclient: 比如我们创建deployment时的apiversion: apps/v1    apps就是资源组Group   v1就是资源版本Version   资源信息 就是kind 。我们一般也不会用这个客户端工具
ClientSet: 只能针对K8S内置的资源进行操作,不能操作自定义的资源
DyanmicClient: 我们经常使用这个客户端,但是对于内置资源,我们还是习惯使用ClientSet,因为它更好用,自定义资源我们使用DyanmicClient。

我们可以通过命令 kubectl api-resources 查看每种资源的资源组
在这里插入图片描述

4. client-go客户端工具依赖关系

在这里插入图片描述

5. 安装client-go

client-go是一个Go模块,可以通过Go Module的方式进行安装。在你的Go项目中,执行以下命令:

go get k8s.io/client-go@latest

在这里插入图片描述

这将安装最新版本的client-go。此外,你还需要安装一些相关的依赖库,例如apimachinery,用于处理Kubernetes API对象。

go get k8s.io/apimachinery@latest

在这里插入图片描述

安装完还需要运行go mod tidy 加载依赖包
在这里插入图片描述

二、使用client-go进行基本操作

创建Kubernetes客户端
在使用client-go之前,首先需要创建一个Kubernetes客户端。client-go提供了两种创建客户端的方式:in-cluster配置和out-of-cluster配置。

我们根据我们之前写好的脚手架,改个名字,在此基础上开发我们的项目
在这里插入图片描述

并不是说在此改了就可以了,因为很多包用的还是原来的名字,

我们可以批量替换
在Goland IDE中想要替换某一段特定的字符串,可以使用Find and Replace 功能来实现。这是一种全局性的操作,将会在你的整个项目或指定的文件/文件夹中进行。

使用Ctrl + Shift + R 打开Find and Repalce对话框
在这里插入图片描述

我们测试client-go,要用到k8s集群,得有~/.kube/config 这个文件
里面是加载集群的配置信息
在这里插入图片描述
在这里插入图片描述

将这个文件复制到我们的项目中
在这里插入图片描述

2.1 in-cluster配置

在Kubernetes 集群内部运行时,可以使用in-cluster配置。这种方式不需要手动指定kubeconfig文件路径,client-go会自动使用集群中的服务账户进行身份验证。

2.2 out-of-cluster配置

测试client-go,我们使用out-of-cluster方式来测试,发布项目的时候,我们使用in-cluster方式配置
在本地电脑开发环境或其他非Kubernetes集群中运行时,可以使用out-of-cluster配置。这需要指定kubeconfig文件的路径。kubeconfig文件通常位于$HOME/.kube/config,它包含了访问Kubernetes集群所需的配置信息。

这是github上面看用法举例
在这里插入图片描述

package mainimport ("context""fmt"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {//1. 初始化config实例//var kubeconfig *string// 通过家目录找到kubeconfig文件。我们的路径是已知的,所以不用此项配置//if home := homedir.HomeDir(); home != "" {//    kubeconfig = flag.String("meta.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()// 1. 初始化config实例// 因为我们的路径是已知的,所以不用上面的配置。use the current context in kubeconfig// masterUrl就是离我们主节点的ip地址和端口号,我们在kubeconfig文件中有了,所以可以省略config, err := clientcmd.BuildConfigFromFlags("", "meta.kubeconfig")//要想正常应用我们的服务,必须能够实例化成功kubeconfig,要不然后面所有的功能都无法使用,所以这里直接报panic即可if err != nil {panic(err.Error())}// 2. 创建客户端工具 create the clientsetclientset, err := kubernetes.NewForConfig(config)//这个客户端工具如果生成失败的话,后面的操作也无法完成,所以这里也报panic即可if err != nil {panic(err.Error())}//3. 操作集群pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})//此时报错的话,不应该是panic了,但是这里官方用的还是panic。后期需要优化,我么可以返回个错误信息if err != nil {panic(err.Error())}//打印pod的数量fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))// 获取指定名称空间下的pod数量,如果namespace不传值,默认查的是所有命名空间下的podnamespace := "h5-web"pods, err = clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})if err != nil {panic(err.Error())}//打印pod的数量fmt.Printf("%s namespce has %d pods in the cluster\n", namespace, len(pods.Items))//看下返回的pod是什么fmt.Println("pods是什么:", pods)
}

在这里插入图片描述

2.3 client-go 查询列表功能使用

我们看下List方法的参数,包含两个,一个context,一个是ListOptions。
在这里插入图片描述

这个ListOptions就可以在里面做些筛选条件,比如传json串,标签等
在这里插入图片描述

我们看下List的返回值
在这里插入图片描述
在这里插入图片描述

所以我们要查询具体的pod里面的信息,可以在Items字段中获取到所有的pod
跟我们通过在k8s集群中通过kubectl … -ojson的得到的信息是一样的
在这里插入图片描述

如果要取其中某个pod,可以通过下标来获取
在这里插入图片描述

如果忘记pod的层级关系,可以使用k8s命令的-ojson 查看一下

完整代码:

package mainimport ("context""fmt"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {// 1. 初始化config实例// masterUrl就是离我们主节点的ip地址和端口号,我们在kubeconfig文件中有了,所以可以省略config, err := clientcmd.BuildConfigFromFlags("", "meta.kubeconfig")//要想正常应用我们的服务,必须能够实例化成功kubeconfig,要不然后面所有的功能都无法使用,所以这里直接报panic即可if err != nil {panic(err.Error())}// 2. 创建客户端工具 create the clientsetclientset, err := kubernetes.NewForConfig(config)//这个客户端工具如果生成失败的话,后面的操作也无法完成,所以这里也报panic即可if err != nil {panic(err.Error())}//3. 操作集群pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})//此时报错的话,不应该是panic了,但是这里官方用的还是panic。后期需要优化,我么可以返回个错误信息if err != nil {panic(err.Error())}//打印pod的数量fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))// 获取指定名称空间下的pod数量,如果namespace不传值,默认查的是所有命名空间下的podnamespace := "h5-web"pods, err = clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})if err != nil {panic(err.Error())}//打印pod的数量fmt.Printf("%s namespce has %d pods in the cluster\n", namespace, len(pods.Items))//看下返回的pod是什么fmt.Println("pods是什么:", pods)//获取到某个podfmt.Println(pods.Items[0].Spec.NodeName)//获取到某个容器的镜像fmt.Println(pods.Items[0].Spec.Containers[0].Image)}

下面,我们探讨下,我们怎么知道我们要操作的资源是属于CoreV1()或者是其他什么组呢?
之前,我们说过,在K8S集群中,可以通过命令 kubectl api-resources查看
在这里插入图片描述
在这里插入图片描述

deployment 的apiversion是 apps/v1 对应的client-go里面的方法就是 clientset.AppsV1()
crontabs 的apiversion是batch/v1 对应的client-go里面的方法就是clientset.BatchV1()
ingresses的apiversion是networking.k8s.io/v1 对应client-go里面的方法就是clientset.NetworkingV1()

以此类推,由此我们就知道了个汇总资源对应的操作方法
这种V1的apiversion的资源,对应的就是clientset.CoreV1()
在这里插入图片描述

如果不想通过K8S命令来查,也可以在代码中查看
点进来
在这里插入图片描述
在这里插入图片描述

这里可看看到个各种方法,不过我们用的时候要把首字母大写
在这里插入图片描述

比如查询deployment

//查询deployment列表,用法与pod类似
deploy, _ := clientset.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{})
//查看所有名称空间下deploy的数量
fmt.Println("deployment的数量", len(deploy.Items))
//打印deploy名称,由于是多个,我们循环打印
for _, i := range deploy.Items {fmt.Printf("当前资源的名称空间: %s, deployment名称是: %s\n", i.Namespace, i.Name)
}//查询没有名称空间限制的资源,比如名称空间,工作节点,clusterrole,clusterrolebinding等
//查的都是集群的资源
//比如我们查询集群有多少个名称空间
ns, _ := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
fmt.Printf("There are %d namespaces in the cluster\n", len(ns.Items))

在这里插入图片描述

完整代码:

package mainimport ("context""fmt"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {// 1. 初始化config实例// masterUrl就是离我们主节点的ip地址和端口号,我们在kubeconfig文件中有了,所以可以省略config, err := clientcmd.BuildConfigFromFlags("", "meta.kubeconfig")//要想正常应用我们的服务,必须能够实例化成功kubeconfig,要不然后面所有的功能都无法使用,所以这里直接报panic即可if err != nil {panic(err.Error())}// 2. 创建客户端工具 create the clientsetclientset, err := kubernetes.NewForConfig(config)//这个客户端工具如果生成失败的话,后面的操作也无法完成,所以这里也报panic即可if err != nil {panic(err.Error())}//3. 操作集群pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})//此时报错的话,不应该是panic了,但是这里官方用的还是panic。后期需要优化,我么可以返回个错误信息if err != nil {panic(err.Error())}//打印pod的数量fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))// 获取指定名称空间下的pod数量,如果namespace不传值,默认查的是所有命名空间下的pod//namespace := "h5-web"//pods, err = clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})//if err != nil {//    panic(err.Error())//}打印pod的数量//fmt.Printf("%s namespce has %d pods in the cluster\n", namespace, len(pods.Items))看下返回的pod是什么//fmt.Println("pods是什么:", pods)//获取到某个pod//fmt.Println(pods.Items[0].Spec.NodeName)获取到某个容器的镜像//fmt.Println(pods.Items[0].Spec.Containers[0].Image)//查询deployment列表,用法与pod类似deploy, _ := clientset.AppsV1().Deployments("").List(context.TODO(), metav1.ListOptions{})//查看所有名称空间下deploy的数量fmt.Println("deployment的数量", len(deploy.Items))//打印deploy名称,由于是多个,我们循环打印for _, i := range deploy.Items {fmt.Printf("当前资源的名称空间: %s, deployment名称是: %s\n", i.Namespace, i.Name)}//查询没有名称空间限制的资源,比如名称空间,工作节点,clusterrole,clusterrolebinding等//查的都是集群的资源//比如我们查询集群有多少个名称空间ns, _ := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})fmt.Printf("There are %d namespaces in the cluster\n", len(ns.Items))
}

2.4 client-go查询资源详情

Get()方法,可以获取单个资源的详情,获取详情之后,我们可以传给前端展示,或者根据查询出来的数据进行更改
比如说,我们对K8S集群中h5-web名称空间下的 pods 查询详情
在这里插入图片描述

// 查询资源详情 Get()方法
// Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Pod, error)
poddetail, _ := clientset.CoreV1().Pods("h5-web").Get(context.TODO(), "web-864f4c6988-95sw4", metav1.GetOptions{})
//fmt.Println("pod详情:", poddetail)
//打印pod的镜像名称
fmt.Println("pod第一个容器的镜像名称", poddetail.Spec.Containers[0].Image)//获取名称空间的详情
namespace, _ := clientset.CoreV1().Namespaces().Get(context.TODO(), "h5-web", metav1.GetOptions{})
fmt.Println("名称空间详情:", namespace)

在这里插入图片描述

完整代码

package mainimport ("context""fmt"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {// 1. 初始化config实例// masterUrl就是离我们主节点的ip地址和端口号,我们在kubeconfig文件中有了,所以可以省略config, err := clientcmd.BuildConfigFromFlags("", "meta.kubeconfig")//要想正常应用我们的服务,必须能够实例化成功kubeconfig,要不然后面所有的功能都无法使用,所以这里直接报panic即可if err != nil {panic(err.Error())}// 2. 创建客户端工具 create the clientsetclientset, err := kubernetes.NewForConfig(config)//这个客户端工具如果生成失败的话,后面的操作也无法完成,所以这里也报panic即可if err != nil {panic(err.Error())}//3. 操作集群// 查询资源详情 Get()方法// Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Pod, error)poddetail, _ := clientset.CoreV1().Pods("h5-web").Get(context.TODO(), "web-864f4c6988-95sw4", metav1.GetOptions{})//fmt.Println("pod详情:", poddetail)//打印pod的镜像名称fmt.Println("pod第一个容器的镜像名称", poddetail.Spec.Containers[0].Image)//获取名称空间的详情namespace, _ := clientset.CoreV1().Namespaces().Get(context.TODO(), "h5-web", metav1.GetOptions{})fmt.Println("名称空间详情:", namespace)}

其他资源查询方式类似,感兴趣的朋友可以尝试下

2.5 client-go更新资源功能

更新的前提是该字段是可更改的
比如这种can’t be updated的字段,就不能被修改
在这里插入图片描述

注意:如果修改的字段在资源中不存在,比如labels 。修改时会报空指针错误,此时就要初始化下才能修改

//更新资源操作  Update()
//先获取资源详情,再修改
//比如,我们修改service的暴露的端口号
service, _ := clientset.CoreV1().Services("h5-web").Get(context.TODO(), "web", metav1.GetOptions{})
fmt.Printf("service对外的端口号是 %d\n", service.Spec.Ports[0].NodePort)
// 修改端口号
// service-node-port-range 默认可以设置的范围 30000-32767
service.Spec.Ports[0].NodePort = 32050
// 修改暴露的端口号
// Update(ctx context.Context, service *v1.Service, opts metav1.UpdateOptions) (*v1.Service, error)
_, err = clientset.CoreV1().Services("h5-web").Update(context.TODO(), service, metav1.UpdateOptions{})
if err != nil {panic(err.Error())
}
fmt.Printf("修改后service对外的端口号是 %d\n", service.Spec.Ports[0].NodePort)//修改deploy的副本数
deploy, _ := clientset.AppsV1().Deployments("h5-web").Get(context.TODO(), "web", metav1.GetOptions{})
//查看当前deploy的副本数
fmt.Println("当前deploy的副本数是:", *deploy.Spec.Replicas)
//修改副本数
replacs := int32(3)
//注意Replicas 是int32的指针类型
deploy.Spec.Replicas = &replacs_, err = clientset.AppsV1().Deployments("h5-web").Update(context.TODO(), deploy, metav1.UpdateOptions{})
//查看修改后deploy的副本数
fmt.Println("修改后deploy的副本数是:", *deploy.Spec.Replicas)

在这里插入图片描述

完整代码:

package mainimport ("context""fmt"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {// 1. 初始化config实例// masterUrl就是离我们主节点的ip地址和端口号,我们在kubeconfig文件中有了,所以可以省略config, err := clientcmd.BuildConfigFromFlags("", "meta.kubeconfig")//要想正常应用我们的服务,必须能够实例化成功kubeconfig,要不然后面所有的功能都无法使用,所以这里直接报panic即可if err != nil {panic(err.Error())}// 2. 创建客户端工具 create the clientsetclientset, err := kubernetes.NewForConfig(config)//这个客户端工具如果生成失败的话,后面的操作也无法完成,所以这里也报panic即可if err != nil {panic(err.Error())}//3. 操作集群//更新资源操作  Update()//先获取资源详情,再修改//比如,我们修改service的暴露的端口号service, _ := clientset.CoreV1().Services("h5-web").Get(context.TODO(), "web", metav1.GetOptions{})fmt.Printf("service对外的端口号是 %d\n", service.Spec.Ports[0].NodePort)// 修改端口号// service-node-port-range 默认可以设置的范围 30000-32767service.Spec.Ports[0].NodePort = 32050// 修改暴露的端口号// Update(ctx context.Context, service *v1.Service, opts metav1.UpdateOptions) (*v1.Service, error)_, err = clientset.CoreV1().Services("h5-web").Update(context.TODO(), service, metav1.UpdateOptions{})if err != nil {panic(err.Error())}fmt.Printf("修改后service对外的端口号是 %d\n", service.Spec.Ports[0].NodePort)//修改deploy的副本数deploy, _ := clientset.AppsV1().Deployments("h5-web").Get(context.TODO(), "web", metav1.GetOptions{})//查看当前deploy的副本数fmt.Println("当前deploy的副本数是:", *deploy.Spec.Replicas)//修改副本数replacs := int32(3)//注意Replicas 是int32的指针类型deploy.Spec.Replicas = &replacs_, err = clientset.AppsV1().Deployments("h5-web").Update(context.TODO(), deploy, metav1.UpdateOptions{})//查看修改后deploy的副本数fmt.Println("修改后deploy的副本数是:", *deploy.Spec.Replicas)
}

2.6 client-go删除资源

删除pod,比如我们将下列的pod删除
在这里插入图片描述

//删除资源 Delete()
//删除pod
err = clientset.CoreV1().Pods("h5-web").Delete(context.TODO(), "web-864f4c6988-r456g", metav1.DeleteOptions{})
if err != nil {panic(err.Error())

可见pod已被删除
在这里插入图片描述

2.7 client-go创建资源

创建namespace

//创建名称空间
var namespace corev1.Namespace
//创建namespace只需要传个名字就可以了
namespace.Name = "test1"
// Create(ctx context.Context, namespace *v1.Namespace, opts metav1.CreateOptions) (*v1.Namespace, error)
//传的是指针
_, err = clientset.CoreV1().Namespaces().Create(context.TODO(), &namespace, metav1.CreateOptions{})
if err != nil {panic(err.Error())
}

注意,这个corev1的导包,我们要根据Create()这个方法里面的导包,导过来,不要导错了,因为很多v1的包
在这里插入图片描述
在这里插入图片描述

创建deployment
注意,这个deployment的v1,
在这里插入图片描述

导包的时候,不要导错
在这里插入图片描述

传参时,要把必须得参数都传进去
在这里插入图片描述
在这里插入图片描述

可以通过这个命令来查看哪些是必须传的参数

kubectl create deployment mynginx --image="nginx" --dry-run=client -oyaml

它会导出一份yaml文件
在这里插入图片描述

package mainimport ("context""fmt"deployv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {// 1. 初始化config实例// masterUrl就是离我们主节点的ip地址和端口号,我们在kubeconfig文件中有了,所以可以省略config, err := clientcmd.BuildConfigFromFlags("", "meta.kubeconfig")//要想正常应用我们的服务,必须能够实例化成功kubeconfig,要不然后面所有的功能都无法使用,所以这里直接报panic即可if err != nil {panic(err.Error())}// 2. 创建客户端工具 create the clientsetclientset, err := kubernetes.NewForConfig(config)//这个客户端工具如果生成失败的话,后面的操作也无法完成,所以这里也报panic即可if err != nil {panic(err.Error())}//3. 操作集群//创建deploymentvar deploy deployv1.Deployment//给deployment传参,要把必须传的参数都传进去,不然创建会报错deploy.Name = "mydeploy"deploy.Namespace = "test1"//副本数replicas := int32(1)deploy.Spec.Replicas = &replicas//mathlabelslabels := make(map[string]string)labels["app"] = "nginx"//Selector 是个指针类型,需要先初始化//Selector *metav1.LabelSelector `json:"selector" protobuf:"bytes,2,opt,name=selector"`deploy.Spec.Selector = &metav1.LabelSelector{}deploy.Spec.Selector.MatchLabels = labels//deployment label   metadata会将里面的资源发布出去,metadata可以省略掉deploy.Labels = labels// 创建template 这个template模版就是pod的模板// Template v1.PodTemplateSpec `json:"template" protobuf:"bytes,3,opt,name=template"`// 此时的labels要和selector的labels一样,否则deployment就无法管理到poddeploy.Spec.Template.ObjectMeta.Labels = labels//创建容器,容器是个切片,可以创建多个容器var containers []corev1.Containervar container corev1.Containercontainer.Name = "nginx"container.Image = "nginx:1.7.9"containers = append(containers, container)container.Name = "redis"container.Image = "redis:6-alpine"containers = append(containers, container)deploy.Spec.Template.Spec.Containers = containers_, err = clientset.AppsV1().Deployments("test1").Create(context.TODO(), &deploy, metav1.CreateOptions{})}

查看创建的deploy
在这里插入图片描述

查看yaml文件,两个容器都创建成功

[root@master01 svc ]#kubectl get deploy -n test1 -oyaml
apiVersion: v1
items:
- apiVersion: apps/v1kind: Deploymentmetadata:annotations:deployment.kubernetes.io/revision: "1"creationTimestamp: "2024-11-05T09:58:43Z"generation: 1labels:app: nginxname: mydeploynamespace: test1resourceVersion: "1079640"uid: 8df3654a-71c6-45d5-888d-6329ed81dad7spec:progressDeadlineSeconds: 600replicas: 1revisionHistoryLimit: 10selector:matchLabels:app: nginxstrategy:rollingUpdate:maxSurge: 25%maxUnavailable: 25%type: RollingUpdatetemplate:metadata:creationTimestamp: nulllabels:app: nginxspec:containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginxresources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: File- image: redis:6-alpineimagePullPolicy: IfNotPresentname: redisresources: {}terminationMessagePath: /dev/termination-logterminationMessagePolicy: FilednsPolicy: ClusterFirstrestartPolicy: AlwaysschedulerName: default-schedulersecurityContext: {}terminationGracePeriodSeconds: 30status:conditions:- lastTransitionTime: "2024-11-05T09:58:43Z"lastUpdateTime: "2024-11-05T09:58:43Z"message: Deployment does not have minimum availability.reason: MinimumReplicasUnavailablestatus: "False"type: Available- lastTransitionTime: "2024-11-05T09:58:43Z"lastUpdateTime: "2024-11-05T09:58:43Z"message: ReplicaSet "mydeploy-68dcc7d46d" is progressing.reason: ReplicaSetUpdatedstatus: "True"type: ProgressingobservedGeneration: 1replicas: 1unavailableReplicas: 1updatedReplicas: 1
kind: List
metadata:resourceVersion: ""

2.8 client-go使用json串创建资源

上面使用手动填值的方式创建,还是比较麻烦的,稍微有不注意的地方还容易犯错,因此,在前后端分离的项目中,在web页面,一般我们不悔通过手动填值进行创建资源。
一般我们会根据json串来创建资源
首先我们通过先通过kubectl命令导出json串
在这里插入图片描述
在这里插入图片描述

–dry-run 选项只能为 “none”、“server”、"client"三者中的一个,默认是none;当不加该参数,或者为none的时候,该操作后资源会生效 ,请求会被发送到kube-apiserver并做实际更改;
当该参数为client的时候,只打印该对象并不会发送请求且并不会实际创建该对象;
当该参数为server的时候,会发送请求到服务端,但是并不会实际创建该对象。
比如我们拿到一个创建deploy的json串

kubectl create deployment myredis --image="redis" --dry-run=client -ojson

在这里插入图片描述

我们将json串拿出来

{"kind": "Deployment","apiVersion": "apps/v1","metadata": {"name": "myredis","creationTimestamp": null,"labels": {"app": "myredis"}},"spec": {"replicas": 1,"selector": {"matchLabels": {"app": "myredis"}},"template": {"metadata": {"creationTimestamp": null,"labels": {"app": "myredis"}},"spec": {"containers": [{"name": "redis","image": "redis","resources": {}}]}},"strategy": {}},"status": {}
}

使用json创建deploy完整代码:

package mainimport ("context""encoding/json""fmt"deployv1 "k8s.io/api/apps/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"
)func main() {// 1. 初始化config实例// masterUrl就是离我们主节点的ip地址和端口号,我们在kubeconfig文件中有了,所以可以省略config, err := clientcmd.BuildConfigFromFlags("", "meta.kubeconfig")//要想正常应用我们的服务,必须能够实例化成功kubeconfig,要不然后面所有的功能都无法使用,所以这里直接报panic即可if err != nil {panic(err.Error())}// 2. 创建客户端工具 create the clientsetclientset, err := kubernetes.NewForConfig(config)//这个客户端工具如果生成失败的话,后面的操作也无法完成,所以这里也报panic即可if err != nil {panic(err.Error())}//3. 操作集群//通过json串创建k8s资源,注意多行字符串用反引号包裹deployJson := `{"kind": "Deployment","apiVersion": "apps/v1","metadata": {"name": "myredis","creationTimestamp": null,"labels": {"app": "myredis"}},"spec": {"replicas": 1,"selector": {"matchLabels": {"app": "myredis"}},"template": {"metadata": {"creationTimestamp": null,"labels": {"app": "myredis"}},"spec": {"containers": [{"name": "redis","image": "redis","resources": {}}]}},"strategy": {}},"status": {}
}`//我们需要将json串转换成deployv1类型的资源var redisdeploy deployv1.Deployment//将json转换成struct// func Unmarshal(data []byte, v any) errorerr = json.Unmarshal([]byte(deployJson), &redisdeploy)if err != nil {panic(err.Error())}fmt.Println("将json转换成的struct:", redisdeploy)//创建deploy_, err = clientset.AppsV1().Deployments("default").Create(context.TODO(), &redisdeploy, metav1.CreateOptions{})if err != nil {panic(err.Error())}}

在K8S集群查看下,创建成功

在这里插入图片描述

三、总结

client-go是Kubernetes官方提供的Go客户端库,它封装了与Kubernetes API服务器的交互,提供了便捷的方式进行各种资源的管理。通过创建客户端并使用相应的API客户端进行操作,你可以轻松地进行Pod、Deployment、Service等资源的增删改查。

本文详细介绍了client-go的安装、配置和使用方法,并通过示例代码展示了如何进行常见的Kubernetes操作。希望这些内容能帮助大家更好地理解和使用client-go,从而提高你的Kubernetes开发效率。

相关文章:

【云原生开发】如何通过client-go来操作K8S集群

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

八.MySQL复合查询

一.基本查询回顾 分组统计 group by 函数作用示例语句说明count(*)统计记录条数select deptno, count(*) from emp group by deptno;每个部门有多少人?sum(sal)某字段求和select deptno, sum(sal) from emp group by deptno;每个部门总工资avg(sal)求平均值select…...

cacti导出的1分钟监控数据csv文件读取并按5分钟求平均值,然后计算95计费值,假设31天的月份

cacti导出的1分钟监控数据csv文件读取并按5分钟求平均值,然后计算95计费值,假设31天的月份 import pandas as pd import openpyxl from openpyxl.styles import Font from openpyxl.utils.dataframe import dataframe_to_rows import os import chardet…...

FastMCP vs MCP:协议标准与实现框架的协同

你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益: 了解大厂经验拥有和大厂相匹配的技术等 希望看什么,评论或者私信告诉我! 文章目录 一…...

AI视频“入驻”手机,多模态成智能终端的新战场

文|乐乐 今天,无线蓝牙耳机(TWS)已经成为人人都用得起的产品。 但退回到9年前,苹果AirPods是全球第一款真正意义上的无线蓝牙耳机。靠着自研并申请专利的Snoop监听技术,苹果解决了蓝牙耳机左右延时和能耗…...

nginx+tomcat负载均衡群集

一 案例部署Tomcat 目录 一 案例部署Tomcat 1.案例概述 1.1案例前置知识点 (1)Tomcat简介 (2)应用场景 2.实施准备 (1)关闭Linux防火墙 (2)安装Java 2.1 安装配置TOMACT …...

DEEPSEEK帮写的STM32消息流函数,直接可用.已经测试

#include "main.h" #include "MessageBuffer.h"static RingBuffer msgQueue {0};// 初始化队列 void InitQueue(void) {msgQueue.head 0;msgQueue.tail 0;msgQueue.count 0; }// 检查队列状态 type_usart_queue_status GetQueueStatus(void) {if (msgQ…...

day45 python预训练模型

目录 知识点回顾 1. 预训练的概念 2. 常见的分类预训练模型 3. 图像预训练模型的发展史 4. 预训练的策略 5. 预训练代码实战:ResNet18 作业:在 CIFAR-10 上对比 AlexNet 预训练模型 实验结果对比 在深度学习领域,预训练模型已经成为了…...

二维 根据矩阵变换计算缩放比例

在二维空间中,根据矩阵变换计算缩放比例是一个常见的图形学问题。通常,我们通过分析变换矩阵的结构来提取出缩放(Scale)信息。以下是详细的分析和计算方法。 🧮 一、基础:二维变换矩阵结构 在二维仿射变换…...

Vue-Cropper:全面掌握图片裁剪组件

Vue-Cropper 完全学习指南:Vue图片裁剪组件 🎯 什么是 Vue-Cropper? Vue-Cropper 是一个简单易用的Vue图片裁剪组件,支持Vue2和Vue3。它提供了丰富的配置选项和回调方法,可以满足各种图片裁剪需求。 🌟 …...

建造者模式:优雅构建复杂对象

引言 在软件开发中,有时我们需要创建一个由多个部分组成的复杂对象,这些部分可能有不同的变体或配置。如果直接在一个构造函数中设置所有参数,代码会变得难以阅读和维护。当对象构建过程复杂,且需要多个步骤时,我们可…...

现场总线结构在楼宇自控系统中的技术要求与实施要点分析

在建筑智能化程度不断提升的当下,楼宇自控系统承担着协调建筑内各类设备高效运行的重任。传统的集中式控制系统在面对复杂建筑环境时,逐渐暴露出布线繁琐、扩展性差、可靠性低等问题。而现场总线结构凭借其分散控制、通信高效等特性,成为楼宇…...

Axure组件即拖即用:垂直折叠菜单(动态展开/收回交互)

亲爱的小伙伴,在您浏览之前,请关注一下,在此深表感谢!如有帮助请订阅专栏!免费哦! 你是不是也这样崩溃过? 明明设置了点击交互,菜单却像死机一样纹丝不动,F5按烂了都没反…...

学习路之PHP--easyswoole使用视图和模板

学习路之PHP--easyswoole使用视图和模板 一、安装依赖插件二、 实现渲染引擎三、注册渲染引擎四、测试调用写的模板五、优化六、最后补充 一、安装依赖插件 composer require easyswoole/template:1.1.* composer require topthink/think-template相关版本: "…...

《云原生安全攻防》-- K8s网络策略:通过NetworkPolicy实现微隔离

默认情况下,K8s集群的网络是没有任何限制的,所有的Pod之间都可以相互访问。这就意味着,一旦攻击者入侵了某个Pod,就能够访问到集群中任意Pod,存在比较大的安全风险。 在本节课程中,我们将详细介绍如何通过N…...

06 APP 自动化- H5 元素定位

文章目录 H5 元素定位1、APP 分类2、H5 元素3、H5 元素定位环境的搭建4、代码实现: H5 元素定位 1、APP 分类 1、Android 原生 APP2、混合 APP(Android 原生控件H5页面)3、纯 H5 App 2、H5 元素 H5 元素容器 WebViewWebView 控件实现展示网页 3、H5 元素定位环…...

Axure疑难杂症:中继器新增数据时如何上传并存储图片(玩转中继器)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 案例视频: 中继器新增数据时如何上传并存储图片 课程主题:中继器新增数据时如何上传并存储图片 主…...

定时线程池失效问题引发的思考

最近在做的一个新功能,在结果探测的时候使用了定时线程池和普通线程池结合,定时线程池周期性创建子任务并往普通线程池提交任务。 问题: 在昨天测试老师发现,业务实际上已经成功了,但是页面还是一直显示进行中。 收到…...

Vue-ref 与 props

一、前言 在 Vue 的组件化开发中,父子组件之间的数据传递 是一个非常核心的需求。常见的场景包括: 父组件向子组件传递数据;子组件向父组件发送事件或数据;父组件直接调用子组件的方法或访问其属性。 Vue 提供了多种机制来实现…...

AXURE安装+汉化-Windows

安装网站:https://www.axure.com/release-history/rp9 Axure中文汉化包下载地址 链接:https://pan.baidu.com/s/1U62Azk8lkRPBqWAcrJMFew?pwd5418 提取码:5418 下载完成之后,crtlc lang文件夹 到下载的Axure路径下 双击点进这个目录里面。ctrlv把lan…...

ArcGIS Pro字段计算器与计算几何不可用,显示灰色

“字段计算器”不可用 如果计算字段命令不可用,请考虑以下可能性: 由 ArcGIS 管理的字段无法手动编辑。因此,无法计算 ObjectID(OID 或 FID)字段或地理数据库要素类的 Shape_Length 和 Shape_Area 字段的字段值。表中…...

mac电脑安装 nvm 报错如何解决

前言 已知:安装nvm成功;终端输入nvm -v 有版本返回 1. 启动全局配置环境变量失败 source ~/.zshrc~ 返回: source: no such file or directory: /Users/你的用户名/.zshrc~2 安装node失败 nvm install 16.13返回: mkdir: /U…...

第11节 Node.js 模块系统

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。 模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的…...

上海工作机会:Technical Writer Senior Technical Writer - 中微半导体设备

大名鼎鼎的中微半导体招聘文档工程师了,就是那家由中国半导体产业的领军人物尹志尧领导的、全员持股的公司。如果你还不了解他,赶快Deepseek一下“尹志尧”了解。 招聘职位:Technical Writer & Senior Technical Writer 公司名称&#…...

String 学习总结

1. 存储机制 短字符串优化(SSO, Small String Optimization) 现代标准库中的字符串实现普遍采用 SSO 技术,将长度较短(例如 ≤15 字节)的字符串数据直接存储在字符串对象内部的固定缓冲区(栈上)…...

Python微积分可视化:从导数到积分的交互式教学工具

Python微积分可视化:从导数到积分的交互式教学工具 一、引言 微积分是理解自然科学的基础,但抽象的导数、积分概念常让初学者感到困惑。本文基于Matplotlib开发一套微积分可视化工具,通过动态图像直观展示导数的几何意义、积分的近似计算及跨学科应用,帮助读者建立"数…...

Juce实现Table自定义

Juce实现Table自定义 一.总体展示概及概述 在项目中Juce中TableList往往无法满足用户需求,头部和背景及背景颜色设置以及在Cell中添加自定义按钮,所以需要自己实现自定义TabelList,该示例是展示实现自定义TableList,实现自定义标…...

【25.06】fabric进行caliper测试加环境部署

前置条件 安装一个Ubuntu20+的镜像 基础环境安装 Git cURL vim jq sudo apt install -y git curl vim jq Docker和Docker-compose 这个命令会自动安装docker sudo apt install docker-compose sudo chmod +x /usr/bin/docker-compose docker versiondocker-compose vers…...

【后端高阶面经:架构篇】51、搜索引擎架构与排序算法:面试关键知识点全解析

一、搜索引擎核心基石:倒排索引技术深度解析 (一)倒排索引的本质与构建流程 倒排索引(Inverted Index)是搜索引擎实现快速检索的核心数据结构,与传统数据库的正向索引(文档→关键词&#xff0…...

Windows应用-音视频捕获

下载“Windows应用-音视频捕获”项目 本应用可以同时捕获4个视频源和4个音频源,可以监视视频源图像,监听音频源;可以将视频源图像写入MP4文件,将音频源写入MP3或WAV文件;还可以录制系统播放的声音。本应用使用MFC对话框…...