Skip to content

Application Descriptor Specifications

Introduction

ICOS is an agnostic Meta Operating System. The aim of this document is to define the minimalist syntax required to provide ICOS with an agnostic Application Descriptor manifest to run on the ICOS system.

Application model

An application is made of a set of components plus the interaction between them. Different entities that do not make sense separately (for instance a Deployment and a Service exposing it) should be defined as part of the same component. Therefore, they will run in the same resources (which could be a list of nodes in the same cluster).

Note

having two manifests that have requirements in the same component does not make sense, because in fact we created the component so that we can group together entities that do not need computational resources with entities that need them. (Aka. Docker compose does this grouping and calls it a service).

Overall structure of the application Descriptor File

It has 2 mandatory sections: components and manifests. And three optional: requirements, policies and communication.

name: uc4-app-emds
description: "the description"
namespace: uc4
components:
- name: house-component
  type: dcompose
  manifests:
  - name: house-manifest

manifests:
 # List of manifests in the specified format

Components section

For each component we need to specify a name, a list of manifests belonging to this component and the type of the orchestration engine that the manifests are prepared for.

name: my_application
description: "the description"
[namespace: optional-namespace]
components:  
- name: component-1
  type: dcompose
  manifests:
  - name: comp-1-manifest
- name: component-2
  type: kubernetes
  manifests:
  - name: comp-2-manifest-1
  - name: comp-2-manifest-2
- name: component-3
  type: multiple
  manifests:
  - name: comp-3-manifest1

Supported types are:

  • dcompose: A docker compose manifest is provided in the list of manifests.

  • kubernetes: A kubernetes manifest is provided.

  • multiple: Means that both a kubernetes and dcompose manifests are provided, this gives more flexibility to the icos system to schedule the components in any resource, regardless of the orchestration engine. Whereas if a component is specified type kubernetes, it can only be scheduled at kubernetes clusters

Note

In the current icos implementation it is not allowed to mix component types. I.e. if one of the components is type kubernetes, the rest should be either kubernetes or multiple, and the application will be scheduled at kubernetes clusters.

Requirements

Requirements section states the requested resources of the application. It can apply to all applications, in which case the section will appear at the same level as the components or to each component, in which case it will be specified under the component it applies to.

Note

At the moment the former option has not been implemented.

name: my_application
description: "my app description"
[namespace: optional-namespace]
components:
  - name: component-1
    type: dcompose
    manifests:
    - name: comp-1-manifest1
    requirements:
      architecture: intel
      cpu: 0.5
      memory: 200Mb
      nodelabel: 
        key: <node-label-key>
        values:
          - <node-label-robot1>
          - <node-label-robot2>
      devices: squat.ai/video
      replicas: 7

Accepted requirements are:

  • architecture: intel/x86_64 or arm64/aarch64

  • cpu: number of cpu cores requested.

  • memory: Amount of memory requested, the unit can be specified (following K8s syntax).

  • devices: devices that are necessary to be present for the component to run.

  • nodelabel: often the component is intended to run on specific nodes of the icos system (i.e. specific robots, specific houses, specific cars…). In that case a (key,value) pair can be specified to identify the nodes. Value can be a list of nodes, which would imply that replicas of the component will be deployed in all of the specified values (nodes)

  • replicas: specify the number of replicas of the component.

  • deployment/replicaset/job: to accommodate the k8s and dcompose workload types. If the previous requirements are specified under this tag it means that resources should be provided by the number of replicas specified but scheduled only once (i.e. the replicas are inside the manifest). See examples below.

A note on defining the requirements for the iCOS header

In k8s the smallest deployable units of computing are the Pods, therefore resources are allocated to Pods, whereas in ICOS the resource allocation unit is the component.

Because each container has its own resource needs, the user (Application developer) needs to abstract (add up) the needs of each container (which can be part of a workload management controller such as Deployment, ReplicaSets , Job in K8s…) that belong to the same component. Similarly, if a component contains several manifests each of them with their list of requirements, in the header the requirements for each manifest should be merged. I.e.

-  manifests:
    -   apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: comp-2-manifest1
          namespace: demo
          labels:
            app: video-producer
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: video-producer
          template:
            metadata:
              name: video-producer
              labels:
                app: video-producer
            spec:
              containers:
                - name: hello-cloud-one
                  image: busybox
                  command: [ 'sleep' ]
                  args: [ '100' ]
                  resources:
                   requests:
                    cpu: 0.5
                    memory: 200Mi
