mirror of
https://github.com/openshift/openshift-docs.git
synced 2026-02-05 21:46:22 +01:00
434 lines
14 KiB
Plaintext
434 lines
14 KiB
Plaintext
// Module included in the following assemblies:
|
|
//
|
|
// * applications/operators/olm-understanding-olm.adoc
|
|
|
|
[id="olm-operatorgroups_{context}"]
|
|
= OperatorGroups
|
|
|
|
An _OperatorGroup_ is an OLM resource that provides multitenant configuration to
|
|
OLM-installed Operators. An OperatorGroup selects a set of 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 CSV's
|
|
`olm.targetNamespaces` annotation. This annotation is applied to member
|
|
Operator's CSV instances and is projected into their deployments.
|
|
|
|
[id="olm-operatorgroups-membership_{context}"]
|
|
== OperatorGroup membership
|
|
|
|
An Operator is considered a _member_ of an OperatorGroup if the following
|
|
conditions are true:
|
|
|
|
* The Operator's CSV exists in the same namespace as the OperatorGroup.
|
|
* The Operator's CSV's InstallModes support the set of namespaces targeted by
|
|
the OperatorGroup.
|
|
|
|
An InstallMode consists of an `InstallModeType` field and a boolean `Supported`
|
|
field. A CSV's spec can contain a set of InstallModes of four distinct
|
|
`InstallModeTypes`:
|
|
|
|
.InstallModes and supported OperatorGroups
|
|
[cols="1,2",options="header"]
|
|
|===
|
|
|InstallModeType |Description
|
|
|
|
|`OwnNamespace`
|
|
|The Operator can be a member of an OperatorGroup that selects its own
|
|
namespace.
|
|
|
|
|`SingleNamespace`
|
|
|The Operator can be a member of an OperatorGroup that selects one namespace.
|
|
|
|
|`MultiNamespace`
|
|
|The Operator can be a member of an OperatorGroup that selects more than one
|
|
namespace.
|
|
|
|
|`AllNamespaces`
|
|
|The Operator can be a member of an OperatorGroup that selects all namespaces
|
|
(target namespace set is the empty string `""`).
|
|
|===
|
|
|
|
[NOTE]
|
|
====
|
|
If a CSV's spec omits an entry of `InstallModeType`, then that type is
|
|
considered unsupported unless support can be inferred by an existing entry that
|
|
implicitly supports it.
|
|
====
|
|
|
|
[id="olm-operatorgroups-membership-troubleshooting_{context}"]
|
|
=== Troubleshooting OperatorGroup membership
|
|
|
|
* If more than one OperatorGroup exists in a single namespace, any CSV created
|
|
in that namespace will transition to a failure state with the reason
|
|
`TooManyOperatorGroups`. CSVs in a failed state for this reason will
|
|
transition to pending once the number of OperatorGroups in their namespaces
|
|
reaches one.
|
|
* If a CSV's InstallModes do not support the target namespace selection of the
|
|
OperatorGroup in its namespace, the CSV will transition to a failure state
|
|
with the reason `UnsupportedOperatorGroup`. CSVs in a failed state for this
|
|
reason will transition to pending once either the OperatorGroup's target
|
|
namespace selection changes to a supported configuration, or the CSV's
|
|
InstallModes are modified to support the OperatorGroup's target namespace
|
|
selection.
|
|
|
|
[id="olm-operatorgroups-target-namespace_{context}"]
|
|
== Target namespace selection
|
|
|
|
Specify the set of namespaces for the OperatorGroup using a label
|
|
selector with the `spec.selector` field:
|
|
|
|
[source,yaml]
|
|
----
|
|
apiVersion: operators.coreos.com/v1
|
|
kind: OperatorGroup
|
|
metadata:
|
|
name: my-group
|
|
namespace: my-namespace
|
|
spec:
|
|
selector:
|
|
matchLabels:
|
|
cool.io/prod: "true"
|
|
----
|
|
|
|
You can also explicitly name the target namespaces using the
|
|
`spec.targetNamespaces` field:
|
|
|
|
[source,yaml]
|
|
----
|
|
apiVersion: operators.coreos.com/v1
|
|
kind: OperatorGroup
|
|
metadata:
|
|
name: my-group
|
|
namespace: my-namespace
|
|
spec:
|
|
targetNamespaces:
|
|
- my-namespace
|
|
- my-other-namespace
|
|
- my-other-other-namespace
|
|
----
|
|
|
|
[NOTE]
|
|
====
|
|
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_ OperatorGroup, which selects all namespaces:
|
|
|
|
[source,yaml]
|
|
----
|
|
apiVersion: operators.coreos.com/v1
|
|
kind: OperatorGroup
|
|
metadata:
|
|
name: my-group
|
|
namespace: my-namespace
|
|
----
|
|
|
|
The resolved set of selected namespaces is shown in an OperatorGroup's
|
|
`status.namespaces` field. A global OperatorGroup's `status.namespace` contains
|
|
the empty string (`""`), which signals to a consuming Operator that it should
|
|
watch all namespaces.
|
|
|
|
[id="olm-operatorgroups-csv-annotations_{context}"]
|
|
== OperatorGroup CSV annotations
|
|
|
|
Member CSVs of an OperatorGroup have the following annotations:
|
|
|
|
[cols="1,1",options="header"]
|
|
|===
|
|
|Annotation |Description
|
|
|
|
|`olm.operatorGroup=<group_name>`
|
|
|Contains the name of the OperatorGroup.
|
|
|
|
|`olm.operatorGroupNamespace=<group_namespace>`
|
|
|Contains the namespace of the OperatorGroup.
|
|
|
|
|`olm.targetNamespaces=<target_namespaces>`
|
|
|Contains a comma-delimited string that lists the OperatorGroup's target
|
|
namespace selection.
|
|
|===
|
|
|
|
[NOTE]
|
|
====
|
|
All annotations except `olm.targetNamespaces` are included with copied CSVs.
|
|
Omitting the `olm.targetNamespaces` annotation on copied CSVs prevents the
|
|
duplication of target namespaces between tenants.
|
|
====
|
|
|
|
[id="olm-operatorgroups-provided-apis-annotation_{context}"]
|
|
== Provided APIs annotation
|
|
|
|
Information about what `GroupVersionKinds` (GVKs) are provided by an
|
|
OperatorGroup are shown in an `olm.providedAPIs` annotation. The annotation's
|
|
value is a string consisting of `<kind>.<version>.<group>` delimited with
|
|
commas. The GVKs of CRDs and APIServices provided by all active member CSVs of
|
|
an OperatorGroup are included.
|
|
|
|
Review the following example of an OperatorGroup with a single active member CSV
|
|
that provides the PackageManifest resource:
|
|
|
|
[source,yaml]
|
|
----
|
|
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
|
|
----
|
|
|
|
[id="olm-operatorgroups-rbac_{context}"]
|
|
== Role-based access control
|
|
|
|
When an OperatorGroup is created, three ClusterRoles are generated. Each
|
|
contains a single AggregationRule with a ClusterRoleSelector set to match a
|
|
label, as shown below:
|
|
|
|
[cols="1,1",options="header"]
|
|
|===
|
|
|ClusterRole |Label to match
|
|
|
|
|`<operatorgroup_name>-admin`
|
|
|`olm.opgroup.permissions/aggregate-to-admin: <operatorgroup_name>`
|
|
|
|
|`<operatorgroup_name>-edit`
|
|
|`olm.opgroup.permissions/aggregate-to-edit: <operatorgroup_name>`
|
|
|
|
|`<operatorgroup_name>-view`
|
|
|`olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>`
|
|
|===
|
|
|
|
The following RBAC resources are generated when a CSV becomes an active member of an OperatorGroup, as long as the CSV is watching all namespaces with the `AllNamespaces` InstallMode and is not in a failed state with reason `InterOperatorGroupOwnerConflict`.
|
|
|
|
* xref:olm-resources-per-api-resource-crd_{context}[ClusterRoles for each API resource from a CRD]
|
|
* xref:olm-resources-per-api-resource-api_{context}[ClusterRoles for each API resource from an APIService]
|
|
* xref:olm-resources-additional-roles-rolebindings_{context}[Additional Roles and RoleBindings]
|
|
|
|
[id="olm-resources-per-api-resource-crd_{context}"]
|
|
.ClusterRoles generated for each API resource from a CRD
|
|
[cols="1,1a",options="header"]
|
|
|===
|
|
|ClusterRole |Settings
|
|
|
|
|`<kind>.<group>-<version>-admin`
|
|
|Verbs on `<kind>`:
|
|
|
|
* `*`
|
|
|
|
Aggregation labels:
|
|
|
|
* `rbac.authorization.k8s.io/aggregate-to-admin: true`
|
|
* `olm.opgroup.permissions/aggregate-to-admin: <operatorgroup_name>`
|
|
|
|
|`<kind>.<group>-<version>-edit`
|
|
|Verbs on `<kind>`:
|
|
|
|
* `create`
|
|
* `update`
|
|
* `patch`
|
|
* `delete`
|
|
|
|
Aggregation labels:
|
|
|
|
* `rbac.authorization.k8s.io/aggregate-to-edit: true`
|
|
* `olm.opgroup.permissions/aggregate-to-edit: <operatorgroup_name>`
|
|
|
|
|`<kind>.<group>-<version>-view`
|
|
|Verbs on `<kind>`:
|
|
|
|
* `get`
|
|
* `list`
|
|
* `watch`
|
|
|
|
Aggregation labels:
|
|
|
|
* `rbac.authorization.k8s.io/aggregate-to-view: true`
|
|
* `olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>`
|
|
|
|
|`<kind>.<group>-<version>-view-crdview`
|
|
|Verbs on `apiextensions.k8s.io` `customresourcedefinitions` `<crd-name>`:
|
|
|
|
* `get`
|
|
|
|
Aggregation labels:
|
|
|
|
* `rbac.authorization.k8s.io/aggregate-to-view: true`
|
|
* `olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>`
|
|
|
|
|===
|
|
|
|
[id="olm-resources-per-api-resource-api_{context}"]
|
|
.ClusterRoles generated for each API resource from an APIService
|
|
[cols="1,1a",options="header"]
|
|
|===
|
|
|ClusterRole |Settings
|
|
|
|
|`<kind>.<group>-<version>-admin`
|
|
|Verbs on `<kind>`:
|
|
|
|
* `*`
|
|
|
|
Aggregation labels:
|
|
|
|
* `rbac.authorization.k8s.io/aggregate-to-admin: true`
|
|
* `olm.opgroup.permissions/aggregate-to-admin: <operatorgroup_name>`
|
|
|
|
|`<kind>.<group>-<version>-edit`
|
|
|Verbs on `<kind>`:
|
|
|
|
* `create`
|
|
* `update`
|
|
* `patch`
|
|
* `delete`
|
|
|
|
Aggregation labels:
|
|
|
|
* `rbac.authorization.k8s.io/aggregate-to-edit: true`
|
|
* `olm.opgroup.permissions/aggregate-to-edit: <operatorgroup_name>`
|
|
|
|
|`<kind>.<group>-<version>-view`
|
|
|Verbs on `<kind>`:
|
|
|
|
* `get`
|
|
* `list`
|
|
* `watch`
|
|
|
|
Aggregation labels:
|
|
|
|
* `rbac.authorization.k8s.io/aggregate-to-view: true`
|
|
* `olm.opgroup.permissions/aggregate-to-view: <operatorgroup_name>`
|
|
|
|
|===
|
|
|
|
[id="olm-resources-additional-roles-rolebindings_{context}"]
|
|
.Additional Roles and RoleBindings
|
|
* If the CSV defines exactly one target namespace that contains `*`, then a
|
|
ClusterRole and corresponding ClusterRoleBinding are generated for each
|
|
permission defined in the CSV's permissions field. All resources generated are
|
|
given the `olm.owner: <csv_name>` and `olm.owner.namespace: <csv_namespace>`
|
|
labels.
|
|
* If the CSV does _not_ define exactly one target namespace that contains `*`,
|
|
then all Roles and RoleBindings in the Operator namespace with the
|
|
`olm.owner: <csv_name>` and `olm.owner.namespace: <csv_namespace>` labels are
|
|
copied into the target namespace.
|
|
|
|
[id="olm-operatorgroups-copied-csvs_{context}"]
|
|
== Copied CSVs
|
|
|
|
OLM creates copies of all active member CSVs of an OperatorGroup in each of that
|
|
OperatorGroup's target namespaces. 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
|
|
OperatorGroup that their source CSV belongs to no longer targets the copied
|
|
CSV's namespace.
|
|
|
|
[id="olm-operatorgroups-static_{context}"]
|
|
== Static OperatorGroups
|
|
|
|
An OperatorGroup is _static_ if its `spec.staticProvidedAPIs` field is set to
|
|
`true`. As a result, OLM does not modify the OperatorGroup's `olm.providedAPIs`
|
|
annotation, which means that it can be set in advance. This is useful when a
|
|
user wants to use an OperatorGroup 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 OperatorGroup that protects Prometheus resources in
|
|
all namespaces with the `something.cool.io/cluster-monitoring: "true"`
|
|
annotation:
|
|
|
|
[source,yaml]
|
|
----
|
|
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"
|
|
----
|
|
|
|
[id="olm-operatorgroups-intersection_{context}"]
|
|
== OperatorGroup intersection
|
|
|
|
Two OperatorGroups 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 OperatorGroups with intersecting provided APIs can
|
|
compete for the same resources in the set of intersecting namespaces.
|
|
|
|
NOTE: When checking intersection rules, an OperatorGroup's namespace is always
|
|
included as part of its selected target namespaces.
|
|
|
|
[id="olm-operatorgroups-intersection-rules_{context}"]
|
|
=== Rules for intersection
|
|
|
|
Each time an active member CSV synchronizes, OLM queries the cluster for the set
|
|
of intersecting provided APIs between the CSV's OperatorGroup 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 OperatorGroup's:
|
|
** Continue transitioning.
|
|
* If `true` and the CSV's provided APIs are _not_ a subset of the
|
|
OperatorGroup's:
|
|
** If the OperatorGroup is static:
|
|
*** Clean up any deployments that belong to the CSV.
|
|
*** Transition the CSV to a failed state with status reason
|
|
`CannotModifyStaticOperatorGroupProvidedAPIs`.
|
|
** If the OperatorGroup is _not_ static:
|
|
*** Replace the OperatorGroup's `olm.providedAPIs` annotation with the union of
|
|
itself and the CSV's provided APIs.
|
|
* If `false` and the CSV's provided APIs are _not_ a subset of the
|
|
OperatorGroup'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 OperatorGroup's:
|
|
** If the OperatorGroup is static:
|
|
*** Clean up any deployments that belong to the CSV.
|
|
*** Transition the CSV to a failed state with status reason
|
|
`CannotModifyStaticOperatorGroupProvidedAPIs`.
|
|
** If the OperatorGroup is _not_ static:
|
|
*** Replace the OperatorGroup's `olm.providedAPIs` annotation with the
|
|
difference between itself and the CSV's provided APIs.
|
|
|
|
[NOTE]
|
|
====
|
|
Failure states caused by OperatorGroups are non-terminal.
|
|
====
|
|
|
|
The following actions are performed each time an OperatorGroup 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 if `olm.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.
|