Have you ever wondered how Operators show up inside OpenShift OperatorHub?
Let's say you have just written your brand new Operator using the operator-sdk and you would like to make it available for installing inside some OpenShift cluster: this post shows the steps to follow.
The step are:
- Create the Operator image (using the operator-sdk)
- Create the Operator Bundle: a bunch of files with information about the operator image you just created
- Create the Operator Bundle Image: just an image created “FROM scratch” containing the Operator Bundle files
- Create the Operator Catalog Image: an image that contains bundles (in our case just one)
- Create the CatalogSource resource in OpenShift: an OLM specific Custom Resource pointing to an Operator Catalog Image
Create the Operator image
This is the regular workflow for creating an Operator in GO;
Create a dumb Operator that monitors when a Custom Resource named "PippoBaudo" is created but then takes no action:
mkdir operator-test
cd operator-test
operator-sdk init --domain sample.com --repo github.com/<YOUR_GITHUB_ACCOUNT>/operator-test
operator-sdk create api --group sample --version v1alpha1 --kind PippoBaudo --resource --controller
make docker-build docker-push IMG="quay.io/<YOUR_QUAY_ACCOUNT>/operator-test:v0.0.1"
Create the Operator Bundle
The bundle basically describes your operator to OLM. The “make bundle” command creates folder bundle containing a bunch of files with information about the operator image you just created:
make bundle IMG="quay.io/<YOUR_QUAY_ACCOUNT>/operator-test:v0.0.1"
if you inspect the the bundle folder (inside the operator-test folder) you can see the bundle files:
tree bundle
bundle
├── manifests
│ ├── operator-test.clusterserviceversion.yaml
│ ├── operator-test-controller-manager-metrics-service_v1_service.yaml
│ ├── operator-test-manager-config_v1_configmap.yaml
│ ├── operator-test-metrics-reader_rbac.authorization.k8s.io_v1_clusterrole.yaml
│ └── sample.sample.com_pippobaudoes.yaml
├── metadata
│ └── annotations.yaml
└── tests
└── scorecard
└── config.yaml
Create the Operator Bundle Image
After creating the bundle, wrap it into an image:
make bundle-build bundle-push BUNDLE_IMG="quay.io/<YOUR_QUAY_ACCOUNT>/operator-test-bundle:v0.0.1"
Create the Operator Catalog Image
This is the so called “index image” which is used by OLM and Operator Registry; It contains bundles forming a sort of catalog; In our specific case it's going to contain just one bundle:
make catalog-build catalog-push \
CATALOG_IMG="quay.io/<YOUR_QUAY_ACCOUNT>/operator-test-catalog:v0.0.1" \
BUNDLE_IMG="quay.io/<YOUR_QUAY_ACCOUNT>/operator-test-bundle:v0.0.1" \
IMG="quay.io/<YOUR_QUAY_ACCOUNT>/operator-test:v0.0.1"
Create the CatalogSource
Finally, tell OpenShift to load this new catalog by creating a specific resource called CatalogSource;
Create file CatalogSource.yaml with the following content:
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: operator-test-catalog
namespace: openshift-marketplace
spec:
sourceType: grpc
image: quay.io/<YOUR_QUAY_ACCOUNT>/operator-test-catalog:v0.0.1
displayName: Test Operator
publisher: sample.com
and load it in your OpenShift cluster:
oc apply -f CatalogSource.yaml
Please note namespace openshift-marketplace was used because all catalog PODs run inside this namespace:
oc get CatalogSource --all-namespaces
NAMESPACE NAME DISPLAY TYPE PUBLISHER AGE
openshift-marketplace certified-operators Certified Operators grpc Red Hat 8d
openshift-marketplace community-operators Community Operators grpc Red Hat 8d
openshift-marketplace operator-test-catalog Test Operator grpc sample.com 20s
...
Create a Subscription
Now install our Operator from the catalog using the usual proedure:
create file Subscription.yaml:
kind: Subscription
metadata:
name: operator-test
namespace: my-namespace
spec:
channel: alpha
name: operator-test
source: operator-test-catalog
sourceNamespace: openshift-marketplace
startingCSV: operator-test.v0.0.1
and apply it to your namespace:
oc apply -f Subscription.yaml
Create Custom Resource
In the very last step, create a PippoBaudo resource:
create file PippoBaudo.yaml:
apiVersion: sample.sample.com/v1alpha1
kind: PippoBaudo
metadata:
name: pippobaudo-sample
namespace: my-namespace
and apply it to your namespace:
oc apply -f PippoBaudo.yaml
Now, if you look at the Operators POD logs you see the Operator noticed PippoBaudo resource creation :
oc logs operator-test-controller-manager-99f659974-8vc2z manager -n openshift-operators
...
2021-12-03T13:37:15.423Z INFO controller.pippobaudo Starting EventSource {"reconciler group": "sample.sample.com", "reconciler kind": "PippoBaudo", "source": "kind source: /, Kind="}
2021-12-03T13:37:15.423Z INFO controller.pippobaudo Starting Controller {"reconciler group": "sample.sample.com", "reconciler kind": "PippoBaudo"}
2021-12-03T13:37:15.533Z INFO controller.pippobaudo Starting workers {"reconciler group": "sample.sample.com", "reconciler kind": "PippoBaudo", "worker count": 1}
Obviously nothing else happend at this point since our Operator is a dummy operator.