欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

系列文章链接

  1. client-go实战之一:准备工作
  2. client-go实战之二:RESTClient
  3. client-go实战之三:Clientset
  4. client-go实战之四:dynamicClient
  5. client-go实战之五:DiscoveryClient

本篇概览

  • 本文是《client-go实战》系列的第二篇,前文咱们提到过client-go一共有四种客户端:RESTClient、ClientSet、DynamicClient、DiscoveryClient,而RESTClient是最基础的版本,其他三种都是基于RESTClient封装的,今天咱们通过实战编码来学习RESTClient,熟悉最基础的远程操作步骤;
  • 本篇由以下几部分组成:
  1. 简介RESTClient
  2. 每次编码前的准备工作
  3. 正式编码
  4. 验证
  5. 关键源码分析

RESTClient简介

  • RESTClient是client-go最基础的客户端,主要是对HTTP Reqeust进行了封装,对外提供RESTful风格的API,并且提供丰富的API用于各种设置,相比其他几种客户端虽然更复杂,但是也更为灵活;
  • 使用RESTClient对kubernetes的资源进行增删改查的基本步骤如下:
  1. 确定要操作的资源类型(例如查找deployment列表),去官方API文档中找到对于的path、数据结构等信息,后面会用到;
  2. 加载配置kubernetes配置文件(和kubectl使用的那种kubeconfig完全相同);
  3. 根据配置文件生成配置对象,并且通过API对配置对象就行设置(例如请求的path、Group、Version、序列化反序列化工具等);
  4. 创建RESTClient实例,入参是配置对象;
  5. 调用RESTClient实例的方法向kubernetes的API Server发起请求,编码用fluent风格将各种参数传入(例如指定namespace、资源等),如果是查询类请求,还要传入数据结构实例的指针,改数据结构用于接受kubernetes返回的查询结果;
  • 接下来的编码实战也是按照上述流程进行的;

实战内容

  • 本次实战内容很简单:查询kube-system这个namespace下的所有pod,然后在控制台打印每个pod的几个关键字段;
  • 感谢您耐心听我啰嗦了一大堆,接下来开始实战吧;

源码下载

名称 链接 备注
项目主页 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文件夹下有多个子文件夹,本篇对应的源码在restclientdemo目录下,如下图红框所示:

查看官方文档,获取编码所需内容

  • 然后还要关注响应的数据结构,如下图红框,返回的是:

  • 点击上图红框中的内容,可见PodList的详情,这就是我们编码时所需的数据结构:

  • 掌握了请求和响应的详细信息,可以开始编码了;

编码

  • 新建文件夹restclientdemo,在里面执行以下命令,新建module:
go mod init restclientdemo
  • 添加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"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"path/filepath"
) 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")
} flag.Parse() // 从本机加载kubeconfig配置文件,因此第一个参数为空字符串
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) // kubeconfig加载失败就直接退出了
if err != nil {
panic(err.Error())
} // 参考path : /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 {
panic(err.Error())
} // 保存pod结果的数据结构实例
result := &corev1.PodList{} // 指定namespace
namespace := "kube-system"
// 设置请求参数,然后发起请求
// GET请求
err = restClient.Get().
// 指定namespace,参考path : /api/v1/namespaces/{namespace}/pods
Namespace(namespace).
// 查找多个pod,参考path : /api/v1/namespaces/{namespace}/pods
Resource("pods").
// 指定大小限制和序列化工具
VersionedParams(&metav1.ListOptions{Limit:100}, scheme.ParameterCodec).
// 请求
Do(context.TODO()).
// 结果存入result
Into(result) if err != nil {
panic(err.Error())
} // 表头
fmt.Printf("namespace\t status\t\t name\n") // 每个pod都打印namespace、status.Phase、name三个字段
for _, d := range result.Items {
fmt.Printf("%v\t %v\t %v\n",
d.Namespace,
d.Status.Phase,
d.Name)
}
}
  • 编码完成,执行go run main.go,即可获取指定namespace下所有pod的信息,控制台输出如下:
(base) zhaoqindeMBP:restclientdemo zhaoqin$ go run main.go
namespace status name
kube-system Running coredns-7f89b7bc75-5pdwc
kube-system Running coredns-7f89b7bc75-nvbvm
kube-system Running etcd-hedy
kube-system Running kube-apiserver-hedy
kube-system Running kube-controller-manager-hedy
kube-system Running kube-flannel-ds-v84vc
kube-system Running kube-proxy-hlppx
kube-system Running kube-scheduler-hedy
  • 至此,RESTClient客户端从编码到验证都完成了;

如何将收到的数据反序列化为PodList对象?

  • 前面的代码比较简单,但是有一处引起了我的兴趣,如下图红框所示,result是corev1.PodList类型的结构体指针,restClient收到kubernetes返回的数据后,如何知道要将数据反序列化成corev1.PodList类型呢(Into方法入参类型为runtime.Object)?

  • 之前的代码中有一行设置了编解码工具:config.NegotiatedSerializer = scheme.Codecs,展开这个scheme.Codecs,可见设置的时候确定了序列化工具为runtime.Serializer:

  • Serializer的typer字段类型是runtime.ObjectTyper,这里实际上是runtime.Scheme,因此ObjectTyper.ObjectKinds方法,实际上就是Scheme.ObjectKinds方法,在里面根据s.typeToGVK[t]拿到了GVK,也就是v1.PodList:

  • 有了这个GVK就确定的返回数据的类型,最终调用caseSensitiveJSONIterator.Unmarshal(data, obj)完成byte数组到对象的反序列化操作:

  • 最后还有一行关键代码,将data的内容写到最外层的Into方法的入参中:

  • 源码分析完成,简单来说除了利用反射获取实际类型,还有就是Scheme内部维护的数据类型和GVK的关系映射表;
  • 至此,RESTClient的实战就完成了,希望本篇能帮助您打好基础,这样后面在体验其他三种客户端时已对其底层的实现原理了然于胸;

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...

