Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Process

In general, the process to build a multiplatform-cpu architecture agnostic container image follows the flow depicted on the following figure.

The commands to needed to implement the flow are described, using an example, in the next section.

...

Gliffy Diagram
namebuilding-multi-cpu-container-image
pagePin79

Example

...

using a Python Micro-Service

Main steps

The following diagram captures the main steps we need to take to enable platform-agnostic containers:

(1) and (2) Build and push container images for each platform.

(3)  Create and push a manifest list for the images above

(4) Pull and run the exact same image/tag  on different platforms.

Gliffy Diagram
size1200
nameparis-f2f-workshop
pagePin17

Manifest List and Image Layers

Digging a little bit deeper into step (4), the following diagram shows the relationship between a manifest list and image manifests for our platform-agnostic image (tag).


Gliffy Diagram
nameoci-fat-manifest
pagePin6




The following sections describe the commands needed to create a multi-cpu architecture container image. Let's call the image onap/py-app.

Note that this flow could be used by ONAP developers during the development-test-debug process.

For the release process, the flow will implemented using CI/CD pipelines as shown in the next section.

Source code

Code structure

Code Block
.
├── app
│   ├── main.py
│   └── requirements.txt
└── Dockerfile


Python App

Code Block
from flask import Flask
import platform
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello ONAP. I am a Python service running on " + platform.machine()

if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=True, port=5000)

Requirements

Code Block
Flask==0.10.1


Dockerfile

Code Block
FROM python:2.7-alpine

LABEL maintainer="adolfo@orangemonk.net"

# Keep it simple

COPY ./app /app
WORKDIR /app
RUN pip install -r requirements.txt

ENTRYPOINT ["python"]
CMD ["main.py"]


Build arm image (A)

Log into an arm server, copy the code into the structure depicted above.

cd to the root of the code tree above,  then execute

Code Block
docker build -t onap/py-app-arm64 .

Push arm image to the registry

Once the image has been successfully built, push it to the repository.

Note that if you are using a private repository, you might need to "docker tag" the image before executing the next command.

Code Block
docker push onap/py-app-arm64v8:latest

Build Intel image (B)

Log into an intel server, setup the code structure as before.

Let's now repeat the process for the intel layers of the multi-cpu container image.

Code Block
docker build -t onap/py-app-amd64 .

Push Intel image to the registry

Code Block
docker push onap/py-app-amd64:latest

Create a manifest list for image A and image B

Now that we have built and pushed layers for each cpu architecture, we can create the manifest list to put the final container image together with

Code Block
docker manifest create onap/py-app \ 

Following are the commands you need to create a multi-cpu architecture container image. Let's call the image onap/multi-cpu-app-py

Note that this flow can be used during the ONAP development-test-debug process. For the release process, the flow is implemented using CI/CD pipelines as shown in the next section.

Build arm image (A)

Code Block
docker build -t onap/app-py-arm-linux .

Push arm image to the registry

Code Block
docker push onap/app-py-arm-linux:latest

Build Intel image (B)

Code Block
docker build -t onap/app-py-amd-linux .

Push Intel image to the registry

Code Block
docker push onap/app-py-amd-linux:latest

Create the manifest list for image A and image B

Code Block
docker manifest create onap/multi-cpu-app-py \ 
                       onap/app-py-arm-linux \ 
                       onap/app-py-amd-linux 

Inspect the multi-cpu architecture manifest

Code Block
docker manifest inspect --verbose onap/multi-cpu-app-py

Notice how the the manifest shows layers for both arm and Intel cpu architectures.

