Saturday, November 21, 2015

Docker through my eyes - The Beginning

In the impending cloud IT era, we have come to heard of many breakthrough technologies and trends which seemed unthinkable few years back. Docker touted as the next 'big thing' of this era stands well above the rest.

But what is Docker? Why is it so popular? Well, I think the next few posts which I will deliver may aid you to gain a sound understanding about Docker's concepts and its roots.

Docker is simply an open-source containerization engine which automates the packaging, shipping and deployment of any software application presented in the form of lightweight, portable and isolated but highly elegant and self-sufficient containers. Hence, the bottom-line "build once, configure once and run anywhere" is well highlighted. Docker simply makes the containerization paradigm easy to grasp, utilize and achieve the intended objectives quickly with less hassle.

When considering further, I have found out that the new users of Docker find it a little confusing in understanding and remembering the concepts associated. Primarily, Docker uses a client-server architecture to serve its purpose. Well, here is a brief coverage of Docker concepts - its components and elements.
  • Docker client - this is simply the user interface which enables communication between the Docker daemon and the user, in order to carry out container management. It uses either RESTful API or sockets for communication. The Docker client is capable of connecting with a Docker daemon residing in the same host as it resides or can communicate with a remote Docker daemon, also. 
  • Docker daemon - this is the process that carries out container management and resides in the host machine. As mentioned in the case of Docker client, the communication between the user and the daemon does not take place directly, but only through the client. Docker daemon requires root privileges to run where as the Docker client does not need such privileges. 
The following architecture diagram may provide a clear picture of what Docker offers:
Docker architecture diagram

  • Docker image - this is simply a read-only template structure that helps in providing directions on building and launching Docker containers. These directions may be configuration data, processes that are to run within the container or etc. An image primarily consists of a layered structure and union file systems are responsible for combining these layers into a single Docker image. An image starts with another image, popularly known as a base image. A template is created with the use of instructions defined in a file called, the Dockerfile. Each instruction will add a new layer to the image. You can push an image you have created into the public Docker registry, which is explained in the next section. Docker image is the build component of Docker.
Docker image architecture diagram

  • Docker registry - this acts as the storage for Docker images. The publicly available Docker repository commonly known as, the Docker Hub in the Docker community plays host to repositories which contain publicly available images (created by others before) downloadable freely and also to private repositories which have access rights only to users with required permissions. In other terms, public repositories are searchable and re-usable. Private repositories come at a fee. You have to register in the Docker Hub to push your own images. This also means that Docker has provided a version management system similar to Git to distribute the images. In addition, Docker does maintain a local registry which holds the images you download (pull) and create. Docker registries play the part of being the distribution component of Docker
  • Docker container - is similar to a bucket or in computing terms, a directory which holds everything needed for an application to run inside it such as, configuration files, scripts, libraries and etc. ensuring an isolated environment. As depicted in the Docker architecture diagram above, containers running inside a single host are completely isolated from not only each other, but the host machine, as well. As mentioned before, a Docker image provides the directions required to create and bootstrap a container. The primary idea is to maintain the homogeneity of the application's behavior in the development environment as well as after being shipped to the deployment environment. Docker uses union file systems within containers as this is a layered file system. It is possible to configure the container to run a different types of file system, as well. The layers of union file systems are read-only and the processes running inside the container can only witness the merger of these layers. When a container is launched, it creates a read-write layer on top of the Docker image. A running process can make a change in the file system thus creating a new layer, which will represent the difference between the current state and the original state. A Docker container is the running component of Docker.
Docker container architecture


The above sections provides a non-exhaustive depiction of what Docker and its sub-components are. When analyzing further, I could point out the following non-exhaustive set of advantages of Docker as reasons for its successful arrival in the scene.
  • Faster delivery of applications.
  • Fast and elegant isolation framework.
  • Lower resource usage overhead (CPU/memory)
  • Easy to acquire and use.
  • Advantages over virtualization technology which will be discussed in a future post, more exhaustively. 
    • operating system level virtualization
    • lightweight nature of containers
    • native performance
    • real-time provisioning due to Docker's speed and scalability
In simple if you are to run an application using Docker what you have to do is,
  1. Write a Dockerfile which contains the required instructions to generate a Docker image for running the desired application
  2. Build the Docker image. using the Dockerfile. The command to build the Docker image can be invoked using the Docker daemon through the Docker client. The built Docker image will be added to your local Docker image registry and if you intend, you can push the Docker image to a Docker Hub's public or private repository.   
  3. Run the generated Docker image in the form of a Docker container, after the allocation of appropriate network and IP address. The command to run the Docker image can be invoked using the Docker daemon through the Docker client.
It is as simple as that!!! But still I think the above summary is quite non-exhaustive. There are more facts associated with these concepts. Hence, I am intending of moving in-depth into these associated concepts, one-by-one in the future posts.

Before concluding, I would like to mention that any comments, suggestions and ideas with regards to the topic under discussion are highly appreciated.

References:

Thursday, October 29, 2015

WSO2 Carbon Kernel 5.0.0-alpha: Introduction to the all new jar-to-OSGi-bundle converter tool

WSO2 Carbon-kernel 5.0.0-alpha has been released with all new features integrated into it. You will be able to gather an excellent insight into it from the release notesWSO2 Carbon documentation and you can check out the source code from this link.

But speaking of its all new features, I am intending to analyse one such new feature that has been introduced into the kernel, through this post. The new Java Archive (.jar) to OSGi-bundle converter, a functionality which had been part of the earlier Carbon-kernel versions as well, has been revamped and brought forward along with a fresh approach. 

A good introduction to this feature can be found in the documentation itself and I believe reading the docs will be really beneficial in order to understand its functionality, usage, imposed restrictions, reasons for the change in implementation and etc.

Since the above link I have provided covers the high level details about the tool, I intend to analyse its implementation within this post.

As mentioned in the article, this functionality was part of the org.wso2.carbon.server module of the previous Carbon-kernel versions. The following two Java classes primarily contained all implementation of the jar-to-bundle converter functionality.
When you observed these two classes, the following points would become evident to you:
  • The implementation is tightly coupled with the Carbon-kernel such that you cannot specify any desired source Java archive (.jar) file or directory containing such files and a destination directory for the generated OSGi bundles. 
  • No usage of the all new Java features such as NIO package, lambda expressions, streams and etc.
  • The execution of this functionality occurs at the server startup, which effectively increments the server startup time, further. 
Hence, we have decided to implement this as a separate module which is equivalent to an optional tool which the user can execute rather than executing it at the server startup, by default. Hence, we have introduced a fresh Maven module within the Carbon-kernel code base named tools. Plus this tool can be used to make jar-to-bundle conversion(s) between any two specified locations unlike in the previous case which only transacted between the CARBON_HOME/repository/components/lib and CARBON_HOME/repository/components/dropins directories. The usage instructions for this tool has been provided in the documentation

The new implementation is primarily composed of four classes which are as follows:
  • BundleGenerator.java - Contains the executor main method along with validations on file paths and file permissions, user arguments and etc.
  • BundleGeneratorUtils.java - Contains utility methods which are used during the conversion process.
  • Constants.java - Defines constants used within BundleGeneratorUtils.java class' utility methods.
  • JarToBundleConverterException.java - a custom exception class for the tool.
In-depth analysis of all classes and their methods can be found in the Java Doc comments.

Finally, it has to be mentioned that further improvements will take place in the future in relation with this tool. Any suggestions and ideas in relation with this tool are highly appreciated.  

Saturday, October 3, 2015

An analysis of a Proof of Concept (PoC) Java application which deploys the WSO2 Carbon 5 kernel in Docker Containers with the support of orchestration capabilities of Google Kubernetes

In this post, I have chosen to provide an analysis of a Proof of Concept (PoC) Java application which is capable of deploying a sample version of the WSO2 Carbon 5 kernel in Docker Containers with the help of Docker Container orchestration capabilities of Google Kubernetes. This post may not contain detailed analysis of all the Docker and Google Kubernetes concepts utilized but I intend to make future posts which may cover advanced details related to these concepts. 

Following are the basic functionalities, I have added to the application:
  • Deploy a tenant-specified number of Docker Container instances (inside Kubernetes Pods) with the WSO2 Carbon kernel running inside, each of them.
  • Scale the number of Docker Container instances (inside Kubernetes Pods) running during the application run time.
  • Make a rolling update to a currently deployed version of the Carbon kernel with an updated version of the Carbon kernel.
  • Roll back to an older build version of the currently deployed version of the Carbon kernel.
  • Remove a currently deployed tenant specific set of Docker Container instances.


Note: In this application, a particular tenant (user) can have only a single set of Docker instances  (with Carbon kernel deployed) running during the application run time. The tenant can make a rolling update to deploy an updated kernel version.

You can use this GitHub link to check the Java implementation of these functionalities and the instructions to run this application has been provided in the README.md file in the repository. In addition, I have added the sample wso2carbon-kernel-5.0.0-SNAPSHOT.zip file to the following GitHub link.

When analyzing the application implementation, the Docker and Kubernetes concepts have been used as follows:
  • The tenant has to provide the Carbon kernel zip file which will be deployed. 
    • Initially, the application will generate a Dockerfile which provides instructions to deploy the kernel zip and run the bin/wso2server.sh file at the initiation of each Docker Container.
    • Build up a Docker Image using the Dockerfile generated.   
  • Google Kubernetes Replication Controller concept has been used to generate the tenant specified number of Pods, where each pod contains one running Docker Container instance of the above generated Docker Image.
  • During scaling, the Replication Controller is updated with the new number of replicas. Depending on the updated value, new replicas are added to the existing number of Pods to meet the new value (if the updated value is higher than the previous) or existing Pods are deleted to meet the new value (if the updated value is lower than the previous)
  • During a rolling update, it is first checked if the specified tenant has an already running set of Container instances and if yes, a new Docker Image will be built as in the case of deployment operation and that particular Image will be updated in the already running Replication Controller. The currently running Pods will be deleted (since they are running the previous Docker Image) in order to make way for the Replication Controller to spring up new Pods with the updated Docker Image. If not deployed, the tenant is requested to deploy the kernel before making a rolling update. 
  • During a rollback operation, a similar procedure to that of a rolling update is carried out from the point of updating the Replication Controller, with the only difference being that the tenant has to choose the new Docker Image from existing Docker Images (previous build versions of the kernel from the same tenant) before the Replication Controller is updated.
Note
  • This application has been well tested in Ubuntu 14.04.3 LTS OS trusty version and has not  yet been tested in any other platform. 
  • Except for minor bugs in relation with file permissions which have not yet been fixed, this application performs the basic functionalities mentioned above quite convincingly.
  • I have used spotify/docker-client as the Docker Remote API, fabric8's Kubernetes API and Apache Stratos' Kubernetes client for Kubernetes operations in the Java code.
I expect to spend further time on fixing existing bugs and carrying out further testing in the future. Any comments, suggestions and help with regards to this application and related topics are highly appreciated.