Operator groups
This guide outlines the use of Operator groups with Operator Lifecycle Manager (OLM) in OKD.
About Operator groups
An Operator group, defined by the OperatorGroup
resource, provides multitenant configuration to OLM-installed Operators. An Operator group selects target namespaces in which to generate required RBAC access for its member Operators.
The set of target namespaces is provided by a comma-delimited string stored in the olm.targetNamespaces
annotation of a cluster service version (CSV). This annotation is applied to the CSV instances of member Operators and is projected into their deployments.
Operator group membership
An Operator is considered a member of an Operator group if the following conditions are true:
The CSV of the Operator exists in the same namespace as the Operator group.
The install modes in the CSV of the Operator support the set of namespaces targeted by the Operator group.
An install mode in a CSV consists of an InstallModeType
field and a boolean Supported
field. The spec of a CSV can contain a set of install modes of four distinct InstallModeTypes
:
InstallModeType | Description |
---|---|
| The Operator can be a member of an Operator group that selects its own namespace. |
| The Operator can be a member of an Operator group that selects one namespace. |
| The Operator can be a member of an Operator group that selects more than one namespace. |
| The Operator can be a member of an Operator group that selects all namespaces (target namespace set is the empty string |
If the spec of a CSV omits an entry of |
Target namespace selection
You can explicitly name the target namespace for an Operator group using the spec.targetNamespaces
parameter:
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: my-group
namespace: my-namespace
spec:
targetNamespaces:
- my-namespace
You can alternatively specify a namespace using a label selector with the spec.selector
parameter:
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: my-group
namespace: my-namespace
spec:
selector:
cool.io/prod: "true"
Listing multiple namespaces via |
If both spec.targetNamespaces
and spec.selector
are defined, spec.selector
is ignored. Alternatively, you can omit both spec.selector
and spec.targetNamespaces
to specify a global Operator group, which selects all namespaces:
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: my-group
namespace: my-namespace
The resolved set of selected namespaces is shown in the status.namespaces
parameter of an Opeator group. The status.namespace
of a global Operator group contains the empty string (""
), which signals to a consuming Operator that it should watch all namespaces.
Operator group CSV annotations
Member CSVs of an Operator group have the following annotations:
Annotation | Description |
---|---|
| Contains the name of the Operator group. |
| Contains the namespace of the Operator group. |
| Contains a comma-delimited string that lists the target namespace selection of the Operator group. |
All annotations except |
Provided APIs annotation
A group/version/kind (GVK) is a unique identifier for a Kubernetes API. Information about what GVKs are provided by an Operator group are shown in an olm.providedAPIs
annotation. The value of the annotation is a string consisting of <kind>.<version>.<group>
delimited with commas. The GVKs of CRDs and API services provided by all active member CSVs of an Operator group are included.
Review the following example of an OperatorGroup
object with a single active member CSV that provides the PackageManifest
resource:
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
annotations:
olm.providedAPIs: PackageManifest.v1alpha1.packages.apps.redhat.com
name: olm-operators
namespace: local
...
spec:
selector: {}
serviceAccount:
metadata:
creationTimestamp: null
targetNamespaces:
- local
status:
lastUpdated: 2019-02-19T16:18:28Z
namespaces:
- local
Role-based access control
When an Operator group is created, three cluster roles are generated. Each contains a single aggregation rule with a cluster role selector set to match a label, as shown below:
Cluster role | Label to match |
---|---|
|
|
|
|
|
|
The following RBAC resources are generated when a CSV becomes an active member of an Operator group, as long as the CSV is watching all namespaces with the AllNamespaces
install mode and is not in a failed state with reason InterOperatorGroupOwnerConflict
:
Cluster roles for each API resource from a CRD
Cluster roles for each API resource from an API service
Additional roles and role bindings
Cluster role | Settings |
---|---|
| Verbs on
Aggregation labels:
|
| Verbs on
Aggregation labels:
|
| Verbs on
Aggregation labels:
|
| Verbs on
Aggregation labels:
|
Cluster role | Settings |
---|---|
| Verbs on
Aggregation labels:
|
| Verbs on
Aggregation labels:
|
| Verbs on
Aggregation labels:
|
Additional roles and role bindings
If the CSV defines exactly one target namespace that contains
*
, then a cluster role and corresponding cluster role binding are generated for each permission defined in thepermissions
field of the CSV. All resources generated are given theolm.owner: <csv_name>
andolm.owner.namespace: <csv_namespace>
labels.If the CSV does not define exactly one target namespace that contains
*
, then all roles and role bindings in the Operator namespace with theolm.owner: <csv_name>
andolm.owner.namespace: <csv_namespace>
labels are copied into the target namespace.
Copied CSVs
OLM creates copies of all active member CSVs of an Operator group in each of the target namespaces of that Operator group. The purpose of a copied CSV is to tell users of a target namespace that a specific Operator is configured to watch resources created there.
Copied CSVs have a status reason Copied
and are updated to match the status of their source CSV. The olm.targetNamespaces
annotation is stripped from copied CSVs before they are created on the cluster. Omitting the target namespace selection avoids the duplication of target namespaces between tenants.
Copied CSVs are deleted when their source CSV no longer exists or the Operator group that their source CSV belongs to no longer targets the namespace of the copied CSV.
Static Operator groups
An Operator group is static if its spec.staticProvidedAPIs
field is set to true
. As a result, OLM does not modify the olm.providedAPIs
annotation of an Operator group, which means that it can be set in advance. This is useful when a user wants to use an Operator group to prevent resource contention in a set of namespaces but does not have active member CSVs that provide the APIs for those resources.
Below is an example of an Operator group that protects Prometheus
resources in all namespaces with the something.cool.io/cluster-monitoring: "true"
annotation:
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: cluster-monitoring
namespace: cluster-monitoring
annotations:
olm.providedAPIs: Alertmanager.v1.monitoring.coreos.com,Prometheus.v1.monitoring.coreos.com,PrometheusRule.v1.monitoring.coreos.com,ServiceMonitor.v1.monitoring.coreos.com
spec:
staticProvidedAPIs: true
selector:
matchLabels:
something.cool.io/cluster-monitoring: "true"
Operator group intersection
Two Operator groups are said to have intersecting provided APIs if the intersection of their target namespace sets is not an empty set and the intersection of their provided API sets, defined by olm.providedAPIs
annotations, is not an empty set.
A potential issue is that Operator groups with intersecting provided APIs can compete for the same resources in the set of intersecting namespaces.
When checking intersection rules, an Operator group namespace is always included as part of its selected target namespaces. |
Rules for intersection
Each time an active member CSV synchronizes, OLM queries the cluster for the set of intersecting provided APIs between the Operator group of the CSV and all others. OLM then checks if that set is an empty set:
If
true
and the CSV’s provided APIs are a subset of the Operator group’s:- Continue transitioning.
If
true
and the CSV’s provided APIs are not a subset of the Operator group’s:If the Operator group is static:
Clean up any deployments that belong to the CSV.
Transition the CSV to a failed state with status reason
CannotModifyStaticOperatorGroupProvidedAPIs
.
If the Operator group is not static:
- Replace the Operator group’s
olm.providedAPIs
annotation with the union of itself and the CSV’s provided APIs.
- Replace the Operator group’s
If
false
and the CSV’s provided APIs are not a subset of the Operator group’s:Clean up any deployments that belong to the CSV.
Transition the CSV to a failed state with status reason
InterOperatorGroupOwnerConflict
.
If
false
and the CSV’s provided APIs are a subset of the Operator group’s:If the Operator group is static:
Clean up any deployments that belong to the CSV.
Transition the CSV to a failed state with status reason
CannotModifyStaticOperatorGroupProvidedAPIs
.
If the Operator group is not static:
- Replace the Operator group’s
olm.providedAPIs
annotation with the difference between itself and the CSV’s provided APIs.
- Replace the Operator group’s
Failure states caused by Operator groups are non-terminal. |
The following actions are performed each time an Operator group synchronizes:
The set of provided APIs from active member CSVs is calculated from the cluster. Note that copied CSVs are ignored.
The cluster set is compared to
olm.providedAPIs
, and ifolm.providedAPIs
contains any extra APIs, then those APIs are pruned.All CSVs that provide the same APIs across all namespaces are requeued. This notifies conflicting CSVs in intersecting groups that their conflict has possibly been resolved, either through resizing or through deletion of the conflicting CSV.
Limitations for multi-tenant Operator management
OKD provides limited support for simultaneously installing different variations of an Operator on a cluster. Operators are control plane extensions. All tenants, or namespaces, share the same control plane of a cluster. Therefore, tenants in a multi-tenant environment also have to share Operators.
The Operator Lifecycle Manager (OLM) installs Operators multiple times in different namespaces. One constraint of this is that the Operator’s API versions must be the same.
Different major versions of an Operator often have incompatible custom resource definitions (CRDs). This makes it difficult to quickly verify OLMs.
Additional resources
Troubleshooting Operator groups
Membership
An install plan’s namespace must contain only one Operator group. When attempting to generate a cluster service version (CSV) in a namespace, an install plan considers an Operator group invalid in the following scenarios:
No Operator groups exist in the install plan’s namespace.
Multiple Operator groups exist in the install plan’s namespace.
An incorrect or non-existent service account name is specified in the Operator group.
If an install plan encounters an invalid Operator group, the CSV is not generated and the
InstallPlan
resource fails with a relevant message. For example, the following message is provided if more than one Operator group exists in the same namespace:attenuated service account query failed - more than one operator group(s) are managing this namespace count=2
where
count=
specifies the number of Operator groups in the namespace.If the install modes of a CSV do not support the target namespace selection of the Operator group in its namespace, the CSV transitions to a failure state with the reason
UnsupportedOperatorGroup
. CSVs in a failed state for this reason transition to pending after either the target namespace selection of the Operator group changes to a supported configuration, or the install modes of the CSV are modified to support the target namespace selection.