Code Block
[
    {
        "Ref": "docker.io/onap/app-py-amd-linux:latest",
        "Descriptor": {
            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "digest": "sha256:4b1b8361d47770668ff4c728dc388f376158d9e8d82c0b4cdb22147cc8ca1be6",
            "size": 1579,
            "platform": {
                "architecture": "amd64",
                "os": "linux"
            }
        },onap/py-app-arm64v8 \ 
        "SchemaV2Manifest": {
            "schemaVersion":  onap/py-app-amd64 


Verify that the manifest describes a platform-agnostic container image.


Code Block
docker manifest inspect --verbose onap/py-app


Verify that the manifest actually represents a multi-cpu architecture by looking at the different "platform" entries.

Notice how, in this case, the manifest shows layers for both arm and Intel cpu architectures.


Code Block
[2,
            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
    {
        "configRef": {"docker.io/onap/py-app-amd64:latest",
        "Descriptor": {
            "mediaType": "application/vnd.docker.containerdistribution.imagemanifest.v1v2+json",
                "sizedigest": 6616"sha256:4b1b8361d47770668ff4c728dc388f376158d9e8d82c0b4cdb22147cc8ca1be6",
                "digestsize": "sha256:f2947f4a0e9d5d0a4ccf74a7b3ad94611a8921ca022b154cabcad9e453ea6ec5"1579,
            },
"platform": {
                "layersarchitecture": ["amd64",
                {"os": "linux"
            }
        "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip"},
          "SchemaV2Manifest": {
            "sizeschemaVersion": 22069312,
                    "digestmediaType": "sha256:4fe2ade4980c2dda4fc95858ebb981489baec8c1e4bd282ab1c3560be8ff9bde"application/vnd.docker.distribution.manifest.v2+json",
                },"config": {
                {
                    "mediaType": "application"mediaType": "application/vnd.docker.container.image.rootfs.diff.tar.gzipv1+json",
                    "size": 3089726616,
                    "digest": "sha256:1b23fa3ccba56eced7bd53d424b29fd05cd66ca0203d90165e988fdd8e71fed7f2947f4a0e9d5d0a4ccf74a7b3ad94611a8921ca022b154cabcad9e453ea6ec5"
                },
            "layers": [
   {
             {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 177117802206931,
                    "digest": "sha256:b714494d7662fbb89174690cefce1051117ed524ec7995477b222b8d96fb8f0c4fe2ade4980c2dda4fc95858ebb981489baec8c1e4bd282ab1c3560be8ff9bde"
                },
                {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 1776866308972,
                    "digest": "sha256:1098418f3d2f83bcccdbb3af549d75d9a5e9c37420e5c0d474fd84b022f6c9951b23fa3ccba56eced7bd53d424b29fd05cd66ca0203d90165e988fdd8e71fed7"
                },
                {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 36017711780,
                    "digest": "sha256:ca727cee7c2469ab6edb7ca86378985b3747938a325ddb7d90f3b85a3d14b34fb714494d7662fbb89174690cefce1051117ed524ec7995477b222b8d96fb8f0c"
                },
                {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 43155531776866,
                    "digest": "sha256:767bbe8ba063767093b0350e8d1b86b438c677e3884c2a21851c00970d88317c1098418f3d2f83bcccdbb3af549d75d9a5e9c37420e5c0d474fd84b022f6c995"
                },
            ]
    {
    }
    },
    {
        "RefmediaType": "application/vnd.docker.io/onap/app-py-arm-linux:latest.image.rootfs.diff.tar.gzip",
        "Descriptor": {
            "mediaTypesize": "application/vnd.docker.distribution.manifest.v2+json"360,
                    "digest": "sha256:8a06f997353177dae82d7e01bc3893b2f05c6ac27b317655df3ca2287f9b83a9ca727cee7c2469ab6edb7ca86378985b3747938a325ddb7d90f3b85a3d14b34f",
               "size": 1786},
            "platform":     {
                    "architecturemediaType": "arm64application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "ossize": "linux"4315553,
             }
        },
"digest": "sha256:767bbe8ba063767093b0350e8d1b86b438c677e3884c2a21851c00970d88317c"
         "SchemaV2Manifest": {
      }
      "schemaVersion": 2      ]
        }
    },
    {
        "mediaTypeRef": "application/vnd.docker.distribution.manifest.v2+jsondocker.io/onap/py-app-arm64v8:latest",
            "configDescriptor": {
                ""mediaType": "application/vnd.docker.containerdistribution.imagemanifest.v1v2+json",
                "sizedigest": 6864"sha256:8a06f997353177dae82d7e01bc3893b2f05c6ac27b317655df3ca2287f9b83a9",
                "digestsize": "sha256:b097a21c92a9a0dde06f9b36bf10def56a028b3b9b1617d6d6c6a8559d14d9d7"1786,
            },
"platform": {
                "layersarchitecture": ["arm64",
                {
 "os": "linux"
            }
       "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip" },
        "SchemaV2Manifest": {
            "sizeschemaVersion": 20995142,
            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "digestconfig": "sha256:47e04371c99027fae42871b720fdc6cdddcb65062bfa05f0c3bb0a594cb5bbbd"{
                } "mediaType": "application/vnd.docker.container.image.v1+json",
                {
    "size": 6864,
                "mediaTypedigest": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"sha256:b097a21c92a9a0dde06f9b36bf10def56a028b3b9b1617d6d6c6a8559d14d9d7"
            },
            "sizelayers": 176,[
                {
    "digest": "sha256:b4103359e1ecd9a7253d8b8a041d4e81db1ff4a5e1950bc0e02305d221c9e6c2"
                }"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                {
    "size": 2099514,
                    "mediaTypedigest": "application/vnd.docker.image.rootfs.diff.tar.gzip",sha256:47e04371c99027fae42871b720fdc6cdddcb65062bfa05f0c3bb0a594cb5bbbd"
                    "size": 308518},
                {
    "digest": "sha256:92079a442932f09a622f4a0f863e5cc2f6e0471a98e5121fa719d2a276440386"
                },
                {
                    "mediaType": ""mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 18605961176,
                    "digest": "sha256:f1fc35806f46347993a2cd1eb7f7dd7837b0bef0392c8e2c973b24c02ad874a9b4103359e1ecd9a7253d8b8a041d4e81db1ff4a5e1950bc0e02305d221c9e6c2"
                },
                {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 1786389308518,
                    "digest": "sha256:c2983ee3d71107a9a0bc1996fc3a58e050026995fad4aee9d72539153db1df3d92079a442932f09a622f4a0f863e5cc2f6e0471a98e5121fa719d2a276440386"
                },
                {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 39118605961,
                    "digest": "sha256:44c3eae5ed66bb040727a64fd78573fe6cc4a94a9317d5cd6f39e53332c2ae21f1fc35806f46347993a2cd1eb7f7dd7837b0bef0392c8e2c973b24c02ad874a9"
                },
                {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 43055581786389,
                    "digest": "sha256:8daa79c3024a565c320ff69990ad48273937cc3f6f0cdb324e086c268cf6245ec2983ee3d71107a9a0bc1996fc3a58e050026995fad4aee9d72539153db1df3d"
                },
               ]
 {
                    }
    }
]


Building Multi-CPU container images using CI/CD pipelines

The following diagram depicts a CI/CD flow that implements the production of multi-cpu architecture container images.

Although the flow shows a pipeline for two branches: arm-linux and intel-linux, the model can be extended --given the hardware and software resources-- to any number of platforms.

"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 391,
                    "digest": "sha256:44c3eae5ed66bb040727a64fd78573fe6cc4a94a9317d5cd6f39e53332c2ae21"
                },
                {
                    "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
                    "size": 4305558,
                    "digest": "sha256:8daa79c3024a565c320ff69990ad48273937cc3f6f0cdb324e086c268cf6245e"
                }
            ]
        }
    }
]




