{"id":19024899,"url":"https://github.com/sonujose/kubernetes-raspberrypi","last_synced_at":"2025-07-15T23:34:03.735Z","repository":{"id":115803913,"uuid":"158320888","full_name":"sonujose/kubernetes-raspberrypi","owner":"sonujose","description":"Running a kubernetes cluster in a raspberry pi 3","archived":false,"fork":false,"pushed_at":"2021-12-11T13:52:52.000Z","size":11,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-21T19:12:46.654Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sonujose.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-20T02:42:54.000Z","updated_at":"2021-12-11T13:52:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"df2106af-4381-4a87-bd93-d4cab72d45fa","html_url":"https://github.com/sonujose/kubernetes-raspberrypi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sonujose/kubernetes-raspberrypi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonujose%2Fkubernetes-raspberrypi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonujose%2Fkubernetes-raspberrypi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonujose%2Fkubernetes-raspberrypi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonujose%2Fkubernetes-raspberrypi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sonujose","download_url":"https://codeload.github.com/sonujose/kubernetes-raspberrypi/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sonujose%2Fkubernetes-raspberrypi/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265467536,"owners_count":23770743,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T20:39:27.196Z","updated_at":"2025-07-15T23:34:03.691Z","avatar_url":"https://github.com/sonujose.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kubernetes on raspberry pi 3\n\nYes - you can create a Kubernetes cluster with Raspberry Pis with the default operating system called Raspbian. This means you can carry on using all the tools and packages you're used to with the officially-supported OS.\n\n## Pre-reqs:\n\n* You must use an RPi 2 or 3 for use with Kubernetes\n* I'm assuming you're using wired ethernet (Wi-Fi also works, but it's not recommended)\n* You must have a Raspbean OS running on yout raspberry pi (Raspbian Jessie recommented)\n\nhttps://www.raspberrypi.org/downloads/raspbian/\n\n## Master node setup\n\n* Change hostname\n\nUse the `raspi-config` utility to change the hostname to k8s-master-1 or similar and then reboot.\n\n* Set a static IP address\n\nIt's not fun when your cluster breaks because the IP of your master changed. The master's certificates will be bound to the IP address, so let's fix that problem ahead of time:\n\n```\ncat \u003e\u003e /etc/dhcpcd.conf\n```\n\nPaste this block:\n\n```\nprofile static_eth0\nstatic ip_address=192.168.0.100/24\nstatic routers=192.168.0.1\nstatic domain_name_servers=8.8.8.8\n```\n\nHit Control + D.\n\nChange 100 for 101, 102, 103 etc.\n\nYou may also need to make a reservation on your router's DHCP table so these addresses don't get given out to other devices on your network.\n\n* Install Docker\nTake care while installing docker, ned to make sure the latest verified docker version by kubernetes, here i am adding code for bth downloadng latest version as well as specified version (I spend a lot time figuring out the version mismatch issue)\n\nUse the specified docker version\n```\nexport VERSION=18.03 \u0026\u0026 curl -sSL get.docker.com | sh \u0026\u0026 \\\nsudo usermod pi -aG docker\n```\nDownload the latest docker version\n```\n$ curl -sSL get.docker.com | sh \u0026\u0026 \\\nsudo usermod pi -aG docker\nnewgrp docker\n```\n\n* Disable swap\n\nFor Kubernetes 1.7 and onwards you will get an error if swap space is enabled.\n\nTurn off swap:\n\n```\n$ sudo dphys-swapfile swapoff \u0026\u0026 \\\n  sudo dphys-swapfile uninstall \u0026\u0026 \\\n  sudo update-rc.d dphys-swapfile remove\n```\n\nThis should now show no entries:\n\n```\n$ sudo swapon --summary\n```\n\n* Edit `/boot/cmdline.txt`\n\nAdd this text at the end of the line, but don't create any new lines:\n\nYou can use vim (or any editor of you choice (nano))\n```bash\nsudo vim /boot/cmdline.txt\n```\n\n```\ncgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory\n```\n\nNow reboot - do not skip this step.\n\n* Add repo lists \u0026 install `kubeadm`\n\n```\n$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - \u0026\u0026 \\\n  echo \"deb http://apt.kubernetes.io/ kubernetes-xenial main\" | sudo tee /etc/apt/sources.list.d/kubernetes.list \u0026\u0026 \\\n  sudo apt-get update -q \u0026\u0026 \\\n  sudo apt-get install -qy kubeadm\n```\n\n\u003e I realise this says 'xenial' in the apt listing, don't worry. It still works.\n\n### Initialize your master node\n\n* You now have two new commands installed:\n * kubeadm - used to create new clusters or join an existing one\n * kubectl - the CLI administration tool for Kubernetes\n\nIf using Weave Net\n\n* Initialize your master node:\n\n```\n$ sudo kubeadm init --token-ttl=0\n```\n\nIf using Flannel:\n\n* Initialize your master node with a Pod network CIDR:\n\n```\n$ sudo kubeadm init --token-ttl=0 --pod-network-cidr=10.244.0.0/16\n```\n\nWe pass in `--token-ttl=0` so that the token never expires - do not use this setting in production. The UX for `kubeadm` means it's currently very hard to get a join token later on after the initial token has expired. \n\n\u003e Optionally also pass `--apiserver-advertise-address=192.168.0.27` with the IP of the Pi as found by typing `ifconfig`.\n\nNote: This step can take a long time, even up to 15 minutes.\n\nSometimes this stage can fail, if it does then you should patch the API Server to allow for a higher failure threshold during initialization around the time you see `[controlplane] wrote Static Pod manifest for component kube-apiserver to \"/etc/kubernetes/manifests/kube-apiserver.yaml\"`\n\n```\nsudo sed -i 's/failureThreshold: 8/failureThreshold: 20/g' /etc/kubernetes/manifests/kube-apiserver.yaml\n```\n\nAfter the `init` is complete run the snippet given to you on the command-line:\n\n```\n  mkdir -p $HOME/.kube\n  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config\n  sudo chown $(id -u):$(id -g) $HOME/.kube/config\n```\n\nThis step takes the key generated for cluster administration and makes it available in a default location for use with `kubectl`.\n\n* Now save your join-token\n\nYour join token is valid for 24 hours, so save it into a text file. Here's an example of mine:\n\n```\n$ kubeadm join --token 9e700f.7dc97f5e3a45c9e5 192.168.0.27:6443 --discovery-token-ca-cert-hash sha256:95cbb9ee5536aa61ec0239d6edd8598af68758308d0a0425848ae1af28859bea\n```\n\n* Check everything worked:\n\n```\n$ kubectl get pods --namespace=kube-system\nNAME                                  READY   STATUS    RESTARTS   AGE\ncoredns-576cbf47c7-n85xt              1/1     Running   0          6m25s\ncoredns-576cbf47c7-rq6lc              1/1     Running   0          6m25s\netcd-raspberrypi                      1/1     Running   0          5m55s\nkube-apiserver-raspberrypi            1/1     Running   1          7m57s\nkube-controller-manager-raspberrypi   1/1     Running   0          7m58s\nkube-proxy-w26jz                      1/1     Running   0          6m25s\nkube-scheduler-raspberrypi            1/1     Running   0          5m47s\nweave-net-wdq4f                       2/2     Running   0          2m39s\n```\n\nYou should see the \"READY\" count showing as 1/1 for all services as above. DNS uses three pods, so you'll see 3/3 for that.\n\n### Setup networking with Weave Net or Flannel\n\nSome users have reported stability issues with Weave Net on ARMHF. These issues do not appear to affect x86_64 (regular PCs/VMs). You may want to try Flannel instead of Weave Net for your RPi cluster.\n\n#### Weave Net\n\nInstall [Weave Net](https://www.weave.works/oss/net/) network driver\n\n```\n$ kubectl apply -f \\\n \"https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\\n')\"\n```\n\nIf you run into any issues with Weaveworks' networking then [flannel](https://github.com/coreos/flannel) is also a popular choice for the ARM platform.\n\n#### Flannel (alternative)\n\nApply the Flannel driver on the master:\n\n```\n$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/c5d10c8/Documentation/kube-flannel.yml\n```\n\nOn each node that joins including the master:\n\n```\n$ sudo sysctl net.bridge.bridge-nf-call-iptables=1\n```\n\n### Join other nodes\n\nOn the other RPis, repeat everything apart from `kubeadm init`.\n\n* Change hostname\n\nUse the `raspi-config` utility to change the hostname to `k8s-worker-1` or similar and then reboot.\n\n* Join the cluster\n\nReplace the token / IP for the output you got from the master node, for example:\n\n```\n$ sudo kubeadm join --token 1fd0d8.67e7083ed7ec08f3 192.168.0.27:6443\n```\n\nYou can now run this on the master:\n\n```\n$ kubectl get nodes\nNAME      STATUS     AGE       VERSION\nk8s-1     Ready      5m        v1.7.4\nk8s-2     Ready      10m       v1.7.4\n```\n\n## Deploy a container\n\nThis container will expose a HTTP port and convert Markdown to HTML. Just post a body to it via `curl` - follow the instructions below. \n\n*function.yml*\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n  name: markdownrender\n  labels:\n    app: markdownrender\nspec:\n  type: NodePort\n  ports:\n    - port: 8080\n      protocol: TCP\n      targetPort: 8080\n      nodePort: 31118\n  selector:\n    app: markdownrender\n---\napiVersion: apps/v1beta1 # for versions before 1.6.0 use extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: markdownrender\nspec:\n  replicas: 1\n  template:\n    metadata:\n      labels:\n        app: markdownrender\n    spec:\n      containers:\n      - name: markdownrender\n        image: functions/markdownrender:latest-armhf\n        imagePullPolicy: Always\n        ports:\n        - containerPort: 8080\n          protocol: TCP\n```\n\nDeploy and test:\n\n```\n$ kubectl create -f function.yml\n```\n\nOnce the Docker image has been pulled from the hub and the Pod is running you can access it via `curl`: \n\n```\n$ curl -4 http://127.0.0.1:31118 -d \"# test\"\n\u003cp\u003e\u003ch1\u003etest\u003c/h1\u003e\u003c/p\u003e\n```\n\nIf you want to call the service from a remote machine such as your laptop then use the IP address of your Kubernetes master node and try the same again.\n\n## Start up the Kubernetes dashboard\n\nThe dashboard can be useful for visualising the state and health of your system, but it does require the equivalent of \"root\" in the cluster. If you want to proceed you should first run in a [ClusterRole from the docs](https://github.com/kubernetes/dashboard/wiki/Access-control#admin-privileges).\n\n```\necho -n 'apiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRoleBinding\nmetadata:\n  name: kubernetes-dashboard\n  labels:\n    k8s-app: kubernetes-dashboard\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: cluster-admin\nsubjects:\n- kind: ServiceAccount\n  name: kubernetes-dashboard\n  namespace: kube-system' | kubectl apply -f -\n```\n\nThis is the development/alternative dashboard which has TLS disabled and is easier to use.\n\n```\n$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/alternative/kubernetes-dashboard-arm.yaml\n```\n\nYou can then find the IP and port via `kubectl get svc -n kube-system`. To access this from your laptop you will need to use `kubectl proxy` and navigate to `http://localhost:8001/` on the master, or tunnel to this address with `ssh`.\n\nSee also: [Kubernetes Dashboard](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/) docs.\n\n## Remove the test deployment\n\nNow on the Kubernetes master remove the test deployment:\n\n```\n$ kubectl delete -f function.yml\n```\n\n### Wrapping up\n\nYou should now have an operational Kubernetes master and several worker nodes ready to accept workloads.\n\nNow let's head back [over to the tutorial and deploy OpenFaaS](https://blog.alexellis.io/serverless-kubernetes-on-raspberry-pi/) to put the cluster through its paces with Serverless functions.\n\nSee also: [Kubernetes documentation](https://kubernetes.io/docs/home/?path=users\u0026persona=app-developer\u0026level=foundational)\n\nThis is part of a blog post [Serverless Kubernetes home-lab with your Raspberry Pis\n](https://blog.alexellis.io/serverless-kubernetes-on-raspberry-pi/) written by [Alex Ellis](https://twitter.com/alexellisuk).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsonujose%2Fkubernetes-raspberrypi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsonujose%2Fkubernetes-raspberrypi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsonujose%2Fkubernetes-raspberrypi/lists"}