installers.virt.kubernetes_installer #
K3s Installer
Complete K3s cluster installer with multi-master HA support, worker nodes, and Mycelium IPv6 networking.
Features
- Multi-Master HA: Install multiple master nodes with
--cluster-init - Worker Nodes: Add worker nodes to the cluster
- Mycelium IPv6: Automatic detection of Mycelium IPv6 addresses from the 400::/7 range
- Lifecycle Management: Start, stop, restart K3s via startupmanager (systemd/zinit/screen)
- Join Scripts: Auto-generate heroscripts for joining additional nodes
- Complete Cleanup: Destroy removes all K3s components, network interfaces, and data
Quick Start
Install First Master
import incubaid.herolib.installers.virt.kubernetes_installer
heroscript := '
!!kubernetes_installer.configure
name:'k3s_master_1'
k3s_version:'v1.33.1'
node_name:'master-1'
mycelium_interface:'mycelium0'
!!kubernetes_installer.install_master name:'k3s_master_1'
!!kubernetes_installer.start name:'k3s_master_1'
'
kubernetes_installer.play(heroscript: heroscript)!
Join Additional Master (HA)
heroscript := '
!!kubernetes_installer.configure
name:'k3s_master_2'
node_name:'master-2'
token:'<TOKEN_FROM_FIRST_MASTER>'
master_url:'https://[<MASTER_IPV6>]:6443'
!!kubernetes_installer.join_master name:'k3s_master_2'
!!kubernetes_installer.start name:'k3s_master_2'
'
kubernetes_installer.play(heroscript: heroscript)!
Install Worker Node
heroscript := '
!!kubernetes_installer.configure
name:'k3s_worker_1'
node_name:'worker-1'
token:'<TOKEN_FROM_FIRST_MASTER>'
master_url:'https://[<MASTER_IPV6>]:6443'
!!kubernetes_installer.install_worker name:'k3s_worker_1'
!!kubernetes_installer.start name:'k3s_worker_1'
'
kubernetes_installer.play(heroscript: heroscript)!
Configuration Options
| Field | Type | Default | Description |
|---|---|---|---|
name |
string | 'default' | Instance name |
k3s_version |
string | 'v1.33.1' | K3s version to install |
data_dir |
string | '~/hero/var/k3s' | Data directory for K3s |
node_name |
string | hostname | Unique node identifier |
mycelium_interface |
string | auto-detected | Mycelium interface name (auto-detected from 400::/7 route) |
token |
string | auto-generated | Cluster authentication token |
master_url |
string | - | Master URL for joining (e.g., 'https://[ipv6]:6443') |
node_ip |
string | auto-detected | Node IPv6 (auto-detected from Mycelium) |
Actions
Installation Actions
install_master- Install first master node (generates token, uses --cluster-init)join_master- Join as additional master (requires token + master_url)install_worker- Install worker node (requires token + master_url)
Lifecycle Actions
start- Start K3s via startupmanagerstop- Stop K3srestart- Restart K3sdestroy- Complete cleanup (removes all K3s components)
Utility Actions
get_kubeconfig- Get kubeconfig contentgenerate_join_script- Generate heroscript for joining nodes
Requirements
- OS: Ubuntu (installer checks and fails on non-Ubuntu systems)
- Mycelium: Must be installed and running with interface in 400::/7 range
- Root Access: Required for installing system packages and managing network
How It Works
Mycelium IPv6 Detection
The installer automatically detects your Mycelium IPv6 address by:
- Finding the 400::/7 route via the Mycelium interface
- Extracting the next-hop IPv6 and getting the prefix (first 4 segments)
- Matching global IPv6 addresses on the interface with the same prefix
- Using the matched IPv6 for K3s
--node-ip
This ensures K3s binds to the correct Mycelium IPv6 even if the server has other IPv6 addresses.
Cluster Setup
First Master:
- Uses
--cluster-initflag - Auto-generates secure token
- Configures IPv6 CIDRs: cluster=2001:cafe:42::/56, service=2001:cafe:43::/112
- Generates join script for other nodes
Additional Masters:
- Joins with
--server <master_url> - Requires token and master_url from first master
- Provides HA for control plane
Workers:
- Joins as agent with
--server <master_url> - Requires token and master_url from first master
Cleanup
The destroy action performs complete cleanup:
- Stops K3s process
- Removes network interfaces (cni0, flannel.*, etc.)
- Unmounts kubelet mounts
- Removes data directory
- Cleans up iptables/ip6tables rules
- Removes CNI namespaces
Example Workflow
- Install first master on server1:
hero run templates/examples.heroscript
##
- Join additional master on server2:
##hero run templates/examples.heroscript
- Add worker on server3:
##hero run templates/examples.heroscript
- Verify cluster:
kubectl get nodes
kubectl get pods --all-namespaces
Kubeconfig
The kubeconfig is located at: <data_dir>/server/cred/admin.kubeconfig
To use kubectl:
export KUBECONFIG=~/hero/var/k3s/server/cred/admin.kubeconfig
kubectl get nodes
Or copy to default location:
mkdir -p ~/.kube
cp ~/hero/var/k3s/server/cred/admin.kubeconfig ~/.kube/config
Troubleshooting
K3s won't start:
- Check if Mycelium is running:
ip -6 addr show mycelium0 - Verify 400::/7 route exists:
ip -6 route | grep 400::/7 - Check logs:
journalctl -u k3s_* -f
Can't join cluster:
- Verify token matches first master
- Ensure master_url uses correct IPv6 in brackets:
https://[ipv6]:6443 - Check network connectivity over Mycelium:
ping6 <master_ipv6>
Cleanup issues:
- Run destroy with sudo if needed
- Manually check for remaining processes:
pgrep -f k3s - Check for remaining mounts:
mount | grep k3s
See Also
Constants #
const version = 'v1.33.1'
fn delete #
fn delete(args ArgsGet) !
fn exists #
fn exists(args ArgsGet) !bool
does the config exists?
fn get #
fn get(args ArgsGet) !&KubernetesInstaller
fn heroscript_dumps #
fn heroscript_dumps(obj KubernetesInstaller) !string
///////////NORMALLY NO NEED TO TOUCH
fn heroscript_loads #
fn heroscript_loads(heroscript string) !KubernetesInstaller
fn list #
fn list(args ArgsList) ![]&KubernetesInstaller
if fromdb set: load from filesystem, and not from mem, will also reset what is in mem
fn new #
fn new(args ArgsGet) !&KubernetesInstaller
fn play #
fn play(mut plbook PlayBook) !
fn set #
fn set(o KubernetesInstaller) !
register the config for the future
fn switch #
fn switch(name string)
switch instance to be used for kubernetes_installer
struct ArgsGet #
struct ArgsGet {
pub mut:
name string = 'default'
fromdb bool // will load from filesystem
create bool // default will not create if not exist
}
///////FACTORY
struct ArgsList #
struct ArgsList {
pub mut:
fromdb bool // will load from filesystem
}
struct InstallArgs #
struct InstallArgs {
pub mut:
reset bool
}
struct KubernetesInstaller #
struct KubernetesInstaller {
pub mut:
name string = 'default'
// K3s version to install
k3s_version string = version
// Data directory for K3s (default: ~/hero/var/k3s)
data_dir string
// Unique node name/identifier
node_name string
// Mycelium interface name (auto-detected if not specified)
mycelium_interface string
// Cluster token for authentication (auto-generated if empty)
token string
// Master URL for joining cluster (e.g., 'https://[ipv6]:6443')
master_url string
// Node IPv6 address (auto-detected from Mycelium if empty)
node_ip string
// Is this a master/control-plane node?
is_master bool
// Is this the first master (uses --cluster-init)?
is_first_master bool
}
K3s installer - handles K3s cluster installation with Mycelium IPv6 networking
fn (KubernetesInstaller) destroy #
fn (mut self KubernetesInstaller) destroy() !
fn (KubernetesInstaller) generate_join_script #
fn (self &KubernetesInstaller) generate_join_script() !string
Generate join script for other nodes
fn (KubernetesInstaller) get_kubeconfig #
fn (self &KubernetesInstaller) get_kubeconfig() !string
Get kubeconfig content
fn (KubernetesInstaller) get_mycelium_ipv6 #
fn (self &KubernetesInstaller) get_mycelium_ipv6() !string
Get Mycelium IPv6 address from interface
fn (KubernetesInstaller) install #
fn (mut self KubernetesInstaller) install(args InstallArgs) !
fn (KubernetesInstaller) install_master #
fn (mut self KubernetesInstaller) install_master() !
Install first master node
fn (KubernetesInstaller) install_start #
fn (mut self KubernetesInstaller) install_start(args InstallArgs) !
fn (KubernetesInstaller) install_worker #
fn (mut self KubernetesInstaller) install_worker() !
Install worker node
fn (KubernetesInstaller) join_master #
fn (mut self KubernetesInstaller) join_master() !
Join as additional master
fn (KubernetesInstaller) kubeconfig_path #
fn (self &KubernetesInstaller) kubeconfig_path() string
Get path to kubeconfig file
fn (KubernetesInstaller) reload #
fn (mut self KubernetesInstaller) reload() !
load from disk and make sure is properly intialized
fn (KubernetesInstaller) restart #
fn (mut self KubernetesInstaller) restart() !
fn (KubernetesInstaller) running #
fn (mut self KubernetesInstaller) running() !bool
fn (KubernetesInstaller) start #
fn (mut self KubernetesInstaller) start() !
fn (KubernetesInstaller) stop #
fn (mut self KubernetesInstaller) stop() !