178 lines
4.9 KiB
Go
178 lines
4.9 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
monov1alpha1 "undecided.project/monok8s/pkg/apis/monok8s/v1alpha1"
|
|
"undecided.project/monok8s/pkg/node"
|
|
"undecided.project/monok8s/pkg/system"
|
|
)
|
|
|
|
type Runner struct {
|
|
NodeCtx *node.NodeContext
|
|
Registry *Registry
|
|
|
|
initSteps []StepInfo
|
|
}
|
|
|
|
type StepInfo struct {
|
|
RegKey string
|
|
Name string
|
|
Desc string
|
|
}
|
|
|
|
type StepSelection struct {
|
|
Indices []int // 1-based
|
|
}
|
|
|
|
func NewRunner(cfg *monov1alpha1.MonoKSConfig) *Runner {
|
|
runnerCfg := system.RunnerConfig{}
|
|
nctx := &node.NodeContext{
|
|
Config: cfg,
|
|
SystemRunner: system.NewRunner(runnerCfg),
|
|
}
|
|
return &Runner{
|
|
NodeCtx: nctx,
|
|
Registry: NewRegistry(nctx),
|
|
initSteps: []StepInfo{
|
|
{
|
|
RegKey: "ConfigureHostname",
|
|
Name: "Configure hostname",
|
|
Desc: "Set system hostname according to cluster configuration",
|
|
},
|
|
{
|
|
RegKey: "ConfigureMgmtInterface",
|
|
Name: "Configure management interface",
|
|
Desc: "Configure management network interface, IP address, and gateway",
|
|
},
|
|
{
|
|
RegKey: "ConfigureDNS",
|
|
Name: "Configure DNS",
|
|
Desc: "Set system DNS resolver configuration for cluster and external access",
|
|
},
|
|
{
|
|
RegKey: "EnsureIPForward",
|
|
Name: "Ensure IP forwarding",
|
|
Desc: "Enable kernel IP forwarding required for pod networking",
|
|
},
|
|
{
|
|
RegKey: "ConfigureDefaultCNI",
|
|
Name: "Configure default CNI",
|
|
Desc: "Install or configure default container networking (CNI bridge, IPAM, etc.)",
|
|
},
|
|
{
|
|
RegKey: "StartCRIO",
|
|
Name: "Start CRI-O runtime",
|
|
Desc: "Start container runtime and verify it is ready for Kubernetes workloads",
|
|
},
|
|
{
|
|
RegKey: "ValidateRequiredImagesPresent",
|
|
Name: "Validate required images",
|
|
Desc: "Ensure all required Kubernetes images are present or available locally",
|
|
},
|
|
{
|
|
RegKey: "ValidateNodeIPAndAPIServerReachability",
|
|
Name: "Validate Node IP and wether API Server is available",
|
|
Desc: "Verify the local ip address with the api server advertise address. Contact remote api server",
|
|
},
|
|
{
|
|
RegKey: "DetectLocalClusterState",
|
|
Name: "Detect local cluster state",
|
|
Desc: "Inspect local node to determine existing Kubernetes membership and configuration",
|
|
},
|
|
{
|
|
RegKey: "ClassifyBootstrapAction",
|
|
Name: "Classify bootstrap action",
|
|
Desc: "Decide whether to init, join, upgrade, or reconcile based on local state and desired version",
|
|
},
|
|
{
|
|
RegKey: "WaitForExistingClusterIfNeeded",
|
|
Name: "Wait for existing cluster",
|
|
Desc: "Block until control plane is reachable when joining or reconciling an existing cluster",
|
|
},
|
|
{
|
|
RegKey: "ReconcileControlPlane",
|
|
Name: "Reconcile control plane",
|
|
Desc: "Ensure control plane components match desired state without full reinitialization",
|
|
},
|
|
{
|
|
RegKey: "CheckUpgradePrereqs",
|
|
Name: "Check upgrade prerequisites",
|
|
Desc: "Validate cluster state and version compatibility before upgrade",
|
|
},
|
|
{
|
|
RegKey: "RunKubeadmUpgradeApply",
|
|
Name: "Run kubeadm upgrade apply",
|
|
Desc: "Upgrade control plane components using kubeadm",
|
|
},
|
|
{
|
|
RegKey: "RunKubeadmInit",
|
|
Name: "Run kubeadm init",
|
|
Desc: "Initialize a new Kubernetes control plane using kubeadm",
|
|
},
|
|
{
|
|
RegKey: "RunKubeadmJoin",
|
|
Name: "Run kubeadm join",
|
|
Desc: "Join node to existing cluster as worker or control-plane",
|
|
},
|
|
{
|
|
RegKey: "ReconcileNode",
|
|
Name: "Reconcile node state",
|
|
Desc: "Ensure node configuration matches desired state after join or upgrade",
|
|
},
|
|
{
|
|
RegKey: "RunKubeadmUpgradeNode",
|
|
Name: "Run kubeadm upgrade node",
|
|
Desc: "Upgrade node components (kubelet, config) to match control plane",
|
|
},
|
|
{
|
|
RegKey: "ApplyLocalNodeMetadataIfPossible",
|
|
Name: "Apply node metadata",
|
|
Desc: "Apply labels/annotations to the local node if API server is reachable",
|
|
},
|
|
{
|
|
RegKey: "AllowSingleNodeScheduling",
|
|
Name: "Allow single-node scheduling",
|
|
Desc: "Remove control-plane taints to allow workloads on single-node clusters",
|
|
},
|
|
{
|
|
RegKey: "PrintSummary",
|
|
Name: "Print summary",
|
|
Desc: "Output final bootstrap summary and detected state",
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func (r *Runner) RunNamedStep(ctx context.Context, name string) error {
|
|
step, err := r.Registry.Get(name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return step(ctx, r.NodeCtx)
|
|
}
|
|
|
|
func (r *Runner) InitSteps() []StepInfo {
|
|
return r.initSteps
|
|
}
|
|
|
|
func (r *Runner) Init(ctx context.Context) error {
|
|
for i, step := range r.initSteps {
|
|
if err := r.RunNamedStep(ctx, step.RegKey); err != nil {
|
|
return fmt.Errorf("step %d (%s): %w", i+1, step.Name, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *Runner) InitSelected(ctx context.Context, sel StepSelection) error {
|
|
for _, idx := range sel.Indices {
|
|
step := r.initSteps[idx-1]
|
|
if err := r.RunNamedStep(ctx, step.RegKey); err != nil {
|
|
return fmt.Errorf("step %d (%s): %w", idx, step.Name, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|