Table of Contents

Kubernetes

This guide provides information on how to manage and deploy applications using Kubernetes, including best practices and common configurations.

Development environment

Activate Kubernetes in Docker Desktop

  • Open Docker Desktop.
  • Go to Settings > Kubernetes.
  • Enable the checkbox: Enable Kubernetes.
  • Wait for Kubernetes to start (you'll see a green light or similar status when ready).

Install Required Tools

Make sure you have the following installed:

  • kubectl – Kubernetes command-line tool.
  • helm – Kubernetes package manager.

Kubernetes Dashboard

Enable the Kubernetes Dashboard by installing Headlamp:

Windows

Using winget:

winget install headlamp

Using Chocolatey:

choco install headlamp

Or download the .exe installer directly from the latest release.

macOS

Using Homebrew (recommended):

brew install --cask

Or download the .dmg file from the latest release.

If macOS blocks the app from running, open a terminal and run:

xattr -dr com.apple.quarantine /Applications/Headlamp.app

After this, running the app should work.

Open the Dashboard

Launch Headlamp and select your local Docker Desktop Kubernetes cluster. The dashboard gives you a visual overview of your cluster resources, workloads, and namespaces.

Install Traefik

Install Traefik as the ingress controller:

helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik -n traefik --create-namespace
helm upgrade traefik traefik/traefik -n traefik \
  --set-json 'providers.kubernetesIngress.namespaces=["byakko-development"]' \
  --set ports.web.transport.respondingTimeouts.readTimeout=0 \
  --set ports.websecure.transport.respondingTimeouts.readTimeout=0

Setup TLS with mkcert

Install mkcert and create locally-trusted certificates:

mkcert -install
mkcert byakko.dev "*.byakko.dev"
kubectl create secret tls umiko-tls \
  --cert=byakko.dev+1.pem \
  --key=byakko.dev+1-key.pem \
  -n byakko-development

Configure Hosts File

Add the following entries to your hosts file so the local domains resolve to your machine:

Windows: C:\Windows\System32\drivers\etc\hosts macOS / Linux: /etc/hosts

127.0.0.1       byakko.dev
127.0.0.1       www.byakko.dev
127.0.0.1       admin.byakko.dev
127.0.0.1       status.byakko.dev
127.0.0.1       api.byakko.dev
127.0.0.1       database.byakko.dev
127.0.0.1       authentication.byakko.dev
127.0.0.1       grafana.byakko.dev
127.0.0.1       kubernetes.byakko.dev

Deploy to Development

Navigate to the folder deployments/helm/byakko and execute the commands below.

Install

helm install -f Values.yaml -f Values.Development.yaml byakko .

Upgrade

helm upgrade -f Values.yaml -f Values.Development.yaml byakko .

Remove

helm uninstall -f byakko .

Production environment

Before starting, make sure your server is set up according to the server setup guide.

Install on production

Step 1: Install MicroK8s

sudo snap install microk8s --classic
sudo microk8s status --wait-ready

Step 2: Enable services

Required:

sudo microk8s enable dns
sudo microk8s enable helm
sudo microk8s enable cert-manager
sudo microk8s enable hostpath-storage

Optional:

sudo microk8s enable metrics-server
sudo microk8s enable prometheus

Step 3: Install Traefik

Install Traefik as the ingress controller:

sudo microk8s helm repo add traefik https://traefik.github.io/charts
sudo microk8s helm repo update
sudo microk8s helm install traefik traefik/traefik -n traefik --create-namespace
sudo microk8s helm upgrade traefik traefik/traefik -n traefik \
  --set ports.web.hostPort=80 \
  --set ports.websecure.hostPort=443 \
  --set "additionalArguments={--entrypoints.web.http.redirections.entryPoint.to=:443,--entrypoints.web.http.redirections.entryPoint.scheme=https}" \
  --set deployment.strategy.type=Recreate \
  --set ports.web.transport.respondingTimeouts.readTimeout=0 \
  --set ports.websecure.transport.respondingTimeouts.readTimeout=0

If the new Traefik pod is stuck in Pending after an upgrade, the old pod may still be holding ports 80/443. Delete it manually:

sudo microk8s kubectl delete pod <old-traefik-pod-name> -n traefik

Configure DNS

Before deploying, make sure DNS A records are configured for your domain. See the DNS configuration guide for details.

Usage on production

Step 1 — Download source code

git clone https://github.com/MadWorldEU/Byakko

Step 2 — Install or upgrade cluster

Navigate to the folder deployments/helm/byakko and execute one of the commands below.

Install:

sudo microk8s helm install -f Values.yaml -f Values.Production.yaml byakko .

Upgrade:

sudo microk8s helm upgrade -f Values.yaml -f Values.Production.yaml byakko .

Step 3 — Install Headlamp

Install Headlamp as the Kubernetes dashboard:

sudo microk8s helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
sudo microk8s helm repo update
sudo microk8s helm install my-headlamp headlamp/headlamp --namespace kube-system

Step 4 — Create Headlamp token

Create a token for logging in to Headlamp:

sudo microk8s kubectl create token my-headlamp --namespace kube-system

Step 5 — Access Headlamp

Option A — Via the byakko ingress (recommended for production)

After deploying the Helm chart with headlamp.enabled: true, access the dashboard at:

https://kubernetes.<domain>

Use the token from Step 4 to log in.

Option B — Via port forwarding (local / without ingress)

Forward the Headlamp port to access the dashboard:

export POD_NAME=$(sudo microk8s kubectl get pods --namespace kube-system -l "app.kubernetes.io/name=headlamp,app.kubernetes.io/instance=my-headlamp" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(sudo microk8s kubectl get pod --namespace kube-system $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
sudo microk8s kubectl --namespace kube-system port-forward --address 0.0.0.0 $POD_NAME 10443:$CONTAINER_PORT

Then open http://localhost:10443 and use the token from Step 4 to log in.

Step 6 — Connect Headlamp with Keycloak (optional)

By default Headlamp uses token-based login. To use Keycloak instead, follow these steps.

Create a Keycloak client

In the MadWorld realm at https://authentication.<domain>, create a new client with these settings:

Setting Value
Client ID headlamp-client
Client authentication On (confidential)
Valid redirect URIs https://kubernetes.<domain>/*
Web origins https://kubernetes.<domain>

Then copy the client secret from the Credentials tab.

Upgrade Headlamp with OIDC configuration

sudo microk8s helm upgrade my-headlamp headlamp/headlamp --namespace kube-system \
  --set config.oidc.issuerURL="https://authentication.<domain>/realms/MadWorld" \
  --set config.oidc.clientID="headlamp-client" \
  --set config.oidc.clientSecret="<your-client-secret>" \
  --set config.oidc.scopes="profile email"

After this, Headlamp redirects unauthenticated users to Keycloak automatically.

Configure the Kubernetes API server for OIDC

The API server must be configured to validate Keycloak tokens. Find the versioned args file (use the highest number):

sudo find /var/snap/microk8s -name "kube-apiserver" 2>/dev/null

Edit the file:

sudo nano /var/snap/microk8s/<version>/args/kube-apiserver

Add these lines at the end:

--oidc-issuer-url=https://authentication.<domain>/realms/MadWorld
--oidc-client-id=headlamp-client
--oidc-username-claim=email
--oidc-groups-claim=groups

Restart microk8s and verify the flags loaded:

sudo microk8s stop && sudo microk8s start && sudo microk8s status --wait-ready
sudo cat /var/snap/microk8s/<version>/args/kube-apiserver | grep oidc

Grant Kubernetes permissions to Keycloak users

Keycloak controls authentication; Kubernetes RBAC controls what users can do. Create a ClusterRoleBinding to grant a Keycloak user access to the cluster:

sudo microk8s kubectl create clusterrolebinding headlamp-view \
  --clusterrole=view \
  --user=<keycloak-email>

The --user value must match the email field of the user in Keycloak (Admin consoleMadWorld realm → Users → your user → Details tab). Replace view with cluster-admin to grant full access, or create a custom ClusterRole for finer-grained control.

Restrict Headlamp login to Administrators only

By default any user with a valid Keycloak account can authenticate to Headlamp. To restrict login to users with the Administrator realm role, create a custom authentication flow and bind it to the headlamp-client.

  1. Go to AuthenticationFlows → find browserActionDuplicate → name it headlamp-browser.

  2. In the new administrator-only-browser flow, locate the Forms sub-flow (the one containing Username Password Form). Inside Forms, click Add sub-flow → name it Administrator check, type Conditional.

  3. Inside the Administrator check sub-flow, add two steps:

    • Add conditionCondition - User Role → set to Required → click the gear icon:
      • Role: Administrator (realm role)
      • Negate output: ✅ ON
    • Add stepDeny Access → set to Required

    The sub-flow now reads: "If the authenticated user does NOT have the Administrator role → deny access."

    ⚠️ The Administrator check sub-flow must be placed inside the Forms sub-flow, after Username Password Form — not at the top of the flow. If placed before credentials are collected, Keycloak has no user context to evaluate the role and will immediately deny everyone with "Invalid username or password".

  4. Go to Clientsheadlamp-clientAdvanced tab → Authentication flow overrides → set Browser Flow to administrator-only-browserSave.

After this, non-Administrator users receive "You don't have access to this application" from Keycloak before reaching Headlamp.

Before a server shutdown

Gracefully drain the cluster before shutting down to avoid data corruption and incomplete requests.

Step 1 — Drain all workloads

sudo microk8s kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

Replace <node-name> with the output of:

sudo microk8s kubectl get nodes

Step 2 — Stop MicroK8s

sudo microk8s stop

Step 3 — Shut down the server

sudo shutdown -h now

After a server reboot

MicroK8s does not start automatically after a reboot. Follow the steps below to bring the cluster back up.

Step 1 — Start MicroK8s

sudo microk8s start

Step 2 — Uncordon the node

If the node was drained before shutdown, mark it schedulable again:

sudo microk8s kubectl uncordon <node-name>

Step 3 — Wait for MicroK8s to be ready

sudo microk8s status --wait-ready

Step 4 — Verify all pods are running

sudo microk8s kubectl get pods -A

All pods should reach Running or Completed status within a few minutes. If any pod is stuck in Pending or CrashLoopBackOff, inspect it with:

sudo microk8s kubectl describe pod <pod-name> -n <namespace>
sudo microk8s kubectl logs <pod-name> -n <namespace>

Updating microk8s

Check the available channels before upgrading:

sudo snap info microk8s

Upgrade to the desired channel, then restart microk8s to apply the update:

sudo microk8s stop
sudo snap refresh microk8s --classic --channel=1.36/stable
sudo microk8s start

Reference