百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

K8S官方java客户端之六:OpenAPI基本操作

wptr33 2024-11-16 01:28 25 浏览

欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

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

概览

  • 本文是《K8S官方java客户端》系列的第六篇,以下提到的java客户端都是指client-jar.jar
  • 前文《K8S官方java客户端之五:proto基本操作 》已经提到,java客户端的基本功能由两个主要脉络组成,第一个是proto,主要功能是使用ProtoClient类提供的增删改查接口,这些接口用到的入参和返回对象所涉及到的java类,都是通过K8S的protobuf生成的;
  • 除了使用ProtoClient对K8S资源进行增删改查,还提供了另一种更强大的方式:OpenAPI,本章咱们就来一起学习OpenAPI相关的操作;

K8S的OpenAPI

  • 先抛开java客户端不提,咱们来看看K8S本身的OpenAPI,地址是:https://kubernetes.io/zh/docs/concepts/overview/kubernetes-api/ ,关键信息如下图所示,可见K8S提供了OpenAPI规范:
  • 如果您想查看当前K8S环境的OpenAPI规范,请打开K8S环境的/etc/kubernetes/manifests/kube-apiserver.yaml文件,增加下图红框中的内容:
  • 修改完毕后请稍候,系统会根据文件的变化自动更新(千万不要执行kubectl apply -f kube-apiserver.yaml,这会导致新建api-server的pod,由于端口占用而启动失败);
  • 假设宿主机IP地址是192.168.50.135,那么在浏览器上访问:http://192.168.50.135:8080/openapi/v2,就能得到所有OpenAPI信息如下图:
  • 上图的原始数据没有可读性,复制到在线JSON格式化网站,得到的内容如下图,例如查询pod列表的API信息已经非常详细了:
  • 以上就是对K8S的OpenAPI简介,接下来回到java客户端本身,看看它提供了哪些OpenAPI相关的能力;

java客户端的OpenAPI

  • 打开java客户端工程的源码如下图,红框1就是和OpenAPI相关的子工程,提供服务的功能类都在红框2的package中,也就是说,依靠红框2中的API以及红框3中的数据结构,我们可以完成大部分K8S资源控制相关的操作:
  • 打开常用的CoreV1Api.java,如下图红框,顶部的注释已经说明了一切:这些代码都是工具生成的(至于如何生成就不在本文中讨论了):
  • 如果您下载了java客户端源码,可以在client-java-api这个子工程中看到完整的OpenAPI接口文档:
  • 前文《K8S官方java客户端之五:proto基本操作 》的代码中,咱们尝试过获取pod列表,但是ProtoClient的已有API不支持提交更详细的业务参数,此时选择OpenAPI接口即可输入详细的业务参数,接口详细信息可以在文档中查到,还带有完整的demo代码,如下图所示:
  • 上图中的listNamespacedPod接口有两个重要参数:fieldSelector和labelSelector,这是过滤用的,详细的用法请参考K8S官方文档,地址是:https://kubernetes.io/docs/concepts/overview/working-with-objects/ ,如下图红框:
  • 弄清楚了K8S的OpenAPI规范,以及java客户端依据此规范生成的API服务,还有详细的接口文档在手,可以编码实战了;

源码下载

  • 如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示(
    https://github.com/zq2599/blog_demos):
    • 这个git项目中有多个文件夹,《K8S官方java客户端》系列的源码在kubernetesclient文件夹下,如下图红框所示:

    开始编码

    • 打开《K8S官方java客户端之一:准备 》中创建的kubernetesclient工程,在里面新建子工程openapi,其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>openapi</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>openapi</name>
        <description>Demo project for openapi 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>
    • 新增OpenAPIDemoApplication.java,这是新工程的引导类,也有两个web接口,一个创建namespace,另一个按照namespace查询pod列表,关键位置已添加了注释,就不多赘述了:
    package com.bolingcavalry.openapi;
    
    import com.google.gson.GsonBuilder;
    import io.kubernetes.client.openapi.ApiClient;
    import io.kubernetes.client.openapi.ApiException;
    import io.kubernetes.client.openapi.Configuration;
    import io.kubernetes.client.openapi.apis.CoreV1Api;
    import io.kubernetes.client.openapi.models.V1Namespace;
    import io.kubernetes.client.openapi.models.V1NamespaceBuilder;
    import io.kubernetes.client.openapi.models.V1PodList;
    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 javax.annotation.PostConstruct;
    import java.io.FileReader;
    
    @SpringBootApplication
    @RestController
    @Slf4j
    public class OpenAPIDemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OpenAPIDemoApplication.class, args);
        }
    
        /**
         * 默认的全局设置
         * @return
         * @throws Exception
         */
        @PostConstruct
        private void setDefaultApiClient() 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();
    
            // 创建操作类
            Configuration.setDefaultApiClient(client);
        }
    
        @RequestMapping(value = "/openapi/createnamespace/{namespace}", method = RequestMethod.GET)
        public V1Namespace createnamespace(@PathVariable("namespace") String namespace) throws Exception {
    
            CoreV1Api coreV1Api = new CoreV1Api();
    
            V1Namespace v1Namespace = new V1NamespaceBuilder()
                    .withNewMetadata()
                    .withName(namespace)
                    .endMetadata()
                    .build();
    
            V1Namespace ns = coreV1Api.createNamespace(v1Namespace, null, null, null);
    
            // 使用Gson将集合对象序列化成JSON,在日志中打印出来
            log.info("ns info \n{}", new GsonBuilder().setPrettyPrinting().create().toJson(ns));
    
            return ns;
        }
    
    
        @RequestMapping(value = "/openapi/pods/{namespace}", method = RequestMethod.GET)
        public V1PodList pods(@PathVariable("namespace") String namespace) throws ApiException {
    
            CoreV1Api apiInstance = new CoreV1Api();
    
            // String | If 'true', then the output is pretty printed.
            String pretty = null;
    
            // 订阅事件相关的参数,这里用不上
            Boolean allowWatchBookmarks = false;
    
            // 连续查找的标志,类似于翻页
            String _continue = null;
    
            //  字段选择器
            String fieldSelector = "status.phase=Running";
    
            // 根据标签过滤
            // String labelSelector = "component=kube-apiserver";
            String labelSelector = null;
    
            Integer limit = null;
            String resourceVersion = null;
            Integer timeoutSeconds = null;
            Boolean watch = false;
    
            V1PodList v1PodList = apiInstance.listNamespacedPod(namespace,
                    pretty,
                    allowWatchBookmarks,
                    _continue,
                    fieldSelector,
                    labelSelector,
                    limit,
                    resourceVersion,
                    timeoutSeconds,
                    watch);
    
            // 使用Gson将集合对象序列化成JSON,在日志中打印出来
            log.info("pod info \n{}", new GsonBuilder().setPrettyPrinting().create().toJson(v1PodList));
    
            return v1PodList;
        }
    
    }
    • 将OpenAPIDemoApplication运行起来,先测试创建namespace的服务,在浏览器访问:http://localhost:8080/openapi/createnamespace/dddeeefff ,浏览器返回信息如下图:
    • SSH登录K8S主机,执行命令查看namespace,如下图红框,已经创建成功:
    • 再试试Pod列表,地址是 :http://localhost:8080/openapi/pods/kube-system ,如下图:

    至此,OpenAPI接口的实践就完成了,现在已将java客户端的最基本的功能都实践过了,接下来的文章咱们将开始学习精彩的高级功能;

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

    相关推荐

    Linux高性能服务器设计

    C10K和C10M计算机领域的很多技术都是需求推动的,上世纪90年代,由于互联网的飞速发展,网络服务器无法支撑快速增长的用户规模。1999年,DanKegel提出了著名的C10问题:一台服务器上同时...

    独立游戏开发者常犯的十大错误

    ...

    学C了一头雾水该咋办?

    学C了一头雾水该怎么办?最简单的方法就是你再学一遍呗。俗话说熟能生巧,铁杵也能磨成针。但是一味的为学而学,这个好像没什么卵用。为什么学了还是一头雾水,重点就在这,找出为什么会这个样子?1、概念理解不深...

    C++基础语法梳理:inline 内联函数!虚函数可以是内联函数吗?

    上节我们分析了C++基础语法的const,static以及this指针,那么这节内容我们来看一下inline内联函数吧!inline内联函数...

    C语言实战小游戏:井字棋(三子棋)大战!文内含有源码

    井字棋是黑白棋的一种。井字棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、三子旗等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时...

    C++语言到底是不是C语言的超集之一

    C与C++两个关系亲密的编程语言,它们本质上是两中语言,只是C++语言设计时要求尽可能的兼容C语言特性,因此C语言中99%以上的功能都可以使用C++完成。本文探讨那些存在于C语言中的特性,但是在C++...

    在C++中,如何避免出现Bug?

    C++中的主要问题之一是存在大量行为未定义或对程序员来说意外的构造。我们在使用静态分析器检查各种项目时经常会遇到这些问题。但正如我们所知,最佳做法是在编译阶段尽早检测错误。让我们来看看现代C++中的一...

    ESL-通过事件控制FreeSWITCH

    通过事件提供的最底层控制机制,允许我们有效地利用工具箱,适时选择使用其中的单个工具。FreeSWITCH是一个核心交换与混合矩阵,它周围有几十个模块提供各种功能特性。我们完全控制了所有的即时信息,这些...

    物理老师教你学C++语言(中篇)

    一、条件语句与实验判断...

    C语言入门指南

    当然!以下是关于C语言入门编程的基础介绍和入门建议,希望能帮你顺利起步:C语言入门指南...

    C++选择结构,让程序自动进行决策

    什么是选择结构?正常的程序都是从上至下顺序执行,这就是顺序结构...

    C++特性使用建议

    1.引用参数使用引用替代指针且所有不变的引用参数必须加上const。在C语言中,如果函数需要修改变量的值,参数必须为指针,如...

    C++程序员学习Zig指南(中篇)

    1.复合数据类型结构体与方法的对比C++类:...

    研一自学C++啃得动吗?

    研一自学C++啃得动吗?在开始前我有一些资料,是我根据网友给的问题精心整理了一份「C++的资料从专业入门到高级教程」,点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!!个人...

    C++关键字介绍

    下表列出了C++中的常用关键字,这些关键字不能作为变量名或其他标识符名称。1、autoC++11的auto用于表示变量的自动类型推断。即在声明变量的时候,根据变量初始值的类型自动为此变量选择匹配的...