buildfarm

package module
v0.0.0-...-f503570 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2024 License: Apache-2.0 Imports: 41 Imported by: 0

README

podman buildfarm/team/crew/bunch Cirrus CI Status

(still workshopping the name)

This repository is a PoC for a feature in podman, and once the feature arrives in a podman release, this repository will be archived.

What are we doing here?

We're living in a future when building container images for just one target architecture isn't always enough. An image built in one place can may be expected to run as a container in clouds, on workstations, on smaller/edge/embedded devices, and in places I haven't thought to list, and those devices won't always share a common CPU architecture.

What is this not?

podman build has been able to accept a list of values to its --platform option for some time now. When invoked with a list of platforms and with its --manifest option, podman will build an image for multiple target platforms and then create a manifest list that enumerates the various newly-built architecture-specific images.

They can then all be pushed, as a group, to a registry by podman manifest push --all.

If the build host has the qemu-user-static package or an equivalent installed, RUN instructions in Dockerfiles won't even cause builds to fail with "Exec format error" errors.

This describes things podman does right now. This... is not that.

What is this?

podman has a notion of "system connections", by which one copy of podman (more often, podman-remote running on a non-Linux system) "drives" a copy of podman running on a remote Linux system, connecting to that system via an SSH tunnel. This feature is how podman machine makes the VMs it manages available to podman or podman-remote.

Instead of performing the build locally, the way podman build does, this tool ships the build context off over a system connection, and when the image build is complete, it pulls the new image back over that connection into local storage.

It actually expects to perform builds using multiple system connections, and after they've all succeeded, it will generate a manifest list that includes the images that it has just built.

If the podman instances that it uses for performing builds are running on different architectures, it will mark their results correctly.

They can then all be pushed, as a group, to a registry by podman manifest push --all.

It's intentional that the final push step is the same as it would have been after podman build --manifest.

What does that look like?

Run everything locally using emulation (podman 4.0 and later):

> : setup that only needs to happen once
> sudo dnf install qemu-user-static
> : do the thing
> podman build --platforms=linux/arm64,linux/amd64 --manifest registry.tld/my/repository:tag .
> podman manifest push --all registry.tld/my/repository:tag

Notes:

  • Emulation works at the instruction level, so binaries which are run using emulation still see the host's true CPU information in /proc/cpuinfo, which can confuse them.
  • qemu-user emulators use multiple threads, and this can cause certain system calls which they make on behalf of single-threaded binaries that they are interpreting to fail in ways those binaries do not expect.
  • qemu-user-static emulators typically are not registered with the kernel's binfmt_misc feature with the flag ("C") that would be required for allowing interpreted setuid/setgid binaries to run setuid/setgid.

Use remote machines to do the heavy lifting (this repository):

> : setup that only needs to happen once
> ssh f37box systemctl --user enable podman.socket
> podman system connection add f37 ssh://f37box
> podman machine init
> podman machine start
> : do the thing
> buildfarm --node f37,podman-machine-default build -t registry.tld/my/repository:tag .
> podman manifest push --all registry.tld/my/repository:tag

Notes:

  • By default, a build farm will build images for all architectures which its nodes are able to run natively.
  • If multiple system connections in a build farm can build for the same target architecture, one of them is chosen to do the work, and the other is left idle. We'll want to make that scheduler smarter.
  • The --node option instructs the tool to use an ad-hoc group of system connections as a build farm.
  • The --farm option instructs the tool to use a named set of system connections as a build farm. Storing this information in containers.conf(5) requires adding to its format, but that format is maintained elsewhere, so it is not usably implemented here.
  • When neither --node nor --farm is specified, the tool uses an ad-hoc farm which includes every known system connection.

Documentation

Index

Constants

