The Raspberry Pi 3 is the third generation Raspberry Pi, on this I will be installing Mulesoft enterprise runtime with latest Java 8 running inside Kubernetes. The pods will register themselves with Anypoint platform runtime manager. This is not to be used as a guide for production, its the quick and dirty version ;)

The Kubernetes cluster features:

  • 4x The Raspberry Pi 3 nodes
  • A mule deployment of 2x pods with
  • mule-ee-distribution-standalone-3.9.0
  • Oracle jdk1.8.0_162
  • Automatic registration of pod in Anypoint Platform Runtime Manager on pod startup.
  • Health monitoring
  • A mule-service exposing cluster IP to the world.
  • A dashboard

alt text

Raspberry setup

Raspbian is the raspberry’s officially supported OS which we will be using. For the installation of Kubernetes on raspberry we will be following instructions from Kasper Nissen which has made an excellent blog post about this. Setup a Kubernetes 1.9.0 Raspberry Pi cluster on Raspbian using Kubeadm

When installation has completed, I suggest you change the default password on your raspberry’s with the default pi user and raspberry password to something different.

When the installation is done we now have:

1 master (192.168.1.x) called e.g red and 3 workers (192.168.1.x+1,+2,+3) called e.g pill1, pill2, pill3

Installing dashboard on Kubernetes

To get a simple system overview we will install Kubernetes Dashboard which is a general purpose, web-based UI for Kubernetes clusters

login to red and run the command:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/alternative/kubernetes-dashboard-arm.yaml

A quick way to access the dashboard is to run

kubectl edit svc/kubernetes-dashboard --namespace=kube-system

This will load the Dashboard config (yaml) into an editor where you can edit it.

Change line type: ClusterIP to type: NodePort.

Get the TCP port it’s running on:

kubectl get svc kubernetes-dashboard -o json --namespace=kube-system

Give privileges to the default service account run

kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default

Get the default service accounts token

kubectl describe secret default

Add the token to your Browser HTTP request with a addon.

Authorization : Bearer <token>

without passing the token you will see a dashboard but get errors like:

deployments.apps is forbidden: User “system:serviceaccount:kube-system:kubernetes-dashboard” cannot list deployments.apps in the namespace “default”

you should now be able to visit

http://<external ip of red>:<nodeport>/#!/deployment?namespace=default 

and see as pictured below

alt text

build docker image for arm on Linux

My last post on Mulesoft Enterprise Standalone Runtime on Raspberry Pi 3 with docker I was building on the raspberry. This time I build it from Linux, and to be able to do so I’ve run this docker image

docker run --rm --privileged multiarch/qemu-user-static:register --reset

Running a local docker registry to feed the nodes

To send my docker image to Kubernetes I’m running a local docker registry

docker run -d -p 5000:5000 --restart=always --name registry registry:2

to make things easy for myself I just allowed unsecured access e.g no https

accept unsecured local registry

vi /etc/docker/daemon.json

{ "insecure-registries":["<ip of local registry>:5000"] }

on the machine pushing to registry, and on the pods retreiving from registry.

Configure docker image

The docker image for running mule on docker/arm has been updated to a newer mule runtime and compressed a bit since my last post on this. e.g run commands have been chained. Its also been updated to handle a 404 error of oracle-jdk8-installer and using the latest version available at the time of this writing.

git clone https://github.com/simonvalter/Dockerfiles.git

the mule-ee-3.9/startMule.sh should be modified with your Anypoint platform credentials for automatic registration. eg to:

username="myuser"
password="mypassword"
orgName="Redpill-Linpro Org"
envName="Dev"
serverName=$(hostname -f) # we want unique names to be registered in anypoint platform runtime manager

Build docker image

cd Dockerfiles/mule-ee-3.9
docker build --no-cache=true -t <ip of local registry>:5000/mule-ee:3.9.0 .

Shrink docker image

An optional step is to shrink the image size additionally as the nodes don’t have that much to give, and this will reduce it by about 30%

For this, I’m using the python version of docker-squash, and on Ubuntu installing it would be

sudo apt-get install pip
pip install docker-squash --user
export PATH=$PATH:/home/<your user>/.local/bin
docker-squash -t <ip of local registry>:5000/mule-ee:squashed <ip of local registry>:5000/mule-ee:3.9.0

Push docker image to registry

docker push <ip of local registry>:5000/mule-ee:squashed

Create and deploy a mule deployment on Kubernetes

cat mule-deployment.yml

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: mule-deployment  
  labels:
    app: mule 
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mule 
  template:
    metadata:
      labels:
        app: mule  
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - mule     
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: mule 
        image: <ip of local registry>:5000/mule-ee:squashed 
        ports:
        - containerPort: 8081
        readinessProbe:
          httpGet:
            path: /healthz
            port: 8087
          initialDelaySeconds: 120
          periodSeconds: 1

Here we are creating a deployment which is using podAntiAffinity to make sure that we don’t co-locate the pods on the same nodes, as its otherwise very likely that Kubernetes might just schedule a pod on the same node during failover when we have so few nodes and with so few resources it won’t work very well. We are also calling a health check application on the mule runtime so there won’t be sent traffic to it in case it goes down for some reason. As these nodes are quite slow to startup on raspberry we will wait about 120 seconds before checking.

After the deployment description has been created we will create it in Kubernetes

kubectl create -f mule-deployment.yml

Now we want to expose the deployment as a service to an external IP

kubectl expose deployment mule-deployment --type=LoadBalancer --name=mule-service --external-ip=<ip of red>

Within minutes you should see it downloaded, deployed and running on your raspberry’s (2 of them).

check with

kubectl get pods -o wide
NAME                               READY     STATUS    RESTARTS   AGE       IP           NODE
mule-deployment-6b9d849cdc-2hv4r   1/1       Running   0          20h       10.34.0.12   pill2
mule-deployment-6b9d849cdc-qhzn6   1/1       Running   0          20h       10.38.0.15   pill1

That’s it, on Anypoint platform the pods should have registered themselves, and in this case, I’ve put them into a group and deployed a health application that just returns 200 OK, and the Hello World example from Anypoint exchange. I’m setting the parameter http.port through runtime manager to the exposed port 8081.

alt text

We can now call the mule-service on the external IP and get the famous Hello World! response.

curl http://<external ip>:8081/helloWorld

Hello World!

Simon Nyborg Valter

Integration Consultant at Redpill Linpro

Simon Valter works as an integration specialist and Java developer, from our office in Copenhagen, creating integrations in Mule for various customers.

Layer 3 routing on Cumulus Linux MLAG

We build our network in order to simultaneously achieve high availability and maximum utilisation of available bandwidth. To that end, we are using Multi-Chassis Link Aggregation (MLAG) between our data centre switches running Cumulus Linux and our firewall cluster ... [continue reading]

Mule 4 SDK custom connector example

Published on February 02, 2018

Jenkinsfile to Anypoint platform and Artifactory

Published on January 26, 2018