Skip to main contentIBM Garage for Cloud

Architecture as Code with SolSA

SolSA makes it possible to specify the software architecture of Kubernetes-managed cloud applications as JavaScript or TypeScript programs.

Overview

Kubernetes is becoming the de facto standard for managing applications in the cloud. Thanks to operators, Kubernetes can be extended to manage virtually any kind of application resources: not only containers and microservices, but also virtual machines, cloud functions and events, managed cloud services, policies, meshes, etc. Each resource can be declared and configured with a few lines of YAML. However, while YAML is a fine language to perform some basic configuration, SolSA is designed to enable application developers to reason about applications at a higher-level of abstraction using familiar languages and development tools.

The SolSA library for Node.js —a shorthand for Solution Service Architecture — makes it possible to specify the architecture of cloud applications as programs. SolSA enables developers to configure Kubernetes-managed resources by writing JavaScript or TypeScript code instead of YAML. SolSA automatically translates the developer written code to the required lower-level YAML. SolSA integrates with IDEs such as Visual Studio Code to provide online validation, code completion, and documentation of the various resources and configuration parameters.

Getting Started

The solsa CLI is included in the Tools Image and is pre-configured as a plugin to the ArgoCD instance installed in the tools namespace of your cluster. No further setup is needed for basic usage of SolSA. To enable full IDE support, you will need to install the solsa package using npm in the same manner in which you would install any npm package you want to use in your IDE. Some typical installation options are discussed in the SolSA setup instructions.

Usage Scenarios

SolSA can be applied in any scenario where it is desirable to use a higher-level of abstraction to programmatically generate YAML to be applied to a Kubernetes or OpenShift cluster. The use of SolSA is particularly compelling to:

  • Specify the architecture of complex applications composed of multiple Kubernetes resources. SolSA augments the base Kubernetes resources with additional abstractions that simplify the specification of common patterns and reduce the amount of code written.
  • Enable full IDE-support for your software architecture, including validation, code assist, and integrated documentation of Kubernetes resources and operators.
  • Allow a single architecture specification to be programmatically specialized to different contexts (eg. dev vs. test vs. prod).

Specification of Kubernetes Resources

Deploying just a single microservice that is accessible outside of a Kubernetes cluster requires specifying three related Kubernetes resources: a Deployment, a Service, and an Ingress. SolSA simplifies this task by reducing the amount of repetitive code a developer needs to write and maintain.

To illustrate how to use SolSA to specify the architecture of a simple cloud native application, we use the Bookinfo sample application from the Istio project. Bookinfo consists of four containerized microservices: an externally exposed productpage service that is implemented using three internal backend microservices.

The tabs below contain two variants of the SolSA specification of Bookinfo’s architecture and the (identical) Kubernetes YAML that is generated from either one of these specifications by the solsa CLI.

A very common Kubernetes pattern is the combination of a Deployment and a Service to implement a single logical microservice. SolSA’s ContainerizedService provides a higher level abstraction for this pattern that allows the developer to specify the essential elements while eliding virtually all of the Kubernetes-specific details. As shown below, simple microservices can be specified very concisely. By providing additional arguments to the ContainerizedService constructor it is possible to control many aspects of the generated YAML. Specifying that the productpage service should be exposed outside the cluster is declared by invoking getIngress passing the desired virtual host name bookinfo.

let solsa = require('solsa')
let details = new solsa.ContainerizedService({ name: 'details', image: 'istio/examples-bookinfo-details-v1:1.15.0', port: 9080 })
let ratings = new solsa.ContainerizedService({ name: 'ratings', image: 'istio/examples-bookinfo-ratings-v1:1.15.0', port: 9080 })
let reviews = new solsa.ContainerizedService({ name: 'reviews', image: 'istio/examples-bookinfo-reviews-v1:1.15.0', port: 9080 })
let productpage = new solsa.ContainerizedService({ name: 'productpage', image: 'istio/examples-bookinfo-productpage-v1:1.15.0', port: 9080 })
productpage.env = {
DETAILS_HOSTNAME: details.name,
RATINGS_HOSTNAME: ratings.name,

Using SolSA with Kubernetes Operators

The SolSA library includes JavaScript/TypeScript bindings for every Kubernetes Operator available on OperatorHub.io. These enables full IDE-support for defining applications that utilize operators to manage the life-cycles of some portions of their resources.

As an example, the tabs below show the SolSA specification and the generated YAML of a simple language translation application in which a microservice defined using SolSA’s ContainerzedService abstraction is combined with an instance of the Watson Translator service on the IBM Public Cloud. The IBM Cloud Operator is used to instantiate the Watson Translator Service instance and make the credentials for accessing it available to the dependent microservice via a Kubernetes secret.

const path = require('path')
const solsa = require('solsa')
function translator ({ name, language }) {
let watson = new solsa.LanguageTranslator({ name: 'watson-translator-for-' + name })
let translator = new solsa.ContainerizedService({ name, image: 'solsa-translator', build: path.join(__dirname, 'solsa-translator'), port: 8080 })
translator.env = { LANGUAGE: { value: language }, WATSON_URL: watson.getSecret('url'), WATSON_APIKEY: watson.getSecret('apikey') }
let ingress = translator.getIngress()

Using SolSA with ArgoCD

The usage of ArgoCD is described in more detail in the continuous delivery section of this guide. A SolSA-specified application can be used in exactly the same workflows as an application specified by a Helm chart or Kustomize tree. The only additional step is to inform ArgoCD that it should use its SolSA plugin to generate the YAML for the application. In the instructions below, we will continue using the Bookinfo sample from the solsa-examples git repo. The main SolSA file for this application is instance.js

  1. Log into ArgoCD

  2. Click New Application and provide the following values:

  3. Click the EDIT AS YAML button and add the plugin stanza shown below to the source: block

source:
plugin:
name: solsa
env:
- name: SOLSA_APP_MAIN
value: instance.js

Finally deploy Bookinfo by clicking the Create button.

More Information

Additional information on SolSA, including a tutorial and sample applications, is available from the SolSA open source project.