Introduction

After building your application/microservice, you start thinking about deploying it to Kubernetes cluster. Thus, a set of kubernetes resources (deployment, service, ingress,…) should be implemented in order to achieve that.

However, using Ballerina, a Cloud Native Programming Language, eases the development of microservices by smoothly integrating them with Kubernetes. Indeed, Ballerina provides a set of elegant annotations (@kubernetes:*) to scaffold Kubernetes resources throughout the “Build” stage.

Prerequisites

  • Docker.
brew install docker
  • Minikube or any Kubernetes Cluster.
brew install minikube # More details: https://kubernetes.io/docs/tasks/tools/install-minikube/

minikube start 
# Starting local Kubernetes v1.10.0 cluster...

minikube status
# minikube: Running ...

eval $(minikube docker-env);
# Point docker CLI to communicate with minikube directly
  • Ballerina Platform

https://ballerina.io/downloads/

which ballerina
# /Library/Ballerina/ballerina-0.975.1

For productivity concerns, VisualCode is a recommended editor to develop Ballerina code; It has a popular Ballerina extension that should be installed too.

After installing the extension, editor’s settings should be updated as following:

    "ballerina.home": "/Library/Ballerina/ballerina-0.975.1"

Note that, /Library/Ballerina/ballerina-0.975.1 is the output of which ballerina command line.

Getting Started

ballerina banner

1. Hello World

Snippet

import  ballerina/io;

function main (string... args) {
    io:println("Hello World From elegance.abdennoor.com!");
}

Related Commit

Test it

ballerina run hello.bal

ballerina run hello.bal

2. Hello World Service/API

Snippet

import ballerina/http;
import ballerina/log;

endpoint http:Listener helloListener {
    port:8888
};

@http:ServiceConfig {
    basePath: "/"
}
service<http:Service> hello bind helloListener {
    sayHello (endpoint caller, http:Request request) {
        http:Response response = new;
        response.setPayload("Hello API from elegance.abdennoor.com!");
         _ = caller -> respond(response);
    }
}

This is a simple web service that was bounded to an HTTP endpoint with port 8888. You can define endpoints as many as you want, then bind one of them to your service.

Related commit

Run it

ballerina run hello_api.bal

Validate

curl -s http://localhost:8888/sayHello
# Hello API from elegance.abdennoor.com!

3. Hello World Kubernetes

As you noted, Ballerina provides a set of annotations that are useful to change the behaviour of the logic whenever it is decorated.

The scope of the annotation can be :

  • Service : like @http:ServiceConfig
@http:ServiceConfig {
    basePath: "/"
}
service<http:Service> hello bind helloListener {
    //....
}    
  • Microservice: like @http:ResourceConfig
service<http:Service> hello bind helloListener {    
    @http:ResourceConfig {
        methods: ["POST"],
        path: "/"
    }
    sayHello (endpoint caller, http:Request request) {
        //......
    }
}        

With the same approach, integration with Kubernetes is done by using Kubernetes annotations supported by Ballerina Platform:

  • @kubernetes:Service annotation should decorate Ballerina endpoint.
  • @kubernetes:Deployment annotation should decorate Ballerina service.

Snippet

import ballerina/http;
import ballerina/log;
import ballerinax/kubernetes;


@kubernetes:Service {
    serviceType: "NodePort",
    name: "ballerina-demo"

}
endpoint http:Listener helloListener {
    port:8888
};

@kubernetes:Deployment {
    enableLiveness: true,
    image: "abdennour/ballerina-demo",
    name: "ballerina-demo"
}
@http:ServiceConfig {
    basePath: "/"
}
service<http:Service> hello bind helloListener {
    sayHello (endpoint caller, http:Request request) {
        http:Response response = new;
        response.setPayload("Hello Kubernetes from elegance.abdennoor.com!");
         _ = caller -> respond(response);
    }
}

Related commit

Build it

When you build a Ballerina code with Kubernetes annotations, The platform generate a set of files, namely:

  1. .balx which is bytecode after compile (like .class in java)
  2. Generate Dockerfile and Kubernetes templates inside kubernetes/ directory.
  3. Build the docker image according to the Dockerfile which is already scaffolded according to the usage of @kubernetes:* annotations.
eval $(minikube docker-env);
ballerina build hello_kubernetes.bal

ballerina Build Kubernetes

Run it

In order to make the application up and running in Kubernetes, there are two more steps after the build step:

  1. Push the docker image to the registry (not required with minikube).
  2. Deploy the kubernetes templates using kubectl
#1.  Push the docker image to the registry
docker push abdennour/ballerina-demo # NOT needed with "eval $(minikube docker-env)"

# 2.Deploy the kubernetes templates using
kubectl apply -f kubernetes/

Validate

BASE_URL=$(minikube service ballerina-demo --url)
curl -s ${BASE_URL}/sayHello
# Hello Kubernetes from elegance.abdennoor.com!

Congratulations! The Ballerina helloworld is now up and running in Kubernetes.

ballerina Build Kubernetes

Conclusion

“Ballerina is a compiled, type-safe, concurrent programming language targeting microservice development and integration”.

Ballerina proves that it is a diffrent language by introducing new programing paradigms. Since the language is still under development, we hope it will be mature as soon as possible.