Kubernetes Container Orchestration through Java APIs

Overview

In this article we will look at how to drive Kubernetes using Java APIs. More general information about Kubernetes and containers can be found here. Kubernetes itself offers a RESTful API but of course most prefer to use a client that is already handling low-level HTTP protocol operations.

Kubernetes_API_Architecture It turns out Fabric8 is providing an integration and management platform above kubernetes and docker. In addition to integrating container orchestration through Kubernetes, Fabric8 also integrates with OpenShift v3 and Jube. OpenShift v3 exposes Kubernetes extensions such as app templates and builds. These Kubernetes extensions allow the container to be bundled with the application code and thus greatly increase application deployment cycles. Jube is a pure Java implementation of Kubernetes to provide containers to non-Linux world. In this article we will just focus on Kubernetes using the Fabric8 Java API.

Setup

The easiest way to get access to the Fabric8 Kubernetes Java API is through maven. Both Kubernetes and Fabric8 are changing fast so make sure you update and stay current with versions. The below dependency can be added to your pom.xml file.


<dependency>
   <groupId>io.fabric8</groupId>
   <artifactId>kubernetes-api</artifactId>
   <version>2.0.37</version>
</dependency>

After updating the pom.xml you can run maven to add the new dependency to the local maven repository.

mvn clean compile

Connection

In order to communicate with Kubernetes through the Fabric8 Java API a connection must be established. The Kubernetes API support HTTPS through TLS certificates but in this example we are just using HTTP and no authentication. The ConnectionExample class requires only IP and Port in order to return a kube connection object. By default unless specified the Kubernetes API will be read-only. In oder to get access to the read-write API the following environment parameters must be exported:

export KUBERNETES_SERVICE_HOST=192.168.2.14
export KUBERNETES_SERVICE_PORT=8080
package examples;

import io.fabric8.kubernetes.api.KubernetesClient;
import io.fabric8.kubernetes.api.KubernetesFactory;

public class ConnectionExample {
   private String ip;
   private String port;

   public ConnectionExample(String ip, String port) {
      this.ip= ip;
      this.port = port;
   }

   public KubernetesClient getConnection() {
      final String URI = "http://" + ip+ ":" + port;
      final KubernetesClient kubernetes = new KubernetesClient(new KubernetesFactory(URI));

      return kubernetes;
   }
}

Once we have a Kubernetes connection object we can manage pods, replication controllers and services. We can perform typical RESTFul operations such as get, post, update and delete.

Pods

A pod is the most granular unit of management in Kubernetes and contains one or more containers that share the same resources. The main operations that can be performed are listing, creating and deleting pods.

Listing Pods

 public List<KubePodModel> getKubePods() {
    List<KubePodModel> kubePodList = new ArrayList<KubePodModel>();

    for (Pod pod : kubernetes.getPods().getItems()) {
       KubePodModel model = new KubePodModel();

       model.setId(pod.getId());
       model.setApiVersion(pod.getApiVersion());
       model.setCreationTime(pod.getCreationTimestamp());
       model.setNamespace(pod.getNamespace());
       model.setPodHostName(pod.getCurrentState().getHost());
       model.setPodIp(pod.getCurrentState().getPodIP());
       model.setStatus(pod.getCurrentState().getStatus());

       kubePodList.add(podModel);

    }

    return kubePodModelList;
 }

Creating Pods


public void createKubePod(String id, String namespace, List<String> containerPorts, String image, Map<String, String> labels) {

   Pod pod = new Pod();
   pod.setId(id);

   pod.setLabels(labels);
   PodState desiredState = new PodState();
   ContainerManifest manifest = new ContainerManifest();

   Container manifestContainer = new Container();
   manifestContainer.setName(podId);
   manifestContainer.setImage(image);

   List<Port> ports = new ArrayList<Port>();
   for (String containerInputPort : containerPorts) {
      CharSequence inputStr = containerInputPort;
      String patternStr = "(\\S+):(\\S+)";
      Pattern pattern = Pattern.compile(patternStr);
      Matcher matcher = pattern.matcher(inputStr);
      boolean matchFound = matcher.find();

      if (matchFound) {
         int contanierPort = Integer.valueOf(matcher.group(1));
         String containerProto = matcher.group(2);

         Port port = new Port();
         port.setContainerPort(contanierPort);
         port.setProtocol(containerProto);
         ports.add(port);
     }
   }

   manifestForContainer.setPorts(ports);

   List<Container> containers = new ArrayList<>();
   containers.add(manifestForContainer);
   manifest.setContainers(containers);

   desiredState.setManifest(manifest);
   pod.setDesiredState(desiredState);

   kubernetes.createPod(pod, namespace);
}

Deleting Pods


public void deleteKubePod(String id, String namespace) {
   kubernetes.deletePod(id, namespace);
}

Replication Controllers

A replication controller is a pod that has N replicas. The replication controller ensures the number of pod replicas defined also exists. The replication controller will automatically manage pod deployments.The main operations that can be performed are listing, creating and deleting replication controllers.

Listing Replication Controllers


