NAME
Rex::Rancher::Server - Rancher Kubernetes server (control plane) installation
VERSION
version 0.001
SYNOPSIS
use Rex::Rancher::Server;
# Install RKE2 server (default)
install_server(
token => 'my-cluster-secret',
tls_san => ['lb.example.com'],
);
# Install K3s server
install_server(
distribution => 'k3s',
token => 'my-cluster-secret',
tls_san => ['lb.example.com'],
);
# Join additional control plane node (HA setup)
install_server(
distribution => 'rke2',
token => 'my-cluster-secret',
server => 'https://first-server:9345',
);
# Retrieve kubeconfig and join token from a running server
my $kubeconfig = get_kubeconfig('rke2');
my $token = get_token('rke2');
# Update registry mirrors on an already-running node
update_registries(
distribution => 'rke2',
registries => {
mirrors => { 'docker.io' => { endpoint => ['http://cache:5000'] } },
},
);
DESCRIPTION
Rex::Rancher::Server handles control plane installation for both RKE2 and K3s Kubernetes distributions. It provides a unified interface for installing, configuring, and managing server nodes.
RKE2 installation
The official install script at https://get.rke2.io is fetched and run via curl -sfL … | sh -. The service is started with --no-block to avoid systemd's 90-second activation timeout (RKE2's first start pulls many container images). The function waits only until the kubeconfig file appears at /etc/rancher/rke2/rke2.yaml; API readiness is confirmed separately by the caller using "wait_for_api" in Rex::Rancher::K8s.
K3s installation
The official install script at https://get.k3s.io is used with K3S_TOKEN and optionally K3S_URL environment variables. Traefik and ServiceLB are disabled by default to leave room for Cilium and external load balancers.
Config layout
Both distributions use /etc/rancher/<dist>/config.yaml with the same key names (token, tls-san, node-label, cni, etc.). When cilium => 1 (the default), cni: none and disable-kube-proxy: true are written so that Cilium's kube-proxy replacement is used.
Registry mirrors are written to registries.yaml in the same directory.
FUNCTIONS
install_server(%opts)
Write the cluster configuration file, optionally write registries.yaml, install the distribution, start the service, and wait until the kubeconfig file is written to disk by the server process.
Returns 1 on success. Dies if installation fails or the distribution is unknown.
Options:
distribution-
rke2(default) ork3s. token-
Shared secret used for node joining. Auto-generated (48 random base64 chars) if omitted.
server-
URL of an existing server node to join. Used for multi-server HA setups (omit for the first/only server). For RKE2 the port is
9345; for K3s it is6443. tls_san-
Additional TLS Subject Alternative Names for the API server certificate, as an arrayref or a comma-separated string. Include the load balancer address, public IP, or DNS name so that kubeconfig clients can connect.
node_labels-
Node labels applied at join time, as an arrayref of
key=valuestrings. registries-
Private registry mirror configuration. Written to
registries.yamlin the distribution config directory. Structure:{ mirrors => { 'docker.io' => { endpoint => ['http://registry.internal:5000'] }, }, configs => { 'registry.internal:5000' => { auth => { username => 'user', password => 'pass' }, }, }, } cilium-
If true (default:
1), setcni: noneanddisable-kube-proxy: truein the server config, preparing the node for Cilium CNI with full kube-proxy replacement. Set to0to keep the distribution's default CNI (Canal for RKE2, Flannel for K3s).
install_server(
distribution => 'rke2',
token => 'my-cluster-secret',
tls_san => ['loadbalancer.example.com'],
node_labels => ['role=control-plane'],
);
update_registries(%opts)
Update registries.yaml on an already-running node and restart the distribution service to pick up the new registry mirror configuration.
Use this to add or change registry mirrors after the cluster is up — for example, after deploying an in-cluster registry that you want every node to use as a pull-through cache.
Required options:
registries-
Registry mirror hashref (same structure as
install_server'sregistriesoption).
Optional options:
distribution-
rke2(default) ork3s. Controls which service is restarted.
update_registries(
distribution => 'rke2',
registries => {
mirrors => {
'docker.io' => { endpoint => ['http://registry.internal:5000'] },
'registry.internal' => { endpoint => ['http://registry.internal:5000'] },
},
},
);
get_kubeconfig($distribution)
Read the kubeconfig file from the remote server and return its content as a string. The file is read directly via cat over SSH; no SFTP is used.
$distribution defaults to rke2.
Note: RKE2 and K3s both write https://127.0.0.1 as the server address. The caller is responsible for substituting the real server address before saving the kubeconfig for external use. "rancher_deploy_server" in Rex::Rancher performs this substitution automatically.
Dies if the file cannot be read.
get_token($distribution)
Read the node join token from the server and return it as a string (trailing newline stripped).
$distribution defaults to rke2.
The token is stored at:
Dies if the file cannot be read (e.g. server not yet started).
SEE ALSO
Rex::Rancher, Rex::Rancher::Node, Rex::Rancher::Agent, Rex::Rancher::Cilium, Rex::Rancher::K8s, Rex
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/rex-rancher/issues.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <getty@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.