Skip to content

Latest commit

 

History

History
101 lines (55 loc) · 5.11 KB

File metadata and controls

101 lines (55 loc) · 5.11 KB

internal/pkg/runtime/launcher/oci

This package contains routines that configure and launch a container in an OCI bundle format, using a low-level OCI runtime, either crun or runc at this time. crun is currently preferred. runc is used where crun is not available.

Note - at present, all functionality works with either crun or runc. However, in future crun may be required for all functionality, as runc does not support some limited ID mappings etc. that may be beneficial in an HPC scenario.

The package contrasts with internal/pkg/runtime/launcher/native which executes Singularity format containers (SIF/Sandbox/squashfs/ext3), using one of our own runtime engines (internal/pkg/runtime/engine/*).

There are two flows that are implemented here.

  • Basic OCI runtime operations agains an existing bundle, which will be executed via the singularity oci command group. These are not widely used by end-users of singularity.
  • A Launcher, that implements an Exec function that will be called by 'actions' (run/shell/exec) in --oci mode, and will:
    • Prepare an OCI bundle according to launcher.Options passed through from the CLI layer.
    • Execute the bundle, interactively, via the OCI Run operation.

Note - this area of code is under heavy development for experimental introduction in CE 3.11. It is likely that it will be heavily refactored, and split, in future.

Basic OCI Operations

The following files implement basic OCI operations on a runtime bundle:

oci_linux.go

Defines constants, path resolution, and minimal bundle locking functions.

oci_runc_linux.go

Holds implementations of the Run / Start / Exec / Kill / Delete / Pause / Resume / State OCI runtime operations.

See https://github.com/opencontainers/runtime-spec/blob/main/runtime.md#operations

These functions are thin wrappers around the runc/crun operations of the same name.

oci_conmon_linux.go

Hold an implementation of the Create OCI runtime operation. This calls out to conmon, which in turn calls crun or runc.

conmon is used to manage logging and console streams for containers that are started backgrounded, so we don't have to do that ourselves.

oci_attach_linux.go

Implements an Attach function, which can attach the user's console to the streams of a container running in the background, which is being monitored by conmon.

Testing

End-to-end flows of basic OCI operations on an existing bundle are tested in the OCI group of the e2e suite, e2e/oci.

Launcher Flow

The Launcher type connects the standard singularity CLI actions (run/shell/exec), to execution of an OCI container in a native bundle. Invoked with the --oci flag, this is in contrast to running a Singularity format container, with Singularity's own runtime engine.

spec_linux.go

Provides a minimal OCI runtime spec, that will form the basis of container execution that is roughly comparable to running a native singularity container with --compat (--containall).

mounts_linux.go

Provides code handling the addition of required mounts to the OCI runtime spec.

process_linux.go

Provides code handling configuration of container process execution, including user mapping.

launcher_linux.go

Implements Launcher.Exec, which is called from the CLI layer. It will:

  • Create a temporary bundle directory.
  • Use pkg/ocibundle/native to retrieve the specified image, and extract it in the temporary bundle.
  • Configure the container by creating an appropriate runtime spec.
  • Call the interactive OCI Run function to execute the container with crun or runc.

Namespace Considerations

An OCI container started via Launch.Exec as a non-root user always uses at least one user namespace.

The user namespace is created prior to calling runc or crun, so we'll call it an outer user namespace.

Creation of this outer user namespace is via using the RunNS function, instead of Run. The RunNS function executes the Singularity starter binary, with a minimal configuration of the fakeroot engine ( internal/pkg/runtime/engine/fakeroot/config).

The starter will create a user namespace and ID mapping, and will then execute singularity oci run to perform the basic OCI Run operation against the bundle that the Launcher.Exec function has prepared.

The outer user namespace from which runc or crun is called always maps the host user id to root inside the userns.

When a container is run in --fakeroot mode, the outer user namespace is the only user namespace. The OCI runtime config does not request any additional userns or ID mapping be performed by crun / runc.

When a container is not run in --fakeroot mode, the OCI runtime config for the bundle requests that crun / runc:

  • Create another, inner, user namespace for the container.
  • Apply an ID mapping which reverses the 'fakeroot' outer ID mapping.

I.E. when a container runs without --fakeroot, the ID mapping is:

  • User ID on host (1001)
  • Root in outer user namespace (0)
  • User ID in container (1001)

Testing

End-to-end testing of the launcher flow is via the e2e/actions suite. Tests prefixed oci.