diff --git a/inttest/Makefile b/inttest/Makefile index 7f878b624287..936970223988 100644 --- a/inttest/Makefile +++ b/inttest/Makefile @@ -73,6 +73,12 @@ check-addons: TIMEOUT=10m # Autopilot 3x3 HA test can take a while to run check-ap-ha3x3: export K0S_UPDATE_TO_VERSION ?= $(shell ../k0s version) +# Variant of ap-single that launches the controller with a non-default +# --status-socket and --data-dir, exercising the StatusSocketPath plumbing +# through the autopilot signal controllers (regression test for the +# hardcoded-default-socket bug). +check-ap-single-custom-socket: K0S_INTTEST_PACKAGE = ap-single + check-ap-updater: .update-server.stamp check-ap-updater-periodic: .update-server.stamp check-ap-updater-periodic: TIMEOUT=10m diff --git a/inttest/Makefile.variables b/inttest/Makefile.variables index fe8ff9647c89..097f663a7924 100644 --- a/inttest/Makefile.variables +++ b/inttest/Makefile.variables @@ -16,6 +16,7 @@ smoketests := \ check-ap-removedapis \ check-ap-selector \ check-ap-single \ + check-ap-single-custom-socket \ check-ap-updater \ check-ap-updater-periodic \ check-backup \ diff --git a/inttest/ap-single/single_test.go b/inttest/ap-single/single_test.go index 64877c8f915b..f643fa5fb7f7 100644 --- a/inttest/ap-single/single_test.go +++ b/inttest/ap-single/single_test.go @@ -4,6 +4,8 @@ package single import ( + "os" + "strings" "testing" apconst "github.com/k0sproject/k0s/pkg/autopilot/constant" @@ -18,8 +20,24 @@ import ( const ( ManifestTestDirPerms = "775" + + // customStatusSocketPath is a non-default socket location used by the + // "ap-single-custom-socket" target to verify that autopilot signal + // controllers honor --status-socket. Default would be /run/k0s/status.sock. + customStatusSocketPath = "/run/k0s/custom/status.sock" + // customDataDir places the data dir (and therefore many derived paths) in + // a non-default location, exercising the wider --data-dir surface. + customDataDir = "/var/lib/k0s-custom" ) +// useCustomStatusSocket reports whether the suite was invoked through the +// "ap-single-custom-socket" check target. Driven by K0S_INTTEST_TARGET, the +// same env-var convention used by other parameterized inttests +// (cplb-userspace, dualstack, network-conformance, ...). +func useCustomStatusSocket() bool { + return strings.Contains(os.Getenv("K0S_INTTEST_TARGET"), "custom-socket") +} + type plansSingleControllerSuite struct { common.BootlooseSuite } @@ -35,7 +53,19 @@ func (s *plansSingleControllerSuite) SetupTest() { defer ssh.Disconnect() require.NoError(ssh.Exec(ctx, "cp /dist/k0s /tmp/k0s", common.SSHStreams{})) - require.NoError(s.InitController(0, "--single", "--disable-components=metrics-server")) + args := []string{"--single", "--disable-components=metrics-server"} + if useCustomStatusSocket() { + // Pre-create the parent directories so k0s doesn't have to mkdir at + // odd paths during early boot. These match the flags below. + require.NoError(ssh.Exec(ctx, "mkdir -p /run/k0s/custom "+customDataDir, common.SSHStreams{})) + args = append(args, + "--status-socket="+customStatusSocketPath, + "--data-dir="+customDataDir, + ) + s.T().Logf("Launching controller with custom status socket %q and data dir %q", + customStatusSocketPath, customDataDir) + } + require.NoError(s.InitController(0, args...)) client, err := s.KubeClient(nodeName) require.NoError(err) @@ -97,6 +127,27 @@ spec: s.Empty(cmd.K0sUpdate.Workers) s.Equal(appc.SignalCompleted, cmd.K0sUpdate.Controllers[0].State) } + + if useCustomStatusSocket() { + // Defense against #3719: an AP test can report PlanCompleted even + // when the cluster is unhealthy. Cross-check that: + // 1. The custom status socket was actually created (the controller + // honored --status-socket). + // 2. The default /run/k0s/status.sock was NOT created (no caller + // fell back to the hardcoded path). + // If autopilot's signal controllers had still hardcoded the default + // path (the bug this PR fixes), step 2 would fail because the + // post-restart status probe would either create or contact the + // default socket location. + ssh, err := s.SSH(ctx, s.ControllerNode(0)) + s.Require().NoError(err) + defer ssh.Disconnect() + + s.NoError(ssh.Exec(ctx, "test -S "+customStatusSocketPath, common.SSHStreams{}), + "custom status socket %q should exist", customStatusSocketPath) + s.Error(ssh.Exec(ctx, "test -e /run/k0s/status.sock", common.SSHStreams{}), + "default status socket /run/k0s/status.sock should NOT exist when --status-socket is set") + } } // TestPlansSingleControllerSuite sets up a suite using a single controller, running various diff --git a/pkg/autopilot/controller/root/root.go b/pkg/autopilot/controller/root/root.go index 1ea6b5431b55..6471a9fa2203 100644 --- a/pkg/autopilot/controller/root/root.go +++ b/pkg/autopilot/controller/root/root.go @@ -12,6 +12,7 @@ type RootConfig struct { InvocationID string KubeConfig string K0sDataDir string + StatusSocketPath string KubeletExtraArgs string KubeAPIPort int Mode string diff --git a/pkg/autopilot/controller/root_controller.go b/pkg/autopilot/controller/root_controller.go index f54ccce19db2..28b6dfc02cba 100644 --- a/pkg/autopilot/controller/root_controller.go +++ b/pkg/autopilot/controller/root_controller.go @@ -21,6 +21,7 @@ import ( aproot "github.com/k0sproject/k0s/pkg/autopilot/controller/root" "github.com/k0sproject/k0s/pkg/autopilot/controller/signal" "github.com/k0sproject/k0s/pkg/autopilot/controller/updates" + k0sstatus "github.com/k0sproject/k0s/pkg/component/status" "github.com/k0sproject/k0s/pkg/kubernetes" "github.com/k0sproject/k0s/pkg/leaderelection" @@ -63,6 +64,9 @@ var _ aproot.Root = (*rootController)(nil) // NewRootController builds a root for autopilot "controller" operations. func NewRootController(cfg aproot.RootConfig, logger *logrus.Entry, enableWorker bool, acf apcli.FactoryInterface, clusterInfoCollector *updates.ClusterInfoCollector, apiAddress netip.Addr) (aproot.Root, error) { + if cfg.StatusSocketPath == "" { + cfg.StatusSocketPath = k0sstatus.DefaultSocketPath + } c := &rootController{ cfg: cfg, log: logger, @@ -237,7 +241,7 @@ func (c *rootController) startSubControllerRoutine(ctx context.Context, logger * } clusterID := string(ns.UID) - if err := signal.RegisterControllers(ctx, logger, mgr, delegateMap[apdel.ControllerDelegateController], c.cfg.K0sDataDir, c.enableWorker, clusterID, event, c.cfg.InvocationID); err != nil { + if err := signal.RegisterControllers(ctx, logger, mgr, delegateMap[apdel.ControllerDelegateController], c.cfg.K0sDataDir, c.cfg.StatusSocketPath, c.enableWorker, clusterID, event, c.cfg.InvocationID); err != nil { logger.WithError(err).Error("unable to register signal controllers") return err } @@ -247,7 +251,7 @@ func (c *rootController) startSubControllerRoutine(ctx context.Context, logger * return err } - if err := updates.RegisterControllers(ctx, logger, mgr, c.autopilotClientFactory, c.clusterInfoCollector, leaderMode, clusterID); err != nil { + if err := updates.RegisterControllers(ctx, logger, mgr, c.autopilotClientFactory, c.clusterInfoCollector, leaderMode, clusterID, c.cfg.StatusSocketPath); err != nil { logger.WithError(err).Error("unable to register updates controllers") return err } diff --git a/pkg/autopilot/controller/root_worker.go b/pkg/autopilot/controller/root_worker.go index 96402563c2d4..6b41b7962150 100644 --- a/pkg/autopilot/controller/root_worker.go +++ b/pkg/autopilot/controller/root_worker.go @@ -14,6 +14,7 @@ import ( apdel "github.com/k0sproject/k0s/pkg/autopilot/controller/delegate" aproot "github.com/k0sproject/k0s/pkg/autopilot/controller/root" "github.com/k0sproject/k0s/pkg/autopilot/controller/signal" + "github.com/k0sproject/k0s/pkg/component/status" "github.com/k0sproject/k0s/pkg/leaderelection" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -41,6 +42,9 @@ var _ aproot.Root = (*rootWorker)(nil) // NewRootWorker builds a root for autopilot "worker" operations. func NewRootWorker(cfg aproot.RootConfig, logger *logrus.Entry, cf apcli.FactoryInterface) (aproot.Root, error) { + if cfg.StatusSocketPath == "" { + cfg.StatusSocketPath = status.DefaultSocketPath + } c := &rootWorker{ cfg: cfg, log: logger, @@ -111,7 +115,7 @@ func (w *rootWorker) Run(ctx context.Context) error { return fmt.Errorf("unable to register indexers: %w", err) } - if err := signal.RegisterControllers(ctx, logger, mgr, apdel.NodeControllerDelegate(), w.cfg.K0sDataDir, true, clusterID, leaderelection.StatusPending, w.cfg.InvocationID); err != nil { + if err := signal.RegisterControllers(ctx, logger, mgr, apdel.NodeControllerDelegate(), w.cfg.K0sDataDir, w.cfg.StatusSocketPath, true, clusterID, leaderelection.StatusPending, w.cfg.InvocationID); err != nil { return fmt.Errorf("unable to register signal controllers: %w", err) } diff --git a/pkg/autopilot/controller/signal/init.go b/pkg/autopilot/controller/signal/init.go index 60dcee2de036..f427572f4c8e 100644 --- a/pkg/autopilot/controller/signal/init.go +++ b/pkg/autopilot/controller/signal/init.go @@ -21,8 +21,8 @@ import ( // RegisterControllers registers all of the autopilot controllers used by both controller // and worker modes. -func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Manager, delegate apdel.ControllerDelegate, k0sDataDir string, enableWorker bool, clusterID string, leaseStatus leaderelection.Status, invocationID string) error { - if err := k0s.RegisterControllers(ctx, logger, mgr, delegate, enableWorker, clusterID, leaseStatus, invocationID); err != nil { +func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Manager, delegate apdel.ControllerDelegate, k0sDataDir string, statusSocketPath string, enableWorker bool, clusterID string, leaseStatus leaderelection.Status, invocationID string) error { + if err := k0s.RegisterControllers(ctx, logger, mgr, delegate, statusSocketPath, enableWorker, clusterID, leaseStatus, invocationID); err != nil { return fmt.Errorf("unable to register k0s controllers: %w", err) } diff --git a/pkg/autopilot/controller/signal/k0s/init.go b/pkg/autopilot/controller/signal/k0s/init.go index 3c27be7cefba..0d1c3945e20c 100644 --- a/pkg/autopilot/controller/signal/k0s/init.go +++ b/pkg/autopilot/controller/signal/k0s/init.go @@ -30,7 +30,7 @@ import ( // RegisterControllers registers all of the autopilot controllers used for updating `k0s` // to the controller-runtime manager. -func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Manager, delegate apdel.ControllerDelegate, enableWorker bool, clusterID string, leaseStatus leaderelection.Status, invocationID string) error { +func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Manager, delegate apdel.ControllerDelegate, statusSocketPath string, enableWorker bool, clusterID string, leaseStatus leaderelection.Status, invocationID string) error { logger = logger.WithField("controller", delegate.Name()) hostname, err := apcomm.FindEffectiveHostname() @@ -47,7 +47,7 @@ func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Ma logger.Infof("Using effective hostname = '%v'", hostname) k0sVersionHandler := func() (string, error) { - return getK0sVersion(status.DefaultSocketPath) + return getK0sVersion(statusSocketPath) } if enableWorker { @@ -92,11 +92,11 @@ func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Ma return fmt.Errorf("unable to register applying-update controller: %w", err) } - if err := registerRestart(logger, mgr, restartEventFilter(hostname, apsigpred.DefaultErrorHandler(logger, "k0s restart")), delegate); err != nil { + if err := registerRestart(logger, mgr, restartEventFilter(hostname, apsigpred.DefaultErrorHandler(logger, "k0s restart")), delegate, statusSocketPath); err != nil { return fmt.Errorf("unable to register restart controller: %w", err) } - if err := registerRestarted(logger, mgr, restartedEventFilter(hostname, apsigpred.DefaultErrorHandler(logger, "k0s restarted")), delegate); err != nil { + if err := registerRestarted(logger, mgr, restartedEventFilter(hostname, apsigpred.DefaultErrorHandler(logger, "k0s restarted")), delegate, statusSocketPath); err != nil { return fmt.Errorf("unable to register restarted controller: %w", err) } diff --git a/pkg/autopilot/controller/signal/k0s/restart_unix.go b/pkg/autopilot/controller/signal/k0s/restart_unix.go index 16941eb5f630..442636fe4a0f 100644 --- a/pkg/autopilot/controller/signal/k0s/restart_unix.go +++ b/pkg/autopilot/controller/signal/k0s/restart_unix.go @@ -50,16 +50,17 @@ func restartEventFilter(hostname string, handler apsigpred.ErrorHandler) crpred. } type restart struct { - log *logrus.Entry - client crcli.Client - delegate apdel.ControllerDelegate + log *logrus.Entry + client crcli.Client + delegate apdel.ControllerDelegate + statusSocketPath string } // registerRestart registers the 'restart' controller to the controller-runtime manager. // // This controller is only interested in changes to signal nodes where its signaling // status is marked as `Restart` -func registerRestart(logger *logrus.Entry, mgr crman.Manager, eventFilter crpred.Predicate, delegate apdel.ControllerDelegate) error { +func registerRestart(logger *logrus.Entry, mgr crman.Manager, eventFilter crpred.Predicate, delegate apdel.ControllerDelegate, statusSocketPath string) error { name := strings.ToLower(delegate.Name()) + "_k0s_restart" logger.Info("Registering reconciler: ", name) @@ -69,9 +70,10 @@ func registerRestart(logger *logrus.Entry, mgr crman.Manager, eventFilter crpred WithEventFilter(eventFilter). Complete( &restart{ - log: logger.WithFields(logrus.Fields{"reconciler": "k0s-restart", "object": delegate.Name()}), - client: mgr.GetClient(), - delegate: delegate, + log: logger.WithFields(logrus.Fields{"reconciler": "k0s-restart", "object": delegate.Name()}), + client: mgr.GetClient(), + delegate: delegate, + statusSocketPath: statusSocketPath, }, ) } @@ -93,7 +95,7 @@ func (r *restart) Reconcile(ctx context.Context, req cr.Request) (cr.Result, err // Get the current version of k0s logger.Info("Determining the current version of k0s") - k0sVersion, err := getK0sVersion(status.DefaultSocketPath) + k0sVersion, err := getK0sVersion(r.statusSocketPath) if err != nil { logger.Info("Unable to determine current verion of k0s; requeuing") return cr.Result{}, fmt.Errorf("unable to get k0s version: %w", err) @@ -133,7 +135,7 @@ func (r *restart) Reconcile(ctx context.Context, req cr.Request) (cr.Result, err logger.Info("Preparing to restart k0s") - k0sPid, err := getK0sPid(status.DefaultSocketPath) + k0sPid, err := getK0sPid(r.statusSocketPath) if err != nil { logger.Info("Unable to determine current k0s pid; requeuing") return cr.Result{RequeueAfter: restartRequeueDuration}, fmt.Errorf("unable to get k0s pid: %w", err) diff --git a/pkg/autopilot/controller/signal/k0s/restarted_unix.go b/pkg/autopilot/controller/signal/k0s/restarted_unix.go index 9b777b84703e..a9687f047114 100644 --- a/pkg/autopilot/controller/signal/k0s/restarted_unix.go +++ b/pkg/autopilot/controller/signal/k0s/restarted_unix.go @@ -14,7 +14,6 @@ import ( apdel "github.com/k0sproject/k0s/pkg/autopilot/controller/delegate" apsigpred "github.com/k0sproject/k0s/pkg/autopilot/controller/signal/common/predicate" apsigv2 "github.com/k0sproject/k0s/pkg/autopilot/signaling/v2" - "github.com/k0sproject/k0s/pkg/component/status" "github.com/sirupsen/logrus" cr "sigs.k8s.io/controller-runtime" @@ -25,9 +24,10 @@ import ( ) type restarted struct { - log *logrus.Entry - client crcli.Client - delegate apdel.ControllerDelegate + log *logrus.Entry + client crcli.Client + delegate apdel.ControllerDelegate + statusSocketPath string } // restartedEventFilter creates a controller-runtime predicate that governs which @@ -51,7 +51,7 @@ func restartedEventFilter(hostname string, handler apsigpred.ErrorHandler) crpre // // This controller is only interested in changes to signal nodes where its signaling // status is marked as `Restart` -func registerRestarted(logger *logrus.Entry, mgr crman.Manager, eventFilter crpred.Predicate, delegate apdel.ControllerDelegate) error { +func registerRestarted(logger *logrus.Entry, mgr crman.Manager, eventFilter crpred.Predicate, delegate apdel.ControllerDelegate, statusSocketPath string) error { name := strings.ToLower(delegate.Name()) + "_k0s_restarted" logger.Info("Registering reconciler: ", name) @@ -61,9 +61,10 @@ func registerRestarted(logger *logrus.Entry, mgr crman.Manager, eventFilter crpr WithEventFilter(eventFilter). Complete( &restarted{ - log: logger.WithFields(logrus.Fields{"reconciler": "k0s-restarted", "object": delegate.Name()}), - client: mgr.GetClient(), - delegate: delegate, + log: logger.WithFields(logrus.Fields{"reconciler": "k0s-restarted", "object": delegate.Name()}), + client: mgr.GetClient(), + delegate: delegate, + statusSocketPath: statusSocketPath, }, ) } @@ -87,7 +88,7 @@ func (r *restarted) Reconcile(ctx context.Context, req cr.Request) (cr.Result, e // Get the current version of k0s logger.Info("Determining the current version of k0s") - k0sVersion, err := getK0sVersion(status.DefaultSocketPath) + k0sVersion, err := getK0sVersion(r.statusSocketPath) if err != nil { logger.Info("Unable to determine current verion of k0s; requeuing") return cr.Result{}, fmt.Errorf("unable to get k0s version: %w", err) diff --git a/pkg/autopilot/controller/updates/update_controller.go b/pkg/autopilot/controller/updates/update_controller.go index af646d1c0239..4cb789b5546a 100644 --- a/pkg/autopilot/controller/updates/update_controller.go +++ b/pkg/autopilot/controller/updates/update_controller.go @@ -23,10 +23,11 @@ import ( ) type updateController struct { - log *logrus.Entry - client crcli.Client - clientFactory apcli.FactoryInterface - collector *ClusterInfoCollector + log *logrus.Entry + client crcli.Client + clientFactory apcli.FactoryInterface + collector *ClusterInfoCollector + statusSocketPath string clusterID string @@ -34,19 +35,20 @@ type updateController struct { parentCtx context.Context } -func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Manager, clientFactory apcli.FactoryInterface, collector *ClusterInfoCollector, leaderMode bool, clusterID string) error { +func RegisterControllers(ctx context.Context, logger *logrus.Entry, mgr crman.Manager, clientFactory apcli.FactoryInterface, collector *ClusterInfoCollector, leaderMode bool, clusterID string, statusSocketPath string) error { return cr.NewControllerManagedBy(mgr). Named("updater"). For(&apv1beta2.UpdateConfig{}). Complete( &updateController{ - log: logger.WithField("reconciler", "updater"), - client: mgr.GetClient(), - clientFactory: clientFactory, - collector: collector, - clusterID: clusterID, - updaters: make(map[string]updater), - parentCtx: ctx, + log: logger.WithField("reconciler", "updater"), + client: mgr.GetClient(), + clientFactory: clientFactory, + collector: collector, + statusSocketPath: statusSocketPath, + clusterID: clusterID, + updaters: make(map[string]updater), + parentCtx: ctx, }, ) } @@ -94,7 +96,7 @@ func (u *updateController) Reconcile(ctx context.Context, req cr.Request) (cr.Re } u.log.Debugf("creating new updater for '%s'", req.NamespacedName) // Create new updater - updater, err := newUpdater(u.parentCtx, *updaterConfig, u.client, u.clientFactory, u.clusterID, u.collector, token) + updater, err := newUpdater(u.parentCtx, *updaterConfig, u.client, u.clientFactory, u.clusterID, u.collector, token, u.statusSocketPath) if err != nil { u.log.Errorf("failed to create updater for '%s': %s", req.NamespacedName, err) return cr.Result{}, err diff --git a/pkg/autopilot/controller/updates/updater.go b/pkg/autopilot/controller/updates/updater.go index b23382166c5f..fc68766b9f38 100644 --- a/pkg/autopilot/controller/updates/updater.go +++ b/pkg/autopilot/controller/updates/updater.go @@ -54,7 +54,7 @@ var patchOpts = []crcli.PatchOption{ crcli.ForceOwnership, } -func newUpdater(parentCtx context.Context, updateConfig apv1beta2.UpdateConfig, k8sClient crcli.Client, apClientFactory apcli.FactoryInterface, clusterID string, collector *ClusterInfoCollector, updateServerToken string) (updater, error) { +func newUpdater(parentCtx context.Context, updateConfig apv1beta2.UpdateConfig, k8sClient crcli.Client, apClientFactory apcli.FactoryInterface, clusterID string, collector *ClusterInfoCollector, updateServerToken string, statusSocketPath string) (updater, error) { updateClient, err := uc.NewClient(updateConfig.Spec.UpdateServer, updateServerToken) if err != nil { return nil, err @@ -62,7 +62,7 @@ func newUpdater(parentCtx context.Context, updateConfig apv1beta2.UpdateConfig, switch updateConfig.Spec.UpgradeStrategy.Type { case apv1beta2.UpdateStrategyTypeCron: - return newCronUpdater(parentCtx, updateConfig, k8sClient, clusterID, updateClient) + return newCronUpdater(parentCtx, updateConfig, k8sClient, clusterID, updateClient, statusSocketPath) case apv1beta2.UpdateStrategyTypePeriodic: return newPeriodicUpdater(parentCtx, updateConfig, k8sClient, apClientFactory, collector, build.Version), nil default: @@ -70,13 +70,13 @@ func newUpdater(parentCtx context.Context, updateConfig apv1beta2.UpdateConfig, } } -func newCronUpdater(parentCtx context.Context, updateConfig apv1beta2.UpdateConfig, k8sClient crcli.Client, clusterID string, updateClient uc.Client) (updater, error) { +func newCronUpdater(parentCtx context.Context, updateConfig apv1beta2.UpdateConfig, k8sClient crcli.Client, clusterID string, updateClient uc.Client, statusSocketPath string) (updater, error) { schedule := updateConfig.Spec.UpgradeStrategy.Cron if schedule == "" { schedule = defaultCronSchedule } - status, err := status.GetStatusInfo(status.DefaultSocketPath) + status, err := status.GetStatusInfo(statusSocketPath) if err != nil { return nil, err } diff --git a/pkg/component/controller/autopilot.go b/pkg/component/controller/autopilot.go index f9538c1b24ca..526935475698 100644 --- a/pkg/component/controller/autopilot.go +++ b/pkg/component/controller/autopilot.go @@ -66,6 +66,7 @@ func (a *Autopilot) Start(ctx context.Context) error { InvocationID: a.K0sVars.InvocationID, KubeConfig: a.K0sVars.AdminKubeConfigPath, K0sDataDir: a.K0sVars.DataDir, + StatusSocketPath: a.K0sVars.StatusSocketPath, KubeletExtraArgs: a.KubeletExtraArgs, KubeAPIPort: a.KubeAPIPort, Mode: "controller", diff --git a/pkg/component/worker/autopilot.go b/pkg/component/worker/autopilot.go index d7fc9a8d81fb..625517128ea2 100644 --- a/pkg/component/worker/autopilot.go +++ b/pkg/component/worker/autopilot.go @@ -76,6 +76,7 @@ func (a *Autopilot) Start(ctx context.Context) error { autopilotRoot, err := apcont.NewRootWorker(aproot.RootConfig{ KubeConfig: a.K0sVars.KubeletAuthConfigPath, K0sDataDir: a.K0sVars.DataDir, + StatusSocketPath: a.K0sVars.StatusSocketPath, Mode: "worker", ManagerPort: 8899, MetricsBindAddr: "0",