K3s (K3d)
K3s is a lightweight, certified Kubernetes distribution for resource-constrained environments. K3d runs K3s clusters in Docker containers ā each node is a container, with a dedicated load balancer container routing traffic to control planes ā providing fast 15ā30 s cluster creation with batteries-included defaults (ServiceLB, local-path-provisioner, metrics-server), standard k3d.yaml files, and no vendor lock-in.
K3s (K3d) is ideal for quick local development, CI/CD pipelines with ephemeral clusters, resource-constrained machines or CI runners, and multi-node topology testing.
Quick Start
Section titled āQuick StartāPrerequisites
Section titled āPrerequisitesā- Docker Desktop or Docker Engine installed and running
docker pscommand works
Step 1: Initialize Project
Section titled āStep 1: Initialize Projectāksail cluster init \ --name my-cluster \ --distribution K3s \ --control-planes 1 \ --workers 2This creates:
ksail.yamlā KSail configurationk3d.yamlā K3d-specific cluster configuration
Step 2: Create Cluster
Section titled āStep 2: Create Clusterāksail cluster createStep 3: Verify Cluster
Section titled āStep 3: Verify Clusterāksail cluster infokubectl get nodesStep 4: Deploy Sample Application
Section titled āStep 4: Deploy Sample Applicationākubectl create deployment nginx --image=nginxkubectl expose deployment nginx --port=80 --type=LoadBalancerkubectl get svc nginx # EXTERNAL-IP appears within seconds via ServiceLBStep 5: Cleanup
Section titled āStep 5: Cleanupāksail cluster deleteConfiguration
Section titled āConfigurationāBasic Configuration
Section titled āBasic Configurationā# yaml-language-server: $schema=https://raw.githubusercontent.com/devantler-tech/ksail/main/schemas/ksail-config.schema.jsonapiVersion: ksail.io/v1alpha1kind: Clusterspec: cluster: distribution: K3s distributionConfig: k3d.yamlK3d-Specific Configuration
Section titled āK3d-Specific ConfigurationāapiVersion: k3d.io/v1alpha5kind: Simpleservers: 1 # control-plane nodesagents: 2 # worker nodesports: - port: 8080:80@loadbalancerBuilt-in Components
Section titled āBuilt-in ComponentsāK3s includes these components by defaultāKSail does not reinstall them:
| Component | Notes |
|---|---|
| ServiceLB (Klipper-LB) | LoadBalancer support via host ports |
| local-path-provisioner | Dynamic PersistentVolume provisioning |
| Metrics Server | kubectl top and HPA support |
| CoreDNS | Cluster DNS |
| Traefik | Ingress controller (can be disabled) |
Registry Mirrors
Section titled āRegistry MirrorsāConfigure registry mirrors to avoid rate limits. KSail enables docker.io, ghcr.io, quay.io, and registry.k8s.io mirrors by default. Override with --mirror-registry flags:
ksail cluster init --name my-cluster --distribution K3s \ --mirror-registry 'docker.io=https://registry-1.docker.io' \ --mirror-registry 'ghcr.io=https://ghcr.io' \ --mirror-registry 'quay.io=https://quay.io' \ --mirror-registry 'registry.k8s.io=https://registry.k8s.io'K3d injects registry configuration so all nodes use your mirrors automatically.
Troubleshooting
Section titled āTroubleshootingā1. Cluster Creation Fails
Section titled ā1. Cluster Creation FailsāSymptom: ksail cluster create fails with Docker errors.
docker ps # Check Docker is runningdf -h # Check available disk spacedocker system prune -f # WARNING: removes unused containers, networks, images, and build cacheksail cluster create2. Nodes Not Ready
Section titled ā2. Nodes Not ReadyāSymptom: kubectl get nodes shows NotReady status.
kubectl describe node <node-name>kubectl get pods -n kube-systemksail cluster delete && ksail cluster create3. LoadBalancer Stuck in Pending
Section titled ā3. LoadBalancer Stuck in PendingāK3s uses ServiceLB (Klipper-LB), which binds to host ports. Ensure the port is not already in use and update ports in k3d.yaml (e.g., 9080:80@loadbalancer) if needed.
docker ps --format "table {{.Names}}\t{{.Ports}}" | grep k3d4. Port Already in Use
Section titled ā4. Port Already in UseāSymptom: address already in use error during cluster creation.
k3d cluster listk3d cluster delete <cluster-name># Or initialize with a different name:ksail cluster init --name my-cluster-2 --distribution K3s5. Out of Memory or Disk Space
Section titled ā5. Out of Memory or Disk SpaceāReduce node count in ksail.yaml (workers: 0 for a single-node cluster) and run docker system prune. Increase Docker Desktop resources under Settings ā Resources.
Advanced Topics
Section titled āAdvanced TopicsāWorker Node Scaling
Section titled āWorker Node ScalingāUnlike Vanilla (Kind), K3s supports in-place worker node scaling. Update agents in k3d.yaml and run ksail cluster update to add or remove worker containers without recreation.
Disabling Built-in Components
Section titled āDisabling Built-in Componentsāoptions: k3s: extraArgs: - arg: --disable=traefik # Remove Traefik ingress nodeFilters: ["server:*"] - arg: --disable=servicelb # Remove ServiceLB (use MetalLB instead) nodeFilters: ["server:*"]Custom CNI
Section titled āCustom CNIāspec: cluster: cni: Cilium# k3d.yaml ā disable built-in Flanneloptions: k3s: extraArgs: - arg: --flannel-backend=none nodeFilters: ["server:*"] - arg: --disable-network-policy nodeFilters: ["server:*"]Kubernetes Version
Section titled āKubernetes VersionāK3s version is determined by the K3d image. Pin a specific version in k3d.yaml (see K3d image tags):
image: rancher/k3s:v1.31.0-k3s1Port Mappings
Section titled āPort Mappingsāports: - port: 8080:80@loadbalancer # HTTP - port: 8443:443@loadbalancer # HTTPS - port: 30080:30080@agent:0 # NodePort on first workerIntegration with Native K3d
Section titled āIntegration with Native K3dāKSail generates standard k3d.yaml filesāuse K3d CLI directly (k3d cluster create --config k3d.yaml) if needed. No vendor lock-in: configurations are portable and KSail can interact with any K3d cluster accessible via your kubeconfig.