Kubernetes - The Beginning

The cluster is born, and with it the beginning of, hopefully, a thriving life.

Kubernetes - The Beginning
Photo by Fahim mohammed / Unsplash

So here I am, after installing Kubernetes. I will explain the different choices I made.

First of all, I decided to go with k3s for the Kubernetes distribution. It offers a completely working cluster, and I think it is perfect when starting. I created my cluster without the default traefik install - to have more control over it - and with secrets encryption at rest enabled. The installation was extremely easy, one command on each machine, and that was it.

I started with two machines : server3, which is the control-plane. It's a Lenovo ThinkCenter : 4GB of RAM, 2 cores / 2 threads and 500GB of storage (unfortunately HDD). Not very powerful, but that way I can have a dedicated machine for the control-plane. server4, the only current worker, is a Nuc with 32GB RAM, 14 cores and 20 threads. A beefier machine (although I'd like a bit more RAM to host game servers), that is the only current worker. The final machine, rasp2, currently runs all the remaining docker apps that weren't running on server4. It is a Raspberry Pi 5, with 8GB of RAM. It will continue to host everything until I fully migrate my apps to Kubernetes, and then it will become a worker too.

I also wanted to implement a "GitOps" workflow : having everything stored on a git instances. That way, my cluster in fully declarative. I only have what I declared, or to be more precise, and don't have something I didn't declare. Good to, you know, not forget you deployed something (which I shamefully admit happened sometimes). For that, I chose FluxCD. The installation was again very easy thanks to their documentation. I also configured sops, so that I can put my secrets on the git too.

As for storage, I plan on having a mix between NFS and Longhorn. I have an external SSD on my raspberry pi that holds my Nextcloud data, for example, the raw data of my academic website. For other storage I may not need direct and easy access to, I installed Longhorn. With Flux, and considering it is a simple Helm Chart to deploy, it was very easy to put in place.

Finally, I installed cert-manager - again, a simple Helm Chart - to manage the certificates of my different subdomains. I had to install an additional Helm Chart to configure DNS01 challenge with OVH (which is my registar). A quirk of cert-manager is that, with the Gateway API (that I decided to use, since Ingress will be deprecated soon), I need to create one gateway per certificate. Although this is a little annoying, it is also something that will be fixed really soon, so it will do in the mean time. Well, "fixes", it's not an actual issue, it's just an additional feature that will be added.

And with that, my cluster was ready for the first apps !

The First Apps

I decided to start by configuring Authentik, since I will try to implement a Centralized Authentication System (CAS), so it's easier for my family to access everything. And for that, I first had to configure a PostgreSQL database. I chose to go with Cloudnative-PG, an operator for PostgreSQL databases. Basically, what it allows me to do is simply write a resource declaration file, like I would for a basic Kubernetes component, and the operator deals with the whole installation process. Very cool ! After installing that operator, through an Helm Chart (I feel it will be a lot of my "work", configuring Helm Charts), I was able to configure the Authentik Helm Chart. And here it was !
I do want to mention the reason behind my choice. Before going to Kubernetes, I used Keycloak. And I love Keycloak, it just snapped with me, everything made sense. But there is one feature it lacked : being an LDAP provider. Now, sure, I could host my own LDAP server, but that's one more thing to manage, and one more interface, and it just seemed like a lot for my home use. I mean, in a company or large organization, sure, but me and my 6 users ? Meh. Authentik, although a little more confusing to me, seems fine. So Authentik it is !

The second app I decided to configure was, well, this one ! Ghost, so that I could tell my story. Now, ghost isn't actually the matter of a simple Helm Chart, but I'll be honest : I didn't make the configuration myself. I found a really cool repo, "ghost-on-kubernetes", and used this as my base. I then edited things here and there, delete some, added others, to fit my situation. One thing I did was not using a MySQL database. After my experience with a PostgreSQL operator, I decided I wanted the same thing for MySQL. Except... well, I didn't find it. Or rather, I found one that seemed much too complicated to use, with a helm chart for each database. Okay, maybe I understood wrong, but maybe not. Who knows. What I do know is that I ended up going with a MariaDB operator. A MariaDB database is compatible with a MySQL database, so it was perfect. I plugged a new Helm Chart, create my MariaDB definition, and here I was with a working database.
However... I was not able to transfer the database. I had made a dump of the old database, but unable despite my best efforts to make a successful copy of it. Maybe I did not try hard enough, but I had all the posts backed up anyway, and honestly didn't want to bother too much. So I went with it, re posted my posts, and here we are ! Happy and well.

Edit
I actually widely misunderstood how the operator worked, but hey, what's done is done !

The final step of the beginning was to use Kubernetes as a reverse proxy for all my existent services still running on Docker. That was easy : for each subdomain, I just had to make a Gateway, an HttpRoute, and an EndpointSlice/Service pair. Within an hour or two, everything was up and running. I was able to say goodbye to Caddy (a wonderful piece of software, I'm sad I have to leave it). And now, the transfer of each app to the Kubernetes cluster can slowly start.

Conclusion

I will admit : I did a lot of things wrongs. You can go see the repository, and you'll see lots and lots of commits where I do stupid mistakes, like forgetting to change a name after a copy-and-paste, or some basic typos. Sometimes, I also do big mistakes. But error after error, I work my way onto the solution. And I hope I learn from those mistakes and won't make them again !

I'll post an update, one day. Until then, I wish you a fine piece of life ^^