Designing a Minimal, Trust‑Bound OLM Setup on OpenShift
A concise architecture note for the smallest production‑grade OLM deployment on OpenShift: required objects, trust boundaries, operational checks, failure modes, and redesign triggers.
10 Jul 2026, 01:16 UTC

Requirements
To run Operator Lifecycle Manager (OLM) you need a running OpenShift cluster (4.12+) with OperatorHub enabled. OLM consumes four core custom resources: ClusterServiceVersion (CSV), CatalogSource, Subscription, and InstallPlan. The cluster must have a container image registry that supports image signing and digest verification, and you must hold at least cluster-admin or a dedicated operator-lifecycle-manager role to create cluster‑scoped CatalogSource objects.
Smallest Suitable Design
The minimal, production‑grade topology consists of three objects:
- CatalogSource – points to a signed index image in a trusted registry.
- Subscription – selects a channel and defines install‑plan approval (Automatic or Manual).
- ServiceAccount + RoleBinding – grants the operator only the permissions it needs in its target namespaces.
Example CatalogSource
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: my-trusted-catalog
namespace: openshift-marketplace
spec:
sourceType: grpc
image: registry.example.com/my-org/operator-index:v1.2.3@sha256:abcd1234...
displayName: "My Trusted Operators"
publisher: "My Org"
updateStrategy:
registryPoll:
interval: 30mRun this on a control‑plane node (or any node with oc access) as a user with cluster-admin rights:
oc apply -f catalogsource.yamlExample Subscription
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: my-operator-sub
namespace: my-operator-ns
spec:
channel: stable
name: my-operator
source: my-trusted-catalog
sourceNamespace: openshift-marketplace
installPlanApproval: Manual
startingCSV: my-operator.v1.2.3Apply with a user that can create namespaced resources in my-operator-ns:
oc apply -f subscription.yamlLeast‑Privilege ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-operator-sa
namespace: my-operator-ns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-operator-role
namespace: my-operator-ns
rules:
- apiGroups: ["", "apps"]
resources: ["deployments", "services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: my-operator-binding
namespace: my-operator-ns
subjects:
- kind: ServiceAccount
name: my-operator-sa
namespace: my-operator-ns
roleRef:
kind: Role
name: my-operator-role
apiGroup: rbac.authorization.k8s.ioAttach the ServiceAccount to the operator’s CSV (via spec.install.spec.deployments[].spec.template.spec.serviceAccountName) or let OLM inject it when the CSV declares serviceAccountName.
Trust and Data Boundaries
Operators execute inside the cluster, so the supply chain is the primary attack surface. Enforce image trust by:
- Signing the index image with
cosignor Red Hat Simple Signing. - Configuring an
ImagePolicy(orImageContentSourcePolicy) that requires a valid signature forregistry.example.com/my-org/*. - Scoping the ServiceAccount’s RBAC to the exact namespaces the operator manages; never grant
cluster-adminto the operator’s SA.
Data produced by the operator (CRs, secrets, metrics) stays in the target namespaces. The CatalogSource itself is cluster‑scoped but read‑only for non‑admin users.
Operational Checks
Run these checks daily or integrate them into a monitoring pipeline:
- Subscription health –
oc get subscriptions -A -o custom-columns=NAME:.metadata.name,NAMESPACE:.metadata.namespace,STATE:.status.state,CURRENT:.status.currentCSV. ExpectSTATE=AtLatestKnown. - InstallPlan approval –
oc get installplan -A -o custom-columns=NAME:.metadata.name,NAMESPACE:.metadata.namespace,APPROVAL:.spec.approval,APPROVED:.status.approved. Manual mode should showAPPROVED=falseuntil you runoc patch installplan -n -p '{"spec":{"approved":true}}' --type=merge. - Operator pod status –
oc get pods -n my-operator-ns -l name=my-operatorthenoc describe pod -n my-operator-nsandoc logs -n my-operator-nsfor error lines. - CatalogSource image digest –
oc get catalogsource my-trusted-catalog -n openshift-marketplace -o jsonpath='{.spec.image}'and compare the digest with the registry UI.
Failure Modes
| Symptom | Root Cause | Diagnostic Step |
|---|---|---|
Subscription stuck in UpgradePending | CatalogSource image tag moved without a new digest; OLM cannot resolve the CSV. | Check oc get catalogsource ... -o yaml for stale spec.image; verify registry digest. |
| InstallPlan never approved (Manual) | Operator lacks permission to create the InstallPlan or the approver missed the object. | Run oc get installplan -A and inspect .status.conditions. |
| Operator pod CrashLoopBackOff | RBAC missing for a required API group or the operator image fails signature verification. | Examine oc logs and oc describe pod for Forbidden or ImagePullBackOff events. |
CatalogSource shows ImageSignatureVerificationFailed | Registry signature expired or policy changed. | Validate signature with cosign verify and update ImagePolicy. |
Conditions That Trigger a Redesign
- Upgrading OpenShift beyond the OLM version matrix (e.g., 4.12 → 4.16) – CSV APIs may change.
- Migrating the operator index to a different registry (quay.io → internal Harbor) – CatalogSource image URL and trust policy must be updated.
- Adopting multi‑cluster management (Red Hat Advanced Cluster Management) – you’ll replace per‑cluster CatalogSources with a centralized
MultiClusterCatalogSourceand adjust RBAC to cluster‑scopedClusterRoleBinding. - Regulatory requirement for immutable operator versions – switch
installPlanApproval: Manualand pinstartingCSVin every Subscription.
Verification Checklist (Run After Any Change)
# 1. Confirm CatalogSource image digest matches registry
oc get catalogsource my-trusted-catalog -n openshift-marketplace -o yaml | grep 'image:'
# 2. Verify Subscription reached desired state
oc get subscription my-operator-sub -n my-operator-ns -o jsonpath='{.status.state}'
# 3. Ensure InstallPlan matches approval mode
oc get installplan -n my-operator-ns -o jsonpath='{.items[*].spec.approval}'
# 4. Validate operator pods are Ready
oc get pods -n my-operator-ns -l name=my-operator --field-selector=status.phase=Running
# 5. Spot‑check logs for errors
oc logs -n my-operator-ns -l name=my-operator --tail=50 | grep -i error
If any step returns an unexpected value, treat it as a blocker before promoting the change to production.
Limitations
OLM does not automatically roll back a failed operator installation; you must manually delete the offending InstallPlan and Subscription or patch the CSV. The Manual approval mode adds operational overhead but prevents uncontrolled upgrades. CatalogSource updates that change the image tag without a new digest can cause operator drift – always pin by digest. Finally, OLM’s reconciliation loop runs roughly every 30 seconds; rapid successive changes may be coalesced, so allow a minute between apply and verification.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.