public List<ControllerModel> getKubeReplicationControllers() {
   List<ControllerModel> controllerList = new ArrayList<ReplicationControllerModel>();
   for (ReplicationController controller : kubernetes.getReplicationControllers().getItems()) {
      ControllerModel model = new ControllerModel();

      model.setId(controller.getId());
      model.setApiVersion(controller.getApiVersion());
      model.setCreationTime(controller.getCreationTimestamp());
      model.setReplicas(controller.getCurrentState().getReplicas());

      controllerList.add(model);
   }

   return controllerList;
}

Creating Replication Controllers


public void createKubeReplicationController(String id, String namespace, int replicas, Map<String, String> controllerLabels,
   Map<String, String> selectorLabels, String podId, String image, List<String> containerPorts, Map<String, String> podLabels, String manifestId) {
   ReplicationController controller = new ReplicationController();
   controller.setId(id);
   controller.setNamespace(namespace);
   controller.setLabels(controllerLabels);

   PodState podState = new PodState();
   ReplicationControllerState repState = new ReplicationControllerState();
   repState.setReplicas(replicas);
   repState.setReplicaSelector(selectorLabels);

   PodTemplate podTmpl = new PodTemplate();
   podTmpl.setLabels(podLabels);

   ContainerManifest manifest = new ContainerManifest();
   manifest.setId(manifestId);
   Container manifestContainer = new Container();
   manifestContainer.setName(podId);
   manifestContainer.setImage(image);

   List<Port> ports = new ArrayList<Port>();
   for (String containerInputPort : containerPorts) {
      CharSequence inputStr = containerInputPort;
      String patternStr = "(\\S+):(\\S+)";
      Pattern pattern = Pattern.compile(patternStr);
      Matcher matcher = pattern.matcher(inputStr);
      boolean matchFound = matcher.find();

      if (matchFound) {
         int contanierPort = Integer.valueOf(matcher.group(1));
         String containerProtocol = matcher.group(2);

         Port port = new Port();
         port.setContainerPort(contanierPort);
         port.setProtocol(containerProtocol);
         ports.add(port);
      }
   }

   manifestContainer.setPorts(ports);

   List<Container> containers = new ArrayList<>();
   containers.add(manifestContainer);
   manifest.setContainers(containers);

   podState.setManifest(manifest);
   podTmpl.setDesiredState(podState);
   repState.setPodTemplate(podTmpl);

   controller.setDesiredState(repState);

   kubernetes.createReplicationController(controller, namespace);

}

Deleting Replication Controllers


public void deleteReplicationController(String id, String namespace) {
   kubernetes.deleteReplicationController(id, namespace);
}

Services

A service exposes an application running in a pod externally using the Kubernetes proxy. It essentially maps public IPs / Ports on Kubernetes Minions (nodes) to internal container IPs / Ports. The main operations that can be performed are listing, creating and deleting services.

Listing Services


public List<ServiceModel> getKubeServices() {
   List<ServiceModel> serviceList = new ArrayList<ServiceModel>();
   for (Service service : kubernetes.getServices().getItems()) {
       ServiceModel model = new ServiceModel();

       model.setId(service.getId());
       model.setApiVersion(service.getApiVersion());
       model.setCreationTime(service.getCreationTimestamp());
       model.setIp(service.getPortalIP());
       model.setPort(service.getPort());
       model.setProtocol(service.getProtocol());

       serviceList.add(serviceModel);
   }

   return serviceList;
}

Creating Services


public void createKubeService(String id, String namespace, int containerPort, int port, List<String> publicIps,
   Map<String, String> labels, Map<String, String> selectors) {
   Service service = new Service();

   IntOrString containerPortObj = new IntOrString();
   containerPortPojo.setIntVal(containerPort);

   service.setId(id);
   service.setContainerPort(containerPortObj);
   service.setPort(port);
   service.setPublicIPs(publicIps);
   service.setLabels(labels);
   service.setSelector(selectors);

   kubernetes.createService(service, namespace);
}

Deleting Services


public void deleteService(String id, String namespace) {
   kubernetes.deleteService(id, namespace);
}

Summary

Kubernetes and Linux containers are rapidly developing and emerging technologies. We have seen how to easily orchestrate containers in a Kubernetes environment using the Fabric8 Java APIs. Container orchestration is about performing operations on various Kubernetes components such as pods, replication controllers and services. Using the APIs you can easily build Kubernetes functionality into any Java applications. I hope you found this article useful. If you have examples of orchestrating Kubernetes or containers through APIs please share!

Happy Containerizing!

(c) 2015 Keith Tenzer

3 thoughts on “Kubernetes Container Orchestration through Java APIs

  1. Pingback: KubeWeekly: Issue #8 – KubeWeekly

  2. Hi,
    The Kubernetes API support HTTPS through TLS certificates but in this example we are just using HTTP and no authentication.
    How this example could connect to HTTPS API Server. I tried the same code, but getting error as connection refused and certificates error. Could you please help me on this.
    Thanks & Best Regards,
    Chaitanya

    Like

    • Sorry I haven’t tried with HTTPS. Also this was quite a long time ago, originally Kubernetes before 1.0 was HTTP.

      If you get it working please share what you did? If I get some time I will look into it as well.

      Keith

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s