Open Application Model: Build the Next Generation of Cloud Native Applications
Back in October 2019, Microsoft and Alibaba Cloud jointly announced The Open Application Model which is a standard, platform-agnostic way to describe cloud and edge applications. The main goal of OAM is pretty much twofold:
- Provide a standard application context for any microservice platform
- Define a team-centric model that supports a clear separation of concerns between developers and operators.
We believe that it is important to have a clear definition of an “application” on infrastructure oriented platforms like Kubernetes. We also observed that there are common functional roles in most modern cloud native application development environments. Thus, we formally defined three roles in our Open Application Model, namely application developer, application operator, and infrastructure operator.
What We’ve Worked on Since Then
After releasing the v1alpha1 version of the specification, we immediately started to work with the OAM community both internally and externally. While OAM got some early adopters like Alibaba Cloud’s Enterprise Distributed Application Service (EDAS), we quickly realized that we need to continue to evolve the OAM model.
OAM was designed to be an extendable model at its core so that each platform can choose to expose their unique features and capabilities through a standard application model without being restricted to a “lowest-common-denominator” feature set. However, we realized we need to further improve the extensibility of the model so that it can seamlessly describe any resources native to its specific platform, cloud or edge.
In the next few months, together with crossplane maintainers from upbound, we set out to design the next milestone of the specification. After numerous rounds of discussions and sometimes spirited debate, we are happy to announce that the OAM specification is now at v1alpha2. The new draft of OAM introduces new features that greatly improve its adaptability for various platforms.
Deep Dive into OAM v1Alpha2
As we mentioned, the new OAM specification is more extensible and more friendly to any platform that implements it. We achieved this by introducing several types of resources that replaced the existing ones in v1Alpha1 specification.
First, let us take a look at a diagram that depicts the relations between various OAM resources in the v1alpha2 specification.
We can see that there are four categories of OAM resources and we will use an example to introduce each of them step by step. You can refer back to this diagram from time to time to see how each piece fits in the overall picture.
We replaced the workload resource in v1alpha1 with WorkloadDefinition. A workloadDefinition is a way for an infrastructure operator or platform builder to define what workloads are available to application developers on a given platform. It also serves as a “registration” for native resource definitions to the OAM in the new specification.
Here are some workloadDefinition examples.
A workloadDefinition contains a reference to a native resource definition. Specifically, they can be customer resource definitions in the Kubernetes ecosystem. With the upgraded workloadDefinition, OAM platform builders can now seamlessly import any native resource as an OAM workload by creating a corresponding workloadDefinition. A workloadDefinition can contain optional metadata fields so it also serves as a resource registration for OAM platforms. OAM users can list all the workloadDefinitions in the system with descriptions.
We replaced the componentSchematic in v1alpha1 with component. A component describes a functional unit that may be instantiated as part of a larger distributed application. For example, each microservice in an application is described as a component.
Here is a component example that includes a partially instantiated workload.
A component has two major parts.
- Workload: This sector contains an instantiation of the schema referenced by the corresponding workloadDefinition. Specifically, this is a custom resource corresponding to a custom resource definition referenced in the workloadDefinition in the Kubernetes ecosystem. In this example, the workload part instantiated the ContainerizedWorkload that is referenced in the corresponding workloadDefinition.
- Parameters: this sector defines all of the configurable parameters for this component. This is one way for the application developers to leave operational details to the application operators when they deploy the application. In this example, we have left the backend data api URI as a parameter for the application operator to fill in the applicationConfiguration.
Please note that a component itself is not an instance, but a declaration of the functionality and operational capabilities of that microservice. The real instance that represents a microservice is created and configured in the context of an applicationConfiguration.
We replaced the trait in v1alpha1 with TraitDefinition. A traitDefinition is a runtime overlay that augments a component with additional features. It allows application operators to decide the configuration of components without involving application developers.
Here is a TraitDefinition example.
Similar to workloadDefinition, we have opened up the OAM specification to allow OAM platform builders to seamlessly import any native resource definition as a trait onto the platform. However, unlike workloadDefinition and component, the instantiation of a trait is in the context of an applicationConfiguration. This is because traits are of application operators’ concern, thus, we can put both their configuration and instantiation in an applicationConfiguration.
We also introduced scopeDefinition in v1alpha2. A scope can be used to group components together into logical applications or enforce a common runtime behavior.
Here is a scopeDefinition and an application scope example.
Again, we have opened up the OAM specification to seamlessly import any native resource definition as a scope onto the platform.
However, scope is different from both component and trait as the instance of an application scope is created independently. That is because scopes are mostly application operators’ concern but it is shared between multiple components. Therefore, we need to create a scope instance first and reference it in an applicationConfiguration.
Finally, an Application Configuration defines an instance of an application with its operational capabilities. This is how the Open Application Model puts everything together to represent a cloud native application. In general, an applicationConfiguration is managed by the application operator role.
Here is a simplified example of an applicationConfiguration that incorporates the component/trait we defined earlier in this blog.
In this applicationConfiguration, we define three components. The first one references the component we showed earlier. The application operator sets the uri of the backend data service through the parameterValues. The application operator also applies a manualScaler trait to this component to scale the corresponding microservice to two instances. Now we can deploy this application to any OAM platform. Here is a more detailed demo if you are interested.
The OAM v1alpha2 specification opens up the model to allow OAM users and platform builders to bring their existing resources without any change. This greatly improves the extensibility of the model and we are very excited about the new possibilities this can bring.
We are also very excited to announce that we have a new Golang based OAM Kubernetes runtime on Github. Please give it a try if you want to learn more about the new specification. We look forward to hearing your feedback, and we welcome contributions in any shape or form. Please feel free to create issues, pull requests or just leave comments.
At this time, The New Stack does not allow comments directly on this website. We invite all readers who wish to discuss a story to visit us on Twitter or Facebook. We also welcome your news tips and feedback via email: firstname.lastname@example.org.