isolation

package
v0.25.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package isolation defines where the node stack (containerd, kubelet, CNI and CoreDNS) runs on a host. The agent and its daemon always run on the host; a Backend decides only where the node stack lives and how it is operated.

Phases receive a NodeRoot and call Path and Backend.Exec. They must not reference machine directories, machinectl or systemd-run --machine directly. Operations that need only a slot take a SlotRef; a caller with no filesystem view of the node passes a SlotName.

There is no global backend registry. The agent wires each mode's backend, daemon node operator and bootstrap plan together in one composition table (cmd/agent/internal/cmd/modes.go), so adding a mode is one table entry.

Index

Constants

View Source
const DefaultMode = ModeNSpawn

DefaultMode is the mode used when none is configured or recorded.

Variables

This section is empty.

Functions

func JournalTailArgs

func JournalTailArgs(opts LogOptions) []string

JournalTailArgs returns the journalctl flags for the follow and line-count options. Each backend supplies the flags that select its units or machine, because they differ by mode.

func StartLogStream

func StartLogStream(ctx context.Context, name string, args ...string) (io.ReadCloser, error)

StartLogStream starts a command and returns its standard output. Closing the reader waits for the command, so a stream that was cut short does not leave a zombie. When the command ran to the end of its output and exited non-zero, for example journalctl against a machine that does not exist, Close returns an error carrying the end of its stderr. Stopping the stream early, by closing it or canceling ctx, is not an error.

Types

type Backend

type Backend interface {
	Mode() Mode

	// Requirements declares host requirements checked by preflight before
	// anything is mutated, and ordering dependencies on host-global units.
	Requirements() Requirements

	// Prepare materializes a node root for a slot: it unpacks or installs
	// artifacts and renders backend configuration.
	Prepare(ctx context.Context, n NodeSpec) (NodeRoot, error)

	Start(ctx context.Context, r SlotRef) error
	Stop(ctx context.Context, r SlotRef) error
	// Restart restarts the node stack only, never the host (soft reboot).
	Restart(ctx context.Context, r SlotRef) error
	// Destroy removes the node root and backend configuration for a slot.
	Destroy(ctx context.Context, r SlotRef) error

	Status(ctx context.Context, r SlotRef) (Status, error)

	// Exec runs a command in the node stack.
	Exec(ctx context.Context, r SlotRef, cmd ExecSpec) (ExecResult, error)
	// Logs streams logs for a unit in the node stack.
	Logs(ctx context.Context, r SlotRef, opts LogOptions) (io.ReadCloser, error)
}

Backend owns where the node stack runs.

type DirRoot

type DirRoot struct {
	SlotName string
	Dir      string
}

DirRoot is a NodeRoot whose filesystem is a directory on the host. The nspawn backend uses it with the unpacked rootfs directory.

Dir must be set. A DirRoot never maps paths onto the host root: an empty Dir would turn every path into a host path, so Path panics on one rather than let a phase write the node's files over the host's. Use NewDirRoot to get an error instead, and SlotName to name a slot without a filesystem view.

func NewDirRoot

func NewDirRoot(slot, dir string) (DirRoot, error)

NewDirRoot returns the DirRoot for slot rooted at dir. dir must be an absolute path other than the host root.

func (DirRoot) Path

func (r DirRoot) Path(inNode string) string

Path implements NodeRoot. It panics when Dir is empty, relative or the host root; see DirRoot.

func (DirRoot) Slot

func (r DirRoot) Slot() string

Slot implements NodeRoot.

type ExecResult

type ExecResult struct {
	// Stdout is the captured standard output with trailing newlines trimmed.
	Stdout string
}

ExecResult is the outcome of a successful Exec.

type ExecSpec

type ExecSpec struct {
	// Args is the command and its arguments.
	Args []string
}

ExecSpec is a command run in the node stack.

type FakeBackend

type FakeBackend struct {
	FakeMode Mode
	// Dir is the directory the roots Prepare returns resolve under. It must be
	// an absolute directory other than the host root; see DirRoot.
	Dir string

	PrepareErr, StartErr, StopErr, RestartErr, DestroyErr, StatusErr, ExecErr error

	// FakeStatus is what Status reports when StatusErr is nil.
	FakeStatus Status

	// ExecFunc, when set, produces the result of Exec.
	ExecFunc func(ExecSpec) (ExecResult, error)
	// contains filtered or unexported fields
}

