Kubernetes官方java客户端之五:proto基本操作

简介: 实战K8S官方java客户端的protobuf基本操作

欢迎访问我的GitHub

https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

概览

  1. 本文是《Kubernetes官方java客户端》系列的第五篇,以下提到的java客户端都是指client-jar.jar
  2. 经过前面四篇文章的准备和尝试,我们对java客户端有了初步了解,也成功运行了hello world,接下来要做的是继续深入学习和实践,掌握这门利器;

两个主要脉络

  • java客户端的基本功能并不复杂,就是以何种手段发起对K8S资源的增删改查请求,把握以下两个主脉络即可:
  1. proto主线:用K8S官方的protobuf定义将各种资源生成java类,用少量API处理这些对象(特点,API极少,每个API都通用,处理所有类型的资源对象);
  2. openapi主线:使用openapi工具,将所有资源都自动生成增删改查的API(特点:API极多,每个资源都有自身的API);

今天的文章咱们来学习和了解proto主线

proto主线的核心类ProtoClient

  1. 前面曾提到proto主线的特点是API极少,咱们来看看这些少量的API的源头:ProtoClient类

在这里插入图片描述

  1. 如上图所示,ProtoClient提供了增删改查接口,我们可以用这些接口实现对K8S资源的操作;
  2. 有了接口,接下来要搞清楚参数怎么准备,先看create方法的源码,看它需要什么样的参数:

在这里插入图片描述

  1. 如上图所示,create方法的第一个参数就是K8S资源类,该类的特性是在泛型中约束的,必须实现com.google.protobuf.Message的子接口;
  2. 这些入参Message的子类从哪里来呢?例如我们要创建一个NameSpace的时候,是自己写一个Message子类?还是说哪里有现成的?接下来要做的就是搞清楚K8S资源类来自哪里?毕竟所有K8S资源的操作都要用上这些java类;
  3. 一起去java客户端的源码寻找线索,这是父子结构的maven工程,在名为client-java-proto的子工程中,它的README文件给出了线索,地址是:https://github.com/kubernetes-client/java/tree/master/proto ,如下图:

在这里插入图片描述

  1. 上图红框中的操作向我们揭示了整个过程:先去下载另一个github仓库,然后此仓库里有脚本generate.sh,该脚本根据protobuf配置生成java类,这些java文件被放置在java/proto/src/main/java目录下;
  2. 本文是学习K8S官方java客户端的文章,有关K8S的protobuf详情不在这里展开,只给出一段关键脚本供您参考,这是根据proto自动生成代码时执行的脚本,用于下载protobuf文件,地址:https://github.com/kubernetes-client/gen/blob/master/proto/dependencies.sh ,如下图:

在这里插入图片描述

  1. 上图红框中的地址是:https://raw.githubusercontent.com/kubernetes//api/master/rbac/v1alpha1/generated.proto ,内容如下,java客户端中的java代码就是根据这些内容生成的:

在这里插入图片描述

  1. 结合前面的分析,再回到java客户端源码的子工程client-java-proto,可以找到generate.sh脚本生成的V1.java,这个java文件里面有V1版本的所有protobuf对象,如下图:

在这里插入图片描述

  1. 上图红框中Namespace类是GeneratedMessageV3的子类,来看下GeneratedMessageV3的继承关系,如下图,该类实现了Message接口,满足ProtoClient.create方法对入参的泛型约束:

在这里插入图片描述

小结

  1. ProtoClient类提供的操作K8S资源的增删改查方法;
  2. java客户端的client-java-proto子工程内,有通过K8S官方protobuf生成的对象类,这些类就是ProtoClient的增删查用到的参数;
  3. 增删改查方法有了,涉及的对象也有了,接下来可以实战了;

实战前的准备

现在还不能马上写代码,还差最后一个准备步骤:确认API参数

  • 假设实战的内容是查询kube-system这个namespace下面的所有pod列表,那么API相关信息在哪获取:
  1. 打开API在线文档,我这里K8S版本是1.15,地址是:https: //v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/
  2. 如下图,红框1是pod列表的接口文档,红框2显示了该URL,有了这个URL我们可以编码了:

在这里插入图片描述

  1. 在今后的操作中,所有资源都可以根据该文档找到对应的API信息,辅助我们编码;
  2. 终于,可以开始实战了;

源码下载

  1. 如果您不想编码,可以在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协议
  1. 这个git项目中有多个文件夹,本章的应用在kubernetesclient文件夹下,如下图红框所示:

在这里插入图片描述

开始编码

  1. 打开《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>
  1. 新增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;
    }
}
  1. 上述代码展示了ProtoClient的API的用法,一个是获取pod列表,一个是创建namespace;

验证

  1. 确保K8S环境的config文件在本地可以访问(代码中kubeConfigPath变量的值);
  2. 运行ProtobufApplication;
  3. 先尝试获取kube-system这个namespace下的所有pod列表,在浏览器访问:http://localhost:8080/pods/kube-system ,响应如下图,红框中的items_数组就是所有pod信息:

