Skip to content

codementor/k8s-cli-java

Repository files navigation

k8s-cli-java project

This project is an example of how to extend kubernetes cli (kubectl) with a Java application. It demonstrates the use of Kubernetes client-java and access the Kubernetes API. In order to be a kubectl plugin it is necessary to have a file which uses the defined naming convention of kube-<plugin-name>. This is a challenge in Java. This project shows the use of Graal in order to build a native image using the gradle palantir plugin. In order to provide a good CLI experience picocli is used.

Prerequisites

  • Running Kubernetes 1.15+ cluster. Kind 0.7.0 was used for testing.
  • Java 1.8 and Graal
  • Gradle

Getting Started

Run ./gradlew native

This should boot strap gradle (version 6.1.1), it will also pull down graalvm and nativeImage command used to build the nativeImage.

The output will show a number of graal warnings which for the purposes of this demonstration can be ignored.

example output:

21:12 $ ./gradlew clean native

> Task :nativeImage
Build on Server(pid: 38354, port: 55534)
[kubectl-example:38354]    classlist:   5,357.88 ms
[kubectl-example:38354]        (cap):   1,602.01 ms
[kubectl-example:38354]        setup:   1,785.98 ms
[kubectl-example:38354]   (typeflow):   3,291.87 ms
[kubectl-example:38354]    (objects):   3,970.93 ms
[kubectl-example:38354]   (features):     199.88 ms
[kubectl-example:38354]     analysis:   7,622.07 ms
[kubectl-example:38354]     (clinit):     139.81 ms
[kubectl-example:38354]     universe:     244.68 ms
Warning: Reflection method java.lang.Class.forName invoked at org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider$2.run(Unknown Source)
Warning: Reflection method java.lang.Class.forName invoked at org.bouncycastle.jcajce.provider.symmetric.util.ClassUtil$1.run(Unknown Source)
Warning: Reflection method java.lang.Class.forName invoked at picocli.CommandLine$BuiltIn$ClassConverter.convert(CommandLine.java:12467)
Warning: Reflection method java.lang.Class.newInstance invoked at picocli.CommandLine$DefaultFactory.create(CommandLine.java:4814)
Warning: Reflection method java.lang.Class.newInstance invoked at org.bouncycastle.jce.provider.BouncyCastleProvider.loadAlgorithms(Unknown Source)
Warning: Reflection method java.lang.Class.newInstance invoked at org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider.loadAlgorithms(Unknown Source)
Warning: Reflection method java.lang.Class.getMethods invoked at picocli.CommandLine.getCommandMethods(CommandLine.java:2980)
Warning: Reflection method java.lang.Class.getDeclaredMethods invoked at picocli.CommandLine.getCommandMethods(CommandLine.java:2982)
Warning: Reflection method java.lang.Class.getDeclaredMethods invoked at picocli.CommandLine$Model$CommandReflection.initFromAnnotatedFields(CommandLine.java:9784)
Warning: Reflection method java.lang.Class.getDeclaredConstructor invoked at picocli.CommandLine$DefaultFactory.create(CommandLine.java:4808)
Warning: Reflection method java.lang.Class.getDeclaredConstructor invoked at picocli.CommandLine$DefaultFactory.create(CommandLine.java:4817)
Warning: Reflection method java.lang.Class.getDeclaredFields invoked at picocli.CommandLine$Model$CommandReflection.initFromAnnotatedFields(CommandLine.java:9781)
Warning: Reflection method java.lang.ClassLoader.loadClass invoked at org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider.loadClass(Unknown Source)
Warning: Reflection method java.lang.ClassLoader.loadClass invoked at org.bouncycastle.jcajce.provider.symmetric.util.ClassUtil.loadClass(Unknown Source)
Warning: Aborting stand-alone image build due to reflection use without configuration.
Warning: Use -H:+ReportExceptionStackTraces to print stacktrace of underlying exception
Build on Server(pid: 38354, port: 55534)
[kubectl-example:38354]    classlist:      86.63 ms
[kubectl-example:38354]        (cap):   1,163.05 ms
[kubectl-example:38354]        setup:   1,325.03 ms
[kubectl-example:38354]   (typeflow):   1,351.53 ms
[kubectl-example:38354]    (objects):   1,487.00 ms
[kubectl-example:38354]   (features):      84.36 ms
[kubectl-example:38354]     analysis:   2,962.47 ms
[kubectl-example:38354]     (clinit):      46.62 ms
[kubectl-example:38354]     universe:     102.52 ms
[kubectl-example:38354]      (parse):     109.68 ms
[kubectl-example:38354]     (inline):     530.39 ms
[kubectl-example:38354]    (compile):     422.22 ms
[kubectl-example:38354]      compile:   1,174.70 ms
[kubectl-example:38354]        image:     159.67 ms
[kubectl-example:38354]        write:     114.39 ms
[kubectl-example:38354]      [total]:   5,952.42 ms
Warning: Image 'kubectl-example' is a fallback image that requires a JDK for execution (use --no-fallback to suppress fallback image generation).
native image available at build/graal/kubectl-example (3 MB)

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 23s
4 actionable tasks: 4 executed

This will result in an executable kubectl-example being built in build/graal/ under the project root.

Start a cluster: kind create cluster

and run one of the commands: ./build/graal/kubectl-example pod list

Example:

./build/graal/kubectl-example pod list
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
________________________________________________________________
| Pod Name                                  | namespace         |
|===============================================================|
| coredns-6955765f44-f966p                  | kube-system       |
| coredns-6955765f44-xnzbg                  | kube-system       |
| etcd-kind-control-plane                   | kube-system       |
| kindnet-cznll                             | kube-system       |
| kube-apiserver-kind-control-plane         | kube-system       |
| kube-controller-manager-kind-control-plane| kube-system       |
| kube-proxy-tw9cb                          | kube-system       |
| kube-scheduler-kind-control-plane         | kube-system       |
| local-path-provisioner-7745554f7f-gk5j9   | local-path-storage|

List of Commands

  • pod list
  • pod list2
  • pod add [-n namespace] [-i image]
  • resources

Adding as a kubectl plugin

The executable needs to be the path. From the root of the project run: export PATH=$PATH:$PWD/build/graal/

Now give kubectl a try with example. run: kubectl example pod list You should get the same output as above.

About

Simple Java Demo of Kubernetes kubectl plugin

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages