# Defining Images Tom Gundersen Image Builder @ Red Hat slides: https://bit.ly/3yQAmpd --- ## Building Images --- ## osbuild - anyone can build images<!-- .element: class="fragment" --> - we can build the same image twice <!-- .element: class="fragment" --> - comparable to an assembler - not a compiler<!-- .element: class="fragment" --> - reproducible<!-- .element: class="fragment" --> - low-level<!-- .element: class="fragment" --> - pluggable<!-- .element: class="fragment" --> - extensible<!-- .element: class="fragment" --> - policy-less<!-- .element: class="fragment" --> https://github.com/osbuild/osbuild ---- ### manifests - input to osbuild in JSON format<!-- .element: class="fragment" --> - defines a set of filesystem trees <!-- .element: class="fragment" --> - e.g., one tree containing an image<!-- .element: class="fragment" --> - same manifest produces the same* image<!-- .element: class="fragment" --> - defined in terms of<!-- .element: class="fragment" --> - a set of 'sources' and<!-- .element: class="fragment" --> - a set of 'pipelines'<!-- .element: class="fragment" --> ---- ### pipelines - defines a single filesystem tree<!-- .element: class="fragment" --> - may consume other trees as input<!-- .element: class="fragment" --> - defined as a sequence of 'stages'<!-- .element: class="fragment" --> ---- ### stages - defines a modification to a filesystem tree<!-- .element: class="fragment" --> - declarative<!-- .element: class="fragment" --> - policy-less<!-- .element: class="fragment" --> - reproducible<!-- .element: class="fragment" --> - isolated from the host<!-- .element: class="fragment" --> - scoped to one tool<!-- .element: class="fragment" --> - sandboxes and unifies existing tools<!-- .element: class="fragment" --> ---- ### example ```json { "version": "2", "pipelines": [ { "name": "os", "stages": [ { "type": "org.osbuild.rpm", ... }, ... ] }, ... ] } ``` --- ## Defining Images --- ## osbuild-composer - uniformly define all the images<!-- .element: class="fragment" --> - one services to build everything for everyone everywhere<!-- .element: class="fragment" --> - distros:<!-- .element: class="fragment" --> - Fedora, CentOS Stream, RHEL<!-- .element: class="fragment" --> - footprints:<!-- .element: class="fragment" --> - Bare metal, Cloud, Virt, Edge<!-- .element: class="fragment" --> - architectures:<!-- .element: class="fragment" --> - x86_64, aarch64, ppc64le, s390x<!-- .element: class="fragment" --> - available: on-prem, hosted, soon through koji<!-- .element: class="fragment" --> https://github.com/osbuild/osbuild-composer ---- ### Public API - stable<!-- .element: class="fragment" --> - very high-level<!-- .element: class="fragment" --> - all artefacts end-to-end tested<!-- .element: class="fragment" --> ---- ### Private API - unstable<!-- .element: class="fragment" --> - not end-to-end tested<!-- .element: class="fragment" --> - declarative<!-- .element: class="fragment" --> - policy-rich<!-- .element: class="fragment" --> - reproducible<!-- .element: class="fragment" --> --- ## Image Kind ```go type ImageKind interface { InstantiateManifest(m *manifest.Manifest, ...) error ... } ``` ```go type OSTreeArchive struct { Platform platform.Platform OSCustomizations manifest.OSCustomizations Environment environment.Environment Workload workload.Workload OSTreeParent manifest.OSTree OSTreeRef string ... } ``` <!-- .element: class="fragment" --> ---- ## Manifest ```go func (m Manifest) GetPackageSetChains() map[string][]rpmmd.PackageSet {...} func (m Manifest) Serialize( packageSets map[string][]rpmmd.PackageSpec) ([]byte], error) {...} ``` ---- ### Pipeline ```go type Pipeline interface { Name() string getBuildPackages() []string getPackageSetChain() []rpmmd.PackageSet serialize([]rpmmd.PackageSpec) osbuild2.Pipeline ... } ``` ---- ### Build Pipeline ```go func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig) *Build {...} ``` ---- ### OS Pipeline ```go func NewOS(m *Manifest, buildPipeline *Build, platform platform.Platform, repos []rpmmd.RepoConfig) *OS {...} ``` ---- ### Hardware Platform ```go type Platform interface { GetArch() Arch GetBIOSPlatform() string GetUEFIVendor() string GetPackages() []string GetBuildPackages() []string ... } ``` ```go type X86 struct { BasePlatform BIOS bool UEFIVendor string } ``` <!-- .element: class="fragment" --> ```go type Aarch64 struct { UEFIVendor string } ``` <!-- .element: class="fragment" --> ---- ### RawImage Pipeline ```go func NewRawImage(m *Manifest, buildPipeline *Build, treePipeline *OS) *RawImage {...} ``` ---- ### Customizing Pipelines ```go type OS struct { PartitionTable *disk.PartitionTable Environment environment.Environment Workload workload.Workload ... } ``` ---- ### Environment ```go type Environment interface { GetPackages() []string GetServices() []string } ``` ```go type Azure struct {...} func (p *Azure) GetPackages() []string { return []string{"WALinuxAgent"} } func (p *Azure) GetServices() []string { return []string{"waagent"} } ``` <!-- .element: class="fragment" --> ---- ### Workload ```go type Workload interface { GetPackages() []string GetServices() []string ... } ``` ```go type Custom struct { Packages []string Services []string ... } ``` <!-- .element: class="fragment" --> ```go type MicroShift struct {} ``` <!-- .element: class="fragment" --> ```go type Anaconda struct {} ``` <!-- .element: class="fragment" --> --- ### Demo! :banana: ```sh go run ./cmd/osbuild-playground ``` <div style="text-align: right; color: grey; font-size: 0.5em"> using upstream VSCode devcontainer</div>
{"metaMigratedAt":"2023-06-17T04:30:19.511Z","metaMigratedFrom":"YAML","title":"Defining Images","breaks":true,"description":"How images are defined and built with osbuild","slideOptions":"{\"allottedMinutes\":15,\"transition\":\"slide\",\"image\":\"https://www.osbuild.org/images/osbuild.png\"}","contributors":"[{\"id\":\"8f5474a9-6266-468e-9a82-2653e71aaa7b\",\"add\":10028,\"del\":3585}]"}
    1409 views