Kubernetes官方java客户端之五:proto基本操作
欢迎访问我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
概览
- 本文是《Kubernetes官方java客户端》系列的第五篇,以下提到的java客户端都是指client-jar.jar;
- 经过前面四篇文章的准备和尝试,我们对java客户端有了初步了解,也成功运行了hello world,接下来要做的是继续深入学习和实践,掌握这门利器;
两个主要脉络
- java客户端的基本功能并不复杂,就是以何种手段发起对K8S资源的增删改查请求,把握以下两个主脉络即可:
- proto主线:用K8S官方的protobuf定义将各种资源生成java类,用少量API处理这些对象(特点,API极少,每个API都通用,处理所有类型的资源对象);
- openapi主线:使用openapi工具,将所有资源都自动生成增删改查的API(特点:API极多,每个资源都有自身的API);
今天的文章咱们来学习和了解proto主线;
proto主线的核心类ProtoClient
前面曾提到proto主线的特点是API极少,咱们来看看这些少量的API的源头:ProtoClient类
如上图所示,ProtoClient提供了增删改查接口,我们可以用这些接口实现对K8S资源的操作;
有了接口,接下来要搞清楚参数怎么准备,先看create方法的源码,看它需要什么样的参数:
如上图所示,create方法的第一个参数就是K8S资源类,该类的特性是在泛型中约束的,必须实现com.google.protobuf.Message的子接口;
这些入参Message的子类从哪里来呢?例如我们要创建一个NameSpace的时候,是自己写一个Message子类?还是说哪里有现成的?接下来要做的就是搞清楚K8S资源类来自哪里?毕竟所有K8S资源的操作都要用上这些java类;
一起去java客户端的源码寻找线索,这是父子结构的maven工程,在名为client-java-proto的子工程中,它的README文件给出了线索,地址是:https://github.com/kubernetes-client/java/tree/master/proto ,如下图:
上图红框中的操作向我们揭示了整个过程:先去下载另一个github仓库,然后此仓库里有脚本generate.sh,该脚本根据protobuf配置生成java类,这些java文件被放置在java/proto/src/main/java目录下;
本文是学习K8S官方java客户端的文章,有关K8S的protobuf详情不在这里展开,只给出一段关键脚本供您参考,这是根据proto自动生成代码时执行的脚本,用于下载protobuf文件,地址:https://github.com/kubernetes-client/gen/blob/master/proto/dependencies.sh ,如下图:
上图红框中的地址是:https://raw.githubusercontent.com/kubernetes//api/master/rbac/v1alpha1/generated.proto ,内容如下,java客户端中的java代码就是根据这些内容生成的:
结合前面的分析,再回到java客户端源码的子工程client-java-proto,可以找到generate.sh脚本生成的V1.java,这个java文件里面有V1版本的所有protobuf对象,如下图:
上图红框中Namespace类是GeneratedMessageV3的子类,来看下GeneratedMessageV3的继承关系,如下图,该类实现了Message接口,满足ProtoClient.create方法对入参的泛型约束:
小结
- ProtoClient类提供的操作K8S资源的增删改查方法;
- java客户端的client-java-proto子工程内,有通过K8S官方protobuf生成的对象类,这些类就是ProtoClient的增删查用到的参数;
- 增删改查方法有了,涉及的对象也有了,接下来可以实战了;
实战前的准备
现在还不能马上写代码,还差最后一个准备步骤:确认API参数;
- 假设实战的内容是查询kube-system这个namespace下面的所有pod列表,那么API相关信息在哪获取:
打开API在线文档,我这里K8S版本是1.15,地址是:https://v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/
如下图,红框1是pod列表的接口文档,红框2显示了该URL,有了这个URL我们可以编码了:
在今后的操作中,所有资源都可以根据该文档找到对应的API信息,辅助我们编码;
终于,可以开始实战了;
源码下载
- 如果您不想编码,可以在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项目中有多个文件夹,本章的应用在kubernetesclient文件夹下,如下图红框所示:
开始编码
- 打开《Kubernetes官方java客户端之一:准备 》中创建的kubernetesclient工程,在里面新建子工程protobufclient,其pom.xml内容如下,要注意的是spring-boot-starter-json已经被排除,因此序列化工具会变为Gson(原本默认是jackson):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>kubernetesclient</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>protobufclient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>protobufclient</name>
<description>Demo project for protobuf client</description>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.kubernetes</groupId>
<artifactId>client-java</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
</plugin>
</plugins>
</build>
</project>
- 新增ProtobufApplication.java,这是新工程的引导类,也有通过ProtoClient查询pod列表的代码:
package com.bolingcavalry.protobufclient;
import com.google.gson.GsonBuilder;
import io.kubernetes.client.ProtoClient;
import io.kubernetes.client.ProtoClient.ObjectOrStatus;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.proto.Meta;
import io.kubernetes.client.proto.V1.Namespace;
import io.kubernetes.client.proto.V1.PodList;
import io.kubernetes.client.util.ClientBuilder;
import io.kubernetes.client.util.KubeConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.FileReader;
@SpringBootApplication
@RestController
@Slf4j
public class ProtobufApplication {
public static void main(String[] args) {
SpringApplication.run(ProtobufApplication.class, args);
}
/**
* 根据配置文件创建ProtoClient实例
* @return
* @throws Exception
*/
private ProtoClient buildProtoClient() throws Exception {
// 存放K8S的config文件的全路径
String kubeConfigPath = "/Users/zhaoqin/temp/202007/05/config";
// 以config作为入参创建的client对象,可以访问到K8S的API Server
ApiClient client = ClientBuilder
.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath)))
.build();
// 创建操作类
return new ProtoClient(client);
}
@RequestMapping(value = "/createnamespace/{namespace}", method = RequestMethod.GET)
public ObjectOrStatus<Namespace> createnamespace(@PathVariable("namespace") String namespace) throws Exception {
// 创建namespace资源对象
Namespace namespaceObj =
Namespace.newBuilder().setMetadata(Meta.ObjectMeta.newBuilder().setName(namespace).build()).build();
// 通过ProtoClient的create接口在K8S创建namespace
ObjectOrStatus<Namespace> ns = buildProtoClient().create(namespaceObj, "/api/v1/namespaces", "v1", "Namespace");
// 使用Gson将集合对象序列化成JSON,在日志中打印出来
log.info("ns info \n{}", new GsonBuilder().setPrettyPrinting().create().toJson(ns));
return ns;
}
@RequestMapping(value = "/pods/{namespace}", method = RequestMethod.GET)
public ObjectOrStatus<PodList> pods(@PathVariable("namespace") String namespace) throws Exception {
// 通过ProtoClient的list接口获取指定namespace下的pod列表
ObjectOrStatus<PodList> pods = buildProtoClient().list(PodList.newBuilder(), "/api/v1/namespaces/" + namespace + "/pods");
// 使用Gson将集合对象序列化成JSON,在日志中打印出来
log.info("pod info \n{}", new GsonBuilder().setPrettyPrinting().create().toJson(pods));
return pods;
}
}
- 上述代码展示了ProtoClient的API的用法,一个是获取pod列表,一个是创建namespace;
验证
确保K8S环境的config文件在本地可以访问(代码中kubeConfigPath变量的值);
运行ProtobufApplication;
先尝试获取kube-system这个namespace下的所有pod列表,在浏览器访问:http://localhost:8080/pods/kube-system ,响应如下图,红框中的items_数组就是所有pod信息:
上图中的items_数组,展开一个却name字段是byte数组,没办法看出真实内容:
借助IDEA的断点功能,可以看清上述name_字段的内容,如下图:
再来试试创建namespace的功能,浏览器执行:http://localhost:8080/createnamespace/aaabbbccc ,就会创建名为aaabbbccc的namespace,并将ProtoClient.create的返回信息展现到浏览器上:
SSH登录上K8S服务器,查看namespace,如下图红框,可以见到新增的namespace:
验证完成,基于ProtoClient的API和K8S官方的在线API文档,我们可以轻松操作K8S环境;
ProtoClient的短板
ProtoClient的短板其实在前面已经提到了,如下图红框4所示,在线API文档中提到查询pod列表的时候可以输入一些参数(例如过滤条件),但是ProtoClient提供的API咱们也看过了,并不支持输入查询参数:
来看下ProtoClient请求K8S Api service的核心代码,如下图红框所示,请求参数字段已经写死,所以外面调用ProtoClient的API时根本没办法把参数传进来:
咱们可以参考上述代码自己写一段,把红框位置改为API文档中指定的参数,但是,这样似乎略微麻烦,还有更好的办法吗?
- 当然有,敬请期待下一篇,一起学习和实战openapi主线;
你不孤单,欣宸原创一路相伴
欢迎关注公众号:程序员欣宸
微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...
https://github.com/zq2599/blog_demos
Kubernetes官方java客户端之五:proto基本操作的更多相关文章
- Kubernetes官方java客户端之六:OpenAPI基本操作
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Kubernetes官方java客户端之七:patch操作
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Kubernetes官方java客户端之一:准备
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Kubernetes官方java客户端之二:序列化和反序列化问题
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Kubernetes官方java客户端之三:外部应用
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Kubernetes官方java客户端之四:内部应用
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Kubernetes官方java客户端之八:fluent style
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Apache Zookeeper Java客户端Curator使用及权限模式详解
这篇文章是让大家了解Zookeeper基于Java客户端Curator的基本操作,以及如何使用Zookeeper解决实际问题. Zookeeper基于Java访问 针对zookeeper,比较常用的J ...
- Java与WCF交互(一)补充:用WSImport生成WSDL的Java客户端代码
在<Java与WCF交互(一):Java客户端调用WCF服务>一 文中,我描述了用axis2的一个Eclipse控件生成WCF的Java客户端代理类,后来有朋友建议用Xfire.CXF,一 ...
随机推荐
- PHP代码审计分段讲解(12)
28题 <!DOCTYPE html> <html> <head> <title>Web 350</title> <style typ ...
- [BJDCTF2020]Mark loves cat && [BJDCTF 2nd]简单注入 && [BJDCTF2020]The mystery of ip
[BJDCTF2020]Mark loves cat 源码泄露 使用GitHack.py下载源码 下载之后对源代码进行审计 flag.php代码为: <?php $flag = file_get ...
- web网络漏洞扫描器编写
这两天看了很多web漏洞扫描器编写的文章,比如W12scan以及其前身W8scan,还有猪猪侠的自动化攻击背景下的过去.现在与未来,以及网上很多优秀的扫描器和博客,除了之前写了一部分的静湖ABC段扫描 ...
- 【面试题】在浏览器中输入URL后,执行的全部过程。会用到哪些协议?(一次完整的HTTP请求过程)
整个流程如下: 域名解析 为了将消息从你的PC上传到服务器上,需要用到IP协议.ARP协议和OSPF协议. 发起TCP的三次握手 建立TCP连接后发起HTTP请求 服务器响应HTTP请求 浏览器解析h ...
- python 保存list,map方法
1. 保存list import numpy as np a = [1,2,3,4,5] np.save("number.npy", a) k = np.load("nu ...
- 题解 P5401 [CTS2019]珍珠
蒟蒻语 这题太玄学了,蒟蒻写篇题解来让之后复习 = = 蒟蒻解 假设第 \(i\) 个颜色有 \(cnt_i\) 个珍珠. \(\sum\limits_{i=1}^{n} \left\lfloor\f ...
- 题解-洛谷P4859 已经没有什么好害怕的了
洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...
- linux修改文件所属的用户组以及用户
linux修改文件所属的用户组以及用户 将文件夹从A用户(huangxf)目录复制B用户(zhenglf)目录,其中B没有sudo权限.将A的Downloads文件夹下的所有文件,复制到B的Docum ...
- web前端常用js插件
第一款:截图插件html2Canvas.js html2是一款强大的截图插件,只需引入js文件,依照官方给定的截图方法,就能截取对应DOM区域的内容.对于有些截图出现模糊偏移的问题,网上也有一堆解决方 ...
- 浏览器小程序(Browser Applet)闪亮登场
2017 年 1 月 9 日,微信小程序横空出世.随后,支付宝小程序.今日头条小程序.百度智能小程序.360小程序等纷纷推出,自此国内软件功能扩展领域进入到了小程序时代,小程序为丰富其宿主软件的功能和 ...