{"id":20858849,"url":"https://github.com/adnanhodzic/rpi-microk8s-bootstrap","last_synced_at":"2025-10-24T12:02:01.770Z","repository":{"id":168231382,"uuid":"642431351","full_name":"AdnanHodzic/rpi-microk8s-bootstrap","owner":"AdnanHodzic","description":"Automate RPI device conversion into Kubernetes cluster nodes with Terraform","archived":false,"fork":false,"pushed_at":"2024-08-04T06:52:06.000Z","size":32,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-08-04T08:55:20.742Z","etag":null,"topics":["automate","bootstrap","cluster","k8s","kubernetes","microk8s","module","nodes","project","python","rpi","rpi4","server","template","terraform","ubuntu"],"latest_commit_sha":null,"homepage":"https://foolcontrol.org/?p=4555","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AdnanHodzic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2023-05-18T14:50:08.000Z","updated_at":"2024-08-04T06:52:10.000Z","dependencies_parsed_at":"2024-08-03T08:59:21.146Z","dependency_job_id":null,"html_url":"https://github.com/AdnanHodzic/rpi-microk8s-bootstrap","commit_stats":null,"previous_names":["adnanhodzic/rpi-microk8s-bootstrap"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdnanHodzic%2Frpi-microk8s-bootstrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdnanHodzic%2Frpi-microk8s-bootstrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdnanHodzic%2Frpi-microk8s-bootstrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdnanHodzic%2Frpi-microk8s-bootstrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AdnanHodzic","download_url":"https://codeload.github.com/AdnanHodzic/rpi-microk8s-bootstrap/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225130751,"owners_count":17425506,"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":["automate","bootstrap","cluster","k8s","kubernetes","microk8s","module","nodes","project","python","rpi","rpi4","server","template","terraform","ubuntu"],"created_at":"2024-11-18T04:47:46.241Z","updated_at":"2025-10-24T12:02:01.763Z","avatar_url":"https://github.com/AdnanHodzic.png","language":"Python","funding_links":["https://github.com/sponsors/AdnanHodzic","https://www.paypal.com/donate?business=7AHCP5PU95S4Y\u0026no_recurring=0\u0026item_name=Purpose%3A+Contribution+for+work+on+rpi-microk8s-bootstrap\u0026currency_code=EUR"],"categories":[],"sub_categories":[],"readme":"\n\n# rpi-microk8s-bootstrap\n\nThis repo contains [\"microk8s-bootstrap\" Terraform module](./modules/microk8s-bootstrap) used for automated provisioning of Ubuntu server \u0026 MicroK8s on a Raspberry Pi (RPI) node. In matter of minutes, final result will be a node which is ready to start new Kubernetes cluster, or join an existing one. Ready to have Kubernetes workloads deployed to it.\n\nIt's designed to automatically perform manual steps described as part of:\n\n* \"Step 3: Installing and configuring Ubuntu server on RPI 4’s nodes\" and\n* \"Step 4: Installing and configuring MicroK8s\" \n\nsections of [wp-k8s: WordPress on privately hosted Kubernetes cluster (Raspberry Pi 4 + Synology)](https://foolcontrol.org/?p=4004) blog post. Also related: [wp-k8s: WordPress on Kubernetes project](https://github.com/AdnanHodzic/wp-k8s).\n\n## How can this Terraform project help me?\n\nProject was created and designed with 2 main use-cases in mind:\n\n### 1. Bootstrap Ubuntu server \u0026 MicroK8s to a RPI device, automatically and in matter of minutes\n\nAs mentioned above, installing and configuring Ubuntu server \u0026 MicroK8s to be ready to start new Kubernetes cluster, or join an existing one, consists of many manual steps and is a lengthy process.\n\nBy setting few variable values and running terraform code as explained in section below, this terraform project allows you to seamlessly have Ubuntu server with MicroK8s configured with all necessary changes to deploy Kubernetes workloads on it. Ultimately, turning your RPI device into a Kubernetes cluster or one of its nodes in matter of minutes.\n\nResult of successful Terraform code run:\n\n\u003cimg src=\"https://github.com/user-attachments/assets/954a304c-6a48-438a-9c86-1c913f81f9cf\" width=\"640\" alt=\"Example rpi-microk8s-bootstrap Terraform project run\"/\u003e\n\nFor full list of changes that will be made, please refer to [\"microk8s-bootstrap\" Terraform module README](./modules/microk8s-bootstrap).\n\n### 2. Upgrade to a new Kubernetes (MicroK8s) release and/or perform Ubuntu upgrade on an existing RPI node of your Kubernetes cluster\n\nWithout this project, upgrading to a new Kubernetes (MicroK8s) version is a daunting (manual) task which involves:\n\n* Getting a list of nodes of your K8s cluster\n* Draining worker nodes\n* Verifying no workloads are running on target node\n* Upgrading Kubernetes (MicroK8s) on target node\n* Verifying upgrade went well and then resume pod scheduling on the upgraded node\n\nBy utilizing this project, same process is as simple as taking the target node ouf of the cluster and specifying desired version of Kubernetes (MicroK8s) in [variables](https://github.com/AdnanHodzic/rpi-microk8s-bootstrap/blob/5a3f1f1ab1a483c885137d4ff5a243a9cea7bb3a/main.tf#L33). After Terraform code execution, node can be added back to the cluster and all software updates for Ubuntu will also be installed. If same `microk8s_version` variable value was used as before (during provisioning), terraform code execution will only consist of updating all software on selected node.\n\n## How to use this project?\n\n### Pre-requisites\n* RPI \u003e= 4 device\n* Installed Ubuntu server image to SD card (explained as part of [Step 3.1: Write Ubuntu server \u003e= 20.04.x arm64 image to RPI’s](https://foolcontrol.org/?p=4004) section)\n* Run `terraform init`\n\n\nVerified and tested on Raspberry Pi 4 Model B \u0026 Ubuntu 22.04.\n\n#### Please note! \n\nAs part of [\"microk8s-bootstrap\" module](./modules/microk8s-bootstrap) execution, [microk8s-bootstrap.tpl](./modules/microk8s-bootstrap/microk8s_bootstrap.tpl) file will generate \"rpi-microk8s-boostrap.py\" file during Terraform code execution that has all necessary changes, which is designed to be run numerous times without overwriting existing configurations. Meaning, this code will run *every time* and as such won't need to rely on functionality of Terraform state file. Hence, undocumented terraform [\"inmem\" backend](https://github.com/AdnanHodzic/rpi-microk8s-bootstrap/blob/5a3f1f1ab1a483c885137d4ff5a243a9cea7bb3a/main.tf#L3) is used, which will execute terraform code without generating terraform.tfstate file. To override this behavior, comment/remove its code block.\n\n### How to bootstrap Ubuntu server \u0026 MicroK8s to a new RPI device, ready to deploy Kubernetes workloads\n\nAfter Ubuntu image was written to SD card as described as part of [pre-requisites](#pre-requisites), make sure to refer to [rpi-microk8s-bootstrap/main.tf](./main.tf) file and update all variables accordingly!\n\nIn particular: \n\n  * password\n  * new_hostname\n  * current_ip\n  * new_rpi_ip\n  * microk8s_version\n\nIn case of writing to more then one node, simply update above mentioned variables and subsequently run the same Terraform code on next RPI node, i.e:\n\n```\nterraform plan\nterraform apply\n```\n\nFollowed by running changes explained as part of [Step 4.9: Enable High Availability k8s cluster by adding rest of RPI nodes](https://foolcontrol.org/?p=4004) section.\n\nFor more information, please refer to [rpi-microk8s-bootstrap/main.tf](./main.tf) or [\"microk8s-bootstrap\" module README](./modules/microk8s-bootstrap) file. After successful Terraform code execution, please refer to:\n\n* \"Step 4.4: Check cluster status\" and\n* \"Step 4.6: Configure access to microk8s cluster by configuring kubeconfig\"\n\nsections of [wp-k8s: WordPress on privately hosted Kubernetes cluster (Raspberry Pi 4 + Synology)](https://foolcontrol.org/?p=4004) blog post to complete the node access configuration.  \n\n### How to Upgrade to a new Kubernetes (MicroK8s) or Ubuntu release on an existing RPI node of your Kubernetes cluster\n\nIn case of high availability setup, where for example you had RPI K8s cluster consisting of 3 nodes i.e: rpi-a, rpi-b, rpi-c which were running on Ubuntu server 20.04 and Kubernetes (Microk8s) 1.24 release. \n\n```\nkubectl get nodes -o wide\nNAME    STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME\nrpi-c   Ready    \u003cnone\u003e   61d   v1.24.0   192.168.1.102   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\nrpi-a   Ready    \u003cnone\u003e   63d   v1.24.0   192.168.1.100   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\nrpi-b   Ready    \u003cnone\u003e   59d   v1.24.0   192.168.1.101   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\n```\n\nYou want to identify what's the cluster leader (master) node, by SSH-ing to one of the nodes and running following command, i.e:\n``` \nubuntu@rpi-a:~$ sudo -E /snap/microk8s/current/bin/dqlite -c /var/snap/microk8s/current/var/kubernetes/backend/cluster.crt -k /var/snap/microk8s/current/var/kubernetes/backend/cluster.key -s file:///var/snap/microk8s/current/var/kubernetes/backend/cluster.yaml k8s \".leader\"\n192.168.1.102:19001\n```\n\nIn this case, our leader node is 192.168.1.102 (rpi-c) and to have minimum downtime on your Kubernetes cluster workloads, it would be the best idea to take this node out of the cluster last and start by taking one of the workers node out of the cluster first, i.e: rpi-a\n \nRemove the node from cluster by running following command on departing node: \n```\nubuntu@rpi-a:~$ microk8s leave\nGenerating new cluster certificates.\nWaiting for node to start. . \n``` \n \nVerify status on MicroK8s leader node:\n```\nubuntu@rpi-c:~$ microk8s kubectl get nodes -o wide\nNAME    STATUS     ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME\nrpi-c   Ready      \u003cnone\u003e   61d   v1.24.0   192.168.1.102   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\nrpi-b   Ready      \u003cnone\u003e   63d   v1.24.0   192.168.1.101   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\nrpi-a   NotReady   \u003cnone\u003e   59d   v1.24.0   192.168.1.100   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\n```\n\nRemove microk8s worker node from leader node:\n```\nubuntu@rpi-c:~$ sudo microk8s remove-node rpi-a\nubuntu@rpi-c:~$ microk8s kubectl get nodes -o wide\nNAME    STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME\nrpi-c   Ready      \u003cnone\u003e   61d   v1.24.0   192.168.1.102   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\nrpi-b   Ready      \u003cnone\u003e   63d   v1.24.0   192.168.1.101   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\n```\n\nIn case node can't be removed for some reason, you can always resort to removing it by force:  `sudo microk8s remove-node -f rpi-a`\n\nAfter Ubuntu image was written to SD card (make sure to use new Ubuntu release!) for this node as described of [pre-requisites](#pre-requisites) make sure to refer to [rpi-microk8s-bootstrap/main.tf](./main.tf) file and update all variables accordingly!\n\nIn particular: \n\n  * password\n  * new_hostname\n  * current_ip\n  * new_rpi_ip\n  * microk8s_version\n\nPlease note, \n\n1. [\"microk8s-bootstrap\" module](./modules/microk8s-bootstrap) will setup SSH key based authentication if SSH key was found on local system, hence if this was done value provided in `password` variable won't have any effect now since authentication will be based on SSH key. \n2. `microk8s_version` variable value must be updated with desired Kubernetes (microk8s) release upgrade version.\n3. Also, for this use-case `current_ip` and `new_rpi_ip` variable values *should remain the same*. \n\nIn case of writing to more then one node, simply update above mentioned variables and subsequently run the same Terraform code on next RPI node, i.e:\n\n```\nterraform plan\nterraform apply\n```\n\nFor more information, please refer to [rpi-microk8s-bootstrap/main.tf](./main.tf) or [\"microk8s-bootstrap\" module README](./modules/microk8s-bootstrap) file. After successful Terraform code execution, please refer to:\n\n* \"Step 4.4: Check cluster status\" and\n* \"Step 4.6: Configure access to microk8s cluster by configuring kubeconfig\"\n\nsections of [wp-k8s: WordPress on privately hosted Kubernetes cluster (Raspberry Pi 4 + Synology)](https://foolcontrol.org/?p=4004) blog post to complete the node access configuration.  \n\nTo add new \u0026 updated node as part of the existing cluster, on MicroK8s leader node run: \n```\nubuntu@rpi-c:~$ microk8s add-node\nFrom the node you wish to join to this cluster, run the following:\nmicrok8s join 192.168.1.102:25000/a2b2219af978086966ff6fe2467711a1/18a446d13x81\n\nUse the '--worker' flag to join a node as a worker not running the control plane, eg:\nmicrok8s join 192.168.1.102:25000/a2b2219af978086966ff6fe2467711a1/18a446d13x81 --worker\n\nIf the node you are adding is not reachable through the default interface you can use one of the following:\nmicrok8s join 192.168.1.102:25000/a2b2219af978086966ff6fe2467711a1/18a446d13x81\n```\n\nFollowed by running as instructed on node that's supposed to join the target, i.e:\n```\nubuntu@rpi-a:~$ microk8s join 192.168.1.102:25000/a2b2219af978086966ff6fe2467711a1/18a446d13x81\nWARNING: Hostpath storage is enabled and is not suitable for multi node clusters.\n\nContacting cluster at 192.168.1.102\nWaiting for this node to finish joining the cluster. .. .. .. ..  \nubuntu@rpi-a:~$ microk8s kubectl get nodes -o wide\nNAME    STATUS   ROLES    AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME\nrpi-b   Ready    \u003cnone\u003e   61d   v1.24.0   192.168.1.101   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\nrpi-c   Ready    \u003cnone\u003e   63d   v1.24.0   192.168.1.102   \u003cnone\u003e        Ubuntu 20.04.5 LTS   5.10.0-1022-raspi   containerd://1.5.9\nrpi-a   Ready    \u003cnone\u003e   25s   v1.27.1   192.168.1.100   \u003cnone\u003e        Ubuntu 22.04.2 LTS   5.15.0-1027-raspi   containerd://1.6.15\n```\n\nKubernetes can run existing Kubernetes workloads on nodes consisting of different Kubernetes (MicroK8s) \u0026 Ubuntu releases, which will allow your cluster to run in uninterrupted state, as portrayed in code block above.\n\n### To only create \"microk8s_boostrap.py\" file from [microk8s-bootstrap.tpl](./modules/microk8s-bootstrap/microk8s_bootstrap.tpl) run:\n\n```\nterraform plan -target=module.microk8s-bootstrap.local_file.save-rendered-bootstrapfile\nterraform apply -target=module.microk8s-bootstrap.local_file.save-rendered-bootstrapfile\n```\n\n### Discussion: \n\n* Blog post: [rpi-microk8s-bootstrap: Automate RPI device conversion into Kubernetes cluster nodes with Terraform](https://foolcontrol.org/?p=4555)\n\n## Donate\n\nIf you found this project useful, show your support and appreciation by donating or contributing code. Otherwise, giving credits and acknowledgments also goes a long way.\n\n### Financial donation\n\nIf wp-k8s helped you out and you find it useful, show your appreciation by donating (any amount) to the project!\n\n##### Become Github Sponsor\n\n[Become a sponsor to Adnan Hodzic on Github](https://github.com/sponsors/AdnanHodzic) to acknowledge my efforts and help project's further open source development.\n\n##### PayPal\n[![paypal](https://www.paypalobjects.com/en_US/NL/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/donate?business=7AHCP5PU95S4Y\u0026no_recurring=0\u0026item_name=Purpose%3A+Contribution+for+work+on+rpi-microk8s-bootstrap\u0026currency_code=EUR)\n\n##### BitCoin\n[bc1qlncmgdjyqy8pe4gad4k2s6xtyr8f2r3ehrnl87](bitcoin:bc1qlncmgdjyqy8pe4gad4k2s6xtyr8f2r3ehrnl87)\n\n[![bitcoin](https://foolcontrol.org/wp-content/uploads/2019/08/btc-donate-displaylink-debian.png)](bitcoin:bc1qlncmgdjyqy8pe4gad4k2s6xtyr8f2r3ehrnl87)\n\n### Code contribution\n\nOther ways of supporting the project consists of making a code or documentation contribution. If you have an idea for a new features or want to implement some of the existing feature requests or fix some of the [bugs \u0026 issues](https://github.com/AdnanHodzic/wp-k8s/issues). Please make your changes and submit a [pull request](https://github.com/AdnanHodzic/wp-k8s/pulls) which I'll be glad to review. If your changes are accepted you'll be credited for your contiribution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadnanhodzic%2Frpi-microk8s-bootstrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadnanhodzic%2Frpi-microk8s-bootstrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadnanhodzic%2Frpi-microk8s-bootstrap/lists"}