feat: manage node-level kernel sysctls on the k3s scheduler

Sysctls the kernel does not namespace, such as `vm.max_map_count`, cannot be set from a pod spec and previously had no answer beyond editing `/etc/sysctl.d` on each host by hand. `scheduler-k3s:node-sysctls:set` now applies them through a privileged daemonset, which reaches nodes joined later and reapplies after a reboot. Sysctls may be scoped to a node profile, with a profile scope inheriting the global values and overriding them on conflict so that every node is covered by exactly one daemonset. Clearing a sysctl stops dokku managing it but does not restore the previous value, which persists until the node reboots.
This commit is contained in:
Jose Diaz-Gonzalez
2026-08-07 02:46:30 -04:00
parent cd1089500b
commit 44cd566178
12 changed files with 964 additions and 20 deletions

View File

@@ -30,6 +30,8 @@ Additional commands:`
scheduler-k3s:initialize [--server-ip SERVER_IP] [--taint-scheduling] [--kubelet-args KUBELET_ARGS], Initializes a cluster
scheduler-k3s:labels:set <app|--global> <property> (<value>) [--process-type PROCESS_TYPE] <--resource-type RESOURCE_TYPE>, Set or clear a label for a given app/process-type/resource-type combination
scheduler-k3s:labels:report [<app>|--global] [--format stdout|json] [--process-type PROCESS_TYPE] [--resource-type RESOURCE_TYPE], Displays a scheduler-k3s labels report for one or more apps
scheduler-k3s:node-sysctls:set <sysctl> (<value>) [--global|--profile PROFILE], Set or clear a node-level kernel sysctl for unprofiled nodes or a single node profile
scheduler-k3s:node-sysctls:report [--format stdout|json], Displays the node-level kernel sysctls applied to each scope
scheduler-k3s:preview <app> [--context N] [--show-secrets] [--show-secrets-decoded], Displays a diff between the current and next deployment for an app
scheduler-k3s:profiles:add <profile> [--role ROLE] [--insecure-allow-unknown-hosts] [--taint-scheduling] [--kubelet-args KUBELET_ARGS], Adds a node profile to the k3s cluster
scheduler-k3s:profiles:list [--format json|stdout], Lists all node profiles in the k3s cluster

View File

@@ -164,6 +164,23 @@ func main() {
appName = "--global"
}
err = scheduler_k3s.CommandLabelsReport(appName, *format, *processType, *resourceType, infoFlag)
case "node-sysctls:set":
args := flag.NewFlagSet("scheduler-k3s:node-sysctls:set", flag.ExitOnError)
global := args.Bool("global", false, "--global: scope to all nodes without a node profile")
profileName := args.String("profile", "", "--profile: scope to a node profile instead of all unprofiled nodes")
args.Parse(os.Args[2:])
key := args.Arg(0)
value := args.Arg(1)
if *global && *profileName != "" {
err = fmt.Errorf("Only one of --global and --profile may be specified")
break
}
err = scheduler_k3s.CommandNodeSysctlsSet(*profileName, key, value)
case "node-sysctls:report":
args := flag.NewFlagSet("scheduler-k3s:node-sysctls:report", flag.ExitOnError)
format := args.String("format", "stdout", "format: [ stdout | json ]")
args.Parse(os.Args[2:])
err = scheduler_k3s.CommandNodeSysctlsReport(*format)
case "preview":
args := flag.NewFlagSet("scheduler-k3s:preview", flag.ExitOnError)
context := args.Int("context", 3, "--context: number of unchanged lines of context around each change (-1 for full output)")