Skip to content

Latest commit

 

History

History
120 lines (96 loc) · 6.81 KB

README.md

File metadata and controls

120 lines (96 loc) · 6.81 KB

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.