kubernetes/kubernetes · critical

unable to acquire file lock on %q: %w

Error message

unable to acquire file lock on %q: %w

What it means

From run() (server.go:701-702): flock.Acquire failed on --lock-file-path. The lock file enforces that only one kubelet runs per node (and supports --exit-on-lock-contention for self-termination on contention). Acquisition fails when the file cannot be created/opened or an existing holder won't release within the retry window.

Source

Thrown at cmd/kubelet/app/server.go:702

			kernelVersion, err := utilkernel.GetVersion()
			if err != nil {
				logger.Error(err, "Failed to detect kernel version for MemoryQoS compatibility check")
			} else if kernelVersion.LessThan(utilversion.MustParseGeneric(utilkernel.MemoryQoSMinKernelVersion)) {
				logger.Info("Warning: MemoryQoS memory.high throttling may cause process livelock on older kernels",
					"currentKernel", kernelVersion,
					"minimumKernel", utilkernel.MemoryQoSMinKernelVersion)
			}
		}
	}
	// Obtain Kubelet Lock File
	if s.ExitOnLockContention && s.LockFilePath == "" {
		return errors.New("cannot exit on lock file contention: no lock file specified")
	}
	done := make(chan struct{})
	if s.LockFilePath != "" {
		logger.Info("Acquiring file lock", "path", s.LockFilePath)
		if err := flock.Acquire(s.LockFilePath); err != nil {
			return fmt.Errorf("unable to acquire file lock on %q: %w", s.LockFilePath, err)
		}
		if s.ExitOnLockContention {
			logger.Info("Watching for inotify events", "path", s.LockFilePath)
			if err := watchForLockfileContention(ctx, s.LockFilePath, done); err != nil {
				return err
			}
		}
	}

	if len(s.ShowHiddenMetricsForVersion) > 0 {
		metrics.SetShowHidden()
	}

	// About to get clients and such, detect standaloneMode
	standaloneMode := true
	if len(s.KubeConfig) > 0 {
		standaloneMode = false
	}

View on GitHub (pinned to b882c60b40)

Solutions

  1. Check for a running kubelet: `pgrep -a kubelet` and `systemctl status kubelet` — stop duplicates.
  2. Confirm the lock-file directory exists and is writable by the kubelet user.
  3. If the prior process is truly dead but the lock lingers, remove the lock file and restart.
  4. On shared/read-only filesystems, move --lock-file-path to a local writable dir (e.g. /var/run).

Example fix

# before (read-only mount)
--lock-file-path=/etc/kubernetes/kubelet.lock
# after (local writable)
--lock-file-path=/var/run/kubelet.lock
Defensive patterns

Strategy: validation

Validate before calling

// Preflight: confirm no other kubelet holds the lock and the dir is writable.
if running, _ := pgrepKubelet(); running {
    return errors.New("kubelet already running; refusing to start a second instance")
}

Prevention

When it happens

Trigger: Another kubelet process is already running and holds the lock; the lock-file path's directory does not exist or is not writable; permission denied on the path; or the filesystem does not support flock semantics.

Common situations: A second kubelet was started (double-launch); a previous kubelet crashed without releasing the lock and the stale lock is still held (rare with flock, which releases on process exit); --lock-file-path points at a read-only mount.

Related errors


AI-assisted analysis of kubernetes/kubernetes@b882c60b40 (2026-08-07). Data as JSON: /api/errors/6231c7d2f9656a16. Report an issue: GitHub.