{"id":303,"date":"2022-01-30T14:24:22","date_gmt":"2022-01-30T14:24:22","guid":{"rendered":"https:\/\/blog.hslracing.com\/myhome\/?p=303"},"modified":"2022-02-07T11:42:29","modified_gmt":"2022-02-07T11:42:29","slug":"kubernetes-test-cluster","status":"publish","type":"post","link":"https:\/\/blog.hslracing.com\/myhome\/2022\/01\/kubernetes-test-cluster.html","title":{"rendered":"Kubernetes &#8211; Test Cluster"},"content":{"rendered":"<p>I had some time to spare whilst waiting for my access and laptop to be sorted for my new work role so decided to use the time to learn <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> (K8s &#8211; K 8 letters s).<\/p>\n<p><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/blog.hslracing.com\/wp-content\/uploads\/sites\/6\/2022\/01\/Docker-Kubernetes.png\" \/><\/p>\n<p><a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> is an orchestration tool for <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> containers that also ensures that containers are restarted automatically elsewhere in the cluster if a node fails.<\/p>\n<p>I had been looking into how to make my various websites more resilient from a database point of view and scalable from an app point of view and <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> looked like it could be the way to go.<\/p>\n<p>I watched <a href=\"https:\/\/www.youtube.com\/c\/JeffGeerling\">Jeff Geerling&#8217;s<\/a> <a href=\"https:\/\/www.youtube.com\/watch?v=IcslsH7OoYo&amp;list=PL2_OBreMn7FoYmfx27iSwocotjiikS5BD\">Kubernetes 101<\/a> series of <a href=\"https:\/\/www.youtube.com\/\">Youtube<\/a> videos to obtain a basic understanding of the concepts, these gave me a good basic understanding of its history and how it fits together.<\/p>\n<p>Next I decided to try building a cluster on a few virtual machines.<\/p>\n<p>I initially created 3 VMs, each with 4GB of RAM and 2 CPUs, as clones of my Ubuntu template that I keep shut down as a cloning source.<\/p>\n<p>I setup a load balancer with HAProxy on port 6443 on my PFsense firewall and then installed <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> and then the <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> kubeadm software on the first node with apt. (instructions <a href=\"https:\/\/kubernetes.io\/docs\/setup\/production-environment\/tools\/kubeadm\/install-kubeadm\/\">here<\/a>).<\/p>\n<p>The only problem was that the bootstrap environment did not like using my load balancer and had major issues with the self certified certificates. The local ones did not match the ones it had generated for the cluster via the load balancer.<\/p>\n<p>After much playing around with attempting to generate my own certificates, I have a wildcard domain certificate for hslracing.com, so thought it was worth a try, but I was really struggling to work out exactly how many certs of what kind the cluster required, I decided to watch some more videos.<\/p>\n<p>This is when I stumbled across some videos by <a href=\"https:\/\/www.youtube.com\/c\/adriandotgoins\">Adrian Goins<\/a>, where he shows various installs of <a href=\"https:\/\/k3s.io\/\">K3s<\/a> (half the letters in <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a>), a much slimmer version of <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> which is potentially much more suited for homelab use.<\/p>\n<p>I reset and cleared down my VMs, I set up 3 master nodes and 3 worker nodes and then followed his video on <a href=\"https:\/\/www.youtube.com\/watch?v=9PLw1xalcYA&amp;t=914s\">HA K3s with etcd, Kube-VIP, MetalLB and Rancher<\/a> to build a cluster. This had none of the certificate issues I had previously encountered and seemed to be going well.<\/p>\n<p>The first problem came as soon as I installed <a href=\"https:\/\/rancher.com\/products\/rancher\">Rancher<\/a>, the CPU on the various nodes went haywire and the entire cluster seemed to be in some sort of never ending death spiral.<\/p>\n<p>After much searching for suitable commands to use to interrogate the cluster I discovered that it was complaining about disk pressure on ephemeral storage which meant next to nothing to me and all of the searches I did implied that the resolution was to make use of faster SSD storage.<\/p>\n<p>The real issue I eventually realised is that because of where <a href=\"https:\/\/containerd.io\/\">containerd<\/a> (<a href=\"https:\/\/www.youtube.com\/watch?v=9PLw1xalcYA&amp;t=914s\">K3s<\/a> <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> equivilent) installs under \/var\/lib and then proceeds to generate loop back mounts from here as well as generate log files under here.<\/p>\n<p>I had only provisioned a 10GB OS file system and once the installs were complete and it attempted to create a new container for <a href=\"https:\/\/rancher.com\/products\/rancher\">Rancher<\/a> the filesystems showed as more than 85% full and so killed off the container and tried again on the next worker node. This lead to High CPU on the worker node, which in turn affected the underlying physical server, impacted the responsiveness of the active database node and then caused that to fail over to the next node, in turn generating yet more CPU load &#8211; as mentioned above, a never ending death spiral.<\/p>\n<p>Once I realised what was happening, I cleared down the cluster, presented an additional 10GB of disk to each cluster node migrated the \/var file system onto this new storage and then started from scratch once again. This time I had a stable cluster.<\/p>\n<p>After further reading I discovered that ideally <a href=\"https:\/\/rancher.com\/products\/rancher\">Rancher<\/a> should be installed on its own cluster and then used to remotely manage the rest of your <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> clusters.<\/p>\n<p>At this point I decided to simply install the <a href=\"https:\/\/rancher.com\/products\/rancher\">Rancher<\/a> <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> container and use that to manage my cluster instead of having <a href=\"https:\/\/rancher.com\/products\/rancher\">Rancher<\/a> installed on the cluster itself. I also found a more recent <a href=\"https:\/\/www.youtube.com\/watch?v=QqSgiezqMAA\">video<\/a> by Adrian that skips the use of <a href=\"https:\/\/metallb.universe.tf\/\">MetalLB<\/a> and simply uses <a href=\"https:\/\/kube-vip.chipzoller.dev\/\">Kube-VIP<\/a> as the load balancer (simpler is always better in my opinion).<\/p>\n<p>I then decided to install <a href=\"https:\/\/longhorn.io\/\">Longhorn<\/a> to manage local dedicated file systems for stateful environments like <a href=\"https:\/\/www.mysql.com\/\">MySQL<\/a>. I added an additional 40GB of local storage to each of the worker nodes that I mounted under \/var\/lib\/longhorn. I then found a <a href=\"https:\/\/github.com\/longhorn\/longhorn\/issues\/3576\">bug<\/a> in <a href=\"https:\/\/longhorn.io\/\">Longhorn<\/a> whereby it attempts to use the wrong arguments to mount NFS for its Backup storage.<\/p>\n<p>I also installed the <a href=\"https:\/\/github.com\/kubernetes-sigs\/nfs-subdir-external-provisioner\">NFS Subdirectory External Provisioner<\/a> for shared volume claims within the cluster such that I can have multiple <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> instances running for the same website.<\/p>\n<p>I installed the <a href=\"https:\/\/bitnami.com\/\">Bitnami<\/a> <a href=\"https:\/\/github.com\/longhorn\/longhorn\/issues\/3576\">MYSQL<\/a> cluster via <a href=\"https:\/\/helm.sh\/\">Helm<\/a> within <a href=\"https:\/\/rancher.com\/products\/rancher\">Rancher<\/a> after adding the <a href=\"https:\/\/rancher.com\/products\/rancher\">Bitnami<\/a> repository as a backend for my <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> sites and then installed <a href=\"https:\/\/rancher.com\/products\/rancher\">Bitnami<\/a> <a href=\"https:\/\/wordpress.com\/\">WordPress<\/a> again from the App store in <a href=\"https:\/\/rancher.com\/products\/rancher\">Rancher<\/a>.<\/p>\n<p>This has all been good testing and I may\/may not keep this test cluster, but I have decided to build a bare metal <a href=\"https:\/\/kubernetes.io\/\">Kubernetes<\/a> cluster running <a href=\"https:\/\/www.youtube.com\/watch?v=9PLw1xalcYA&amp;t=914s\">K3s<\/a> on a bunch of Lenovo Tiny desktop machines.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I had some time to spare whilst waiting for my access and laptop to be sorted for my new work role so decided to use the time to learn Kubernetes (K8s &#8211; K 8 letters s). Kubernetes is an orchestration tool for Docker containers that also ensures that containers are restarted automatically elsewhere in the&hellip;<\/p>\n","protected":false},"author":1,"featured_media":305,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[5],"class_list":["post-303","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorised","tag-homelab"],"_links":{"self":[{"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/posts\/303","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=303"}],"version-history":[{"count":2,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/posts\/303\/revisions"}],"predecessor-version":[{"id":325,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/posts\/303\/revisions\/325"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/media\/305"}],"wp:attachment":[{"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/media?parent=303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/categories?post=303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.hslracing.com\/myhome\/wp-json\/wp\/v2\/tags?post=303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}