在这里插入图片描述

  1. 上图中的items_数组,展开一个却name字段是byte数组,没办法看出真实内容:

在这里插入图片描述

  1. 借助IDEA的断点功能,可以看清上述name_字段的内容,如下图:

在这里插入图片描述

  1. 再来试试创建namespace的功能,浏览器执行:http://localhost:8080/createnamespace/aaabbbccc ,就会创建名为aaabbbccc的namespace,并将ProtoClient.create的返回信息展现到浏览器上:

在这里插入图片描述

  1. SSH登录上K8S服务器,查看namespace,如下图红框,可以见到新增的namespace:

在这里插入图片描述

  1. 验证完成,基于ProtoClient的API和K8S官方的在线API文档,我们可以轻松操作K8S环境;

ProtoClient的短板

  1. ProtoClient的短板其实在前面已经提到了,如下图红框4所示,在线API文档中提到查询pod列表的时候可以输入一些参数(例如过滤条件),但是ProtoClient提供的API咱们也看过了,并不支持输入查询参数:

在这里插入图片描述

  1. 来看下ProtoClient请求K8S Api service的核心代码,如下图红框所示,请求参数字段已经写死,所以外面调用ProtoClient的API时根本没办法把参数传进来:

在这里插入图片描述

  1. 咱们可以参考上述代码自己写一段,把红框位置改为API文档中指定的参数,但是,这样似乎略微麻烦,还有更好的办法吗?
  • 当然有,敬请期待下一篇,一起学习和实战openapi主线;

欢迎关注阿里云开发者社区:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...
相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
人工智能 Java API
MCP客户端调用看这一篇就够了(Java版)
本文详细介绍了MCP(Model Context Protocol)客户端的开发方法,包括在没有MCP时的痛点、MCP的作用以及如何通过Spring-AI框架和原生SDK调用MCP服务。文章首先分析了MCP协议的必要性,接着分别讲解了Spring-AI框架和自研SDK的使用方式,涵盖配置LLM接口、工具注入、动态封装工具等步骤,并提供了代码示例。此外,还记录了开发过程中遇到的问题及解决办法,如版本冲突、服务连接超时等。最后,文章探讨了框架与原生SDK的选择,认为框架适合快速构建应用,而原生SDK更适合平台级开发,强调了两者结合使用的价值。
6051 33
MCP客户端调用看这一篇就够了(Java版)
|
4月前
|
存储 网络协议 Java
Java获取客户端IP问题:返回127.0.0.1
总结:要解决Java获取客户端IP返回127.0.0.1的问题,首先要找出原因,再采取合适的解决方案。请参考上述方案来改进代码,确保在各种网络环境下都能正确获取客户端IP地址。希望本文对您有所帮助。
275 25
|
6月前
|
Kubernetes 负载均衡 Java
k8s的出现解决了java并发编程胡问题了
Kubernetes通过提供自动化管理、资源管理、服务发现和负载均衡、持续交付等功能,有效地解决了Java并发编程中的许多复杂问题。它不仅简化了线程管理和资源共享,还提供了强大的负载均衡和故障恢复机制,确保应用程序在高并发环境下的高效运行和稳定性。通过合理配置和使用Kubernetes,开发者可以显著提高Java应用程序的性能和可靠性。
122 31
|
10月前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
743 4
|
12月前
|
JSON NoSQL Java
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
这篇文章介绍了在Java中使用Redis客户端的几种方法,包括Jedis、SpringDataRedis和SpringBoot整合Redis的操作。文章详细解释了Jedis的基本使用步骤,Jedis连接池的创建和使用,以及在SpringBoot项目中如何配置和使用RedisTemplate和StringRedisTemplate。此外,还探讨了RedisTemplate序列化的两种实践方案,包括默认的JDK序列化和自定义的JSON序列化,以及StringRedisTemplate的使用,它要求键和值都必须是String类型。
redis的java客户端的使用(Jedis、SpringDataRedis、SpringBoot整合redis、redisTemplate序列化及stringRedisTemplate序列化)
|
11月前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
289 3
|
11月前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
191 1
|
12月前
|
存储 Kubernetes Cloud Native
部署Kubernetes客户端和Docker私有仓库的步骤
这个指南涵盖了部署Kubernetes客户端和配置Docker私有仓库的基本步骤,是基于最新的实践和工具。根据具体的需求和环境,还可能需要额外的配置和调整。
262 1
|
12月前
|
Kubernetes Cloud Native Java
探索未来编程新纪元:Quarkus带你秒建高性能Kubernetes原生Java应用,云原生时代的技术狂欢!
Quarkus 是专为 Kubernetes 设计的全栈云原生 Java 框架,凭借其轻量级、快速启动及高效执行特性,在 Java 社区脱颖而出。通过编译时优化与原生镜像支持,Quarkus 提升了应用性能,同时保持了 Java 的熟悉度与灵活性。本文将指导你从创建项目、编写 REST 控制器到构建与部署 Kubernetes 原生镜像的全过程,让你快速上手 Quarkus,体验高效开发与部署的乐趣。
334 1
|
4月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
144 9

热门文章

最新文章