Solution archive guidelines¶
To provide a predictable interface with packaged Solutions, MetalK8s expects a few criteria to be respected, described below.
Archive format¶
Solution archives must use the ISO-9660:1988 format, including Rock Ridge and Joliet directory records. The character encoding must be UTF-8. The conformance level is expected to be at most 3, meaning:
Directory identifiers may not exceed 31 characters (bytes) in length
File name +
'.'
+ file name extension may not exceed 30 characters (bytes) in lengthFiles are allowed to consist of multiple sections
The generated archive should specify a volume ID, set to
{project_name} {version}
.
Todo
Clarify whether Joliet/Rock Ridge records supersede the conformance level w.r.t. filename lengths
Here is an example invocation of the common Unix mkisofs tool to generate such archive:
mkisofs
-output my_solution.iso
-R # (or "-rock" if available)
-J # (or "-joliet" if available)
-joliet-long
-l # (or "-full-iso9660-filenames" if available)
-V 'MySolution 1.0.0' # (or "-volid" if available)
-gid 0
-uid 0
-iso-level 3
-input-charset utf-8
-output-charset utf-8
my_solution_root/
Todo
Consider if overriding the source files UID/GID to 0 is necessary
File hierarchy¶
Here is the file tree expected by MetalK8s to exist in each Solution archive:
.
├── images
│ └── some_image_name
│ └── 1.0.1
│ ├── <layer_digest>
│ ├── manifest.json
│ └── version
├── manifest.yaml
├── operator
| └── deploy
│ ├── crds
│ │ └── some_crd_name.yaml
│ └── role.yaml
└── registry-config.inc
Product information¶
General product information about the packaged Solution must be stored in the
manifest.yaml
file, stored at the archive root.
It must respect the following format (currently
solutions.metalk8s.scality.com/v1alpha1
, as specified by the
apiVersion
value):
apiVersion: solutions.metalk8s.scality.com/v1alpha1
kind: Solution
metadata:
annotations:
solutions.metalk8s.scality.com/display-name: Solution Name
labels: {}
name: solution-name
spec:
images:
- some-extra-image:2.0.0
- solution-name-operator:1.0.0
- solution-name-ui:1.0.0
operator:
image:
name: solution-name-operator
tag: 1.0.0
version: 1.0.0
It is recommended for inspection purposes to include some annotations related
to the build-time conditions, such as the following (where command invocations
should be statically replaced in the generated manifest.yaml
):
solutions.metalk8s.scality.com/build-timestamp: \
$(date -u +%Y-%m-%dT%H:%M:%SZ)
solutions.metalk8s.scality.com/git-revision: \
$(git describe --always --long --tags --dirty)
A simple script to generate this manifest can be found in MetalK8s repository examples/metalk8s-solution-example/manifest.py, use it as follows:
./manifest.py --name "example-solution" \
--annotation "solutions.metalk8s.scality.com/build-timestamp" \
"$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--annotation "solutions.metalk8s.scality.com/build-host" "$(hostname)" \
--annotation "solutions.metalk8s.scality.com/development-release" "1" \
--annotation "solutions.metalk8s.scality.com/display-name" "Example Solution" \
--annotation "solutions.metalk8s.scality.com/git-revision" \
"$(git describe --always --long --tags --dirty)" \
--extra-image "base-server" "0.1.0-dev" \
--operator-image "example-solution-operator" "0.1.0-dev" \
--ui-image "example-solution-ui" "0.1.0-dev" \
--version "0.1.0-dev"
OCI images¶
MetalK8s exposes container images in the OCI format through a static
read-only registry. This registry is built with nginx, and relies on having
a specific layout of image layers to then replicate the necessary parts of the
Registry API that CRI clients (such as containerd
or cri-o
) rely on.
Using skopeo, images can be saved as a directory of layers:
$ mkdir images/my_image
$ # from your local Docker daemon
$ skopeo copy --format v2s2 --dest-compress docker-daemon:my_image:1.0.0 dir:images/my_image/1.0.0
$ # from Docker Hub
$ skopeo copy --format v2s2 --dest-compress docker://docker.io/example/my_image:1.0.0 dir:images/my_image/1.0.0
The images
directory should now resemble this:
images
└── my_image
└── 1.0.0
├── 53071b97a88426d4db86d0e8436ac5c869124d2c414caf4c9e4a4e48769c7f37
├── 64f5d945efcc0f39ab11b3cd4ba403cc9fefe1fa3613123ca016cf3708e8cafb
├── manifest.json
└── version
Once all the images are stored this way, de-duplication of layers can be done with hardlinks, using the tool hardlink:
$ hardlink -c images
A detailed procedure for generating the expected layout is available at
NicolasT/static-container-registry. The script provided there,
or the one vendored in this repository (located at
buildchain/static-container-registry
) can be used to generate the NGINX
configuration to serve these image layers with the Docker Registry API.
MetalK8s, when deploying the Solution, will include the registry-config.inc
file provided at the root of the archive. In order to let MetalK8s control
the mountpoint of the ISO, the configuration must be generated using the
following options:
$ ./static-container-registry.py \
--name-prefix '{{ repository }}' \
--server-root '{{ registry_root }}' \
/path/to/archive/images > /path/to/archive/registry-config.inc.j2
Each archive will be exposed as a single repository, where the name will be
computed as <metadata:name>-<spec:version>
from
Product information, and will be mounted at
/srv/scality/<metadata:name>-<spec:version>
.
Warning
Operators should not rely on this naming pattern for finding the images for their resources. Instead, the full repository endpoints will be exposed to the Operator container through a configuration file passed to the operator binary. See Solution Operator guidelines for more details.
The images names and tags will be inferred from the directory names chosen when
using skopeo copy
. Using hardlink is highly recommended if one wants to
define alias tags for a single image.
MetalK8s also defines recommended standards for container images, described in Container Images.
Operator¶
See Solution Operator guidelines for how the /operator
directory should be
populated.
Web UI¶
Todo
Create UI guidelines and reference here