Kubernetes
Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications. Jolie microservices deployed inside a Docker container can be managed by Kubernetes as well. We are going to use what learnt in Docker section to deploy an easily-scalable application, with multiple containers running the same service behind a load balancer. To run the example a Kubernetes environment is needed, the easiest way to get it is to install Minikube.
Deploying "Hello" Jolie service in a container Docker
Let's make some modifications to helloservice.ol used in the previous Docker example:
include "runtime.iol"
interface HelloInterface {
RequestResponse:
    hello( string )( string )
}
execution{ concurrent }
inputPort Hello {
    Location: "socket://localhost:8000"
    Protocol: sodep
    Interfaces: HelloInterface
}
init {
    getenv@Runtime( "HOSTNAME" )( HOSTNAME )
}
main {
    hello( request )( response ) {
        response = HOSTNAME + ":" + request
    }
}
The HOSTNAME environment variable is set by Kubernetes itself and it's printed out to show what microservice instance is answering the request.
Creating a docker image
The Dockerfile needed to create a docker image of this microservice is the same seen in the Docker section:
FROM jolielang/jolie
EXPOSE 8000
COPY helloservice.ol main.ol
CMD jolie main.ol
Typing the following command in the console actually creates the image:
docker build -t hello .
Creating a Kubernetes Deployment
This image can now be wrapped in Pods, the smallest deployable units of computing that can be created and managed in Kubernetes. A Deployment describes in a declarative way the desired state of a ReplicaSet having the purpose to maintain a stable set of replica Pods running at any given time:
apiVersion: apps/v1
kind: Deployment
metadata:
    name: jolie-sample-deployment
    labels:
        app: jolie-sample
spec:
    replicas: 2
    selector:
        matchLabels:
            app: jolie-sample
    template:
        metadata:
            labels:
                app: jolie-sample
        spec:
            containers:
            - name: jolie-k8s-sample
                image: hello
                ports:
                - containerPort: 8000
                imagePullPolicy: IfNotPresent
To create the Deployment save the text above in jolie-k8s-deployment.yml file and type this command:
kubectl apply -f jolie-k8s-deployment.yml
After a few seconds you can see your pods up and running using this command:
kubectl get pods
Exposing Deployment by a Service
Now we have 2 running Pods, each one listening on port 8000, but with 2 issues: 1. they're reachable only from the internal Kubernetes cluster network; 2. they're ephemeral. As explained here, a Service is needed to expose the application in the right way. Following the Minikube tutorial, just type:
kubectl expose deployment jolie-sample-deployment --type=LoadBalancer --port=8000
to create such Service. The result can be verified with this command:
kubectl get services
and the output should be something like this:
NAME                                            TYPE                     CLUSTER-IP            EXTERNAL-IP     PORT(S)                    AGE
jolie-sample-deployment     LoadBalancer     10.109.47.147     <pending>         8000:30095/TCP     13s
kubernetes                                ClusterIP            10.96.0.1             <none>                443/TCP
The last step is to make the Service visible from your host going through a "minikube service":
minikube service jolie-sample-deployment
|-----------|-------------------------|-------------|-----------------------------|
| NAMESPACE   | NAME                      | TARGET PORT   | URL                           |
|-------------|---------------------------|---------------|-------------------------------|
| default     | jolie-sample-deployment   |               | http://<your_IP>:<ext_port>   |
| ----------- | ------------------------- | ------------- | ----------------------------- |
Invoking microservices from client
Now we a stable access door to our application, and it can be invoked by a client:
include "console.iol"
interface HelloInterface {
RequestResponse:
    hello( string )( string )
}
outputPort Hello {
    Location: "socket://<your_IP>:<ext_port>"
    Protocol: sodep
    Interfaces: HelloInterface
}
main {
    hello@Hello( "hello" )( response );
    println@Console( response )()
}
Each time you make a request typing:
jolie client.ol
your local is hit and the LoadBalancer redirects the request to one of the 2 available Pods running the service. Printing out the HOSTNAME variable makes visible the load balancing, showing which Pod is serving the response:
$ jolie client.ol
jolie-sample-deployment-655f8b759d-mq8cn:hello
$ jolie client.ol
jolie-sample-deployment-655f8b759d-bmzk7:hello
$ jolie client.ol
jolie-sample-deployment-655f8b759d-mq8cn:hello
$ jolie client.ol
jolie-sample-deployment-655f8b759d-bmzk7:hello