- manifests:
    -   apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: comp-2-manifest2
          namespace: demo
          labels:
            app: video-producer
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: video-producer
          template:
            metadata:
              name: video-producer
              labels:
                app: video-producer
            spec:
              containers:
                - name: hello-cloud-two
                  image: busybox
                  command: [ 'sleep' ]
                  args: [ '100' ]
                  resources:
                   requests:
                    cpu: 0.5
                    memory: 200Mi
                    squat.io/video: 1
Would result in a header like:

- name: component-2
    type: kubernetes
    manifests:
    - name: comp-2-manifest1
    - name: comp-2-manifest2
    requirements:
      devices: squat.ai/video
      cpu: 1
      memory: 400Mi

The implications of placing two manifests in the same component is that their requirements will be merged and a suitable target will be searched matching ALL the requirements from both components. Therefore, it is understood that if two manifests can run apart from each other they should belong to different components so that the matchmaking process has more options.

When considering replicas or workload management controller such as Deployment, ReplicaSets , Job that imply replicas for a better allocation they should belong to different components. Affinity between components can be specified in the communication section.

-  manifests:
     -  apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: comp-2-manifest1
          namespace: demo
          labels:
            app: video-producer
        spec:
          replicas: 5
          selector:
            matchLabels:
              app: video-producer
          template:
            metadata:
              name: video-producer
              labels:
                app: video-producer
            spec:
              containers:
                - name: hello-cloud-two
                  image: busybox
                  command: [ 'sleep' ]
                  args: [ '100' ]
                  resources:
                   requests:
                    cpu: 0.5
                    memory: 200Mi
                    squat.io/video: 1

Would result in a header like:

- name: component-2
    type: kubernetes
    manifests:
    - name: comp-2-manifest1
    - name: comp-2-manifest2
    requirements:
      deployment:
    replicas: 5
        devices: squat.ai/video
        cpu: 0.5
        memory: 200Mi
Note

the management of replicas has not been implemented.

From Docker compose to ICOS header

An example for Docker compose:

version: '3.8'
  services:
    frontend:
      image: example/webapp
      deploy:
        replicas: 6
        resources:
          reservations:
            cpus: '0.25'
            memory: 20M

The header would look like:

- name: component-1
    type: kubernetes
    manifests:
    - name: comp-1-manifest1
    requirements:
      deployment:
    replicas: 6
        cpu: 0.25
        memory: 20Mi

Scheduling or runtime?

When are requirements taken into account? In the current version at scheduling time only. However some of the requirements could be monitored and enforced at runtime too, in any case the remediation action to take would be defined by icos (i.e. migrate).

Policies

Policies are more dynamic than requirements. They are rules that can be defined by the user. As requirements, policies can be inside a component or outside if they apply to all the applications.

The syntax is as follows:

policies:
  - name: policy-name
    type: policy-type

The rest of the dictionary entries depending on the type of policy. Supported types:

  • Security

  • Scheduler

  • Custom

Security policy

policies:
  - name: securitypolicyexample
    type: security
    level:low    # or médium high
    [remediation_action: none # or default or migrate
    functionality: encription]

Security level specifies the minimal security level for the application to run: low, medium or high. The system will define the thresholds.

Note

TODO: Provide a description for the meaning of each level (low, medium, high) in terms of usability (storage encryption or vulnerability level of the node)

Scheduling time or runtime? both

Custom policy

The metric and remediation action are provided by the user. Only runtime.

policies:
  - name: my-policy
    type: custom
    fromTemplate: compss-under-allocation
    remediation: scale-up
    variables:
      thresholdTimeSeconds: 120
      compssTask: provesOtel.example_task

Scheduling policy

Scheduling policy is checked at scheduling type. It defines the scheduling strategy to use.

policies:
  - name: scheduling-scoring
    type: scheduler
    algorithm: scoring
    performance: 0.5
    energyconsumption: 0.3
    security:0.1

Comunication

This section specifies the relationship between the components in terms of communication between them (this is necessary in case the components run in different clusters so that ClusterLink can be set up). It will also be used at scheduling time to find a more accuratel allocation.

dependencies:
# any random name, can be optional
  - name: ffmpeg-export
# name of the service that is exported, has to map to the service name defined in manifest
    exportServiceName: mjpeg-service
# name of the component that the service belongs to, is used to determine where the export is created
    exportingComponent: ffmpeg
# defines the port for the import and export (same for both)
    port: 8080
# name of the component that the service has to be imported for, is used to determine where the import is created
    importingComponent: mjpeg