Skip to content

Latest commit

 

History

History
400 lines (319 loc) · 20.5 KB

6.application_configuration.md

File metadata and controls

400 lines (319 loc) · 20.5 KB

6. Application Configuration

This section describes how applications are deployed using application configurations.

A component schematic can be deployed into any number of runtimes, any number of times. We call each deployment of a component an instance. Each time a component is deployed, it must be deployed with a configuration. This section of the specification describes configurations.

An application configuration (sometimes abbreviated to configuration) is managed by the app operator role, and provides information specific to the current instance of a component. The following information is considered specific to the runtime instance of a component:

  • Information about this particular instance, such as:
    • Name
    • Release version
    • Description
  • Values for the defined parameters for a component, and for its respective components
  • Trait assignments to add operational functionality, together with any trait configuration

Instances and upgrades

An instance is a trackable deployment of an application configuration. A component instance is an instance of a component that is created during the deployment of an application configuration. It is created when a component is deployed together with a configuration. Each subsequent upgrade of a component modifies the given instance. And each subsequent upgrade of an application configuration can modify any of the component instances controlled by that application configuration. For the purposes of this specification, workflow practices such as rollback or redeploy are considered to be special cases of upgrade (that is, if the rules here apply to upgrade, they also apply to the other workflow practices). When a deployment of a component is deleted, the instance is considered to be deleted. This does not, however, imply that all data related to the instance must be deleted, or that deletion events cannot be recovered or undone.

When an instance is first created, it is in its initial release state. Each time an upgrade operation occurs, we say that a new release of that instance occurs. (There is, however, no assumption that there is a corresponding release object stored somewhere).

Releases

In 12 factor applications, a release is defined as a build plus a set of configs. That is, any change to either a build or configuration produces a new release. In the Open Application Model, the analog is that component, trait, and scope definitions combined with an application configuration jointly constitute a release.

For OAM applications, release is defined thus:

A release is a named application configuration, together with its description of correlated components, scopes, and traits

In addition, as an application configuration is released, its component instances (running copies of a named component) are also released.

To accommodate this definition of a release, an OAM platform SHOULD make the following assumptions:

  • A component schematic (as defined in the component model section) is immutable. It should not be changed after creation.
  • Any change to an application configuration results (conceptually) in a new release that supersedes older releases.
    • If an application configuration is updated, and the new version includes components not present in the original application configuration, component instances MUST be created
    • If an application configuration is updated, and the new version does not have a record of a component that the previous application configuration contained, that component instance MUST be deleted
    • Traits similarly SHOULD be attached and detached according to the same guidelines
    • Components' relationships to Application Scopes SHOULD be applied or removed according to the same guidelines

Runtime and Application Configuration

The Component Model chapter of the specification defines how schematics are constructed. The resulting schematics may then be used to instantiate a component on a OAM-compliant runtime.

Component schematics can be deployed into numerous different runtimes. But at runtime, there is a one-to-one correspondence between an instance of an configuration and an application configuration.

Conceptually speaking, an application configuration is managed as part of the application operator role. It has three main sections:

  • Parameters that can be supplied by an application operator at deployment time.
  • A list of application scopes, each of which has overrides for that scope's parameters.
  • Component instance definition that defines how an instance of a component spec should be deployed. This section itself has three parts:
    • Overrides of component parameters
    • A list of traits, each of which has overrides for that trait's parameters.
    • A list of application scopes that the component should be deployed into.

Defining an application configuration

Top-Level Attributes

The top-level attributes of a application configuration define its metadata, version, kind, and spec.

Attribute Type Required Default Value Description
apiVersion string Y The specific version of the specification in use. At present only core.oam.dev/v1alpha1 is defined.
kind string Y The string ApplicationConfiguration
metadata Metadata Y Application configuration metadata.
spec Spec Y A container for exposing application configuration attributes.

Spec

The specification defines three major things: Parameters that can be overridden at deployment time, a set of scopes to create, and component instances to create.

Attribute Type Required Default Value Description
variables []Variable N Variables that can be referenced in parameter values and properties.
scopes []Scope N Application scope definitions. If defined, scopes are accessible by components from any other application configurations.
components []Component N Component instance definitions.

Variable

The Variables section defines variables that may be used elsewhere in the application configuration. The variable section provides a way for an application operator to specify common values that can be substituted into multiple other locations in this configuration (using the [fromVariable(VARNAME)] syntax).

Attribute Type Required Default Value Description
name string Y The parameter's name. Must be unique per configuration.
value string Y The scalar value.

A name is any Unicode letter or numeric character, _, -, and .. A value is any sequence of printable Unicode characters.

The function [fromVariable(VARNAME)] (where VARNAME corresponds to the name field in a variable definition) may be used in predefined locations (parameter values and properties objects) to access the value of a parameter.