https://github.com/zq2599/blog_demos

client-go实战之二:RESTClient的更多相关文章

  1. [Java聊天室server]实战之二 监听类

    前言 学习不论什么一个稍有难度的技术,要对其有充分理性的分析,之后果断做出决定---->也就是人们常说的"多谋善断":本系列尽管涉及的是socket相关的知识,但学习之前,更 ...

  2. apollo入门demo实战(二)

    1. apollo入门demo实战(二) 1.1. 下载demo 从下列地址下载官方脚本和官方代码 https://github.com/nobodyiam/apollo-build-scripts ...

  3. Spring Boot 揭秘与实战(二) 数据存储篇 - ElasticSearch

    文章目录 1. 版本须知 2. 环境依赖 3. 数据源 3.1. 方案一 使用 Spring Boot 默认配置 3.2. 方案二 手动创建 4. 业务操作5. 总结 4.1. 实体对象 4.2. D ...

  4. Docker从入门到实战(二)

    Docker从入门到实战(二) 一:什么是docker Docker是一个开源的应用容器引擎,开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到主流的Linux.MacOS.Windo ...

  5. MySQL数据库复制技术应用实战(阶段二)

    MySQL数据库复制技术应用实战(阶段二)文档 作者 刘畅 时间 2020-9-27 服务器版本:CentOS Linux release 7.5.1804 主机名 ip地址 服务器配置 安装软件 密 ...

  6. kubebuilder实战之二:初次体验kubebuilder

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. 非阻塞同步算法实战(二)-BoundlessCyclicBarrier

    本人是本文的作者,首发于ifeve(非阻塞同步算法实战(二)-BoundlessCyclicBarrier) 前言 相比上一 篇而言,本文不需要太多的准备知识,但技巧性更强一些.因为分析.设计的过程比 ...

  8. 响应性web设计实战总结(二)

    响应性web设计实战总结(二) 阅读目录 背景知识: Gulp-less安装及配置如下 对响应性web总结,之前总结过2篇文章:可以看如下: http://www.cnblogs.com/tugenh ...

  9. [原创].NET 分布式架构开发实战之二 草稿设计

    原文:[原创].NET 分布式架构开发实战之二 草稿设计 .NET 分布式架构开发实战之二 草稿设计 前言:本篇之所以称为草稿设计,是因为设计的都是在纸上完成的.反映了一个思考的过程. 本篇的议题如下 ...

随机推荐

  1. SLF4J日志桥接的应用

    最近在给公司的测试部门开发一套自动化测试框架,为了是框架产生的测试报告更易于分析,我考虑将每一个用例与运行过程中产生的日志相关联,为了实现这样的效果,首先就需要统一项目的日志输出,那么具体怎么做呢? ...

  2. 【LeetCode】98. 验证二叉搜索树

    98. 验证二叉搜索树 知识点:二叉树:递归 题目描述 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大 ...

  3. 漫谈CUDA优化

    ​ 作者:Lawliet 翻译:仿佛若有光 前言: 几个月前,我根据 Simoncelli 2016 年的论文编写了自己的自动编码器,用于研究目的.一开始,我想使用一些流行的深度学习框架(例如 Ten ...

  4. netty系列之:netty中的ByteBuf详解

    目录 简介 ByteBuf详解 创建一个Buff 随机访问Buff 序列读写 搜索 其他衍生buffer方法 和现有JDK类型的转换 总结 简介 netty中用于进行信息承载和交流的类叫做ByteBu ...

  5. EL表达式和JSTL标签

    什么是 EL 表达式,EL 表达式的作用? EL 表达式的全称是:Expression Language.是表达式语言. EL 表达式的什么作用:EL 表达式主要是代替 jsp 页面中的表达式脚本在 ...

  6. CMMI相关图书

    Integrating CMMI and Agile Development: Case Studies and Proven Techniques for Faster Performance Im ...

  7. 【笔记】CART与决策树中的超参数

    CART与决策树中的超参数 先前的决策树其实应该称为CART CART的英文是Classification and regression tree,全称为分类与回归树,其是在给定输入随机变量X条件下输 ...

  8. 能说会道爱办公——“别人家的”Chrome插件到底怎么做

    根据相关数据显示,谷歌的Chrome浏览器目前已达近七成的市场占有率,成为浏览器的"霸主".大家选择Chrome,除了是因为性能的优越以及强大的兼容性之外,Chrome充足的扩展插 ...

  9. 分享一份【饿了么】Java面试专家岗面试题,欢迎留言交流哦!

    前段时间有小伙伴去饿了么面试Java专家岗,记录了一面技术相关的问题,大家可以看看. 基础问题 1.数据库事务的隔离级别? 2.事务的几大特性,并谈一下实现原理 3.如何用redis实现消息的发布订阅 ...

  10. ASP.NET Core 修改开源协议为MIT,.NET全平台 MIT协议开源了

    2021年7月23日,.NET开发团队完成了所有的.NET平台的相关框架的MIT协议更改,我们可以通过 https://github.com/dotnet/aspnetcore/issues/1887 ...