Module 14.2: k0s - Zero Friction Kubernetes
Цей контент ще не доступний вашою мовою.
Toolkit Track | Complexity:
[MEDIUM]| Time: 40-45 minutes
Overview
Section titled “Overview”k0s (pronounced “kay-zero-ess”) takes the “batteries included” philosophy to its logical extreme: a single binary that contains everything—including the container runtime. No dependencies to install, no system services to configure, no packages to manage. Download, run, Kubernetes. That’s it.
Built by Mirantis, k0s was designed to eliminate every friction point in Kubernetes deployment, from initial install to day-2 operations.
This module teaches you to deploy and operate k0s for clean, dependency-free Kubernetes clusters.
Prerequisites
Section titled “Prerequisites”- Kubernetes fundamentals (kubectl, deployments, services)
- Linux command-line basics
- SSH access to Linux machines (or VMs)
- Understanding of container runtimes
What You’ll Be Able to Do
Section titled “What You’ll Be Able to Do”After completing this module, you will be able to:
- Deploy K0s clusters with zero host dependencies using its single-binary architecture
- Configure K0s control plane components and worker profiles for different hardware configurations
- Implement K0s cluster lifecycle management with k0sctl for automated multi-node deployments
- Compare K0s’s zero-dependency approach against K3s and MicroK8s for air-gapped environments
Why This Module Matters
Section titled “Why This Module Matters”k0s answers the question: “What if Kubernetes had zero host dependencies?”
Every other Kubernetes distribution assumes something:
- kubeadm assumes you’ve installed containerd
- k3s assumes systemd for service management
- MicroK8s assumes snap package support
k0s assumes nothing. The single binary contains:
- kube-apiserver, controller-manager, scheduler
- kubelet, kube-proxy
- containerd (with runc)
- etcd (for single-node or HA)
- CoreDNS, konnectivity-server
If your system can execute a binary, it can run k0s.
Did You Know?
Section titled “Did You Know?”- Zero Dependencies: k0s requires only a Linux kernel and some basic utilities (iptables)
- Clean State: All k0s data lives in
/var/lib/k0s—delete the directory, k0s is gone - Mirantis Origin: Created by Mirantis after acquiring Docker Enterprise
- Cluster API Support: k0s integrates with Cluster API for declarative cluster management
- Name Origin: “k0s” = Kubernetes with zero ops, zero dependencies, zero friction
k0s Architecture
Section titled “k0s Architecture”k0s ARCHITECTURE─────────────────────────────────────────────────────────────────────────────
┌─────────────────────────────────────────────────────────────────────────────┐│ k0s Controller Node ││ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ k0s Binary (~180MB) │ ││ │ │ ││ │ ┌──────────────────── Control Plane ───────────────────────┐ │ ││ │ │ │ │ ││ │ │ kube-apiserver kube-controller-manager kube-scheduler │ ││ │ │ │ │ ││ │ └──────────────────────────────────────────────────────────┘ │ ││ │ │ ││ │ ┌──────────────────── Embedded Components ─────────────────┐ │ ││ │ │ │ │ ││ │ │ etcd/SQLite konnectivity-server CoreDNS │ ││ │ │ metrics-server kube-router helm-controller │ ││ │ │ │ │ ││ │ └──────────────────────────────────────────────────────────┘ │ ││ │ │ ││ │ Note: Controller nodes do NOT run workloads by default │ ││ │ (clean separation of control plane and workers) │ ││ │ │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ ││ ┌───────────────────────────────────────────────────────────────────────┐ ││ │ /var/lib/k0s │ ││ │ All state, configs, binaries, and data in one directory │ ││ └───────────────────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────────────┘ │ ┌───────────────────────────┼───────────────────────────┐ │ │ │ ▼ ▼ ▼┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐│ k0s Worker Node │ │ k0s Worker Node │ │ k0s Worker Node ││ │ │ │ │ ││ ┌───────────────┐ │ │ ┌───────────────┐ │ │ ┌───────────────┐ ││ │ k0s Binary │ │ │ │ k0s Binary │ │ │ │ k0s Binary │ ││ │ │ │ │ │ │ │ │ │ │ ││ │ kubelet │ │ │ │ kubelet │ │ │ │ kubelet │ ││ │ containerd │ │ │ │ containerd │ │ │ │ containerd │ ││ │ kube-proxy │ │ │ │ kube-proxy │ │ │ │ kube-proxy │ ││ │ kube-router │ │ │ │ kube-router │ │ │ │ kube-router │ ││ └───────────────┘ │ │ └───────────────┘ │ │ └───────────────┘ ││ │ │ │ │ ││ /var/lib/k0s │ │ /var/lib/k0s │ │ /var/lib/k0s ││ (isolated state) │ │ (isolated state) │ │ (isolated state) ││ │ │ │ │ │└─────────────────────┘ └─────────────────────┘ └─────────────────────┘
KEY DIFFERENTIATORS:─────────────────────────────────────────────────────────────────────────────
1. ZERO HOST DEPENDENCIES • containerd embedded in binary • No pre-installed runtime required • No system packages needed
2. CLEAN SEPARATION • Controllers are pure control plane (no workloads) • Workers are pure workers • Single-node mode runs both
3. ISOLATED STATE • Everything in /var/lib/k0s • Clean uninstall: rm -rf /var/lib/k0s • No scattered configs across filesystem
4. KUBE-ROUTER • CNI, kube-proxy replacement, and service load balancer • All networking in one component • Supports BGP for advanced routingInstalling k0s
Section titled “Installing k0s”Single Node (Development)
Section titled “Single Node (Development)”The simplest deployment—single node with control plane and worker:
# Download k0scurl -sSLf https://get.k0s.sh | sudo sh
# Check versionk0s version
# Start single-node clustersudo k0s install controller --singlesudo k0s start
# Check statussudo k0s status
# Get kubeconfigsudo k0s kubeconfig admin > ~/.kube/configchmod 600 ~/.kube/config
# Verify clusterkubectl get nodeskubectl get pods -AMulti-Node Cluster (Manual)
Section titled “Multi-Node Cluster (Manual)”On the controller node:
# Download and installcurl -sSLf https://get.k0s.sh | sudo sh
# Install controller (NOT --single, workers will join)sudo k0s install controllersudo k0s start
# Wait for control planesudo k0s status
# Generate worker join tokensudo k0s token create --role=worker
# Save this token for worker nodesOn each worker node:
# Download and installcurl -sSLf https://get.k0s.sh | sudo sh
# Install worker with tokensudo k0s install worker --token-file /path/to/token
# Or pass token directlysudo k0s install worker --token "eyJhbG..."
# Start workersudo k0s start
# Check statussudo k0s statusVerify from controller:
kubectl get nodesMulti-Node Cluster with k0sctl
Section titled “Multi-Node Cluster with k0sctl”k0sctl automates multi-node deployment:
# Install k0sctlcurl -sSLf https://github.com/k0sproject/k0sctl/releases/latest/download/k0sctl-linux-amd64 -o k0sctlchmod +x k0sctlsudo mv k0sctl /usr/local/bin/
# Create cluster configurationcat > k0sctl.yaml <<EOFapiVersion: k0sctl.k0sproject.io/v1beta1kind: Clustermetadata: name: my-k0s-clusterspec: hosts: - ssh: address: 192.168.1.10 user: root keyPath: ~/.ssh/id_rsa role: controller - ssh: address: 192.168.1.11 user: root keyPath: ~/.ssh/id_rsa role: worker - ssh: address: 192.168.1.12 user: root keyPath: ~/.ssh/id_rsa role: worker k0s: version: v1.28.5+k0s.0 config: spec: api: externalAddress: 192.168.1.10 network: provider: kube-routerEOF
# Apply configuration (deploys entire cluster)k0sctl apply --config k0sctl.yaml
# Get kubeconfigk0sctl kubeconfig --config k0sctl.yaml > ~/.kube/config
# Verifykubectl get nodesHigh Availability Setup
Section titled “High Availability Setup”# k0sctl.yaml for HAapiVersion: k0sctl.k0sproject.io/v1beta1kind: Clustermetadata: name: ha-k0s-clusterspec: hosts: # 3 controllers for HA - ssh: address: 192.168.1.10 user: root keyPath: ~/.ssh/id_rsa role: controller - ssh: address: 192.168.1.11 user: root keyPath: ~/.ssh/id_rsa role: controller - ssh: address: 192.168.1.12 user: root keyPath: ~/.ssh/id_rsa role: controller # Workers - ssh: address: 192.168.1.20 user: root keyPath: ~/.ssh/id_rsa role: worker - ssh: address: 192.168.1.21 user: root keyPath: ~/.ssh/id_rsa role: worker k0s: version: v1.28.5+k0s.0 config: spec: api: # Load balancer address externalAddress: api.k0s.example.com sans: - api.k0s.example.com - 192.168.1.10 - 192.168.1.11 - 192.168.1.12 storage: type: etcdk0s Configuration
Section titled “k0s Configuration”Configuration File Structure
Section titled “Configuration File Structure”apiVersion: k0s.k0sproject.io/v1beta1kind: ClusterConfigmetadata: name: my-clusterspec: api: address: 192.168.1.10 port: 6443 k0sApiPort: 9443 externalAddress: api.k0s.example.com sans: - api.k0s.example.com - "192.168.1.10" extraArgs: enable-admission-plugins: "NodeRestriction,PodSecurityPolicy"
storage: type: etcd # etcd, kine+sqlite, kine+mysql, kine+postgres etcd: peerAddress: 192.168.1.10
network: provider: kube-router # or calico, custom kubeProxy: disabled: false mode: iptables # iptables or ipvs podCIDR: 10.244.0.0/16 serviceCIDR: 10.96.0.0/12 clusterDomain: cluster.local dualStack: enabled: false
controllerManager: extraArgs: bind-address: "0.0.0.0"
scheduler: extraArgs: bind-address: "0.0.0.0"
installConfig: users: etcdUser: etcd kineUser: kube-apiserver konnectivityUser: konnectivity-server kubeAPIserverUser: kube-apiserver kubeSchedulerUser: kube-scheduler
extensions: helm: repositories: - name: stable url: https://charts.helm.sh/stable charts: - name: prometheus chartname: stable/prometheus namespace: monitoring storage: type: openebs_local_storage # or external_storage
telemetry: enabled: trueNetwork Provider Options
Section titled “Network Provider Options”kube-router (default):
spec: network: provider: kube-router kube-router: # Enable all features metricsPort: 8080 hairpin: Enabled autoMTU: true # BGP configuration peerRouterASNs: "64512" peerRouterIPs: "192.168.1.1"Calico:
spec: network: provider: calico calico: mode: vxlan # vxlan, ipip, bird overlay: Always flexVolumeDriverPath: /usr/libexec/k0s/kubelet-plugins/volume/exec/nodeagent~uds wireguard: falseCustom CNI (Cilium, Flannel, etc.):
spec: network: provider: custom # Install your own CNI after cluster is upStorage Configuration
Section titled “Storage Configuration”SQLite (single node):
spec: storage: type: kine kine: dataSource: sqlite:///var/lib/k0s/db/state.dbExternal database:
spec: storage: type: kine kine: dataSource: mysql://user:password@tcp(mysql.example.com:3306)/k0s # Or PostgreSQL # dataSource: postgres://user:password@postgres.example.com:5432/k0s?sslmode=disableHelm Integration
Section titled “Helm Integration”k0s includes a Helm controller for declarative chart installation:
# In k0s.yamlspec: extensions: helm: repositories: - name: jetstack url: https://charts.jetstack.io - name: ingress-nginx url: https://kubernetes.github.io/ingress-nginx
charts: - name: cert-manager chartname: jetstack/cert-manager version: "v1.13.0" namespace: cert-manager values: | installCRDs: true
- name: ingress-nginx chartname: ingress-nginx/ingress-nginx version: "4.8.0" namespace: ingress-nginx values: | controller: service: type: LoadBalancerApply changes by restarting k0s or using:
# Reconcile Helm chartssudo k0s controller --enable-dynamic-configCluster API Integration
Section titled “Cluster API Integration”k0s integrates with Cluster API for declarative cluster management:
# Install clusterctlcurl -L https://github.com/kubernetes-sigs/cluster-api/releases/latest/download/clusterctl-linux-amd64 -o clusterctlchmod +x clusterctlsudo mv clusterctl /usr/local/bin/
# Initialize CAPI with k0s providerclusterctl init --infrastructure docker --bootstrap k0sproject-k0smotron --control-plane k0sproject-k0smotron
# Create workload clustercat <<EOF | kubectl apply -f -apiVersion: cluster.x-k8s.io/v1beta1kind: Clustermetadata: name: my-clusterspec: clusterNetwork: pods: cidrBlocks: ["10.244.0.0/16"] services: cidrBlocks: ["10.96.0.0/12"] controlPlaneRef: apiVersion: controlplane.cluster.x-k8s.io/v1beta1 kind: K0sControlPlane name: my-cluster-cp infrastructureRef: apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 kind: DockerCluster name: my-clusterEOFDay-2 Operations
Section titled “Day-2 Operations”Backup and Restore
Section titled “Backup and Restore”# Backup etcd (on controller)sudo k0s backup --save-path /backup/k0s-backup.tar.gz
# Restore from backupsudo k0s stopsudo k0s restore /backup/k0s-backup.tar.gzsudo k0s startUpgrading k0s
Section titled “Upgrading k0s”# Check current versionk0s version
# With k0sctl (recommended for multi-node)k0sctl apply --config k0sctl.yaml --debug
# Manual upgradesudo k0s stopcurl -sSLf https://get.k0s.sh | sudo K0S_VERSION=v1.29.0+k0s.0 shsudo k0s startReset and Cleanup
Section titled “Reset and Cleanup”# Stop k0ssudo k0s stop
# Uninstall servicesudo k0s reset
# This removes:# - /var/lib/k0s# - /run/k0s# - All containers# - Network interfaces# - iptables rulesMonitoring and Troubleshooting
Section titled “Monitoring and Troubleshooting”Built-in Status
Section titled “Built-in Status”# Check k0s statussudo k0s status
# Check component healthsudo k0s kubectl get --raw /healthz
# View control plane logssudo journalctl -u k0scontroller
# View worker logssudo journalctl -u k0sworker
# Check etcd health (HA setup)sudo k0s etcd member-listDebugging
Section titled “Debugging”# Run with debug loggingsudo k0s controller --debug
# Get detailed component statussudo k0s kubectl get componentstatuses
# Check CNI statussudo k0s kubectl -n kube-system get pods -l k8s-app=kube-router
# Verify networkingsudo k0s kubectl run test --image=busybox --rm -it --restart=Never -- wget -qO- kubernetes.defaultWar Story: The Clean Slate Infrastructure
Section titled “War Story: The Clean Slate Infrastructure”A fintech startup needed Kubernetes across hybrid infrastructure:
The Challenge:
- Mixed infrastructure: AWS, on-prem, edge locations
- Different Linux distributions (Ubuntu, RHEL, Amazon Linux)
- Strict security requirements (no unnecessary packages)
- Need for consistent deployment across all environments
Why Other Solutions Had Issues:
- kubeadm: Required pre-installing containerd, different steps per distro
- k3s: Assumed systemd, had dependency issues on older RHEL
- Managed K8s: Not available on-prem or edge
The k0s Solution:
# Same installation everywherecurl -sSLf https://get.k0s.sh | sudo shsudo k0s install controllersudo k0s start
# Worked on:# - Ubuntu 20.04# - RHEL 7.9# - Amazon Linux 2# - Debian 11# - Even Alpine (with glibc compatibility)Fleet Automation with k0sctl:
apiVersion: k0sctl.k0sproject.io/v1beta1kind: Clustermetadata: name: productionspec: hosts: # AWS controllers - ssh: address: 10.0.1.10 user: ec2-user keyPath: ~/.ssh/aws.pem role: controller privateAddress: 10.0.1.10 # On-prem controllers - ssh: address: 192.168.1.10 user: root keyPath: ~/.ssh/onprem.pem role: controller privateAddress: 192.168.1.10 # Edge workers - ssh: address: edge-node-1.example.com user: admin keyPath: ~/.ssh/edge.pem role: workerGitOps for Cluster Configuration:
# k0s.yaml managed in Gitspec: extensions: helm: charts: - name: cert-manager chartname: jetstack/cert-manager namespace: cert-manager version: v1.13.0 - name: vault chartname: hashicorp/vault namespace: vault version: 0.25.0The Results:
- Deployment time: 5 minutes per cluster (automated)
- Same binary, same process across all environments
- Clean uninstall:
k0s resetleaves no traces - Security team approved: minimal attack surface
- Upgrade path:
k0sctl applyupdates entire fleet
The Lesson: Zero dependencies means zero surprises across diverse infrastructure.
Common Mistakes
Section titled “Common Mistakes”| Mistake | Problem | Solution |
|---|---|---|
| Using —single in production | No HA, can’t add workers | Use controller-only for HA |
| Forgetting externalAddress | Certificates don’t include LB IP | Set API externalAddress and sans |
| Not separating controller/worker | Controllers running workloads | Controllers should be control-plane only |
| Ignoring backup | Data loss on failure | Regular k0s backup to external storage |
| Manual token management | Tokens expire, manual process | Use k0sctl for token lifecycle |
| Wrong storage type for HA | SQLite in multi-controller | Use etcd for HA setups |
| Not checking status | Silent failures | Regular k0s status checks |
| Skipping k0s reset | Leftover state causes issues | Always k0s reset before reinstall |
Test your understanding of k0s:
1. What makes k0s different from k3s in terms of dependencies?
Answer: k0s embeds containerd within its binary—no host runtime installation required. k3s assumes containerd is available on the system. This makes k0s truly zero-dependency: the single binary contains everything needed to run Kubernetes, including the container runtime.
2. Why don't k0s controller nodes run workloads by default?
Answer: k0s enforces clean separation of control plane and workers. Controller nodes only run control plane components (API server, controller-manager, scheduler, etcd). This improves security and stability—a workload crash can’t affect the control plane. Use --single mode only for development when you want both on one node.
3. What is k0sctl and when should you use it?
Answer: k0sctl is an automation tool that deploys and manages k0s clusters via SSH. Use it for: (1) Multi-node deployments, (2) HA cluster setup, (3) Fleet upgrades, (4) Consistent configuration across nodes. It’s the recommended way to manage anything beyond single-node development.
4. How does k0s handle CNI differently than k3s?
Answer: k0s defaults to kube-router, which provides CNI, service proxy (kube-proxy replacement), and network policies in one component. It also supports Calico as a built-in option or custom CNI. k3s defaults to Flannel. kube-router’s integration with BGP makes k0s particularly suitable for advanced networking scenarios.
5. What datastore options does k0s support?
Answer: k0s supports: (1) etcd (embedded, for HA), (2) SQLite via kine (single node), (3) MySQL via kine (external HA), (4) PostgreSQL via kine (external HA). Unlike k3s which embeds SQLite/etcd logic, k0s uses kine as an abstraction layer for non-etcd backends.
6. How do you cleanly uninstall k0s?
Answer: Run sudo k0s stop followed by sudo k0s reset. The reset command removes: /var/lib/k0s, /run/k0s, all containers, network interfaces created by k0s, and iptables rules. All state is contained in /var/lib/k0s, so removal is complete and clean.
7. How does k0s integrate with Cluster API?
Answer: k0s provides bootstrap and control plane providers for Cluster API through the k0smotron project. This enables declarative cluster management: define clusters as Kubernetes resources, and CAPI reconciles the desired state. Useful for managing fleets of k0s clusters at scale.
8. What's the purpose of the Helm extension in k0s configuration?
Answer: The Helm extension allows declarative chart installation as part of cluster configuration. Charts defined in k0s.yaml are automatically installed/upgraded when the cluster starts. This enables GitOps-style management of cluster add-ons without external tools like ArgoCD for basic use cases.
Hands-On Exercise: Deploy HA k0s with k0sctl
Section titled “Hands-On Exercise: Deploy HA k0s with k0sctl”Objective
Section titled “Objective”Use k0sctl to deploy a high-availability k0s cluster with automated configuration.
Environment Setup
Section titled “Environment Setup”Using Multipass (or any 3+ Linux VMs):
# Create VMsfor i in 1 2 3; do multipass launch --name k0s-ctrl-$i --cpus 2 --memory 2G --disk 10Gdone
for i in 1 2; do multipass launch --name k0s-worker-$i --cpus 2 --memory 2G --disk 10Gdone
# Get IP addressesmultipass listStep 1: Install k0sctl
Section titled “Step 1: Install k0sctl”# Download k0sctlcurl -sSLf https://github.com/k0sproject/k0sctl/releases/latest/download/k0sctl-linux-amd64 -o k0sctlchmod +x k0sctlsudo mv k0sctl /usr/local/bin/
# Verifyk0sctl versionStep 2: Prepare SSH Access
Section titled “Step 2: Prepare SSH Access”# Copy your SSH key to all nodes (if using Multipass)# Multipass uses its own authentication, so we'll use shell access instead
# For real VMs, ensure SSH key access:# for host in ctrl-1 ctrl-2 ctrl-3 worker-1 worker-2; do# ssh-copy-id root@$host# doneStep 3: Create Cluster Configuration
Section titled “Step 3: Create Cluster Configuration”# Get VM IPsCTRL1_IP=$(multipass info k0s-ctrl-1 | grep IPv4 | awk '{print $2}')CTRL2_IP=$(multipass info k0s-ctrl-2 | grep IPv4 | awk '{print $2}')CTRL3_IP=$(multipass info k0s-ctrl-3 | grep IPv4 | awk '{print $2}')WORKER1_IP=$(multipass info k0s-worker-1 | grep IPv4 | awk '{print $2}')WORKER2_IP=$(multipass info k0s-worker-2 | grep IPv4 | awk '{print $2}')
# For Multipass, we'll do manual install. For real VMs:cat > k0sctl.yaml <<EOFapiVersion: k0sctl.k0sproject.io/v1beta1kind: Clustermetadata: name: ha-k0s-demospec: hosts: - ssh: address: ${CTRL1_IP} user: root keyPath: ~/.ssh/id_rsa role: controller privateInterface: eth0 - ssh: address: ${CTRL2_IP} user: root keyPath: ~/.ssh/id_rsa role: controller privateInterface: eth0 - ssh: address: ${CTRL3_IP} user: root keyPath: ~/.ssh/id_rsa role: controller privateInterface: eth0 - ssh: address: ${WORKER1_IP} user: root keyPath: ~/.ssh/id_rsa role: worker - ssh: address: ${WORKER2_IP} user: root keyPath: ~/.ssh/id_rsa role: worker k0s: version: v1.28.5+k0s.0 config: spec: api: sans: - ${CTRL1_IP} - ${CTRL2_IP} - ${CTRL3_IP} network: provider: kube-router extensions: helm: charts: - name: metrics-server chartname: metrics-server/metrics-server namespace: kube-system values: | args: - --kubelet-insecure-tlsEOF
# For this exercise with Multipass, we'll do manual deploymentStep 4: Manual Installation (Multipass)
Section titled “Step 4: Manual Installation (Multipass)”Since Multipass doesn’t support direct SSH, we’ll install manually:
# On first controllermultipass shell k0s-ctrl-1curl -sSLf https://get.k0s.sh | sudo shsudo k0s install controllersudo k0s start# Wait for it to startsleep 30sudo k0s status# Create join tokenssudo k0s token create --role=controller > /tmp/controller-tokensudo k0s token create --role=worker > /tmp/worker-tokencat /tmp/controller-tokencat /tmp/worker-tokenexit
# Copy tokens (get them from the output above)# CONTROLLER_TOKEN="..."# WORKER_TOKEN="..."
# On controller 2multipass shell k0s-ctrl-2curl -sSLf https://get.k0s.sh | sudo sh# Use the controller token from ctrl-1echo "PASTE_CONTROLLER_TOKEN_HERE" | sudo tee /tmp/tokensudo k0s install controller --token-file /tmp/tokensudo k0s startexit
# On controller 3multipass shell k0s-ctrl-3curl -sSLf https://get.k0s.sh | sudo shecho "PASTE_CONTROLLER_TOKEN_HERE" | sudo tee /tmp/tokensudo k0s install controller --token-file /tmp/tokensudo k0s startexit
# On workersmultipass shell k0s-worker-1curl -sSLf https://get.k0s.sh | sudo shecho "PASTE_WORKER_TOKEN_HERE" | sudo tee /tmp/tokensudo k0s install worker --token-file /tmp/tokensudo k0s startexit
multipass shell k0s-worker-2curl -sSLf https://get.k0s.sh | sudo shecho "PASTE_WORKER_TOKEN_HERE" | sudo tee /tmp/tokensudo k0s install worker --token-file /tmp/tokensudo k0s startexitStep 5: Verify Cluster
Section titled “Step 5: Verify Cluster”# Get kubeconfig from any controllermultipass shell k0s-ctrl-1sudo k0s kubeconfig admin# Copy the output
# On your local machinecat > ~/.kube/k0s-config << 'EOF'# Paste kubeconfig hereEOF
export KUBECONFIG=~/.kube/k0s-config
# Check nodeskubectl get nodes
# Check etcd membersmultipass exec k0s-ctrl-1 -- sudo k0s etcd member-list
# Check podskubectl get pods -AStep 6: Deploy Test Application
Section titled “Step 6: Deploy Test Application”# Create deploymentkubectl create deployment nginx --image=nginx --replicas=3
# Check pods are on workerskubectl get pods -o wide
# Expose with servicekubectl expose deployment nginx --port=80 --type=ClusterIP
# Test connectivitykubectl run test --image=busybox --rm -it --restart=Never -- wget -qO- nginxStep 7: Test Controller Failover
Section titled “Step 7: Test Controller Failover”# Stop one controllermultipass stop k0s-ctrl-1
# Check cluster is still operationalkubectl get nodeskubectl get pods -A
# etcd should still have quorum (2/3)
# Bring controller backmultipass start k0s-ctrl-1sleep 30
# Verify rejoinkubectl get nodesSuccess Criteria
Section titled “Success Criteria”- 3 controller nodes running
- 2 worker nodes joined
- etcd cluster healthy (3 members)
- Application deployed to workers
- Cluster survives controller failure
- Failed controller rejoins
Cleanup
Section titled “Cleanup”# Stop and delete VMsfor i in 1 2 3; do multipass delete k0s-ctrl-$idonefor i in 1 2; do multipass delete k0s-worker-$idonemultipass purgeKey Takeaways
Section titled “Key Takeaways”- True zero dependencies: containerd embedded—nothing to pre-install
- Clean separation: Controllers don’t run workloads (by design)
- All state in /var/lib/k0s: Clean install, clean uninstall
- k0sctl automates everything: Use it for multi-node clusters
- kube-router provides CNI + service proxy: All networking in one
- Helm extension for add-ons: Declarative chart installation
- Cluster API support: Enterprise-grade cluster management
- Multiple storage backends: etcd, SQLite, MySQL, PostgreSQL
- Backup built-in:
k0s backupfor disaster recovery - Same binary everywhere: Works on any Linux distribution
Next Module
Section titled “Next Module”Continue to Module 14.3: MicroK8s — Canonical’s snap-based Kubernetes with rich add-ons.
“k0s achieves what Kubernetes always promised but never delivered: download one thing, run Kubernetes.”