Scope

The scope section defines application scopes that will be created with this application configuration.

Attribute Type Required Default Value Description
name string Y The name of the application scope. Must be unique to the deployment environment.
type string Y The fully-qualified GROUP/VERSION.KIND name of the application scope.
properties Properties N Overrides of properties that are exposed by this scope.

The name field must be 63 characters or less, beginning and ending with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.), and alphanumerics between.

Component

This section defines the instances of components to create with this application configuration.

Attribute Type Required Default Value Description
componentName string Y The name of the component to create an instance of.
instanceName string Y The name of the instance of this component.
parameterValues []ParameterValue N Overrides of parameters that are exposed by the application scope type defined in type.
traits []Trait N Specifies the traits to attach to this component instance.
applicationScopes []string N Specifies the application scopes that the component should be deployed into. Each item is a name referenced to the pre-defined Scopes.

In addition to being unique, the instanceName must follow these naming rules:

The componentName field is required and must be 63 characters or less, beginning and ending with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.), and alphanumerics between.

The instanceName segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.), and alphanumerics between.

Trait

The trait section defines an instance of a trait and its properties (parameter overrides).

Attribute Type Required Default Value Description
name string Y The name of the Trait. This is used to reference to the definition/schema of the Trait. For one type of trait, there could be only one config/deploy in one component.
properties Properties N Overrides of properties that are exposed by this trait.

The name field is required and must be 63 characters or less, beginning and ending with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), underscores (_), dots (.), and alphanumerics between.

Properties

A properties object (for trait and scope configuration) is an object whose structure is determined by the trait or scope property schema. It may be a simple value, or it may be a complex object.

Properties are validated against the schema appropriate for the trait or scope.

For example, if a trait defines a schema for properties that requires an array of integers with at least one member, the properties object is expected to be an array of integers with at least one member. During validation of the properties object, the trait's property schema will be applied.

If no schema is supplied, a property will be passed to the trait runtime without structural validation. As long as it parses as YAML or JSON, it will be considered valid.

Any string value in a properties object MAY contain a [fromVariable(VARNAME)] function call.

ParameterValue

Values supplied to parameters that are used to override the parameters exposed by other types.

Attribute Type Required Default Value Description
name string Y The name of the component parameter to provide a value for.
value string N The value of this parameter.

A name is any Unicode letter or numeric character, _, -, and .. A value is any sequence of printable Unicode characters.

The value field allows use of the [fromVariable(VARNAME)] function.

Example

The following is an example of a complete YAML file that expresses configuration and traits. This example illustrates the four configurational elements above.

apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
  name: my-app-deployment
  annotations:
    version: v1.0.0
    description: "Description of this deployment"
spec:
  variables:
    - name: VAR_NAME
      value: SUPPLIED_VALUE
  scopes:
    - name: core.oam.dev/v1alpha1.Network
      parameterValues:
        - name: PARAM_NAME
          value: SUPPLIED_VALUE
  components:
    - componentName: my-web-app-component
      instanceName: my-app-frontent
      parameterValues:
        - name: PARAMETER_NAME
          value: SUPPLIED_VALUE
        - name: ANOTHER_PARAMETER
          value: "[fromVariable(VAR_NAME)]"
      traits:
        - name: Ingress
          properties:
            CUSTOM_OBJECT:
              DATA: "[fromVariable(VAR_NAME)]"
              

The example above illustrates a complete application configuration scopes, component instances, their traits, and parameter overrides that allow users to specify values at deployment time from the command line.

An Example Workflow

This section is non-normative. OAM compliant tooling need not implement this section.

This section uses a fictional tool called oamctl to illustrate a workflow pattern for OAM app operations.

Deploying two components with parameter overrides

The following example shows two separate components:

  • a front-end web app in a container, run as a core Server workload type
  • a back-end Cassandra database, represented by an extended workload type.
apiVersion: core.oam.dev/v1alpha1
kind: ComponentSchematic
metadata:
  name: frontend
  annotations:
    version: v1.0.0
    description: "A simple webserver"
spec:
  workloadType: core.oam.dev/v1.Server
  parameters:
    - name: message
      description: The message to display in the web app.
      type: string
      value: "Hello from my app, too"
  containers:
    - name: web
      env:
        - name: MESSAGE
          fromParam: message
      image:
        name: example/charybdis-single:latest
apiVersion: core.oam.dev/v1alpha1
kind: ComponentSchematic
metadata:
  name: backend
  annotations:
    version: v1.0.0
    description: "Cassandra database"