FakeBackend records every call and returns configured results. It is safe for concurrent use. Set the Err fields to inject failures.

func (*FakeBackend) Calls

func (f *FakeBackend) Calls() []string

Calls returns the recorded operations in order, as "op slot" strings.

func (*FakeBackend) Destroy

func (f *FakeBackend) Destroy(_ context.Context, r SlotRef) error

Destroy implements Backend.

func (*FakeBackend) Exec

func (f *FakeBackend) Exec(_ context.Context, r SlotRef, cmd ExecSpec) (ExecResult, error)

Exec implements Backend.

func (*FakeBackend) Execs

func (f *FakeBackend) Execs() []ExecSpec

Execs returns the recorded Exec commands in order.

func (*FakeBackend) Logs

Logs implements Backend.

func (*FakeBackend) Mode

func (f *FakeBackend) Mode() Mode

Mode implements Backend.

func (*FakeBackend) Prepare

func (f *FakeBackend) Prepare(_ context.Context, n NodeSpec) (NodeRoot, error)

Prepare implements Backend.

func (*FakeBackend) Requirements

func (f *FakeBackend) Requirements() Requirements

Requirements implements Backend.

func (*FakeBackend) Restart

func (f *FakeBackend) Restart(_ context.Context, r SlotRef) error

Restart implements Backend.

func (*FakeBackend) Start

func (f *FakeBackend) Start(_ context.Context, r SlotRef) error

Start implements Backend.

func (*FakeBackend) Status

func (f *FakeBackend) Status(_ context.Context, r SlotRef) (Status, error)

Status implements Backend.

func (*FakeBackend) Stop

func (f *FakeBackend) Stop(_ context.Context, r SlotRef) error

Stop implements Backend.

type Grant

type Grant struct {
	Kind    GrantKind
	Purpose GrantPurpose
	// Source is the host path (or device node). It is empty for a GrantDevice
	// that only names a device class and has no node to expose.
	Source string
	// Target is the in-node path. Empty means the same as Source.
	Target   string
	ReadOnly bool
	// DeviceClass is a cgroup device class selector such as char-input, for a
	// GrantDevice that has no Source.
	DeviceClass string
	// DeviceAllow lists the device node paths or device group specifiers (for
	// example char-infiniband_verbs) a GrantMount of a device directory needs,
	// so nodes created in the directory after the node stack starts are usable.
	DeviceAllow []string `json:",omitempty"`
}

Grant is a backend-neutral request for host resources. Each backend applies it in its own way, and a backend with nothing to apply ignores it.

type GrantKind

type GrantKind string

GrantKind is the type of a Grant.

const (
	// GrantMount exposes a host path inside the node stack.
	GrantMount GrantKind = "mount"
	// GrantDevice exposes a host device inside the node stack.
	GrantDevice GrantKind = "device"
	// GrantLibraryPath adds a directory to the node stack's library search path.
	GrantLibraryPath GrantKind = "library-path"
)

type GrantPurpose

type GrantPurpose string

GrantPurpose says what a Grant is for. Backends use it to place a grant in the right section of their own configuration and to keep a stable rendering order. It carries no host paths.

const (
	// PurposeHostDevice is a discovered or configured host device node, or a
	// systemd device group specifier, such as /dev/kvm or char-input.
	PurposeHostDevice GrantPurpose = "host-device"
	// PurposeHostMount is a configured host path, or a whole device directory
	// such as /dev/infiniband whose Grant.DeviceAllow covers the nodes in it.
	PurposeHostMount GrantPurpose = "host-mount"
	// PurposeNvidiaDevice is an NVIDIA GPU device node or directory.
	PurposeNvidiaDevice GrantPurpose = "nvidia-device"
	// PurposeNvidiaLibDir is a host directory of NVIDIA driver libraries.
	PurposeNvidiaLibDir GrantPurpose = "nvidia-lib-dir"
	// PurposeNvidiaI386LibDir is a host directory of 32-bit NVIDIA libraries.
	PurposeNvidiaI386LibDir GrantPurpose = "nvidia-i386-lib-dir"
	// PurposeNvidiaHelperBin is the host directory of NVIDIA helper binaries
	// that node-start copies into the node.
	PurposeNvidiaHelperBin GrantPurpose = "nvidia-helper-bin"
	// PurposeAMDDevice is an AMD GPU device node.
	PurposeAMDDevice GrantPurpose = "amd-device"
	// PurposeAMDSysFS is a host sysfs path the AMD device plugin reads.
	PurposeAMDSysFS GrantPurpose = "amd-sysfs"
)

