Defining Dependencies in Kubernetes Operators

Operators can automate the deployment and operations of custom Kubernetes resources. These resources might dependent on other third party resources. This article describes how to define these dependencies.

I’m working on a sample that describes different patterns and best practices to build operators with Golang. The repo demonstrates how a custom resource ‘Application’ uses internally a third party ‘Database’ resource which is managed by another controller. This is a simplified version of the typical scenario to use a managed database in the cloud. Read my previous blog that explains how to access third party resources in controllers’ Go code.

Additionally you need to ensure that the dependent operator (in my sample the database operator) exists when an operator (in my sample the application operator) is deployed. This can be done in the cluster service version (CSV). The CSV is the operator bundle/package which contains the definition of a specific operator version.

Here is the CSV of the application operator. The dependency is defined in the ‘required’ section of the spec.

kind: ClusterServiceVersion
  apiservicedefinitions: {}
    - displayName: Application
      kind: Application
      version: v1alpha1
    - displayName: Database
      kind: Database
      version: v1alpha1    

When you try to deploy the application operator, but the database operator doesn’t exist, you get an error.

$ operator-sdk run bundle "$REGISTRY/$ORG/$BUNDLEIMAGE" -n operators
INFO[0040] Successfully created registry pod: docker-io-nheidloff-application-controller-bundle-v15 
INFO[0041] Created CatalogSource: operator-application-catalog 
INFO[0041] Created Subscription: operator-application-v0-0-1-sub 
FATA[0120] Failed to run bundle: install plan is not available for the subscription operator-application-v0-0-1-sub: timed out waiting for the condition 

The logs in the catalog pod describe the error.

$ kubectl get pods -n olm
$ kubectl logs catalog-operator-b4dfcff47-55plr -n olm
Event(v1.ObjectReference{Kind:"Namespace", Namespace:"", Name:"operators", ... type: 'Warning' reason: 'ResolutionFailed' constraints not satisfiable: bundle operator-application.v0.0.1 requires an operator providing an API with group:, version: v1alpha1, kind: Database

The following resources describe more details.

Check out the repo and keep an eye on my blog. I’ll write more about other operator patterns soon.