View Source
const (
	LocalImageBuilderName = "(local)"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type BuildOptions

type BuildOptions struct {
	OutputFormat                      string
	Out                               io.Writer
	Err                               io.Writer
	ForceRemoveIntermediateContainers bool
	RemoveIntermediateContainers      bool
	RemoveIntermediateImages          bool
	PruneImagesOnSuccess              bool
	Platforms                         []struct{ OS, Arch, Variant string }
	Pull                              bool
	IIDFile                           string
	ContextDirectory                  string
	Labels                            []string
	Args                              map[string]string
	ShmSize                           string
	Ulimit                            []string
	Memory                            int64
	MemorySwap                        int64
	CPUShares                         uint64
	CPUQuota                          int64
	CPUPeriod                         uint64
	CPUSetCPUs                        string
	CPUSetMems                        string
	CgroupParent                      string
	NoCache                           bool
	Quiet                             bool
	CacheFrom                         []reference.Named
	CacheTo                           []reference.Named
	AddHost                           []string
	Target                            string
	ConfigureNetwork                  *bool
}

type BuildReport

type BuildReport struct {
	ImageID    string
	SaveFormat string
}

type Farm

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

Farm represents a group of connections to builders.

func CreateFarm

func CreateFarm(ctx context.Context, name string) (*Farm, error)

CreateFarm creates an empty farm which will use a set of named connections which will be added to it later.

func NewAdHocFarm

func NewAdHocFarm(ctx context.Context, destinations []string, storeOptions *storage.StoreOptions, flags *pflag.FlagSet) (*Farm, error)

NewAdHocFarm returns a Farm that uses the specified system connections and which has no name. If storeOptions is not nil AND the list of destinations includes the empty string, the local system will be included as an unnamed connection.

func NewDefaultFarm

func NewDefaultFarm(ctx context.Context, storeOptions *storage.StoreOptions, flags *pflag.FlagSet) (*Farm, error)

NewDefaultFarm returns a Farm that uses all known system connections and which has no name. If storeOptions is not nil, the local system will be included as an unnamed connection.

func NewFarm

func NewFarm(ctx context.Context, name string, storeOptions *storage.StoreOptions, flags *pflag.FlagSet) (*Farm, error)

NewFarm returns a Farm that has a preconfigured set of system connections.

func UpdateFarm

func UpdateFarm(ctx context.Context, add, remove []string) (*Farm, error)

UpdateFarm updates a farm, adding and removing the set of named connections to/from it, respectively.

func (*Farm) Build

func (f *Farm) Build(ctx context.Context, reference string, schedule Schedule, containerFiles []string, options BuildOptions) error

Build runs a build using the specified targetplatform:service map. If all builds succeed, it copies the resulting images from the remote hosts to the local service and builds a manifest list with the specified reference name.

func (*Farm) Done

func (f *Farm) Done(ctx context.Context) error

Done performs any necessary end-of-process cleanup for the farm's members.

func (*Farm) EmulatedPlatforms

func (f *Farm) EmulatedPlatforms(ctx context.Context) ([]string, error)

EmulatedPlatforms returns a list of the set of platforms for which the farm can build images with the help of emulation.

func (*Farm) NativePlatforms

func (f *Farm) NativePlatforms(ctx context.Context) ([]string, error)

NativePlatforms returns a list of the set of platforms for which the farm can build images natively.

func (*Farm) PruneImages

func (f *Farm) PruneImages(ctx context.Context, options PruneImageOptions) (map[string]PruneImageReport, error)

PruneImages, well, prunes unused images from each of the builders. We remove images that we build after we've downloaded them when the Rm flag is true, which is its default, but that still leaves base images that we caused to be pulled lying around.

func (*Farm) Schedule

func (f *Farm) Schedule(ctx context.Context, platforms []string) (Schedule, error)

Schedule takes a list of platforms and returns a list of connections which can be used to build for those platforms. It always prefers native builders over emulated builders, but will assign a builder which can use emulation for a platform if no suitable native builder is available.

If platforms is an empty list, all available native platforms will be scheduled.

TODO: add (Priority,Weight *int) a la RFC 2782 to destinations that we know of, and factor those in when assigning builds to nodes in here.

func (*Farm) Status

func (f *Farm) Status(ctx context.Context) (map[string]error, error)

Status polls the connections in the farm and returns a map of their individual status, along with an error if any are down or otherwise unreachable.

type ImageBuilder

type ImageBuilder interface {
	Driver(ctx context.Context) string
	Name(ctx context.Context) string
	Status(ctx context.Context) error
	Info(ctx context.Context, options InfoOptions) (*Info, error)
	NativePlatforms(ctx context.Context, options InfoOptions) ([]string, error)
	EmulatedPlatforms(ctx context.Context, options InfoOptions) ([]string, error)
	Build(ctx context.Context, reference string, containerFiles []string, options BuildOptions) (BuildReport, error)
	PullToFile(ctx context.Context, options PullToFileOptions) (reference string, err error)
	PullToLocal(ctx context.Context, options PullToLocalOptions) (reference string, err error)
	RemoveImage(ctx context.Context, options RemoveImageOptions) error
	PruneImages(ctx context.Context, options PruneImageOptions) (PruneImageReport, error)
	Done(ctx context.Context) error
}

ImageBuilder is a subset of the entities.ImageEngine interface.

func NewDockerImageBuilder

func NewDockerImageBuilder(ctx context.Context, flags *pflag.FlagSet, name string) (ImageBuilder, error)

NewDockerImageBuilder creates an ImageBuilder which uses a docker engine.

func NewPodmanLocalImageBuilder

func NewPodmanLocalImageBuilder(ctx context.Context, flags *pflag.FlagSet, storeOptions *storage.StoreOptions) (ImageBuilder, error)

NewPodmanLocalImageBuilder creates an ImageBuilder which uses libpod to directly perform a build.

func NewPodmanRemoteImageBuilder

func NewPodmanRemoteImageBuilder(ctx context.Context, flags *pflag.FlagSet, name string) (ImageBuilder, error)

NewPodmanRemoteImageBuilder creates an ImageBuilder which uses a remote connection to a podman service running somewhere else.

type Info

type Info struct {
	NativePlatforms   []string
	EmulatedPlatforms []string
}

type InfoOptions

type InfoOptions struct {
}

type ListBuilder

type ListBuilder interface {
	Build(ctx context.Context, images map[BuildReport]ImageBuilder) (string, error)
}

func NewFileListBuilder

func NewFileListBuilder(directory string, options ListBuilderOptions) (ListBuilder, error)

NewFileListBuilder returns a manifest list builder which saves a manifest list and images to a specified directory in the non-standard dir: format.

func NewPodmanLocalListBuilder

func NewPodmanLocalListBuilder(listName string, flags *pflag.FlagSet, storeOptions *storage.StoreOptions, options ListBuilderOptions) (ListBuilder, error)

NewPodmanLocalListBuilder returns a manifest list builder which saves a manifest list and images to local storage.

type ListBuilderOptions

type ListBuilderOptions struct {
	ForceRemoveIntermediateContainers bool
	RemoveIntermediateContainers      bool
	RemoveIntermediateImages          bool
	PruneImagesOnSuccess              bool
	IIDFile                           string
}

type PruneImageOptions

type PruneImageOptions struct {
	All bool
}

type PruneImageReport

type PruneImageReport struct {
	ImageIDs   []string
	ImageNames []string
}

type PullToFileOptions

type PullToFileOptions struct {
	ImageID    string
	SaveFormat string
	SaveFile   string
}

type PullToLocalOptions

type PullToLocalOptions struct {
	ImageID     string
	SaveFormat  string
	Destination entities.ImageEngine
}

type RemoveImageOptions

type RemoveImageOptions struct {
	ImageID string
}

type Schedule

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

Schedule is a description of where and how we'll do builds.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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