Kubernetes official java client five: proto basic operation

Welcome to my GitHub

https://github.com/zq2599/blog_demos
content: classification summary of all original articles and supporting source code, involving Java, Docker, Kubernetes, DevOPS, etc.;

Overview

  1. This article is the fifth in the "Kubernetes official java client" series. The java clients mentioned below all refer to client-jar.jar ;
  2. After the preparations and attempts of the previous four articles, we have a preliminary understanding of the java client and successfully run hello world. The next thing to do is to continue to study and practice in depth to master this weapon;

Two main lines

  • The basic function of the java client is not complicated, that is, by what means to initiate the addition, deletion, modification, and query request for K8S resources, you can grasp the following two main lines:
  1. proto main line : use K8S official protobuf definition to generate java classes from various resources, and use a small number of APIs to process these objects (features, APIs are very few, each API is common, processing all types of resource objects);
  2. The main line of openapi : Use the openapi tool to automatically generate APIs for adding, deleting, modifying and checking all resources (feature: there are many APIs, and each resource has its own API);

Today’s article, let’s learn and understand the main line of proto ;

ProtoClient, the core class of the proto main line

  1. As mentioned earlier, the main feature of proto is that there are very few APIs. Let’s take a look at the source of these few APIs: ProtoClient class
    Insert picture description here

  2. As shown in the figure above, ProtoClient provides an interface for adding, deleting, modifying, and checking, and we can use these interfaces to implement operations on K8S resources;

  3. With the interface, the next step is to figure out how to prepare the parameters. First look at the source code of the create method to see what parameters it needs:
    Insert picture description here

  4. As shown in the figure above, the first parameter of the create method is the K8S resource class . The characteristics of this class are constrained in generics and must implement the sub-interface of com.google.protobuf.Message ;

  5. Where do these subclasses of Message come from? For example, when we want to create a NameSpace, do we write a Message subclass by ourselves? Or is there a ready-made one? The next thing to do is to figure out where the K8S resource class comes from? After all, all K8S resource operations must use these java classes;

  6. Let's go to the source code of the java client to find clues. This is a maven project with a parent-child structure. In the subproject named client-java-proto , the README file gives the clues. The address is: https://github.com /kubernetes-client/java/tree/master/proto, as shown below:
    Insert picture description here

  7. The operation in the red box in the above figure reveals the whole process: first download another github repository, and then there is a script generate.sh in this repository, which generates java classes according to the protobuf configuration, and these java files are placed in java/proto /src/main/java directory;

  8. This article is an article for learning K8S official java client. The details about K8S protobuf are not expanded here. Only a key script is given for your reference. This is a script executed when the code is automatically generated according to proto. It is used to download the protobuf file. Address: https ://github.com/kubernetes-client/gen/blob/master/proto/dependencies.sh, as shown below:
    Insert picture description here

  9. The address in the red box above is: https://raw.githubusercontent.com/kubernetes//api/master/rbac/v1alpha1/generated.proto, the content is as follows, the java code in the java client is generated based on these contents :
    Insert picture description here

  10. Combining the previous analysis and returning to the subproject client-java-proto of the java client source code , you can find the V1.java generated by the generate.sh script. This java file contains all the protobuf objects of the V1 version, as shown below:
    Insert picture description here

  11. The Namespace class in the red box above is a subclass of GeneratedMessageV3. Take a look at the inheritance relationship of GeneratedMessageV3. As shown in the figure below, this class implements the Message interface and satisfies the generic constraints of the ProtoClient.create method on input parameters:
    Insert picture description here

summary

  1. The method of adding, deleting, modifying and checking operation K8S resources provided by the ProtoClient class;
  2. In the client-java-proto sub-project of the java client, there are object classes generated by K8S official protobuf. These classes are the parameters used for the addition and deletion of ProtoClient;
  3. There are methods for adding, deleting, modifying and checking, and the objects involved are also available, and then you can actually fight;

Preparation before actual combat

It is not possible to write the code immediately, and there is still one final preparation step: confirm the API parameters ;

  • Assuming that the actual content is to query the list of all pods under the kube-system namespace, where can I get the API related information:
  1. Open the API online documentation, my K8S version is 1.15, the address is: https://v1-15.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.15/

  2. As shown in the figure below, the red box 1 is the interface document of the pod list, and the red box 2 shows the URL. With this URL we can encode:
    Insert picture description here

  3. In future operations, all resources can find the corresponding API information according to this document to assist us in coding;

  4. Finally, the actual combat can begin;

Source download

  1. If you don't want to code, you can download all the source code on GitHub. The address and link information are shown in the following table (https://github.com/zq2599/blog_demos):
name link Remarks
Project homepage https://github.com/zq2599/blog_demos The project's homepage on GitHub
git warehouse address (https) https://github.com/zq2599/blog_demos.git The warehouse address of the project source code, https protocol
git warehouse address (ssh) [email protected]:zq2599/blog_demos.git The warehouse address of the source code of the project, ssh protocol
  1. There are multiple folders in this git project. The application of this chapter is under the kubernetesclient folder, as shown in the red box below:
    Insert picture description here

Start coding

  1. Open the kubernetesclient project created in "One of the Official Java Clients of Kubernetes: Preparation" , and create a new subproject protobufclient in it. The content of its pom.xml is as follows. Note that spring-boot-starter-json has been excluded, so it is serialized The tool will become Gson (the original default is 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. Added ProtobufApplication.java , which is the guide class for the new project. There is also code for querying the pod list through ProtoClient:
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. The above code shows the usage of ProtoClient's API, one is to get the pod list, the other is to create the namespace;

verification

  1. Ensure that the config file of the K8S environment is locally accessible (the value of the kubeConfigPath variable in the code);

  2. Run ProtobufApplication;

  3. First try to get a list of all pods under the namespace of kube-system , visit http://localhost:8080/pods/kube-system in the browser, and respond as shown below. The items_ array in the red box is all pod information:
    Insert picture description here

  4. In the items_ array in the above figure , expand one but the name field is a byte array, there is no way to see the real content:
    Insert picture description here

  5. With the help of IDEA's breakpoint function, you can see the contents of the above name_ field, as shown below:
    Insert picture description here

  6. Let's try the function of creating a namespace again, the browser executes: http://localhost:8080/createnamespace/aaabbbccc, a namespace named aaabbbccc will be created , and the return information of ProtoClient.create will be displayed on the browser:
    Insert picture description here

  7. Log in to the K8S server through SSH and check the namespace, as shown in the red box in the figure below, you can see the newly added namespace:
    Insert picture description here

  8. After verification is completed, we can easily operate the K8S environment based on the ProtoClient API and K8S official online API documentation;

ProtoClient's shortcomings

  1. The shortcomings of ProtoClient have been mentioned before, as shown in the red box 4 below. The online API document mentions that you can enter some parameters (such as filter conditions) when querying the pod list, but we have also seen the API provided by ProtoClient. , Does not support input query parameters:
    Insert picture description here

  2. Take a look at the core code of ProtoClient requesting K8S Api service. As shown in the red box in the following figure, the request parameter field has been hard-coded, so there is no way to pass the parameters in when calling ProtoClient's API from outside:
    Insert picture description here

  3. We can refer to the above code and write a paragraph by ourselves, and change the position of the red box to the parameters specified in the API document. However, this seems a little troublesome. Is there a better way?

  • Of course there is, so stay tuned for the next one to learn and practice the openapi mainline together;

Guess you like

Origin blog.csdn.net/boling_cavalry/article/details/107552722