欢迎访问我的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. 冒泡排序(bubble_sort)——Python实现

      # 冒泡排序 # 作用:对给出的n个顺序不定的数进行排序 # 输入:任意数组A # 输出:按顺序排列的数组A   # 冒泡排序过程 # 第一趟:以第一个数为基准,从最后一位数开始,依次与它比较, ...

  2. LS-DYNA SMP R11.1.0 for Win64安装破解教程

    LS-DYNA SMP R11.1.0是一款极其强大的有限元仿真分析工具,可以模拟现实世界的问题.主要用于分析结构的非线性响应等操作,其全自动接触分析和广泛的材料模型使全球用户能够解决复杂的现实问题. ...

  3. SpringMVC中文乱码踩坑

    问题 使用SpringMVC在返回一个字符串时发生了中文乱码问题.produces属性无效 @RequestMapping(value = "/nihao", produces = ...

  4. 获取不到自定义的request的header属性

    java获取headers的代码如下: // 获取http-header里面对应的签名信息 Enumeration<?> headerNames = request.getHeaderNa ...

  5. joomla 3.7.0 (CVE-2017-8917) SQL注入漏洞

    影响版本: 3.7.0 poc http://192.168.49.2:8080/index.php?option=com_fields&view=fields&layout=moda ...

  6. Vue Router根据后台数据加载不同的组件(思考->实现->不止于实现)

    实际项目中遇到的需求 同一个链接需要加载不同的页面组件.根据用户所购买服务的不同,有不同的页面展现. 有一些不好的实现方式 直接把这几个组件写在同一个组件下,通过v-if去判断.如果这么做的话,甚至可 ...

  7. C语言运算符(位运算符)+(赋值运算符)

    实列 1 #include <stdio.h> 2 3 int main() 4 { 5 6 unsigned int a = 60; /* 60 = 0011 1100 */ 7 uns ...

  8. Top10 应用都在用的Android最新知识

    相信各位对Jetpack并不陌生,自从 Google 在 2018 年推出 Jetpack 之后,它就成为了 Android 未来发展的指向标. 作为一名安卓工程师,我们以前会经常吐槽Android碎 ...

  9. 第一个Java文件

    HelloWorld 1.新建一个文件夹,用来存放java文件的 2.用subline来编辑第一个Java文件 要注意的是java的文件名为.java 我们自定义的文件名是Hello 3.编写第一个j ...

  10. springboot上传文件路径存放

    @Beanpublic EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer() { return (Config ...