Welcome to my GitHub


Content: all the original article classification summary and supporting source code, involving Java, Docker, Kubernetes, DevOps and so on;

Links to Series of Articles

  1. Client-Go: Preparation
  2. Client-Go: RestClient
  3. Client-Go: The ClientSet
  4. DynamicClient: DynamicClient
  5. Client-Go: DiscoveryClient

This paper gives an overview of

  • This is the fourth article in the Client-Go series. We looked at the ClientSet client and found that ClientSet is convenient for deployment of Kubernetes built-in resources such as services and services. Each resource has its own methods. With the official API documentation and data structure definition, development is more efficient than RESTClient;
  • But what if you’re not dealing with Kubernetes’ built-in resources? For example, in CRD, there is no user-defined code in the ClientSet, so the DynamicClient is no longer needed.

Relevant knowledge reserve

  • Before learning DynamicClient, there are two important things to know: < font color = “blue” > Object. The runtime < / font > < font color = “blue” > and Unstructured < / font >, they are very important for the whole kubernetes;


  • Before we talk about Object.Runtime, we need to clarify two concepts: Resources and resource objects are familiar to us. POD, deployment, and so on are resources. In my opinion, resources are more like a strict definition.
  • In Kubernetes code world, resource objects correspond to specific data structures that implement the same interface named object.runtime , Source location is < font color = “blue” > staging/SRC/k8s. IO/apimachinery/PKG/runtime/interfaces. Go < / font >, are defined as follows:
