Help

Vars editor

Variables in articles are noted {{myVar}}

Legend

A link to a page of this blog
A link to a section of this page
A link to a template of this guide. Templates are files in which you should replace your variables
A variable
A link to an external tool documentation
Set up a bare-metal kubernetes cluster from scratch
Keep in mind that some things may not work out of the box, and you’ll probably require a lot of try & errors. Kubernetes is complex. Also, I’m not a power user of kubernetes, so there may be things that can be done in a better way. Hey, I did all of this by try & error too.

What are the goals

This guide will walk you through the process of creating a self-hosted kubernetes cluster with the following features:

  • A single master node
  • Internal networking through a VPN
  • A traefik ingress controller to route HTTP(S) traffic
  • Multi-purpose OpenID authentication with keycloak
  • kubectl authentication through OpenID Connect
  • Various dashboards for HTTP routes, kubernetes itself, storages status & management, and logs.

Complete architecture

I’ll try to use as few 3rd party tools outside of kubernetes, except helm (to deploy complex apps more easily) and krew (to add some features to kubectl). But we’ll get to that later. The goal is that you use as much kubernetes itself as possible so that you can get used to it, understand it, and thus, be able to troubleshoot if you have problems later. If you’re a kubernetes power-user, 1. what are you doing here ? and 2. you might find other guides more applicable to your needs.

How to follow this guide

I’ll provide you explanations on each steps we are doing together, & give you templates that you can use with the bare minimum working configuration.

Templates contains placeholders for variables that you will need to replace. If I didn’t broke anything in the meantime, you should be able to fill those vars using the sidebar. Keep in mind that those settings are probably unsafe, or not totally OK for your particular settings. Thus, I highly recommend you to πŸ“š RTFM for each of the containers & tools we set up to tweak things.

Kubernetes configurations are  meant to be versionned. So, I recommend you to init a repository and commit after each steps. For sensible data such as private keys, tokens or OpenID client secrets, .

Kubernetes ecosystem & docker images evolve pretty fast, so this guide may become obsolete. Check regularly if new docker images aren’t available, and how their interactions or configurations evolve.

The author’s comment

To the attention of beginners

Kubernetes is huge. Really. And if you have no specialization in system administration, you will have pretty often bad times. Knowing my background as a software engineer, this guide took me more than 6 weeks of searches, experimentations, trial and errors, and frustration. I learned a huge lot of things that you will require to learn and understand too if you encounter the same problems than me during your setup.

I don’t have special knowing in neither system security nor load management, so I must have done critical errors in some places; thus, don’t take my words as granted. Take this document series as a global guide to kickstart a setup you must adapt and figure out yourself.

Again, if you’re not super determined in learning a lot, you are putting your systems at risks by trying to use this directly in production.

To the attention of everybody

Please, please do comments, post issues, and make pull requests in order to improve this document serie. I will open source as much prod-ready settings as possible (without compromising my own security), and contributing might improve the performance and safety of all futur readers. So, in advance, thank you.

 This site repository is here.

Prerequisites

I’ll assume that:

  • you’re on CentOS 8.
    On other versions/distros/OS, some things may or will differ from what I did. And you gonna help yourself with that.
    1
    2
    
    cat /etc/centos-release
    # Β» CentOS Linux release 8.2.2004 (Core)
    
  • you have SELinux disabled.
    1
    2
    
    getenforce
    # Β» Permissive
    
  • you have the kubernetes CLI installed (kubectl, kubeadm) v1.20.2 or above.
    Other versions may have changes. Again, RTFM.
    1
    2
    3
    4
    
    kubeadm version --output short
    # Β» v1.20.2
    kubectl version --short --client
    # Β» Client Version: v1.20.2
    
  • you are somewhat familiar with kubernetes CLI.
  • You have  Helm charts installed.
    See  Quality Of Life improvements to kubernetes for more infos.
  • You have  krew installed.
    See  Quality Of Life improvements to kubernetes for more infos.

Ready ?

 Start here

Setup the cluster's VPN
· β˜• 6 min read
References   How To Run OpenVPN in a Docker Container on Ubuntu 14.04 | DigitalOcean   Running Docker Containers with Systemd Because we are installing our cluster bare metal on servers exposed on the Internet, we’ll need a way to secure all of our network traffic around the critical parts of kubernetes. To do so, we’ll use OpenVPN to create a virtual secured network where all of our nodes will work.

Setup the cluster's Audit Log
· β˜• 6 min read
References   https://docs.kublr.com/logging/logging-api-audit/   Logging in Kubernetes with Elasticsearch, Kibana, and Fluentd   Auditing | Kubernetes Note : Even if this part is not required, you should not ignore it on dev environment and should really really REALLY not skip it for production. In fact, it can contain useful debug informations and security traces to see what is going on in your kubernetes cluster, and even on your whole server(s).

Kickstart the cluster
· β˜• 7 min read
Create the cluster config file References   kubernetes - kubeadm init --apiserver-advertise-address flag equivalent in config file - Stack Overflow We are now going to configure the cluster. For the sake of traceability, this configuration won’t be done via CLI flags, but via  a configuration file. The path of the cluster config file will later be referenced as the {{cluster.configFile}}, and should be inside /etc/kubernetes.

Setup the cluster's internal router
· β˜• 8 min read
References   Add OpenAPI v3 schemas to CRDs by jrostand Β· Pull Request #157 Β· traefik/traefik-helm-chart Β· GitHub Start by creating traefik required resources. You can directly use resources from the  kubernetes/traefik templates: it does not contain variables. Those are taken from  traefik docs mixed up with  this PR for kubernetes 1.19 support and schemas. Please look forward for  this issue in traefik about official v1.

Make services reachable from the world
· β˜• 4 min read
Now that you have a router installed, you have to pass requests on your server to it. This setup use a single entry point directly binding some ports on the host server. 1. Make a static and previsible configuration As you may have noticed in the step  Kickstart the cluster, the metallb configuration use only dynamic adresses. But for the reverse proxy to work, we’ll need to be sure that our traefik router has a constant IP in your VPN.

Make things persistent
· β˜• 5 min read
References   Persistent Volumes | Kubernetes   Dynamic Volume Provisioning | Kubernetes   Storage Classes | Kubernetes   Kubernetes Volumes explained | Persistent Volume, Persistent Volume Claim & Storage Class - YouTube As you may know, docker (and thus, kubernetes) does not persist anything by default. That means that everytime you restart a pod (container), it is in the exact same state as it was at its first execution, except for the mount points.

Monitoring: See what is going on
· β˜• 12 min read
Well, things are getting real and are on the point to become quite complex. So we’ll setup (super unsafe) dashboards to see what is going on easily. After all, we have nothing critical for now, but we might get troubles soon. And, don’t worry, we’ll make it safe just after that. 1. Traefik dashboard: monitoring routes The traefik dashboard will help us in the diagnostics of our ingress routes and traefik-related stuff.

Setup cluster's authentication
· β˜• 9 min read
Here is a graph of the RBAC setup we are going to implement: 1. Setup keycloak We’ll use keycloak to proxy our authentication for all monitors, using a single realm. You may use several realms in real-life situations. This is probably the tough part, and you may tweak heavily the following guide. Moreover, I may forgot to write some instructions, or somes are heavily linked to your very own setup.

Administrate the cluster with authentication
· β˜• 7 min read
Create the realm and the client References   engineering-notes/kubernetes-keycloak-integration.md at master Β· zufardhiyaulhaq/engineering-notes Β· GitHub 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 REALM_URL="https://keycloak.{{cluster.baseHostName}}/auth/realms/{{apiServer.realmName}}" # Log in TOKEN_RESPONSE="$(curl \ -d "grant_type=password" \ -d "client_id={{apiServer.clientId}}" \ -d "client_secret={{apiServer.clientSecret}}" \ -d "username=admin-user" \ -d "password=admin-user" \ $REALM_URL/protocol/openid-connect/token)" # Extract the access token ACCESS_TOKEN="$(echo "$TOKEN_RESPONSE" | jq '.

Protect monitoring with authentication
· β˜• 2 min read
Now that we have our authentication service up and running, we can protect our dashboards installed in the step  06 - Monitoring: See what is going on using our Keycloak OpenID Connect provider. Here is a diagram on how authorization will be managed: Traefik dashboard TODO Kibana TODO Kube dashboard References   Protect Kubernetes Dashboard with OpenID Connect | by Hidetake Iwata | ITNEXT Again, we are going to set up a new instance of  louketo-proxy.

Scaling up
· β˜• 3 min read
Your setup is running, everything runs smoothly, and suddenly, ‼️ nothing is responding: your cluster is overloaded. Well, I hope you’ll expand your cluster capacity before it happens. It’s always really bad and stressful to do maintenance because of downtime. Hopefully, here comes the real huge advantage of kubernetes: it is meant to scale, up, and down. So, assuming you have followed the full guide so far, let’s review together how to add some juice to our cluster ⚑.

What's on this Page