Skip to content

Latest commit

 

History

History
94 lines (64 loc) · 6.86 KB

File metadata and controls

94 lines (64 loc) · 6.86 KB

Backstage Operator Design

The goal of the Backstage Operator is to deploy a Backstage workload to the Kubernetes namespace and keep this workload synced with the desired state defined by a configuration.

Backstage Kubernetes Runtime

The Backstage Kubernetes workload consists of set of Kubernetes resources (Runtime Objects). The approximate set of Runtime Objects necessary for a Backstage server on Kubernetes is shown on the diagram below:

Backstage Kubernetes Runtime

The most important object is the Backstage Pod created by Backstage Deployment. That is where the 'backstage-backend' container runs that contains the Backstage application. This Backstage application is a web server which can be reached using the Backstage Service. Those two components are the core part of the Backstage workload.

The Backstage application uses a SQL database as a data storage platform, and it is possible to install PostgreSQL DB on the same namespace as the Backstage instance. This includes a PostgreSQL StatefulSet/Pod, a Service to connect to Backstage, and PV/PVC to store the data.

Depending on underlying infrastructure, external access to the Backstage server is possible via an Openshift Route or K8s Ingress on top of Backstage Service. Note that in versions up to 0.0.2, only a Route configuration is supported by the Operator.

Finally, the Backstage Operator supports all the Backstage configuration options, which can be provided by creating dedicated ConfigMaps and Secrets, then injecting them into the Backstage Pod as mounted volumes or environment variables (see Configuration guide for details).

Configuration

Configuration layers

The Backstage Operator can be configured to customize the deployed workload. With no changes to the default configuration, an admin user can deploy a Backstage instance to try it out for a local, personal, or small group test deployment.

When you do want to customize your Backstage instance, there are 3 layers of configuration available.

Backstage Operator Configuration Layers

As shown in the picture above:

  • There is an Operator (Cluster) level Default Configuration implemented as a ConfigMap inside the Backstage system namespace (where Backstage controller is launched). It provides a default configation which is optimal for most cases and will be applied if there are no other config to override (i.e. Backstage CR is empty).
  • One way of overriding the default is instance (Backstage CR) scoped, implemented as a ConfigMap which has the same as default structure but inside the Backstage instance's namespace. The name of this ConfigMap is specified in the Backstage.Spec.RawConfig field. It offers a very flexible way to configure a specific Backstage instance.
  • And finally, there are a set of fields on Backstage.Spec to override configuration made on level 1 and 2 above. It offers simple configuration of some parameters. So, the user is not required to understand the overall structure of a Backstage runtime object and is able to simply configure the "most important" parameters. (see configuration for more details)

Backstage Application

The Backstage Application comes with advanced configuration features.

As per the Backstage configuration, a user can define and overload multiple app-config.yaml files and flexibly configure them by including environment variables. Backstage Operator supports this flexibility allowing to define these configurations components in all the configuration levels (default, raw and CR)

Backstage App with Advanced Configuration

Updating mounted files

As you can see, the Operator mounts ConfigMaps and Secrets to the Backstage container

  • As a part of Default/Raw configuration, configuring certain configuration files
  • As a part of Backstage CR configuration, using the spec.application field

In either case, a ConfigMaps/Secrets data's key/value is transformed to the file's name/content at Backstage CR creation time and the general expectation is to be able to update the file contents by updating the corresponding ConfigMap/Secret. Kubernetes allows this updating but only if volume mount does not contain a subPath. In turn, using a subPath allows for mounting certain files individually on a certain container's directory, and not worrying about directories overlapping, which is beneficial for some cases.

Historically, the Operator actively uses the subPath option which allows a "convenient" Backstage App file structure (e g all the app-config files in the same directory). In this case file(s) are mounted to the default directory or to the spec.application.(appConfig|extraFiles).mountPath field if specified. Also, in the case where a user needs only a certain key (file) to be mounted, the only choice is to use a subPath. In order to be able to update file(s) mounted with subPath volumes, the Operator watches ConfigMaps/Secrets and refreshes (recreates) the Backstage Pod when changes occur. Technically this approach works in either case (with or without subPath) but there are certain disadvantages:

  • recreating of Pod is quite slow
  • it disables in fact using Backstage's file watching mechanism. Indeed, configuration changing causes file-system rebooting, so file-system watchers have no effect.

Another option, implemented in version 0.4.0, is to specify the mountPath and not specify the key (filename). In this case, the Operator relies on the automatic update provided by Kubernetes; it simply mounts a directory with all key/value files at the specified path.

Updating injected environment variables

As you can see, the Operator injects environment variables to the Backstage container with ConfigMaps and Secrets

  • As a part of Default/Raw configuration, configuring certan configuration files
  • As a part of Backstage CR configuration, using spec.application field Kubernetes doesn’t allow you to change environment variables after a Pod has been created, so in order to update enviromnent variables when ConfigMap or Secret changed Operator refreshes the Pod the same way as mentioned here

Status

Backstage Custom Resource contains Deployed condition in the Status field. It is updated by the Operator and can have the following values:

  • DeployInProgress - Backstage Deployment is not available yet. The current state of Deployment can be seen in the message field
  • Deployed - Backstage Deployment is being created and application is available
  • DeployFailed - Backstage Deployment creation failed. The actual error can be seen in the message field