type LibDirMount

type LibDirMount struct {
	Index        int
	HostDir      string
	ContainerDir string
}

LibDirMount is a host library directory made visible at ContainerDir. Index orders the mounts and maps libraries to their directory.

type LogOptions

type LogOptions struct {
	// Unit is the systemd unit inside the node stack. Empty means all units.
	Unit string
	// Follow keeps the stream open for new entries.
	Follow bool
	// Lines limits output to the last N entries when positive.
	Lines int
}

LogOptions selects which logs Logs returns.

type Mode

type Mode string

Mode names an isolation mode.

const (
	// ModeNSpawn runs the node stack in a systemd-nspawn machine. It is the
	// default, and the mode of every host that has no recorded mode.
	ModeNSpawn Mode = "nspawn"
	// ModeNone runs the node stack as agent-owned units directly on the host.
	ModeNone Mode = "none"
	// ModeContainer runs the node stack in a privileged OCI container
	// supervised by an agent-owned systemd unit. It is experimental: the agent
	// operates it only when its configuration opts in.
	ModeContainer Mode = "container"
)

func ParseMode

func ParseMode(s string) (Mode, error)

ParseMode validates s and returns the Mode it names. The empty string is the default mode. Unrecognized values are rejected rather than ignored so an older agent never silently runs a newer mode as nspawn.

ParseMode only says whether a name is a mode. Whether this agent can operate a mode is answered by the agent's mode composition table.

type NodeRoot

type NodeRoot interface {
	SlotRef
	// Path maps an in-node absolute path to its path as seen by the agent.
	Path(inNode string) string
}

NodeRoot resolves paths into the node stack's filesystem view.

type NodeSpec

type NodeSpec struct {
	// Slot is the blue/green slot, for example kube1 or kube2.
	Slot string
	// Version is the Kubernetes version the node runs. It is informational:
	// no backend selects behavior from it.
	Version string
	// Grants are device, mount and library requests the node stack needs.
	Grants []Grant
}

NodeSpec describes the node a backend prepares.

type Requirements

type Requirements struct {
	// HostPackages are packages that must be present on the host.
	HostPackages []string
	// HostCommands are executables that must be resolvable on the host.
	HostCommands []string
	// WritablePaths are host paths that must be writable.
	WritablePaths []string
	// After lists host-global units the node stack must start after.
	After []string
}

Requirements declares what a backend needs from the host. Preflight checks it before anything is mutated.

type SlotName

type SlotName string

SlotName is a SlotRef that carries only a slot name. It has no filesystem view: a backend that needs one builds its own root from the slot.

func (SlotName) Slot

func (s SlotName) Slot() string

Slot implements SlotRef.

type SlotRef

type SlotRef interface {
	Slot() string
}

SlotRef names the blue/green slot an operation acts on. Every NodeRoot is a SlotRef. Operations that need only the slot, such as starting or stopping a node, take a SlotRef, so a caller that has no filesystem view of the node passes a SlotName and never has to make one up.

type Status

type Status struct {
	// Running reports whether the node stack is up.
	Running bool
	// Detail is a human readable explanation.
	Detail string
}

Status is the observed state of a node root.

Directories

Path Synopsis
Package container is the isolation backend that runs the node stack in a privileged OCI container with systemd as PID 1.
Package container is the isolation backend that runs the node stack in a privileged OCI container with systemd as PID 1.
Package isolationtest is the conformance suite every isolation backend must pass.
Package isolationtest is the conformance suite every isolation backend must pass.
Package migrate moves a live node from one isolation mode to another.
Package migrate moves a live node from one isolation mode to another.
Package none is the isolation backend that runs the node stack directly on the host as agent-owned systemd units.
Package none is the isolation backend that runs the node stack directly on the host as agent-owned systemd units.
Package nspawn is the isolation backend that runs the node stack in a systemd-nspawn machine.
Package nspawn is the isolation backend that runs the node stack in a systemd-nspawn machine.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL