Building cloud-native applications is a significant challenge as its complexity has largely evolved over the past few years. The number of new technologies combined with the high-frequency deployments introduces a new challenge when planning a new application release.
The common solution to these challenges has been to increase the teams’ size adding new roles such as DevOps. However, increasing the size of a team comes with its own problems. As applications grow in complexity, and the number of people involved in their conception, development, and management also increases, the need for clear communication becomes a cornerstone for success.
This type of situation brings certain problems and/or practices to come to light. For example, having proper updated documentation at the different application levels (overall architecture, microservice dependencies, critical paths, infrastructure requirements, etc.). This motivates the need for a mechanism that enables capturing these requirements clearly so that overall communication is improved.
OAM addresses these issues by introducing a new layer on top of Kubernetes that defines a set of entities that facilitate an application’s definition, its components, how it will be deployed, etc.
But wait! This sounds like a Yet-Another-Layer-On-Top-Of-Another-Layer!
Kubernetes has become the de-facto standard to deploy distributed applications as it offers an extensible orchestration engine. All major cloud providers offer a Kubernetes-based system with their own extensions (e.g., types of load balancers). While Kubernetes offers a vast collection of entities to define how an application is deployed, it introduces a significant learning curve due to the number of entities and configuration possibilities. In this sense, Kubernetes can be considered a low-level layer that offers an orchestration system for containers with infrastructure-specific features. As happens with programming languages, introducing an abstraction layer that facilitates working with the system improves usability but a significant number of users will never use/discover some of the features.
OAM focuses on defining a method that simplifies how different user personas work with an application. From developers interested in defining single-purpose components to operators instantiating the application with all its associated components and parameters. At this point, you may think that Helm resolves this, and it is also a layer on top of Kubernetes. Helm also aims to simplify how an application is deployed on the cluster, but once deployed, the user faces the maintenance of a collection of low-level Kubernetes entities. Other approaches such as the Application CRD create an object representing an overall application, but its details are still represented as low-level Kubernetes entities.
What is OAM?
- The Open Application Model (OAM) is an application-centric specification to model cloud-native applications in a provider agnostic way. OAM simplifies the definition of the entities that define the composition of an application and its parametrization when compared to the standard Kubernetes approach. This is achieved by introducing higher-level entities (e.g, applications and components) instead of being focused on specific low-level ones (e.g., services). Moreover, OAM brings the possibility of deploying the application to different providers without the need to adapt the application entities to the provider-specific singularities (e.g., how to define a load balancer). The model is extensible by design so components can be modified in terms of their behavior when defining the application.
The main entities in the Open Application Model are:
- Component: Describes functional units of an application that will be deployed as part of it. Each microservice of an application will typically be mapped to a component. The definition allows specifying a set of parameters that will be filled when the application is deployed.
- Trait: The trait elements allow the user to configure different aspects on top of the pure application definition. In this sense, the application operator role will make decisions such as replication strategies, network policies, etc., without requiring a developer to be involved.
- Scope: Enables the definition of a group of components that share a particular characteristic. Each component can be linked to different scopes to capture different behaviors/characteristics. For example, a scope may define a set of components that have the same health checks, and it could define a set of components that can communicate among themselves, etc.
- Application: This is the main element required to deploy an application. The Application contains the definition of which components are part of the application and which traits and scopes are applied.
These entities follow the classic YAML format and Kubernetes Resource Model that has been in use for many years in the Kubernetes scene.
Next, let’s show an example of how WordPress & MySQL can be deployed using OAM.
MySQL component — mysql.yaml
apiVersion: core.oam.dev/v1alpha2 kind: Component metadata: name: mysql-component spec: workload: apiVersion: core.oam.dev/v1alpha2 kind: ContainerizedWorkload metadata: name: mysql-component spec: osType: linux containers: - name: mysql image: mysql:5.7 imagePullPolicy: IfNotPresent ports: - name: port value: 3306 containerPort: 3306 type: tcp env: - name: MYSQL_ROOT_PASSWORD value: "" parameters: - name: password required: true fieldPaths: - "spec.containers.env.value" - name: portNumber required: false fieldPaths: - "spec.containers.ports.value" - "spec.containers.ports.containerPort"
WordPress component — wordpress.yaml
apiVersion: core.oam.dev/v1alpha2 kind: Component metadata: name: wordpress-component spec: workload: apiVersion: core.oam.dev/v1alpha2 kind: ContainerizedWorkload metadata: name: wordpress-component spec: osType: linux containers: - name: wordpress image: wordpress:5.0.0 imagePullPolicy: IfNotPresent ports: - containerPort: 80 name: wordpressport protocol: TCP env: - name: WORDPRESS_DB_HOST value: "" - name: WORDPRESS_DB_PASSWORD value: "" parameters: - name: host required: true fieldPaths: - "spec.containers.env.value" - name: dbpass required: true fieldPaths: - "spec.containers.env.value"
Application — wordpress_app.yaml
apiVersion: core.oam.dev/v1alpha2 kind: ApplicationConfiguration metadata: name: wordpress-app annotations: version: v1.0.0 description: "Customized version of wordpress with mysql" spec: components: - componentName: mysql-component parameterValues: - name: password value: "root" - name: portNumber value: 3306 - componentName: wordpress-component parameterValues: - name: dbpass value: "root" - name: host value: "mysql-component"
So what can we expect from OAM in the future?
OAM has been recently added to the CNCF and has a thriving community that is actively working to improve the standard and accommodate new use cases not previously addressed in the definition. OAM aims to enable developers to spend more time with their applications and reduce the difficulties related to the particularities of the underlying infrastructure. This focus is closely aligned with the objectives that we at Napptive have in mind.
OAM is rapidly evolving to offer a vendor-agnostic approach to specify how an application should be deployed independently of the cluster management or orchestration system and the particularities of that infrastructure. With this approach, we believe that OAM can change how we operationalize enterprise applications, enabling new functionality such as facilitating the migration between two cloud vendors or having a complex multi-cloud multi-vendor deployment.
If you want more in-depth information, we suggest you look at the following:
- OAM web: https://oam.dev/
- OAM specification: https://github.com/oam-dev/spec
We encourage you to test our playground and see how you can accelerate your cloud-native development. It’s completely free, you simply need to sign up and get started!