What it is
K3s is a lightweight, certified Kubernetes distribution designed for edge, IoT, CI, and development environments, offering a simplified installation and operation experience.
Installation
Linux (Systemd)
curl -sfL https://get.k3s.io | sh -
Installs K3s as a systemd service.
Linux (Systemd with specific version)
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="v1.28.5+k3s1" sh -
Installs a specific version of K3s.
Linux (ARM64)
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable servicelb --disable traefik" sh -
Installs K3s on ARM64, disabling default components if needed.
Linux (as a server, without systemd)
curl -sfL https://get.k3s.io | sh -s - --disable servicelb
Installs K3s as a server without systemd, disabling ServiceLB.
Linux (as an agent/worker node)
curl -sfL https://get.k3s.io | K3S_URL=https://your-server-ip:6443 K3S_TOKEN=your-node-token sh -
Joins an existing K3s cluster as an agent. Replace your-server-ip and your-node-token.
Mac (Docker Desktop)
docker run -d --privileged \
-p 6443:6443 \
-p 8472:8472/udp \
-p 10250:10250 \
--name k3s \
rancher/k3s:latest
Runs K3s in a Docker container on macOS.
Windows (WSL2)
Follow the Linux instructions within your WSL2 distribution.
Core Concepts
Server vs. Agent
K3s operates in a client-server model. A server node runs the Kubernetes API server, etcd (or SQLite by default), and scheduler. Agent nodes (formerly called workers) run the Kubelet and Kube-proxy to host your workloads.
Embedded etcd vs. SQLite
By default, K3s uses SQLite for its datastore, simplifying setup. For production or HA, you can configure K3s to use an external etcd cluster.
Embedded Service Load Balancer (ServiceLB)
K3s includes a built-in Service Load Balancer that automatically assigns external IPs to Services of type LoadBalancer.
Embedded Ingress Controller (Traefik)
K3s bundles Traefik as its default Ingress controller, simplifying ingress management.
Commands / Usage
k3s (client)
This is the primary command-line tool for interacting with the K3s API server. You’ll typically use kubectl after configuring it to point to your K3s server.
k3s kubectl ...
Directly invokes kubectl commands through the K3s binary. This is useful if you haven’t set up a separate kubectl configuration.
k3s kubectl get nodes
Gets a list of nodes in the cluster.
k3s kubectl apply -f my-deployment.yaml
Applies a Kubernetes manifest.
k3s server
Starts K3s in server mode. Usually managed by systemd.
--disable servicelb
Disables the embedded Service Load Balancer.
k3s server --disable servicelb
--disable traefik
Disables the embedded Traefik Ingress controller.
k3s server --disable traefik
--data-dir /var/lib/rancher/k3s
Specifies the directory for K3s data.
k3s server --data-dir /mnt/ssd/k3s-data
--cluster-init
Initializes a new K3s cluster (used for HA setups).
k3s server --cluster-init
--server-url https://127.0.0.1:6443
Specifies the server URL (used when joining as an agent).
k3s agent --server-url https://192.168.1.100:6443 --token my-secret-token
--token my-secret-token
Specifies the cluster token for agent registration.
k3s agent --server-url https://192.168.1.100:6443 --token abcdef1234567890
k3s agent
Starts K3s in agent mode (worker node). Usually managed by systemd.
--server https://your-server-ip:6443
The URL of the K3s server to connect to.
k3s agent --server https://10.0.0.5:6443 --token K10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
--token K10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The secret token used to join the cluster.
k3s agent --server https://k3s-master.local:6443 --token K1somerandomlongstringtoken
k3s etcd-snapshot
Commands for managing etcd snapshots.
save --name <snapshot-name>
Saves a new etcd snapshot.
k3s etcd-snapshot save --name my-cluster-backup-20231027
list
Lists available etcd snapshots.
k3s etcd-snapshot list
delete <snapshot-name>
Deletes a specific etcd snapshot.
k3s etcd-snapshot delete my-cluster-backup-20231027
restore --name <snapshot-name>
Restores the cluster from a specific etcd snapshot. Caution: This will overwrite current cluster state.
k3s etcd-snapshot restore --name my-cluster-backup-20231027
prune
Removes old snapshots, keeping a specified number.
k3s etcd-snapshot prune --snapshot-retention 5
Keeps the 5 most recent snapshots.
k3s config
Generates K3s configuration files.
ctr
Generates a containerd configuration file.
k3s config ctr > containerd-config.toml
kubelet
Generates a kubelet configuration file.
k3s config kubelet > kubelet-config.yaml
kube-proxy
Generates a kube-proxy configuration file.
k3s config kube-proxy > kube-proxy-config.yaml
k3s secrets
Encrypts and decrypts secrets.
encrypt <plaintext>
Encrypts a plaintext string.
k3s secrets encrypt "my-super-secret-password"
decrypt <encrypted-string>
Decrypts an encrypted string.
k3s secrets decrypt U2VjcmV0SW5wdXQ=
k3s ctl
Contains helper commands for managing K3s.
channel
Shows the current K3s release channel.
k3s ctl channel
get-token
Retrieves the cluster token.
k3s ctl get-token
k3s collect-logs
Bundles logs for debugging.
k3s collect-logs
Creates a tarball of logs.
k3s reset
Resets a K3s installation. Use with caution, this will remove K3s and associated data.
k3s-uninstall.sh
For systemd installations, this script removes K3s.
k3s reset
Resets the K3s service and cleans up data directories.
Common Patterns
Accessing kubectl
After installing K3s server, its configuration is usually placed at /etc/rancher/k3s/k3s.yaml. To use kubectl:
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get nodes
Or, if you installed K3s directly on your workstation:
k3s kubectl get nodes
Adding a Worker Node
- Get the server IP and token:
A more robust way to get the token on the server:# On the server node SERVER_IP=$(curl -s ifconfig.me) # Or your server's actual IP NODE_TOKEN=$(sudo k3s-agent --server https://${SERVER_IP}:6443 --token-file /var/lib/rancher/k3s/server/node-token --data-dir /tmp | grep "token:" | awk '{print $2}') # Note: The above command is a bit hacky, better to grab the token from /var/lib/rancher/k3s/server/node-token on the serversudo cat /var/lib/rancher/k3s/server/node-token - Install K3s on the worker node using the server’s IP and token:
curl -sfL https://get.k3s.io | K3S_URL=https://<server_ip>:6443 K3S_TOKEN=<your_node_token> sh -
Deploying an Application
Create a deployment YAML file (my-app.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Apply it:
k3s kubectl apply -f my-app.yaml
Exposing an Application with LoadBalancer
Create a service YAML file (my-app-service.yaml):
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer
Apply it:
k3s kubectl apply -f my-app-service.yaml
The K3s ServiceLB will assign an external IP. Check with:
k3s kubectl get svc nginx-service
Exposing an Application with Ingress (Traefik)
Create an ingress YAML file (my-app-ingress.yaml):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
spec:
rules:
- host: myapp.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
Apply it:
k3s kubectl apply -f my-app-ingress.yaml
You’ll need to configure your local DNS or /etc/hosts to resolve myapp.local to the K3s server’s IP.
High Availability (HA) Setup
Requires an external database (like etcd, PostgreSQL, MySQL).
- Start the first server:
# Example using etcd export ENDPOINTS="https://etcd1:2379,https://etcd2:2379,https://etcd3:2379" export ETCD_CAFILE=/path/to/ca.crt export ETCD_CERTFILE=/path/to/etcd.crt export ETCD_KEYFILE=/path/to/etcd.key k3s server \ --cluster-init \ --data-dir /var/lib/rancher/k3s/server \ --tls-san <your_server_ip> \ --disable servicelb \ --disable traefik \ --disable localstorage # If using external storage - Start subsequent servers:
k3s server \ --data-dir /var/lib/rancher/k3s/server \ --tls-san <your_server_ip> \ --disable servicelb \ --disable traefik \ --disable localstorage # If using external storage - Start agent nodes: Use the K3S_URL and K3S_TOKEN pointing to one of the server IPs.
Gotchas
Default Ports
K3s listens on 6443 for the Kubernetes API. Ensure this port is accessible if you’re connecting from other machines.
ServiceLB IP Range
ServiceLB allocates IPs from a default range (10.43.0.0/16). If this conflicts with your network, you might need to configure it.
Traefik Configuration
Traefik is deployed as a DaemonSet and Deployment. Its configuration is managed via ConfigMaps. You can customize it by editing these resources.
Node Token Security
The node token is crucial for joining nodes. Protect it, as anyone with the token can join your cluster. It’s stored at /var/lib/rancher/k3s/server/node-token on the server.
Data Persistence
By default, K3s uses SQLite and stores data in /var/lib/rancher/k3s. For production, consider using an external database and persistent storage for your applications.
k3s-uninstall.sh
This script is automatically installed and is the recommended way to remove K3s from a systemd-based Linux installation. Running it cleans up services, directories, and iptables rules.
kubectl Context
If you have multiple Kubernetes clusters configured, ensure your kubectl context is set correctly to point to your K3s cluster. k3s kubectl bypasses this by default.