spec:
  workloadType: data.oam.dev/v1.Cassandra
  parameters:
    - name: maxStalenessPrefix
      description: Max stale requests.
      type: int
      value: 100000
    - name: defaultConsistencyLevel
      description: The default consistency level
      type: string
      value: "Eventual"
  workloadSettings:
    - name: maxStalenessPrefix
      fromParam: maxStalenessPrefix
    - name: defaultConsistencyLevel
      fromParam: defaultConsistencyLevel

Note that each component allows certain parameters to be overridden. For example, the message parameter is exposed for configuration in the frontend component. Within the component config, the parameter is piped to an environment variable where the component code can read the value.

Components can be designed for reuse by expose such parameters, as these parameters can be tweaked for different deployment scenarios.

An application configuration combines any number of components and sets operational characteristics and configuration for a deployed instance of each component.

apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
  name: custom-single-app
  annotations:
    version: v1.0.0
    description: "Customized version of single-app"
spec:
  variables:
    - name: message
      value: "Well hello there"
  components:
    - componentName: frontend
      instanceName: web-front-end
      parameterValues:
        - name: message
          value: "[fromVariable(message)]"

In this example, the ops config allows a user to override only one of the parameters in the frontend component, and it does not allow the user to change any of the backend parameters. This allows the author of this ops config to control configuration options for the components therein.

The operator can now deploy the components together with this configuration to create running instances of the components:

$ oamctl install -c ./config.yaml ./frontend.yaml ./backend.yaml -p "message=overridden message!"

Adding traits to the components

Traits are attached by application operators. In the next part of this example, traits are added to the two components defined previously.

Our system supports a few different traits:

$ oamctl trait-list
╔════════════╤═════════╤═════════════════════════════════════════════╗
║ NAME       │ VERSION │ PRIMITIVES                                  ║
╟────────────┼─────────┼─────────────────────────────────────────────╢
║ autoscaler │ 0.1.0   │ Server, Worker                              ║
╟────────────┼─────────┼─────────────────────────────────────────────╢
║ ingress    │ 0.1.0   │ SingletonServer, Server                     ║
╚════════════╧═════════╧═════════════════════════════════════════════╝

Here is how the previous application configuration looks with an Ingress trait attached to the front-end component:

apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
  name: custom-single-app
  annotations:
    version: v1.0.0
    description: "Customized version of single-app"
spec:
  variables:
    - name: message
      value: "Well hello there"
    - name: domainName
      value: "www.example.com"
  components:
    - componentName: frontend
      instanceName: web-front-end
      parameterValues:
        - name: message
          value: "[fromVariable(message)]"
      traits:
        - name: Ingress
          properties:
            - name: host
              from: domainName
            - name: path
              value: "/"

This example attaches an ingress to route traffic from another network (public, perhaps) to the internal service. This configuration shows how the trait is both attached and configured. In this example, a new parameter named domainName is added to the application configuration, allowing a user to override the host parameter of the ingress trait.

An implementation of this would then direct inbound traffic bound for www.example.com to the front-end component.

Placing components into application scopes

Up to this point, the frontend component is deployed into the default "root" network and health scopes, as all core workload types are required to be in all core application scope types.

The backend component is an extended workload type and is therefore not automatically deployed into the default "root' application scopes.

In this example, a network scope is defined and attached to an SDN. Both components are then added to the same network scope for direct network connectivity and a shared set of network policies that can be defined by the infrastructure operator on the SDN itself. The SDN name is parameterized in the application configuration to allow an application operator to deploy this configuration into any SDN.

apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
  name: my-vpc-network
spec:
  variables:
    - name: networkName
      value: "my-vpc"
  scopes:
    - name: network
      type: core.oam.dev/v1alpha1.Network
      properties:
        - name: network-id
          value: "[fromVariable(networkName)]"
        - name: subnet-id
          value: "my-subnet"
---
apiVersion: core.oam.dev/v1alpha1
kind: ApplicationConfiguration
metadata:
  name: custom-single-app
  annotations:
    version: v1.0.0
    description: "Customized version of single-app"
spec:
  variables:
    - name: message
      value: "Well hello there"
    - name: domainName
      value: "www.example.com"
  components:
    - componentName: frontend
      instanceName: web-front-end
      parameterValues:
        - name: message
          value: "[fromVariable(message)]"
      traits:
        - name: Ingress
          properties:
            - name: host
              value: "[fromVaraible(domainName)]"
            - name: path
              value: "/"
      applicationScopes:
        - my-vpc-network

    - componentName: backend
      instanceName: database
      applicationScopes:
        - my-vpc-network

This example now shows a complete installation of the application configuration composed of two components, an ingress trait, and a network scope with parameters exposed to an application operator to customize the domain name, the network to deploy it to, and a custom message for the web front end to display.

Tables Next
5. Traits 7. Workload Types