Featured image of post K3s: Lightweight Kubernetes for Go Developers

K3s: Lightweight Kubernetes for Go Developers

Lightweight Kubernetes.

A Comprehensive Guide to k3s: Lightweight Kubernetes for Modern Applications

Introduction

k3s is a lightweight Kubernetes distribution designed to simplify the deployment and management of containerized applications in resource-constrained environments. With 32,454 stars on GitHub, it has become a popular choice for developers seeking a bare-metal or edge computing-friendly Kubernetes solution. Unlike full-featured Kubernetes distributions, k3s focuses on simplicity, speed, and minimal resource overhead, making it ideal for scenarios where traditional Kubernetes clusters would be overkill.

Developers should care about k3s because it bridges the gap between simplicity and scalability. It retains the full power of Kubernetes APIs while requiring fewer resources—often running on a single machine with as little as 512MB RAM. This makes it perfect for IoT deployments, edge computing, or small-scale microservices. Real-world use cases include deploying machine learning models on edge devices, running lightweight CI/CD pipelines, or hosting internal tools without the complexity of a full cluster.

k3s solves problems like slow startup times, high memory usage, and configuration complexity. Its ability to integrate with standard Kubernetes tooling (like kubectl and Helm) while offering a streamlined experience makes it a pragmatic choice for teams needing Kubernetes functionality without the overhead.


Key Features

1. Ultra-Lightweight Binary

k3s is a single binary (~40MB) that includes the Kubernetes control plane, API server, and essential add-ons. This eliminates the need for complex cluster setup scripts or dependency management. Compared to running vanilla Kubernetes from source or third-party distributions, k3s simplifies deployment to a single command: ./k3s.

2. Fast Boot Time

k3s starts in seconds, making it ideal for dynamic environments. Traditional Kubernetes clusters can take minutes to initialize, but k3s reduces this to under 30 seconds. This is critical for edge devices or environments where clusters need to spin up rapidly.

3. Standard Kubernetes API Compatibility

k3s fully implements the Kubernetes API, allowing developers to use kubectl, Helm, and other tools without modification. This ensures seamless integration with existing workflows. For example, you can deploy a Helm chart to a k3s cluster just as you would to a standard Kubernetes cluster.

4. Built-in Add-ons

k3s includes popular add-ons like Ingress, LoadBalancer, and Storage drivers by default. These are optional in standard Kubernetes and require manual configuration. For instance, setting up an Ingress controller in k3s is as simple as enabling it during cluster creation.

5. Low Resource Footprint

k3s is optimized for minimal resource usage. It can run on a machine with 512MB RAM and 1GB storage, making it suitable for edge nodes or IoT devices. This contrasts with full Kubernetes clusters, which often require 2-4GB of RAM per node.

6. Security Features

k3s includes tools like k3sctl for secure cluster management and supports TLS encryption by default. It also integrates with common security tools like Falco for runtime security monitoring.

7. Customizable Configuration

k3s allows fine-grained control over cluster settings via a YAML file (k3s.yaml). You can adjust memory limits, storage drivers, and network settings without rebuilding the binary.


Installation and Setup

Installation Command

To install k3s, run:

1go get github.com/k3s-io/[email protected]

This fetches the latest stable version (as of writing). Ensure you have Go 1.18+ installed.

Configuration

Create a k3s.yaml file to customize cluster settings:

1apiVersion: k3s-io/k3s-v1alpha1
2kind: K3s
3network:
4  podSubnet: 10.244.0.0/16
5volumes:
6  - /var/lib/k3s:/var/lib/k3s

Run the cluster with:

1./k3s --config=k3s.yaml

This starts the k3s server on port 6443.

Verification

Check the cluster status with:

1kubectl get nodes

You should see a Ready node.


Basic Usage: Creating a Pod

Minimal “Hello World” Example

This example creates a pod that runs a simple command:

 1package main
 2
 3import (
 4    "context"
 5    "fmt"
 6    "log"
 7
 8    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 9    corev1 "k8s.io/apimachinery/pkg/apis/core/v1"
10    k3s "github.com/k3s-io/k3s"
11)
12
13func main() {
14    // Initialize k3s client (point to your cluster IP)
15    client, err := k3s.NewClient("http://192.168.1.100:6443") // Replace with your cluster IP
16    if err != nil {
17        log.Fatalf("Failed to connect to k3s: %v", err)
18    }
19
20    // Create a pod
21    pod := &corev1.Pod{
22        ObjectMeta: metav1.ObjectMeta{
23            Name: "hello-pod",
24        },
25        Spec: corev1.PodSpec{
26            Containers: []corev1.Container{
27                {
28                    Name:  "busybox",
29                    Image: "busybox",
30                    Command: []string{"/bin/sh", "-c", "echo 'Hello from k3s!'; sleep 3600"},
31                },
32            },
33        },
34    }
35
36    // Create the pod
37    _, err = client.CoreV1().Pods("default").Create(context.TODO(), pod, metav1.CreateOptions{})
38    if err != nil {
39        log.Fatalf("Failed to create pod: %v", err)
40    }
41
42    fmt.Println("Pod created successfully!")
43}

Explanation

  1. Client Initialization: Connects to the k3s API server.
  2. Pod Definition: Defines a pod with a single container running a Bash command.
  3. API Call: Uses the k3s client to create the pod in the default namespace.

Expected Output

1Pod created successfully!

You can verify the pod with:

1kubectl get pods

Real-World Example: Deploying a Web Service

Complete Production-Ready Example

This example deploys a simple web service with an Ingress controller:

 1package main
 2
 3import (
 4    "context"
 5    "fmt"
 6    "log"
 7
 8    corev1 "k8s.io/apimachinery/pkg/apis/core/v1"
 9    networkingv1 "k8s.io/apimachinery/pkg/apis/networking/v1"
10    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11    k3s "github.com/k3s-io/k3s"
12)
13
14func main() {
15    client, err := k3s.NewClient("http://k3s-server:6443")
16    if err != nil {
17        log.Fatalf("k3s client error: %v", err)
18    }
19
20    // 1. Deploy a Deployment
21    deployment := &corev1.Deployment{
22        ObjectMeta: metav1.ObjectMeta{Name: "my-webapp"},
23        Spec: corev1.DirectorSpec{
24            Replicas: &int32(2),
25            Template: corev1.PodTemplateSpec{
26                Spec: corev1.PodSpec{
27                    Containers: []corev1.Container{
28                        {
29                            Name:  "web",
30                            Image: "nginx:latest",
31                            Ports: []corev1.ContainerPort{{ContainerPort: 80}},
32                        },
33                    },
34                },
35            },
36        },
37    }
38    _, err = client.AppsV1().Deployments("default").Create(context.TODO(), deployment, metav1.CreateOptions{})
39    if err != nil {
40        log.Fatalf("Deployment error: %v", err)
41    }
42
43    // 2. Create a Service
44    service := &corev1.Service{
45        ObjectMeta: metav1.ObjectMeta{Name: "my-webapp-service"},
46        Spec: corev1.ServiceSpec{
47            Type: corev1.ServiceTypeLoadBalancer,
48            Ports: []corev1.ServicePort{{
49                Port:       80,
50                TargetPort: corev1.PortName("http"),
51            }},
52            Selector: map[string]string{"app": "my-webapp"},
53        },
54    }
55    _, err = client.CoreV1().Services("default").Create(context.TODO(), service, metav1.CreateOptions{})
56    if err != nil {
57        log.Fatalf("Service error: %v", err)
58    }
59
60    // 3. Create an Ingress
61    ingress := &networkingv1.Ingress{
62        ObjectMeta: metav1.ObjectMeta{Name: "my-ingress"},
63        Spec: networkingv1.IngressSpec{
64            Rules: []networkingv1.IngressRule{{
65                Host: "example.com",
66                IngressRuleValue: networkingv1.IngressRuleValue{
67                    Path: &networkingv1.PathValue{Path: "/"},
68                    Backend: &networkingv1.IngressBackend{
69                        Service: &networkingv1.ServiceReference{Name: "my-webapp-service", Port: intstr.FromInt(80)},
70                    },
71                },
72            }},
73        },
74    }
75    _, err = client.NetworkingV1().Ingresses("default").Create(context.TODO(), ingress, metav1.CreateOptions{})
76    if err != nil {
77        log.Fatalf("Ingress error: %v", err)
78    }
79
80    fmt.Println("Web service deployed with Ingress!")
81}

Explanation

  1. Deployment: Deploys two replicas of an Nginx container.
  2. Service: Exposes
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy