engine

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2026 License: AGPL-3.0 Imports: 49 Imported by: 0

Documentation

Overview

Package engine installs and talks to Zelie's own containerd.

Index

Constants

View Source
const (
	ContainerdVersion = "2.4.1"
	RuncVersion       = "1.5.1"
	CNIVersion        = "1.9.1"
	RailpackVersion   = "0.40.0"
)
View Source
const BuilderHostID = builderBase

BuilderHostID is the host user and group that root inside the builder is. Directories the builder writes to must belong to it.

View Source
const LocalImages = "zelie.local/"

LocalImages is the prefix of images built on this machine. They are never pulled from a registry.

View Source
const Namespace = "zelie"

Namespace is the containerd namespace that holds everything Zelie creates.

Variables

View Source
var DefaultPaths = Paths{
	Bin:    "/usr/local/lib/zelie/bin",
	CNI:    "/usr/local/lib/zelie/cni",
	Config: "/etc/zelie/containerd.toml",
	Root:   "/var/lib/zelie/containerd",
	State:  "/run/zelie/containerd",
	Socket: "/run/zelie/containerd.sock",
	Unit:   "/etc/systemd/system/zelie-containerd.service",
	Logs:   "/var/lib/zelie/logs",
	Data:   "/var/lib/zelie/engine",
	NetNS:  "/run/zelie/netns",

	Volumes: "/var/lib/zelie/volumes",
}
View Source
var NetworkRange = netip.MustParsePrefix("10.210.0.0/16")

NetworkRange holds every container network. Each network gets a /24 out of it. It is rarely used by hosting providers or home routers, which keeps clashes with the host's own networks unlikely.

Functions

func CheckLinks(app string, links []Link) error

CheckLinks reports whether links may be set on app.

func CheckVolumeTarget

func CheckVolumeTarget(target string) error

CheckVolumeTarget reports whether a volume may be mounted at target.

func ConfigFile

func ConfigFile(p Paths) string

ConfigFile renders containerd's configuration. The CRI plugins are turned off because Zelie is not a Kubernetes node and they would only add attack surface and memory use.

func ImageName

func ImageName(ref string) (string, error)

ImageName is the name an image is stored under: "nginx:alpine" means docker.io/library/nginx:alpine, as it does everywhere else. Local images keep their name.

func LogPathFor

func LogPathFor(p Paths, id string) string

LogPathFor is where a container's output goes. The shim writes to it directly, so logging keeps working while containerd or Zelie restarts.

func UnitFile

func UnitFile(p Paths) string

UnitFile renders the systemd unit. KillMode=process matters most: when containerd stops or restarts, systemd kills only containerd itself and leaves the shims, and therefore every running container, alone.

func ValidID

func ValidID(id string) bool

ValidID reports whether id is safe to use as a container name and in paths.

Types

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine runs containers through Zelie's containerd.

func Connect

func Connect(ctx context.Context, p Paths) (*Engine, error)

func (*Engine) Close

func (e *Engine) Close() error

func (*Engine) CreateVolume

func (e *Engine) CreateVolume(name string) error

CreateVolume makes an empty volume. Its top directory belongs to root in the container, which is who images expect to own a fresh mount.

func (*Engine) Exec

func (e *Engine) Exec(ctx context.Context, id string, args []string, stdin io.Reader, stdout, stderr io.Writer) (uint32, error)

Exec runs a command in a running container and returns its exit code. It runs as root inside the container, with the container's environment, so a database's own tools can read the password it was started with.

When stdin is set the command reads it to the end. The last bytes of stdin can be lost on the way through the shim, so a caller that must know all of it arrived checks that for itself.

func (*Engine) Images

func (e *Engine) Images(ctx context.Context) ([]Image, error)

Images lists the images the engine holds.

func (*Engine) ImportImage

func (e *Engine) ImportImage(ctx context.Context, r io.Reader, name string) error

ImportImage stores an OCI image archive, such as a build's output, under name, which must start with LocalImages.

func (e *Engine) Links(app string) ([]Link, error)

Links returns the links of an app.

func (*Engine) List

func (e *Engine) List(ctx context.Context) ([]Status, error)

func (*Engine) OpenVolume

func (e *Engine) OpenVolume(ctx context.Context, name string) (*os.Root, error)

OpenVolume opens a volume for the core to change its files directly, as a restore does. It is refused while a container using the volume runs. The files came from a container and are not trusted: the root keeps every path, symbolic links included, inside the volume.

func (*Engine) ReadVolume

func (e *Engine) ReadVolume(name string) (*os.Root, error)

ReadVolume opens a volume to copy its files while its containers may still run, for a backup that does not stop the app. The core only reads through it.

func (*Engine) Remove

func (e *Engine) Remove(ctx context.Context, id string) error

Remove stops the container if needed and deletes it with its snapshot and its log. Once started it runs to the end even if ctx is cancelled: a network plugin killed halfway leaves the container's address taken.

func (*Engine) RemoveImage

func (e *Engine) RemoveImage(ctx context.Context, name string) error

RemoveImage deletes an image. Containers already made from it keep running: they hold their own snapshot. containerd's garbage collector frees the layers no other image uses.

func (*Engine) RemoveVolume

func (e *Engine) RemoveVolume(ctx context.Context, name string) error

RemoveVolume deletes a volume and everything in it. A volume a container still has mounted is refused, stopped or not.

