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:
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 console → MadWorld 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.
Go to Authentication → Flows → find browser → Action → Duplicate → name it
headlamp-browser.In the new
administrator-only-browserflow, locate the Forms sub-flow (the one containing Username Password Form). Inside Forms, click Add sub-flow → name itAdministrator check, type Conditional.Inside the Administrator check sub-flow, add two steps:
- Add condition → Condition - User Role → set to Required → click the gear icon:
- Role:
Administrator(realm role) - Negate output: ✅ ON
- Role:
- Add step → Deny 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".
- Add condition → Condition - User Role → set to Required → click the gear icon:
Go to Clients → headlamp-client → Advanced tab → Authentication flow overrides → set Browser Flow to
administrator-only-browser→ Save.
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