“Operators” are one of the key differentiators for Red Hat OpenShift. By using the power of Operators, OpenShift provides automation at every level of the stack, from managing the parts that make up the platform all the way to applications that are provided as a managed service. Allowing users to easily find, install, and manage Operators is an essential key to the success of extending the platform or running the workloads on OpenShift. At Red Hat, we recently went through an internal initiative with a working group consisting of our UXD, PMs, and several key layered Product teams. The group collaboratively took a deeper look at installing Red Hat Operators to get closer to the desired one-two click UX when enabling our Red Hat layered products on OpenShift platform.
We based our investigation on several general characteristics that help provide a great first-time use experience and reviewed those layered products to see where potentially we have room for improvement. We thought some of the findings were interesting, and so we wanted to dive into a few cool ways our Operators are getting better. Those general characteristics we considered are shared at the end of this blog post.
Hints and Auto-Creates for the Correct Namespace
Some Operators (or the Operands managed) must be deployed in a specific namespace, or with ancillary resources in specific namespaces, in order to work properly. At the very least, this should be clearly conveyed to the users without the need to check the documentation. What is even better is to “auto-create” the recommended namespace during the Operator installation.
This is achievable through various approaches. With OpenShift Console (started in 4.4), Operator authors can specify a desired target namespace as the default to the end-users using an annotation in the Operator’s ClusterServiceVersion (CSV) . Adding the Operator to a cluster using OperatorHub enables the web console to auto-populate the suggested namespace (or will be created if it does not exist) during the installation process, as shown in the screenshot below:
Customize Operand Form or Use the CRD’s Structural Schema
At Red Hat, we and our partners strive to provide the best possible UI for guiding end-users to deploy Kubernetes-native applications. With a structural schema for CustomResourceDefinitions (CRDs) provided by the Operator authors, OpenShift web console can generate form UIs for creating custom resource (or Operand) instances. Schema properties are mapped to appropriate form field UI components based on schema types (for example, boolean, text, integer, string, string with enum, object, and array):
Customized Creation Form With specDescriptors
The auto-generated creation form is already powerful, but you may want to customize how the form is rendered. This is where “specDescriptors" come in. Operator authors can customize the form field with a more user-friendly display name, a more concise description, and/or assign it with a customized UI widget that provides more sophisticated interactions to help users fill in the desired inputs.
Take Red Hat Cluster Logging Operator as an example. The ClusterLogging custom resource provided by the Operator comes with a structure schema defined in the CRD. Hence, OpenShift web console can generate a creation form for ClusterLogging based on the schema types.
This works well for most of the form fields; however, we noticed one particular field could often trip up GCP users without obvious error messages surfacing on the UI or in YAML. The field “StorageClassName” is meant to specify a StorageClass for the logStore of elasticsearch, which is defined as “type: string” in the schema. Therefore, the web console maps it to the “text input” field on the form UI, and fills in the default value as “gp2” according to the CR template specified in the Operator CSV.
However, for GCP users, there is no StorageClass named as “gp2”. Hence, we can customize this particular property field with a dropdown menu for easier filtering and selecting the existing “StorageClass” objects that are on the cluster. To do this, simply assign a specDescriptor as k8sResourcePrefix in the Operator CSV by specifying the desired Kubernetes object as “StorageClass” and pointing the path to the particular property field in the schema:
In addition to assigning specDescriptors to help specify the spec of the CR instances managed by the Operators, "statusDescriptors" is another breed of OLM descriptors that help describe the status of the CR instance after getting created. The structure of the statusDescriptors is similar to specDescriptors and includes the same fields. The only difference is the set of valid x-descriptors each link to an associated UI widget. Assigning statusDescriptors will not affect the UX of the creation or the first-time user experience of the Operators, but it is another cool way that can improve the post-installation UX for ongoing managing the Operator-backed services.
Check out the x-descriptors reference guide, which provides more detailed descriptions and examples of how to use them in specDescriptors and statusDescriptors.
Internal CRs Are Hidden and/or Initialization CR Is Annotated (If Any)
Hiding Internal Objects
It is common practice for Operators to use CRDs internally to accomplish a task. These objects are not meant for users to manipulate and can be confusing to users of the Operator. With OpenShift web console (started in 4.3), Operator authors can hide a list of CRDs that are not meant for manipulation by users from the web console using an annotation in the Operator’s CSV. See the screenshots below for “all CRs” (left) vs “internal CRs are hidden” (right):
Initializing Required Custom Resources
Some Operators might require a custom resource (CR) that contains utilities or initialization setups being instantiated before the Operator-backed services can be fully functional. Take Red Hat OpenShift Container Storage (OCS) as an example. After installing the Operator, users have to create a single instance of StorageCluster, which represents a OpenShift Container Storage Cluster including Ceph Cluster, NooBaa, and all the storage and compute resources required in order to enable OpenShift Container Storage on the cluster. Since the OCS Operator provides/manages more than one custom resource (or Operand), it can be challenging for a user to determine what is required or how to define the resource:
To improve the first-time user experience, this could be smoothed out through automating the init CR creation process with default setups or by providing better guidance to users in what and how to create the particular resource.
This again can be achieved with various approaches. With OpenShift web console (started in 4.6), Operator authors can indicate a single required CR that must be created at the time that the Operator is installed using an annotation in the Operator’s CSV that contains a complete YAML template to initialize the resource during installation. This way, after installing the Operator using the web console, the user will be prompted to create that init CR and can easily make the Operator backed service fully functional:
You can see more details in this blog post.
Easy Access to Operator-Backed Service’s Web Interface
Another common feature from many Operator-backed services is to provide their own web interface for their user-users. After deploying the custom resources or Operands managed by the Operator, a URL can be accessible through either a Route or Ingress object on the cluster.
With OpenShift web console (started in 4.2), Operator authors can add the URL of their Operator-backed service to the “Applications launcher” within the web console by creating a ConsoleLink custom resource (CR) along with their logo and service name. This way, both cluster-admins or regular end-users can easily find and access the web interface by clicking on the square icon on the masthead from any pages in both “Admin” and “Developer” perspectives of the OpenShift web console.
In addition to the above mentioned cool ways we adopted to improve our Operators, here is the full list of general characteristics we based our investigation on when reviewing our layered products:
- Clear listing of any prerequisites
- Operator description is sufficiently detailed
- Hints and auto-creates the correct namespace (if required)
- Required secret, configmap, services ship statically with the bundle
- Operator dependencies are specified through OLM (if required)
- OLM descriptors customize Operand form(s), otherwise backed by CRD’s structural schema
- Internal CRs are hidden and/or initialization CR is annotated (if any)
- Resource requirements fit in standard three-node installation
- Resource limits set on all components
- Owner references are correctly set for managed objects
- Meaningful logo + official Product and provider name
- All provided APIs/CRDs have useful names and helpful descriptions of what they do for the user
We hope this post helps you improve the first-time user experience of the Operators you are building. If you are up for trying out or just getting started with OpenShift, visit Try OpenShift to get instant access to a cluster, and check out Red Hat CodeReady Workspace, Red Hat Advance Cluster Management, as well as other certified Operators from our partners.