func (*Engine) Run

func (e *Engine) Run(ctx context.Context, s Spec) (err error)

Run pulls the image if needed, creates the container and starts it.

func (e *Engine) SetLinks(ctx context.Context, app string, links []Link) error

SetLinks replaces the links of an app. They apply at once, to containers already running too.

func (*Engine) SetUnused

func (e *Engine) SetUnused(ctx context.Context, name string, since time.Time) error

SetUnused records since when an image has been unneeded. The zero time clears it.

func (*Engine) StartDNS

func (e *Engine) StartDNS(ctx context.Context) (<-chan error, error)

StartDNS starts the DNS server of every network; they run until ctx is cancelled. Networks made later get theirs as their first container starts. A server that fails later reports it on the channel.

func (*Engine) Stop

func (e *Engine) Stop(ctx context.Context, id string, grace time.Duration) error

Stop asks the container to exit and kills it if it has not exited within the grace period.

func (*Engine) Usage

func (e *Engine) Usage(id string) (Usage, error)

Usage reads a container's memory and CPU time from its cgroup.

func (*Engine) VolumeSize

func (e *Engine) VolumeSize(name string) (int64, error)

VolumeSize returns how much disk one volume takes.

func (*Engine) VolumeSizes

func (e *Engine) VolumeSizes() (map[string]int64, error)

VolumeSizes returns how much disk each volume takes, by name.

func (*Engine) Wait

func (e *Engine) Wait(ctx context.Context, id string) (uint32, error)

Wait waits until the container's process has exited and returns its exit code.

type Host

type Host struct {
	CPUs          int
	MemoryBytes   int64
	DiskBytes     int64 // of the file system that holds Zelie's data
	DiskFreeBytes int64
}

Host is what the server has to give.

func HostInfo

func HostInfo(dir string) (Host, error)

HostInfo describes the server. dir is a directory on the disk that holds the containers.

type Image

type Image struct {
	Name string
	// UnusedSince is when the image was first found unneeded; zero while
	// something needs it.
	UnusedSince time.Time
}

Image is an image the engine holds.

type Installer

type Installer struct {
	Paths  Paths
	Arch   string
	Client *http.Client
	Log    io.Writer
	// contains filtered or unexported fields
}

Installer puts Zelie's containerd and runc on the machine and keeps the systemd service running. Running it again is safe: files that are already correct are left alone, and containerd is only restarted when something changed.

func (*Installer) Install

func (in *Installer) Install(ctx context.Context) error
type Link struct {
	Name string `json:"name"` // what the app looks up, such as "db"
	To   string `json:"to"`   // the app it reaches
	Port uint16 `json:"port"`
}

Apps cannot reach each other: each has its own network, and the host firewall drops traffic between networks. A link opens one way through: the app's containers may connect to one TCP port of another app's containers, and find them by the link's name through the DNS server.

type Mount

type Mount struct {
	Source, Target string
	ReadOnly       bool
}

Mount binds a host directory into a container.

type Paths

type Paths struct {
	Bin    string // containerd, the shim, ctr and runc
	CNI    string // network plugins
	Config string
	Root   string // images, snapshots, container metadata
	State  string // runtime state, cleared on reboot
	Socket string
	Unit   string // systemd unit file
	Logs   string // container output, one file per container
	Data   string // Zelie's own state: networks, IP leases, generated files
	NetNS  string // network namespaces, one per container
	// Volumes holds the files apps keep between deployments, one
	// directory each.
	Volumes string
}

Paths says where Zelie's containerd lives. None of them overlap with a containerd installed by Docker or the distribution, so both can run on the same machine without touching each other.

func (Paths) Railpack

func (p Paths) Railpack() string

func (Paths) Runc

func (p Paths) Runc() string

type Spec

type Spec struct {
	ID    string
	App   string // the app the container belongs to, if any
	Image string
	Args  []string // replaces the image's command when set
	Env   []string

	// Network is the network to join. Containers on the same network can
	// reach each other. Without one the container has only loopback.
	Network string

	MemoryBytes int64   // required
	CPUs        float64 // required, may be fractional
	Pids        int64   // required

	// Volumes are the app's own files that outlive the container.
	Volumes []VolumeMount

	// Mounts are host directories bound into the container. They are for
	// the core's own use, such as a build's source and cache, and are not
	// part of the core's API.
	Mounts []Mount

	// Builder runs the container as the builder: in the builder's own ID
	// block, so what it writes stays readable by the next build step. Only
	// one builder container exists at a time. Like Mounts, only the core
	// sets it.
	Builder bool
	// Nesting lets a builder run containers of its own: see nestingOpts.
	Nesting bool
}

Spec describes a container to run.

func (Spec) Validate

func (s Spec) Validate() error

Validate checks the spec before anything is created.

type Status

type Status struct {
	ID      string
	App     string
	Image   string
	State   string // running, stopped, created, …
	Pid     uint32
	Userns  uint32 // first host ID of the container's user namespace
	Network string
	IP      netip.Addr // zero when the container has no network
}

Status is a short summary of a container.

type Usage

type Usage struct {
	MemoryBytes int64
	// CPUUsec is the CPU time used so far; two readings give the rate.
	CPUUsec int64
}

Usage is what a running container uses.

type VolumeMount

type VolumeMount struct {
	Name, Target string
}

VolumeMount puts a volume at Target inside the container.

Jump to

Keyboard shortcuts

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