type Object interface {
    GetObjectKind() schema.ObjectKind
    DeepCopyObject() Object
  • The deepCopyObject method is, as the name implies, a deep copy, which is to clone an object from memory into a new one.
  • As for what the getObjectKind method does, as you might have guessed, when dealing with a variable of type Object.Runtime, you just need to call its getObjectKind method to know its identity (such as Deployment, Service, etc.).


  • Before we talk about Unstructured, let’s look at a simple JSON string:
    "id": 101,
    "name": "Tom"
  • The above JSON field names and field value types are fixed, so you can write a data structure specifically to handle them:
type Person struct {
    ID int
    Name String
  • The JSON string above is Structured Data, which should be easy to understand.
  • The opposite of structured Data is Unstructured Data. In the actual Kubernetes environment, some Data with unpredictable structure may be encountered. For example, there is a third field in the previous JSON string, and the specific content and type of the field value is unknown at encoding time. You don’t know it until you actually run it, so what do you do when you code it? interface{} > Path is < font color = “blue” > staging/SRC/k8s. IO/apimachinery/PKG/apis/meta/v1 / unstructured/unstructured. Go < / font > :
type Unstructured struct {
    // Object is a JSON compatible map with string, float, int, bool, []interface{}, or
    // map[string]interface{}
    // children.
    Object map[string]interface{}
  • Obviously, the above data structure definition doesn’t play a role. What really matters is the method of association. As shown in the figure below, Client-Go has prepared a wealth of methods for Unstructured data, which can be used for flexible processing of Unstructured data:

Important knowledge: Unstructured and conversion of resource objects

  • And here’s another very important thing to know: The ability to generate Unstructured resource objects with Unstructured instances, and the ability to generate Unstructured instances with resource objects, is achieved by the FromStructured and TounStructured methods of UnstructuredConverter, respectively. The following code snippet shows how to convert an Unstructured instance to a Podlist instance:
// instantiate a Podlist data structure, PodList := &apiv1.podList {} // unstructObj err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructObj.UnstructuredContent(), podList)
  • In case you’re wondering how the FromUnstructured method implements the conversion, let’s take a look at the internal implementation of the method, as shown in the figure below. It’s no surprise, however, that the field information of the Podlist can be obtained by reflection:

  • Is this the end of the Unstructured analysis? No, it’s highly recommended that you go to the fromUnstructured method in red box 2 above to see the details. It’s fascinating. Take Podlist for example, this is a data structure, and fromUnstructured deals only with primitive types, The structFromStructured method is called for processing the data structure, each field of the data structure is processed in the structFromStructured method, and then FromStructured is called, so it’s an iterative process, and finally, No matter how many nesting data structures are in the Podlist, the nesting of the data structure will be handled, so the length of the Podlist will not be sufficient for the trust analysis. Here is some of the key code:

  • Summary: The routine of Unstructured conversion to resource objects is not mysterious. It simply uses reflection to get the field types of the resource object, then obtains the original data in the Unstructured map according to the field names, and then uses reflection to set the data into the fields of the resource object.
  • With that in mind, it’s time to return to the main topic of this article: the DynamicClient client

About dynamicClient

  • Deployment, POD, and other resources have specific and fixed data structures that exactly correspond to the data structures and methods in the ClientSet, but for CRD (user-defined resources), the ClientSet client cannot do anything about it. In this case, a data structure is needed to hold the data of the resource object. You have to have a way to process that data;
  • At this point, the previously mentioned Unstructured structure is in place. That’s right, assigning resource objects not supported by ClientSet to Unstructured hosting. Let’s look at the relationship between DynamicClient and Unstructured:
  • Let’s start with the data structure definition, which is the same as clientset, except for a RestClient field:
type dynamicClient struct {
    client *rest.RESTClient
  • This data structure has only one associated method Resource with GVR and returns another data structure DynamicResourceClient:
func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface {
    return &dynamicResourceClient{client: c, resource: resource}
  • The key to DynamicClient is the data structure DynamicResourceClient and its associated method. All resource related operations are performed by the DynamicClient (proxy mode?). , select the create method, and give serialization and deserialization to unstructured UnstructuredJSONScheme, and give the interaction with kubernetes to Restclient:

  • Summary:
  • Unlike ClientSet, DynamicClient provides a unified API for all types of resources, which need to be wrapped in an Unstructured data structure.
  • Internally, RestClient is used to interact with Kubernetes;
  • This is the introduction and analysis of DynamicClient, we can start the actual combat;

Need to confirm

  • The requirements of this coding practice are very simple: query all PODs under the specified namespace, and then print them out on the console, requiring DynamicClient to implement them;
  • You might ask: POD is a built-in resource to Kubernetes that is better suited to ClientSet, and DynamicClient is better suited to CRD. — You’re right, the reason why I use POD here is because it’s too troublesome to bother with CRD, I have to publish it on Kubernetes, so I just use POD instead of CRD, because DynamicClient can handle it anyway, let’s learn how to use DynamicClient in real practice. After meeting all kinds of resources can deal with it;

Download the source code

  • This source may be downloaded in the lot to in actual combat, address and link information shown in the following table (https://github.com/zq2599/blo… :
The name of the link note
Project home page https://github.com/zq2599/blo… The project’s home page on GitHub
Git repository address (HTTPS) https://github.com/zq2599/blo… The project source warehouse address, HTTPS protocol
Git repository address (SSH) mailto:[email protected]:zq2599/blog_demos.git The project source warehouse address, SSH protocol
  • The tutorials for the client-go tutorials are under the client-go-tutorials > folder, as shown in the red box below:

  • DynamicClientDemo


  • Create a new folder, DynamicClientDemo, and execute the following command to create a new module:
go mod init dynamicclientdemo
  • IO/API and k8s. IO /client-go. Make sure the version matches the Kubernetes environment:
Go get k8s.io/[email protected] go get k8s.io/ right
  • Create a new Main. go and the contents are as follows. I’ll talk about the important points later:
package main import ( "context" "flag" "fmt" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/dynamic" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/util/homedir" "path/filepath" ) func main() { var kubeconfig If home:=homedir. Homedir (); if home:=homedir. Homedir (); home ! = "" {// If the kubeconfig parameter is entered, the value of this parameter is the absolute path of the kubeconfig file. // If no kubeconfig parameter is entered, ~/.kube/config kubeconfig = Flag.string ("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")} else {// If you can't get the current user's home directory, there is no way to set the default directory for kubeconfig, You can only take kubeconFig = Flag.String (" kubeconFig ", "", "Absolute path to the kubeconfig file")} flag.parse () // Load the kubeconfig configuration file from the native, So the first parameter to an empty string config, err: = clientcmd. BuildConfigFromFlags (", "* kubeconfig) / / kubeconfig loaded directly out of the failure if err! = nil { panic(err.Error()) } dynamicClient, err := dynamic.NewForConfig(config) if err ! = nil {panic (err Error ())} / / the only correlation methods required in GVR refs dynamicClient: = schema. GroupVersionResource {Version: "v1", the Resource: "Pods "} // Use DynamicClient's query list method to query all pods in the specified namespace. // Note that the type of data structure returned by this method is UnstructuredList UnstructobJ, err := dynamicClient. Resource(gvr). Namespace("kube-system"). List(context.TODO(), metav1.ListOptions{Limit: 100}) if err ! = nil {panic(err.error ())} // Instantate a Podlist data structure, PodList := &apiv1.PodList{} // Convert Err = runtime.DefaultUnstructuredConverter.FromUnstructured(unstructObj.UnstructuredContent(), podList) if err ! = nil {panic(err.error ())} // header fmt.printf ("namespace\t status\t\t name\n") // For _, d := range podlist.items {FMT.Printf("%v\t %v\t %v\n", d.namespace, d.Status.Phase, d.Name) } }
  • There are three important points to note in the above code:
  • The Resource method specifies the type of Resource for this operation.
  • The List method makes a request to Kubernetes;
  • FromStructured converts Unstructured data structures to podlists, the principle of which was previously analyzed;
  • < FONT color=”blue”>go run main.go
    =” kubernetes “;
zhaoqin@zhaoqindeMBP-2 dynamicclientdemo % 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
  • With that in mind, DynamicClient is a veritable dynamicClient tool that uses a single API to handle all resources. In addition to breaking the built-in resource limits of ClientSet, it also gives our business code more flexibility. I hope this article gives you some ideas. Helps you write code that better matches the scene;

You are not alone, Xin Chen original all the way

  1. Java series
  2. Spring series
  3. The Docker series
  4. Kubernetes series
  5. Database + middleware series
  6. The conversation series

Welcome to pay attention to the public number: programmer Xin Chen

WeChat search “programmer Xin Chen”, I am Xin Chen, looking forward to traveling with you in the JAVA world…