Assertfail

Running minikube on M1 and K8S tutorial

05 Apr 2023

As previously mentioned in the blog I use a M1 mac.

In order to help introduce others to Kubernetes I have done some testing of the K8S tutorial.

In order to try it out I first tried using the qemu driver for minikube. First gotcha was that the image gcr.io/google-samples/kubernetes-bootcamp:v1 does not work on ARM natively.

Let the Yac Shaving begin

Running minikube in docker

In order to get around this limitation you can run minikube in docker. Either by using colima or Docker Desktop with experimental Rosetta emulation.

minikube start --driver docker

Running the first part part of the tutorial works fine. You can create a deployment, you can view pods and nodes. The weird part starts when you forget that minikube is now running in a docker container instance and run:

kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
#...
export NODE_PORT="$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort }}')"
echo "NODE_PORT=$NODE_PORT"

Then try to do:

curl http://"$(minikube ip):$NODE_PORT"

expose intro

Since we are not binding all of the ports for minikube docker instance, the exposed port is not bound.

Instead you can do:

minikube service kubernetes-bootcamp --url

to get the url to the service.

Using qemu and building your own docker images

Since I started out with a simple qemu install I wanted to go all in the next round. I installed socket_vmnet and used:

brew install socket_vmnet
brew tap homebrew/services
HOMEBREW=$(which brew) && sudo ${HOMEBREW} services start socket_vmnet
#...
minikube start --driver qemu --network socket_vmnet

I then built images that uses both arm and x86:

First the Dockerfile:

FROM node:slim
EXPOSE 8080
COPY server.js .
CMD node server.js

based on kubernetes bootcamp Dockerfile

server.js:

var http = require('http');
var requests=0;
var podname= process.env.HOSTNAME;
var startTime;
var host;
var handleRequest = function(request, response) {
  response.setHeader('Content-Type', 'text/plain');
  response.writeHead(200);
  response.write("Hello Kubernetes bootcamp! | Running on: ");
  response.write(host);
  response.end(" | v=1\n");
  console.log("Running On:" ,host, "| Total Requests:", ++requests,"| App Uptime:", (new Date() - startTime)/1000 , "seconds", "| Log Time:",new Date());
}
var www = http.createServer(handleRequest);
www.listen(8080,function () {
    startTime = new Date();;
    host = process.env.HOSTNAME;
    console.log ("Kubernetes Bootcamp App Started At:",startTime, "| Running On: " ,host, "\n" );
});

based on kubernetes bootcamp server.js

My first instinct was to simply build the image and be done with it. But that is not as fun as going deeper. To take it further I wanted to grow the bananas to be used in the smoothie!

First I tried:

version='v1'
name="wallymathieu/kubernetes-bootcamp:$version"

docker buildx build -t $name ./$version -f Dockerfile --platform=linux/arm64,linux/amd64 --push && echo "Image $name built"

I got Error: multiple platforms feature is currently not supported for docker driver.

When running The buildx ls environment looked like it could handle amd64:

> docker buildx ls
NAME/NODE       DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default *       docker
  default       default         running 20.10.23 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux   running 20.10.23 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

I then found that others had solved this issue by simply creating a new buildx multiarch with docker container driver:

docker buildx create --name multiarch --driver docker-container --use

I could then build the images and push them to docker hub, as can be seen here.

Now I could continue on the kubernetes bootcamp tutorial using the custom images.

So instead of using the default 7 year old image (gcr.io/google-samples/kubernetes-bootcamp:v1) I wanted my shining new multi platform image built using the same code as in jocatalin/kubernetes-bootcamp:

kubectl create deployment kubernetes-bootcamp --image=wallymathieu/kubernetes-bootcamp:v1

And instead of upgrade your app using the old image, I used the custom built v2 image:

kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=wallymathieu/kubernetes-bootcamp:v2

Side-note

One thing that struck me was that why did they use gcr.io/google-samples/kubernetes-bootcamp:v1 instead of jocatalin/kubernetes-bootcamp:v1, I did get my answer when I tried using that image and could not connect to port 8080 on that image since the code assumes port 8081 while the dockerfile says port 8080 perhaps to have a reason to patch the image?

Conclusion

Successfully shaved the Yak! I got the tutorial working and only had to do a few smallish things in order to finish it.

Tags


Comments

Do you want to send a comment or give me a hint about any issues with a blog post: Open up an issue on GitHub.

Do you want to fix an error or add a comment published on the blog? You can do a fork of this post and do a pull request on github.