Push the manifest list to the registry

Code Block
docker manifest push onap/py-app


Building Multi-CPU container images using CI/CD pipelines


The following diagram depicts a CI/CD flow that implements the production of multi-cpu architecture container images.

Although the flow shows a pipeline for two branches: arm-linux and intel-linux, the model can be extended --given the hardware and software resources-- to any number of platforms.


Gliffy Diagram
nameonap-multi-cpu-images-ci-cd
pagePin3
version1


The following view illustrates intermediate step of building and storing executable and sequence of image processing

Gliffy Diagram
nameonap-multi-cpu-images-ci-cd
pagePin3

Intermediate Image Naming Convention

As described above, platform-agnostic support requires platform specific images that are put together to expose a multi-platform image. Platform architectures include, among others, arm,intel, mips, ppc64le, and s390x

These platform-specific image names are typically used only by developers that build the images. ONAP end users should only use the aggregate tag but can still inspect the image using docker manifest.

The following is the recommended naming convention for ONAP platform-specific images that will be produced by the different pipelines (<onap-image-name>). This convention is aligned with existing industry standards and naming conventions (amd64, arm64v8).


ArchitectureOSVariantImage Name
amd64Linux
<onap-image-name>-amd64
arm64Linuxv8<onap-image-name>-arm64v8
mipsLinux
<onap-image-name>-mips


Note: This table does not contain a exhaustive list of options and must only be used as an image naming guide. Because ONAP is vendor-agnostic, the list is not a statement of what architectures or OSs ONAP must support. Gliffy Diagramnameonap-multi-cpu-images-ci-cdpagePin1