{"id":1328,"date":"2025-08-11T12:05:22","date_gmt":"2025-08-11T11:05:22","guid":{"rendered":"https:\/\/blog.hslracing.com\/myhome\/?p=1328"},"modified":"2025-08-11T13:00:49","modified_gmt":"2025-08-11T12:00:49","slug":"my-next-cluster-installation-and-configuration","status":"publish","type":"post","link":"https:\/\/blog.hslracing.com\/myhome\/2025\/08\/my-next-cluster-installation-and-configuration.html","title":{"rendered":"My Next Cluster &#8211; Installation and Configuration"},"content":{"rendered":"<p>Some of the technologies that will be used on this installation:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/www.proxmox.com\/en\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1336 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Proxmox_logo-1-300x300.png\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Proxmox_logo-1-300x300.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Proxmox_logo-1-150x150.png 150w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Proxmox_logo-1.png 500w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a> <a href=\"https:\/\/ceph.io\/en\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1330 size-full\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/ceph-241x300-1.png\" alt=\"\" width=\"241\" height=\"300\" \/><\/a> <a href=\"https:\/\/developer.hashicorp.com\/terraform\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1337 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Terraform-Logo-e1754902280935-273x300.png\" alt=\"\" width=\"273\" height=\"300\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Terraform-Logo-e1754902280935-273x300.png 273w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Terraform-Logo-e1754902280935.png 354w\" sizes=\"auto, (max-width: 273px) 100vw, 273px\" \/><\/a> <a href=\"https:\/\/ubuntu.com\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1349 size-full\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Ubuntu.png\" alt=\"\" width=\"242\" height=\"209\" \/><\/a> \u00a0<a href=\"https:\/\/www.rancher.com\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1339 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Rancher_Logo-300x150.png\" alt=\"\" width=\"300\" height=\"150\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Rancher_Logo-300x150.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Rancher_Logo.png 318w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a> <a href=\"https:\/\/k3s.io\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1331 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/K3S_Logo-237x300.png\" alt=\"\" width=\"237\" height=\"300\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/K3S_Logo-237x300.png 237w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/K3S_Logo.png 280w\" sizes=\"auto, (max-width: 237px) 100vw, 237px\" \/><\/a> <a href=\"https:\/\/www.docker.com\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1358 size-full\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Docker-Logo.png\" alt=\"\" width=\"245\" height=\"206\" \/><\/a> \u00a0<a href=\"https:\/\/wordpress.com\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1347 size-full\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Wordpress.png\" alt=\"\" width=\"238\" height=\"212\" \/><\/a><\/p>\n<p><a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> or K8s (K &#8216;8 letters&#8217; S &#8211; pronounced &#8216;cates&#8217;) is a container orchestration system that automates the deployment, scaling and management of containerised applications<\/p>\n<p><a href=\"https:\/\/k3s.io\/\">K3s<\/a> (K &#8216;3 letters&#8217; S) is a lightweight version of <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> designed for <a href=\"https:\/\/en.wikipedia.org\/wiki\/Internet_of_things\">IoT<\/a> and <a href=\"https:\/\/en.wikipedia.org\/wiki\/Edge_computing\">Edge Computing<\/a> platforms<\/p>\n<h2>Cluster #1 &#8211; Proxmox<\/h2>\n<p><a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> Virtual Environment is a virtualisation platform for hosting virtual machines, much like having your own private cloud solution.<\/p>\n<p>Having built the physical servers, it was now time to install the operating systems and guest virtual machines.<\/p>\n<p>The initial install involved a little BIOS configuration, a BIOS update, reset the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Intel_vPro\">vPro<\/a> management utility and then <a href=\"https:\/\/en.wikipedia.org\/wiki\/Preboot_Execution_Environment\">PXE<\/a> booting off my <a href=\"https:\/\/hub.docker.com\/r\/netbootxyz\/netbootxyz\">NetBootXYZ<\/a> <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> container to enable me to install <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> VE on the 64GB SATA NVMe drive on each node<\/p>\n<p>With the base operating system installed I then updated the network configuration &#8211; the default is to have a network bridge configured on the primary interface, however I wanted the primary 1Gb\u00a0 interface to be purely for <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> cluster and management traffic, and then use a bridge on one of the 10GB interfaces for the various outward facing Virtual Machines.<\/p>\n<p>Once the network interfaces had been configured, I joined the servers into a <a href=\"https:\/\/pve.proxmox.com\/wiki\/Cluster_Manager\">Proxmox cluster<\/a>.<\/p>\n<p>Current load on the <a href=\"https:\/\/pve.proxmox.com\/wiki\/Cluster_Manager\">Proxmox cluster:<\/a><\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-scaled.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1343 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-300x74.png\" alt=\"\" width=\"300\" height=\"74\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-300x74.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-1024x252.png 1024w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-768x189.png 768w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-1536x379.png 1536w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-2048x505.png 2048w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.40.26-809x199.png 809w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>Cluster #2 &#8211; Ceph<\/h2>\n<p><a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> is a unified storage solution, providing object, block and file interfaces from a single cluster.<\/p>\n<p>I then installed <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> on each node and configured a <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> cluster\u00a0 with a private network on the 10GB interface, once I have some more cables, I will probably move this to a dedicated 10GB interface to keep it separate from the Virtual Machine data.<\/p>\n<p>Having installed <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a>, I created a Manager, Monitor and MetaData service on each node as well as configuring an OSD for the 1TB NVMe drive on each node, this gave me 1.29TiB of replicated storage across the 4 nodes<\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1329 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52-300x144.png\" alt=\"\" width=\"300\" height=\"144\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52-300x144.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52-1024x491.png 1024w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52-768x368.png 768w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52-1536x736.png 1536w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52-809x388.png 809w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-10-at-17.31.52.png 2024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>I then created a <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> Pool that I could use for backend storage for the Virtual Machines I was about to build.<\/p>\n<h2>Infrastructure as code<\/h2>\n<p>The next part of the setup involved installing <a href=\"https:\/\/developer.hashicorp.com\/terraform\">Terraform<\/a> on my iMac then setting up an API key and user within <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> that <a href=\"https:\/\/developer.hashicorp.com\/terraform\">Terraform<\/a> could interact with along with some provider and node configuration details.<\/p>\n<p>The first step was to make the build image available on each of the nodes, for this I chose to download the &#8216;Noble Numbat&#8217; (<a href=\"https:\/\/ubuntu.com\/\">Ubuntu<\/a> 24.04 LTS) cloud image to each <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> cluster node.<\/p>\n<p>I could then start creating the configuration for my <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a>\u00a0and <a href=\"https:\/\/k3s.io\/\">K3s<\/a> <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> clusters.<\/p>\n<p>I opted to use the <a href=\"https:\/\/registry.terraform.io\/providers\/bpg\/proxmox\/latest\/docs\">bpg\/Proxmox<\/a> <a href=\"https:\/\/developer.hashicorp.com\/terraform\">Terraform<\/a> provider to create my virtual machines along with the <span class=\"s1\"><a href=\"https:\/\/registry.terraform.io\/providers\/integrations\/github\/latest\">integrations\/github<\/a> provider to install my ssh keys from <a href=\"https:\/\/github.com\/\">GitHub<\/a>.<\/span><\/p>\n<p>I knew it was going to take a few goes to perfect the various <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> installations, this way I could stand up and tear down the entire environment in a matter of minutes &#8211; the 7 node <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster only takes just over 2 minutes to create the virtual machines and about 30 seconds to tear them all down again ready for the next run.<\/p>\n<h2>Cluster #3 &#8211; Rancher<\/h2>\n<p><a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> is a platform for managing and deploying <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> clusters, it lives in its own minimal <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster.<\/p>\n<p>My previous <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> installation was a <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> container running a single node instance of <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a>, which, whilst it worked well for managing my last <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster, I wanted something a bit more resilient for this time around.<\/p>\n<p>The <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> cluster is 3 servers, each with 2 cores 4GB or memory and 32GB of disk (supplied from the <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> pool), one assigned to each of the first 3\u00a0 <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> cluster nodes<\/p>\n<p>With the base OS installed, the next step was installing <a href=\"https:\/\/k3s.io\/\">K3s<\/a> via <a href=\"https:\/\/github.com\/alexellis\/k3sup\">k3sup<\/a> (pronounced ketchup), one initial server, then two additional servers<\/p>\n<p>The latest version of <a href=\"https:\/\/github.com\/alexellis\/k3sup\">k3sup<\/a> has a &#8216;plan&#8217; option which if supplied with a <a href=\"https:\/\/en.wikipedia.org\/wiki\/JSON\">json<\/a> file containing host names and IP addresses will create a &#8216;bootstrap&#8217; script to install <a href=\"https:\/\/k3s.io\/\">K3s<\/a> on all of the nodes<\/p>\n<pre>k3sup plan \\\r\ndevices.json \\\r\n--user ubuntu \\\r\n--servers 3 \\\r\n--server-k3s-extra-args \"--disable servicelb\" \\\r\n--background &gt; bootstrap.sh<\/pre>\n<p>After running the bootstrap script, it is then a matter of providing the minimal cluster configuration required to setup <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a><\/p>\n<p>Configure <a href=\"https:\/\/kube-vip.io\/\">Kube VIP<\/a> (virtual cluster IP and load balancer), Install <a href=\"https:\/\/cert-manager.io\/\">Cert-Manager<\/a> via <a href=\"https:\/\/helm.sh\/\">Helm<\/a>, install <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> via <a href=\"https:\/\/helm.sh\/\">Helm<\/a> and finally expose the <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> deployment via the <a href=\"https:\/\/kube-vip.io\/\">Kube VIP<\/a> load balancer.<\/p>\n<p>I have yet to script the configuration post <a href=\"https:\/\/k3s.io\/\">K3s<\/a> cluster creation, but I have all of the steps saved for when I decide on the best automation technology to use<\/p>\n<p><a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> cluster nodes as seen from the <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> dashboard:<\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-scaled.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1342 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-300x62.png\" alt=\"\" width=\"300\" height=\"62\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-300x62.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-1024x213.png 1024w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-768x160.png 768w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-1536x319.png 1536w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-2048x425.png 2048w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.37.10-809x168.png 809w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>Cluster #4 &#8211; Kubernetes<\/h2>\n<p>The <a href=\"https:\/\/k3s.io\/\">K3s<\/a> <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster is made up of 7 servers &#8211; 3 control nodes, each with 2 cores, 4GB or memory and 32GB of disk (supplied from the <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> pool) and 4 worker nodes, each with 4 cores 16GB or memory and 32GB of disk (supplied from the <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> pool)<\/p>\n<p>For the control nodes, one assigned to each of the first 3\u00a0 <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> cluster nodes, for the worker nodes, one is assigned to each of the 4 <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> cluster nodes.<\/p>\n<p><a href=\"https:\/\/k3s.io\/\">K3s<\/a> was once again installed via <a href=\"https:\/\/github.com\/alexellis\/k3sup\">k3sup<\/a>, one initial server, two additional servers, then the four worker servers<\/p>\n<p>The rest of the initial configuration was very similar to the <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> cluster: configure <a href=\"https:\/\/kube-vip.io\/\">Kube VIP<\/a>, install <a href=\"https:\/\/cert-manager.io\/\">Cert-Manager<\/a> via <a href=\"https:\/\/helm.sh\/\">Helm<\/a>, install <a href=\"https:\/\/traefik.io\/\">Traefik<\/a> ingress manager via <a href=\"https:\/\/helm.sh\/\">Helm<\/a>, then import it on the <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> Cluster for easier management.<\/p>\n<p>I then also installed <a href=\"https:\/\/prometheus.io\/\">Prometheus<\/a>\/<a href=\"https:\/\/grafana.com\/\">Grafana<\/a> via <a href=\"https:\/\/helm.sh\/\">Helm<\/a>, from <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> for monitoring<\/p>\n<p>Next I needed to setup the various <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> storage classes, one for <a href=\"https:\/\/docs.ceph.com\/en\/latest\/cephfs\/\">CephFS<\/a> and one for <a href=\"https:\/\/docs.ceph.com\/en\/latest\/rbd\/\">Ceph RBD<\/a> via the <a href=\"https:\/\/github.com\/ceph\/ceph-csi\">Ceph CSI<\/a> driver, this required some setup on the <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> cluster in order for the <a href=\"https:\/\/github.com\/ceph\/ceph-csi\">Ceph CSI<\/a> driver to be able to talk to the <a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> cluster to provision storage as required.<\/p>\n<p>I then needed to create a couple of Cluster Issuers for <a href=\"https:\/\/cert-manager.io\/\">Cert-Manager<\/a> so it could request and manage <a href=\"https:\/\/letsencrypt.org\/\">LetsEncrypt<\/a> site certificates for the various websites that the cluster will be hosting<\/p>\n<p><a href=\"https:\/\/traefik.io\/\">Traefik<\/a> also required some additional configuration to expose and secure the dashboard as well as setup a bunch of re-write middleware rules to ensure all inbound traffic uses the encrypted &#8216;https&#8217; route to these websites.<\/p>\n<p>The post <a href=\"https:\/\/k3s.io\/\">K3s<\/a> cluster configuration is again still manual at this point but again I have all of the steps saved for future automation.<\/p>\n<p><a href=\"https:\/\/k3s.io\/\">K3s<\/a>\u00a0cluster nodes as seen from the <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> dashboard:<\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-scaled.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1341 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-300x125.png\" alt=\"\" width=\"300\" height=\"125\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-300x125.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-1024x426.png 1024w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-768x320.png 768w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-1536x639.png 1536w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-2048x852.png 2048w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.35.55-809x337.png 809w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h2>Application Deployments<\/h2>\n<p>Each application lives in its own <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> namespace for isolation purposes and is made up of a bunch of <a href=\"https:\/\/en.wikipedia.org\/wiki\/YAML\">yaml<\/a> files which are all deployed at once using the <a href=\"https:\/\/kustomize.io\/\">kustomize<\/a> aspect of <a href=\"https:\/\/kubernetes.io\/docs\/reference\/kubectl\/\">kubectl<\/a>, the command line interface for <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a>.<\/p>\n<p>A typical Website install consists of the following:<\/p>\n<ul>\n<li>namespace.yaml &#8211; creates the namespace<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.mysql.com\/\">MySQL<\/a><\/p>\n<ul>\n<li>secret.txt &#8211; <a href=\"https:\/\/www.mysql.com\/\">MySQL<\/a>\u00a0root password<\/li>\n<li>service.yaml &#8211; Service exposing the database port (3306)<\/li>\n<li>pvc.yaml &#8211; Storage Persistent Volume Claim (<a href=\"https:\/\/docs.ceph.com\/en\/latest\/rbd\/\">Ceph RBD<\/a>)<\/li>\n<li>deployment.yaml &#8211; <a href=\"https:\/\/www.mysql.com\/\">MySQL<\/a> <a href=\"https:\/\/www.docker.com\/\">Docker<\/a>\u00a0configuration<\/li>\n<li class=\"p1\"><span class=\"s1\">kustomization.yaml &#8211; how to deploy the entire set of configuration files<\/span><\/li>\n<\/ul>\n<p><a href=\"https:\/\/wordpress.com\/\">WordPress<\/a><\/p>\n<ul>\n<li>certificate.yaml &#8211; request for a <a href=\"https:\/\/letsencrypt.org\/\">LetsEncrypt<\/a> site certificate<\/li>\n<li>ingressroute.yaml &#8211; detail on how to access the application from the outside via <a href=\"https:\/\/traefik.io\/\">Traefik<\/a><\/li>\n<li>redirect-https.yaml &#8211; <a href=\"https:\/\/traefik.io\/\">Traefik<\/a> middleware redirect for http to https<\/li>\n<li>redirect-admin.yaml &#8211; <a href=\"https:\/\/traefik.io\/\">Traefik<\/a> middleware redirect for the WordPress admin pages (more on this later)<\/li>\n<li>secret.txt &#8211; <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> user name and password<\/li>\n<li>service.yaml &#8211; service exposing the website port (80)<\/li>\n<li>pvc.yaml &#8211; Storage Persistent Volume Claim (<a href=\"https:\/\/docs.ceph.com\/en\/latest\/cephfs\/\">CephFS<\/a>)<\/li>\n<li>deployment.yaml &#8211; <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> <a href=\"https:\/\/www.docker.com\/\">Docker<\/a>\u00a0configuration<\/li>\n<li class=\"p1\"><span class=\"s1\">kustomization.yaml &#8211; how to deploy the entire set of configuration files<\/span><\/li>\n<\/ul>\n<p>The namespace is created first, then the <a href=\"https:\/\/www.mysql.com\/\">MySQL<\/a> deployment is run, once that is up and running I log into the <a href=\"https:\/\/www.mysql.com\/\">MySQL<\/a> pod and create the database, set the user password and grant privileges:<\/p>\n<pre>create database &lt;db name&gt;;\r\ncreate user `&lt;db user&gt;`@`%` identified by '&lt;password&gt;';\r\nGRANT ALL PRIVILEGES ON `&lt;db name&gt;`.* TO `&lt;db user&gt;`@`%`;<\/pre>\n<p>I then run the <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> deployment and connect to the website&#8217;s URL, set the website user and password and complete the <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> install.<\/p>\n<p>I use the above process regardless of creating a new website or recovering an existing one, all of my websites are backed up via <a href=\"https:\/\/teamupdraft.com\/updraftplus\/\">Updraft Plus<\/a> to <a href=\"https:\/\/aws.amazon.com\/s3\/\">S3<\/a> buckets on my <a href=\"https:\/\/www.min.io\/\">MinIO<\/a> <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> instance that lives on my media server<\/p>\n<p>Restoration is simply a matter of installing the <a href=\"https:\/\/teamupdraft.com\/updraftplus\/\">Updraft Plus<\/a> <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> plugin, setting the <a href=\"https:\/\/aws.amazon.com\/s3\/\">S3<\/a> configuration for the website, scanning the remote storage for backups and then restoring from the latest one.<\/p>\n<p>The whole process from creating the namespace to starting the restore only takes a couple of minutes.<\/p>\n<p>I use my own cloned version of <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> that allows me to upgrade it properly, for full details, have a read of the following: <a href=\"https:\/\/gitlab.com\/oskapt\/docker\/wordpress\">Adrian Goins &#8211; How to install WordPress &#8216;the right way&#8217;<\/a> this separates the <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> configuration from the actual version specific content.<\/p>\n<p>Typical deployment (this website) as seen from the <a href=\"https:\/\/www.rancher.com\/\">Rancher<\/a> dashboard:<\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-scaled.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1344 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-300x61.png\" alt=\"\" width=\"300\" height=\"61\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-300x61.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-1024x208.png 1024w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-768x156.png 768w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-1536x313.png 1536w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-2048x417.png 2048w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.42.52-809x165.png 809w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><a href=\"https:\/\/traefik.io\/\">Traefik<\/a> proxy dashboard:<\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-scaled.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1345 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-300x158.png\" alt=\"\" width=\"300\" height=\"158\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-300x158.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-1024x541.png 1024w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-768x406.png 768w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-1536x811.png 1536w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-2048x1081.png 2048w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.44.25-809x427.png 809w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><a href=\"https:\/\/ceph.io\/en\/\">Ceph<\/a> storage performance:<\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-scaled.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1353 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-300x68.png\" alt=\"\" width=\"300\" height=\"68\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-300x68.png 300w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-1024x231.png 1024w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-768x173.png 768w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-1536x346.png 1536w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-2048x462.png 2048w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-12.08.39-809x182.png 809w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> nodes and associated virtual machines:<\/p>\n<p><a href=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.46.32.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-1346 size-medium\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.46.32-120x300.png\" alt=\"\" width=\"120\" height=\"300\" srcset=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.46.32-120x300.png 120w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.46.32-408x1024.png 408w, https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2025\/08\/Screenshot-2025-08-11-at-11.46.32.png 608w\" sizes=\"auto, (max-width: 120px) 100vw, 120px\" \/><\/a>I have since bought the parts for two more nodes which I will use to increase the various clusters and spread the load out a bit more evenly.<\/p>\n<p>I still intend to move my <a href=\"https:\/\/ui.com\/download\">Unifi controller<\/a> and <a href=\"https:\/\/pterodactyl.io\/\">Pterodactyl<\/a>\/Wings virtual machines from my Dell R220 ii server onto the <a href=\"https:\/\/www.proxmox.com\/en\/\">Proxmox<\/a> cluster as well, but I want to rearrange my office rack a bit first.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some of the technologies that will be used on this installation: \u00a0 \u00a0 Kubernetes or K8s (K &#8216;8 letters&#8217; S &#8211; pronounced &#8216;cates&#8217;) is a container orchestration system that automates the deployment, scaling and management of containerised applications K3s (K &#8216;3 letters&#8217; S) is a lightweight version of Kubernetes designed for IoT and Edge Computing&hellip;<\/p>\n","protected":false},"author":1,"featured_media":1345,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[5,3],"class_list":["post-1328","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorised","tag-homelab","tag-networking"],"_links":{"self":[{"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/posts\/1328","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/comments?post=1328"}],"version-history":[{"count":16,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/posts\/1328\/revisions"}],"predecessor-version":[{"id":1365,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/posts\/1328\/revisions\/1365"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/media\/1345"}],"wp:attachment":[{"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/media?parent=1328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/categories?post=1328"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/tags?post=1328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}