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

  1. 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
    
  2. A quick way to access the dashboard is to run

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

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

  3. Change line type: ClusterIP to type: NodePort.

  4. Get the TCP port it’s running on:

    kubectl get svc kubernetes-dashboard -o json --namespace=kube-system
    
  5. Give privileges to the default service account run

    kubectl create clusterrolebinding add-on-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default
    
  6. Get the default service accounts token

    kubectl describe secret default
    
  7. Add the token to your Browser HTTP request with a add-on.

    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.

Dashboard

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.

# /etc/docker/daemon.json
{ "insecure-registries":["<ip of local registry>:5000"] }

On the machine pushing to registry and on the pods retrieving 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 file mule-ee-3.9/startMule.sh should be modified with your Anypoint platform credentials for automatic registration, e.g. 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

---
# 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
  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 fail-over 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.

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

    kubectl create -f mule-deployment.yml
    
  3. 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).

  4. 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
    
  5. 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

  6. 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.

Comparison of different compression tools

Working with various compressed files on a daily basis, I found I didn’t actually know how the different tools performed compared to each other. I know different compression will best fit different types of data, but I wanted to compare using a large generic file.

The setup

The file I chose was a 4194304000 byte (4.0 GB) Ubuntu installation disk image.

The machine tasked with doing of the bit-mashing was an Ubuntu with a AMD Ryzen 9 5900X 12-Core ... [continue reading]

Why TCP keepalive may be important

Published on December 17, 2024

The irony of insecure security software

Published on December 09, 2024