---
title: K3s
description: "Install OpenLM Platform on K3s, on one or a few Linux machines: Traefik, local storage, pod limits, HTTPS redirect, and DNS inside the cluster."
product: OpenLM Platform
---

K3s is a small Kubernetes distribution for your own machines. It brings an ingress controller (Traefik) and a storage class (`local-path`), so OpenLM Platform needs little around it. Read this page before [step 1](https://www.openlm.com/documentation/cloud/deployment-operations/on-premise/deployment-guide/kubernetes/install/step-1-prepare-cluster).

:::note[Platform as VM]
If you want OpenLM to set up K3s, the data services, and OpenLM Platform for you on a single machine, use **Platform as VM** instead: a packaged installer with its own guide. This page is for installing the chart on a K3s cluster you run yourself.
:::

## Before you start

Confirm these requirements:

| Item | Requirement |
|---|---|
| Machines | Three machines with **8 vCPU / 32 GiB** each for the standard set, or one machine with **24 vCPU / 96 GiB** (simpler, but with no room for maintenance). Add **32 GiB and 6 to 8 vCPU** if MongoDB, Kafka and Redis run on the same machines. See [Sizing](https://www.openlm.com/documentation/cloud/deployment-operations/on-premise/deployment-guide/kubernetes/before-you-start/sizing). |
| OS | A current 64-bit Linux that K3s supports. RHEL 9-family (RHEL, AlmaLinux, Rocky) is the most tested. |
| Disk | SSD. `local-path` volumes live under `/var/lib/rancher/k3s/storage`. |
| Ports open to users | 443 (and 80 for the redirect) |

## Install K3s with a higher pod limit

K3s allows 110 pods per node by default. OpenLM Platform alone runs about 95, plus the cluster's own, so raise the limit **before** installing K3s:

```bash
sudo mkdir -p /etc/rancher/k3s
printf 'kubelet-arg:\n  - "max-pods=250"\n' | sudo tee /etc/rancher/k3s/config.yaml
curl -sfL https://get.k3s.io | sh -
```

On an existing K3s, add the same lines to `/etc/rancher/k3s/config.yaml` and restart it (`sudo systemctl restart k3s`).

On RHEL-family systems with `firewalld`, let the cluster networks talk to each other:

```bash
sudo firewall-cmd --permanent --zone=trusted --add-source=10.42.0.0/16 --add-source=10.43.0.0/16
sudo firewall-cmd --permanent --add-port=443/tcp --add-port=80/tcp
sudo firewall-cmd --reload
```

With several machines, also open 6443/tcp, 8472/udp and 10250/tcp between them.

### More than one machine

Install the first machine as described in [Install K3s with a higher pod limit](#install-k3s-with-a-higher-pod-limit). It becomes the server. If the machines share a private network, add these lines to its `/etc/rancher/k3s/config.yaml` **before** installing, so cluster traffic stays on that network:

```yaml
node-ip: <this machine's private IP>
node-external-ip: <this machine's public IP>    # only if users reach it on another address
flannel-iface: <private network interface, e.g. eth1>
```

On each further machine, write the same `max-pods` line plus its own `node-ip` / `flannel-iface`, then join it to the server:

```bash
# on the server: the join token
sudo cat /var/lib/rancher/k3s/server/node-token
# on the new machine
curl -sfL https://get.k3s.io | K3S_URL="https://<server private IP>:6443" K3S_TOKEN="<token>" sh -
```

Every machine needs the [Node settings](#node-settings).

### kubectl from your workstation

The guide's commands run on your workstation. To reach the cluster from there, add the address you'll use in the server's `/etc/rancher/k3s/config.yaml` before installing:

```yaml
tls-san: [<server public IP or name>]
```

Then copy the cluster's kubeconfig to the workstation and point it at that address:

```bash
scp <user>@<server>:/etc/rancher/k3s/k3s.yaml ~/.kube/openlm-k3s.yaml    # readable by root: copy it with sudo on the server first
sed -i.bak 's/127.0.0.1/<server public IP or name>/' ~/.kube/openlm-k3s.yaml
export KUBECONFIG=~/.kube/openlm-k3s.yaml
kubectl get nodes
```

Port `6443` must be open from your workstation to the server. Keep this file safe: it gives full admin access to the cluster.

## Ingress

Use the Traefik that K3s brings as the ingress: set `INGRESS_CLASS=traefik` in the worksheet. Point your DNS record at the machine's IP (or a load balancer in front of the machines).

### HTTPS redirect

Make Traefik redirect every `http://` request to `https://`. K3s applies any file in its manifests folder automatically:

```bash
sudo tee /var/lib/rancher/k3s/server/manifests/traefik-config.yaml >/dev/null <<'EOF'
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    ports:
      web:
        http:
          redirections:
            entryPoint:
              to: websecure
              scheme: https
              permanent: true
EOF
```

After a minute, check that `curl -sI http://$DOMAIN/ | head -1` shows `308`.

## Storage

Set `STORAGE_CLASS=local-path`. The class is built in and needs nothing else. Volumes stay on the node where they were first created, which is fine for the small working volumes of OpenLM Platform.

## Node settings

On every machine, set the file-watch limits:

```bash
printf 'fs.inotify.max_user_instances = 8192\nfs.inotify.max_user_watches = 524288\n' | sudo tee /etc/sysctl.d/90-openlm.conf
sudo sysctl --system
```

## DNS inside the cluster

Pods must reach `https://$DOMAIN`. On a K3s machine behind a router or NAT, traffic to the machine's public address often doesn't come back. Make the name resolve inside the cluster to Traefik directly, with K3s's CoreDNS extension point:

```bash
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata: { name: coredns-custom, namespace: kube-system }
data:
  openlm.override: |
    rewrite name exact $DOMAIN traefik.kube-system.svc.cluster.local
EOF
kubectl -n kube-system rollout restart deployment coredns
```

If the machine's own DNS resolvers only answer over IPv6, pods can't resolve anything outside the cluster. Point K3s at IPv4 resolvers: create `/etc/rancher/k3s/resolv.conf` with `nameserver <IPv4 resolver>` lines, add `resolv-conf: /etc/rancher/k3s/resolv.conf` to `/etc/rancher/k3s/config.yaml`, and restart K3s.

## Values

K3s needs no values beyond what step 4 gives you. Leave node placement off on a single machine.

## Data services

SQL Server usually runs outside the cluster (Windows or Linux server, or a cloud database). MongoDB, Kafka and Redis can run on the same K3s cluster, installed with their own charts or operators, in their own namespace. Size the machine for them as well.

## Checks specific to K3s

Confirm the K3s settings with these commands:

```bash
kubectl get nodes                                       # Ready
kubectl get node -o jsonpath='{.items[0].status.capacity.pods}{"\n"}'   # 250
kubectl -n kube-system get pods | grep -E "traefik|coredns"            # Running
```
