2024年Go最全client-go实战之三:Clientset(3),设计思想解读开源框架

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

在这里插入图片描述

  • Clientset果然名副其实,是所有Group和Version组合对象的集合,不过Group和Version组合对象到底是啥呢?以appsV1字段为例,去看看其类型appsv1.AppsV1Client,如下图,AppsV1Client只有一字段,就是咱们熟悉的restClient,所以RESTClient是Clientset的基础,这话没毛病,另外注意红框2中的Deployments方法,返回的是DeploymentInterface接口实现:

在这里插入图片描述

  • 顺藤摸瓜去看DeploymentInterface,打开deployment.go文件后真相大白,接口定义的和实现一目了然:

在这里插入图片描述

  • 挑一个接口实现的代码看看,就选新建deployment的方法吧,如下,和我们使用RESTClient编码差不多:

func (c *deployments) Create(ctx context.Context, deployment *v1.Deployment, opts metav1.CreateOptions) (result *v1.Deployment, err error) {

result = &v1.Deployment{}

err = c.client.Post().

Namespace(c.ns).

Resource(“deployments”).

VersionedParams(&opts, scheme.ParameterCodec).

Body(deployment).

Do(ctx).

Into(result)

return

}

  • 至此,您对Clientset应该心里有数了:其实就是把我们使用RESTClient操作资源的代码按照Group和Version分类再封装而已,这不像技术活,更像体力活—所以,这种体力活是谁做的呢?如下图红框所示,源码中已经注明这些代码是工具client-gen自动生成的:

在这里插入图片描述

  • 至此,Clientset的源码速度就算完成了,咱们已经知道了Clientset的内幕,接下来开始尝试使用它;

需求确认

  • 本次编码实战的需求如下:

  • 写一段代码,检查用户输入的operate参数,该参数默认是create,也可以接受clean;

  • 如果operate参数等于create,就执行以下操作:

  1. 新建名为test-clientset的namespace

  2. 新建一个deployment,namespace为test-clientset,镜像用tomcat,副本数为2

  3. 新建一个service,namespace为test-clientset,类型是NodePort

  • 如果operate参数等于clean,就删除create操作中创建的service、deployment、namespace等资源:

  • 以上需求使用Clientset客户端实现,完成后咱们用浏览器访问来验证tomcat是否正常;

源码下载

  • 本篇实战中的源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):

| 名称 | 链接 | 备注 |

| :-- | :-- | :-- |

| 项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |

| git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |

| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |

  • 这个git项目中有多个文件夹,client-go相关的应用在client-go-tutorials文件夹下,如下图红框所示:

在这里插入图片描述

  • client-go-tutorials文件夹下有多个子文件夹,本篇对应的源码在clientsetdemo目录下,如下图红框所示:

在这里插入图片描述

编码

  • 新建文件夹restclientdemo,在里面执行以下命令,新建module:

go mod init clientsetdemo

  • 添加k8s.io/api和k8s.io/client-go这两个依赖,注意版本要匹配kubernetes环境:

go get k8s.io/api@v0.20.0

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

  • 新建main.go,内容如下,已经都添加了详细的注释,就不赘述了:

package main

import (

“context”

“flag”

“fmt”

appsv1 “k8s.io/api/apps/v1”

apiv1 “k8s.io/api/core/v1”

metav1 “k8s.io/apimachinery/pkg/apis/meta/v1”

“k8s.io/client-go/kubernetes”

“k8s.io/client-go/tools/clientcmd”

“k8s.io/client-go/util/homedir”

“k8s.io/utils/pointer”

“path/filepath”

)

const (

NAMESPACE = “test-clientset”

DEPLOYMENT_NAME = “client-test-deployment”

SERVICE_NAME = “client-test-service”

)

func main() {

var kubeconfig *string

// home是家目录,如果能取得家目录的值,就可以用来做默认值

if home:=homedir.HomeDir(); home != “” {

// 如果输入了kubeconfig参数,该参数的值就是kubeconfig文件的绝对路径,

// 如果没有输入kubeconfig参数,就用默认路径~/.kube/config

kubeconfig = flag.String(“kubeconfig”, filepath.Join(home, “.kube”, “config”), “(optional) absolute path to the kubeconfig file”)

} else {

// 如果取不到当前用户的家目录,就没办法设置kubeconfig的默认目录了,只能从入参中取

kubeconfig = flag.String(“kubeconfig”, “”, “absolute path to the kubeconfig file”)

}

// 获取用户输入的操作类型,默认是create,还可以输入clean,用于清理所有资源

operate := flag.String(“operate”, “create”, “operate type : create or clean”)

flag.Parse()

// 从本机加载kubeconfig配置文件,因此第一个参数为空字符串

config, err := clientcmd.BuildConfigFromFlags(“”, *kubeconfig)

// kubeconfig加载失败就直接退出了

if err != nil {

panic(err.Error())

}

// 实例化clientset对象

clientset, err := kubernetes.NewForConfig(config)

if err!= nil {

panic(err.Error())

}

fmt.Printf(“operation is %v\n”, *operate)

// 如果要执行清理操作

if “clean”==*operate {

clean(clientset)

} else {

// 创建namespace

createNamespace(clientset)

// 创建deployment

createDeployment(clientset)

// 创建service

createService(clientset)

}

}

// 清理本次实战创建的所有资源

func clean(clientset *kubernetes.Clientset) {

emptyDeleteOptions := metav1.DeleteOptions{}

// 删除service

if err := clientset.CoreV1().Services(NAMESPACE).Delete(context.TODO(), SERVICE_NAME, emptyDeleteOptions) ; err != nil {

panic(err.Error())

}

// 删除deployment

if err := clientset.AppsV1().Deployments(NAMESPACE).Delete(context.TODO(), DEPLOYMENT_NAME, emptyDeleteOptions) ; err != nil {

panic(err.Error())

}

// 删除namespace

if err := clientset.CoreV1().Namespaces().Delete(context.TODO(), NAMESPACE, emptyDeleteOptions) ; err != nil {

panic(err.Error())

}

}

// 新建namespace

func createNamespace(clientset *kubernetes.Clientset) {

namespaceClient := clientset.CoreV1().Namespaces()

namespace := &apiv1.Namespace{

ObjectMeta: metav1.ObjectMeta{

Name: NAMESPACE,

},

}

result, err := namespaceClient.Create(context.TODO(), namespace, metav1.CreateOptions{})

if err!=nil {

panic(err.Error())

}

fmt.Printf(“Create namespace %s \n”, result.GetName())

}

// 新建service

func createService(clientset *kubernetes.Clientset) {

// 得到service的客户端

serviceClient := clientset.CoreV1().Services(NAMESPACE)

// 实例化一个数据结构

service := &apiv1.Service{

ObjectMeta: metav1.ObjectMeta{

Name: SERVICE_NAME,

},

Spec: apiv1.ServiceSpec{

Ports: []apiv1.ServicePort{{

Name: “http”,

Port: 8080,

NodePort: 30080,

},

},

Selector: map[string]string{

“app” : “tomcat”,

},

Type: apiv1.ServiceTypeNodePort,

},

}

result, err := serviceClient.Create(context.TODO(), service, metav1.CreateOptions{})

if err!=nil {

panic(err.Error())

}

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

erviceClient.Create(context.TODO(), service, metav1.CreateOptions{})

if err!=nil {

panic(err.Error())

}

[外链图片转存中…(img-cQtZQExt-1715366429439)]
[外链图片转存中…(img-HbxK4SL9-1715366429439)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值