このコンテンツは選択した言語では利用できません。

Chapter 5. Cluster extensions


5.1. Supported extensions

To install an Operator as a cluster extension, it must meet bundle format, install mode, and dependency requirements. Operator Lifecycle Manager (OLM) v1 supports extensions that use webhooks for validation, mutation, or conversion.

Operator Lifecycle Manager (OLM) v1 supports extensions that use the AllNamespaces install mode. With this mode, the Operator watches and manages resources across all namespaces in the cluster.

As a Technology Preview feature, you can configure an extension to watch a specific namespace. This limits watching to one namespace instead of the entire cluster.

5.1.1. Supported bundle formats and dependencies

To install an Operator as a cluster extension, the Operator must be packaged using the registry+v1 bundle format. OLM v1 does not support Operators that declare dependencies by using file-based catalog properties.

To install an Operator as a cluster extension, it must meet the following criteria:

  • The Operator is packaged using the registry+v1 bundle format.
  • The Operator does not declare dependencies by using the following file-based catalog properties:

    • olm.gvk.required
    • olm.package.required
    • olm.constraint

OLM v1 verifies that an Operator meets these requirements during installation. If an Operator does not meet these criteria, OLM v1 reports the issue in the cluster extension status conditions.

Operator Lifecycle Manager (OLM) v1 does not support the OperatorConditions API introduced in OLM (Classic).

If an extension relies on only the OperatorConditions API to manage updates, the extension might not install correctly. Most extensions that rely on this API fail at start time, but some might fail during reconciliation.

As a workaround, you can pin your extension to a specific version. When you want to update your extension, consult the extension’s documentation to find out when it is safe to pin the extension to a new version.

5.1.2. Webhook support

Operator Lifecycle Manager (OLM) v1 supports Operators that use webhooks for validation, mutation, or conversion. Operators use webhooks to enforce security policies or inject configurations into resources.

The OpenShift Service CA Operator automatically manages webhook certificates. When you install an Operator that includes webhooks, the OpenShift Service CA Operator completes the following actions:

  • Applies Service CA annotations to webhook configurations and services.
  • Generates TLS certificates in the namespace where you install the cluster extension.
  • Mounts certificate secrets to the Operator deployment.
  • Configures webhook services with proper TLS settings.

5.2. Managing cluster extensions

You use catalogs to access the versions, patches, and over-the-air updates for extensions and Operators. You use custom resources (CRs) to manage extensions declaratively from the CLI.

Note

For OpenShift Container Platform 5.0, documented procedures for OLM v1 are CLI-based only. Alternatively, administrators can create and view related objects in the web console by using normal methods, such as the Import YAML and Search pages. However, the existing Software Catalog and Installed Operators pages do not yet display OLM v1 components.

5.2.1. Find Operators to install from a catalog

After you add a catalog to your cluster, you can query the catalog to find Operators and extensions to install.

Currently in Operator Lifecycle Manager (OLM) v1, you cannot query on-cluster catalogs managed by catalogd. In OLM v1, you must use the opm and jq CLI tools to query the catalog registry.

Prerequisites

  • You have added a catalog to your cluster.
  • You have installed the jq CLI tool.
  • You have installed the opm CLI tool.

Procedure

  1. To return a list of extensions that support the AllNamespaces install mode and do not use webhooks, enter the following command:

    $ opm render <catalog_registry_url>:<tag> \
      | jq -cs '[.[] | select(.schema == "olm.bundle" \
      and (.properties[] | select(.type == "olm.csv.metadata").value.installModes[] \
      | select(.type == "AllNamespaces" and .supported == true)) \
      and .spec.webhookdefinitions == null) | .package] | unique[]'

    where:

    catalog_registry_url
    Specifies the URL of the catalog registry, such as registry.redhat.io/redhat/redhat-operator-index.
    tag

    Specifies the tag or version of the catalog, such as v5.0 or latest.

    Example command

    $ opm render \
      registry.redhat.io/redhat/redhat-operator-index:v5.0 \
      | jq -cs '[.[] | select(.schema == "olm.bundle" \
      and (.properties[] | select(.type == "olm.csv.metadata").value.installModes[] \
      | select(.type == "AllNamespaces" and .supported == true)) \
      and .spec.webhookdefinitions == null) | .package] | unique[]'

    Example output

    "3scale-operator"
    "amq-broker-rhel8"
    "amq-online"
    "amq-streams"
    "amq-streams-console"
    "ansible-automation-platform-operator"
    "ansible-cloud-addons-operator"
    "apicast-operator"
    "authorino-operator"
    "aws-load-balancer-operator"
    "bamoe-kogito-operator"
    "cephcsi-operator"
    "cincinnati-operator"
    "cluster-logging"
    "cluster-observability-operator"
    "compliance-operator"
    "container-security-operator"
    "cryostat-operator"
    "datagrid"
    "devspaces"
    ...

  2. Inspect the contents of an extension’s metadata by running the following command:

    $ opm render <catalog_registry_url>:<tag> \
      | jq -s '.[] | select( .schema == "olm.package") \
      | select( .name == "<package_name>")'

    Example command

    $ opm render \
      registry.redhat.io/redhat/redhat-operator-index:v5.0 \
      | jq -s '.[] | select( .schema == "olm.package") \
      | select( .name == "openshift-pipelines-operator-rh")'

    Example output

    {
      "schema": "olm.package",
      "name": "openshift-pipelines-operator-rh",
      "defaultChannel": "latest",
      "icon": {
        "base64data": "iVBORw0KGgoAAAANSUhE...",
        "mediatype": "image/png"
      }
    }

5.2.1.1. Common catalog queries

You can query catalogs by using the opm and jq CLI tools to help you install, update, and manage the lifecycle of extensions.

The following examples show common catalog queries for extensions:

Command syntax

$ opm render <catalog_registry_url>:<tag> | <jq_request>

where:

catalog_registry_url
Specifies the URL of the catalog registry, such as registry.redhat.io/redhat/redhat-operator-index.
tag
Specifies the tag or version of the catalog, such as v5.0 or latest.
jq_request
Specifies the query you want to run on the catalog.

Example 5.1. Example command

$ opm render \
  registry.redhat.io/redhat/redhat-operator-index:v5.0 \
  | jq -cs '[.[] | select(.schema == "olm.bundle" and (.properties[] \
  | select(.type == "olm.csv.metadata").value.installModes[] \
  | select(.type == "AllNamespaces" and .supported == true)) \
  and .spec.webhookdefinitions == null) \
  | .package] | unique[]'
Table 5.1. Common package queries
QueryRequest

Available packages in a catalog

$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .schema == "olm.package")'

Packages that support AllNamespaces install mode and do not use webhooks

$ opm render <catalog_registry_url>:<tag> \ | jq -cs '[.[] | select(.schema == "olm.bundle" and (.properties[] \ | select(.type == "olm.csv.metadata").value.installModes[] \ | select(.type == "AllNamespaces" and .supported == true)) \ and .spec.webhookdefinitions == null) \ | .package] | unique[]'

Package metadata

$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .schema == "olm.package") \ | select( .name == "<package_name>")'

Catalog blobs in a package

$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .package == "<package_name>")'
Table 5.2. Common channel queries
QueryRequest

Channels in a package

$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .schema == "olm.channel" ) \ | select( .package == "<package_name>") | .name'

Versions in a channel

$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .package == "<package_name>" ) \ | select( .schema == "olm.channel" ) \ | select( .name == "<channel_name>" ) .entries \ | .[] | .name'
  • Latest version in a channel
  • Upgrade path
$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .schema == "olm.channel" ) \ | select ( .name == "<channel_name>") \ | select( .package == "<package_name>")'
Table 5.3. Common bundle queries
QueryRequest

Bundles in a package

$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .schema == "olm.bundle" ) \ | select( .package == "<package_name>") | .name'
  • Bundle dependencies
  • Available APIs
$ opm render <catalog_registry_url>:<tag> \ | jq -s '.[] | select( .schema == "olm.bundle" ) \ | select ( .name == "<bundle_name>") \ | select( .package == "<package_name>")'

5.2.2. Cluster extension permissions

Operator Lifecycle Manager (OLM) v1 installs and manages cluster extensions in OpenShift Container Platform by using its own service account with cluster-admin permissions. You do not need to create an installer service account or assign permissions for each extension.

Access to the ClusterExtension API controls who can install and manage extensions. By default, only cluster administrators have write access. Unrestricted write access to this API delegates cluster-admin trust.

The spec.serviceAccount field in the ClusterExtension API is optional, deprecated, and ignored. Existing extensions that specify this field continue to work after a cluster update. The API server returns a deprecation warning when you create or update an extension that specifies the field. To stop these warnings, remove the spec.serviceAccount field from your ClusterExtension resource and any manifests that define it.

To delegate extension management, combine a validating admission policy with role-based access control (RBAC).

5.2.2.1. Create an installation namespace

To install a cluster extension in OpenShift Container Platform, first create an installation namespace. Specify this namespace in the spec.namespace field of the extension manifest.

The spec.namespace field does not restrict the resources or permissions of an extension to the installation namespace. Depending on the bundle and configuration, an extension can create resources or use permissions in other namespaces or across the cluster.

Important

Cluster extensions are cluster-scoped.

Prerequisites

  • Access to an OpenShift Container Platform cluster using an account with cluster-admin permissions.

Procedure

  • Create the installation namespace by running the following command:

    $ oc adm new-project <new_namespace>

5.2.3. Install a cluster extension in all namespaces

You can install an extension from a catalog by creating a custom resource (CR) and applying it to the cluster. Operator Lifecycle Manager (OLM) v1 supports installing cluster extensions, including OLM (Classic) Operators in the registry+v1 bundle format, that are scoped to the cluster.

Note

For OpenShift Container Platform 5.0, documented procedures for OLM v1 are CLI-based only. Alternatively, administrators can create and view related objects in the web console by using normal methods, such as the Import YAML and Search pages. However, the existing Software Catalog and Installed Operators pages do not yet display OLM v1 components.

Prerequisites

  • You have access to the cluster by using an account with cluster-admin permissions.
  • You have created the installation namespace.
  • You have identified a supported package and an available version or channel in a catalog on the cluster.

Procedure

  1. Create a CR, similar to the following example:

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      name: <clusterextension_name>
    spec:
      namespace: <installed_namespace>
      source:
        sourceType: Catalog
        catalog:
          packageName: <package_name>
          channels:
            - <channel_name>
          version: <version_or_version_range>
          upgradeConstraintPolicy: CatalogProvided

    where:

    spec.namespace
    Specifies the namespace where you want the bundle installed, such as pipelines or my-extension. Extensions are still cluster-scoped and might contain resources that are installed in different namespaces.
    spec.source.catalog.channels
    Specifies channel names as an array, such as pipelines-1.14 or latest. This field is optional.
    spec.source.catalog.version
    Specifies the version or version range, such as 1.14.0, 1.14.x, or >=1.16, of the package you want to install or update. This field is optional.
    spec.source.catalog.upgradeConstraintPolicy

    Specifies the upgrade constraint policy. If unspecified, the default setting is CatalogProvided. The CatalogProvided setting only updates if the new version satisfies the upgrade constraints set by the package author. To force an update or rollback, set the field to SelfCertified. This field is optional.

    Example pipelines-operator.yaml CR

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      name: pipelines-operator
    spec:
      namespace: pipelines
      source:
        sourceType: Catalog
        catalog:
          packageName: openshift-pipelines-operator-rh
          version: "1.14.x"

  2. Apply the CR to the cluster by running the following command:

    $ oc apply -f pipelines-operator.yaml

    Example output

    clusterextension.olm.operatorframework.io/pipelines-operator created

Verification

  1. View the Operator or extension’s CR in the YAML format by running the following command:

    $ oc get clusterextension pipelines-operator -o yaml

    Example output

    apiVersion: v1
    items:
    - apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"olm.operatorframework.io/v1","kind":"ClusterExtension","metadata":{"annotations":{},"name":"pipes"},"spec":{"namespace":"pipelines","source":{"catalog":{"packageName":"openshift-pipelines-operator-rh","version":"1.14.x"},"sourceType":"Catalog"}}}
        creationTimestamp: "2025-02-18T21:48:13Z"
        finalizers:
        - olm.operatorframework.io/cleanup-unpack-cache
        - olm.operatorframework.io/cleanup-contentmanager-cache
        generation: 1
        name: pipelines-operator
        resourceVersion: "72725"
        uid: e18b13fb-a96d-436f-be75-a9a0f2b07993
      spec:
        namespace: pipelines
        source:
          catalog:
            packageName: openshift-pipelines-operator-rh
            upgradeConstraintPolicy: CatalogProvided
            version: 1.14.x
          sourceType: Catalog
      status:
        conditions:
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: Deprecated
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: PackageDeprecated
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: ChannelDeprecated
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: BundleDeprecated
        - lastTransitionTime: "2025-02-18T21:48:16Z"
          message: Installed bundle registry.redhat.io/openshift-pipelines/pipelines-operator-bundle@sha256:f7b19ce26be742c4aaa458d37bc5ad373b5b29b20aaa7d308349687d3cbd8838
            successfully
          observedGeneration: 1
          reason: Succeeded
          status: "True"
          type: Installed
        - lastTransitionTime: "2025-02-18T21:48:16Z"
          message: desired state reached
          observedGeneration: 1
          reason: Succeeded
          status: "True"
          type: Progressing
        install:
          bundle:
            name: openshift-pipelines-operator-rh.v1.14.5
            version: 1.14.5
    kind: List
    metadata:
      resourceVersion: ""

    where:

    spec.channel
    Displays the channel defined in the CR of the extension.
    spec.version
    Displays the version or version range defined in the CR of the extension.
    status.conditions
    Displays information about the status and health of the extension.
    type: Deprecated

    Displays whether one or more of following are deprecated:

    type: PackageDeprecated
    Displays whether the resolved package is deprecated.
    type: ChannelDeprecated
    Displays whether the resolved channel is deprecated.
    type: BundleDeprecated
    Displays whether the resolved bundle is deprecated.

    The value of False in the status field indicates that the reason: Deprecated condition is not deprecated. The value of True in the status field indicates that the reason: Deprecated condition is deprecated.

    installedBundle.name
    Displays the name of the bundle installed.
    installedBundle.version
    Displays the version of the bundle installed.

5.2.4. Configure a watch namespace for a cluster extension (Technology Preview)

You can configure the watch namespace for extensions that support namespace-scoped resource watching.

Important

Configuring watch namespace for a cluster extension is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

Prerequisites

  • You have access to an OpenShift Container Platform cluster using an account with cluster-admin permissions.
  • You have enabled the TechPreviewNoUpgrade feature set on the cluster.
  • You have created the installation namespace.
  • You have verified the supported install modes for the extension and determined the required watchNamespace configuration.

Procedure

  1. Create a custom resource (CR) based on where you want the extension to watch for resources:

    • To configure the extension to watch its own installation namespace:

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: <extension_name>
      spec:
        namespace: <installation_namespace>
        config:
          configType: Inline
          inline:
            watchNamespace: <installation_namespace>
        source:
          sourceType: Catalog
          catalog:
            packageName: <package_name>
            version: <version>
            upgradeConstraintPolicy: CatalogProvided

      where:

      config.inline.watchNamespace
      Specifies the namespace to watch for resources. For requirements and valid values, see "Extension configuration".
    • To configure the extension to watch a different namespace:

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: <extension_name>
      spec:
        namespace: <installation_namespace>
        config:
          configType: Inline
          inline:
            watchNamespace: <watched_namespace>
        source:
          sourceType: Catalog
          catalog:
            packageName: <package_name>
            version: <version>
            upgradeConstraintPolicy: CatalogProvided
  2. Apply the CR to the cluster by running the following command:

    $ oc apply -f <cluster_extension_cr>.yaml

Verification

  • Verify that the extension installed successfully by running the following command:

    $ oc get clusterextension <extension_name> -o yaml

    Example output

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      name: <extension_name>
    spec:
      namespace: <installation_namespace>
      config:
        configType: Inline
        inline:
          watchNamespace: <installation_namespace>
    status:
      conditions:
      - type: Installed
        status: "True"
        reason: Succeeded

5.2.5. Updating a cluster extension

You can update your cluster extension or Operator by manually editing the custom resource (CR) and applying the changes.

Warning

Automatic updates can install bundles that grant an extension additional permissions without administrator review. To review each bundle before installation, specify an exact approved version. Review the bundle’s permissions and configuration before approving another version.

Prerequisites

  • You have an Operator or extension installed.
  • You have installed the jq CLI tool.
  • You have installed the opm CLI tool.

Procedure

  1. Inspect a package for channel and version information from a local copy of your catalog file by completing the following steps:

    1. Get a list of channels from a selected package by running the following command:

      $ opm render <catalog_registry_url>:<tag> \
        | jq -s '.[] | select( .schema == "olm.channel" ) \
        | select( .package == "openshift-pipelines-operator-rh") | .name'

      Example command

      $ opm render registry.redhat.io/redhat/redhat-operator-index:v5.0 \
        | jq -s '.[] | select( .schema == "olm.channel" ) \
        | select( .package == "openshift-pipelines-operator-rh") | .name'

      Example output

      "latest"
      "pipelines-1.14"
      "pipelines-1.15"
      "pipelines-1.16"
      "pipelines-1.17"

    2. Get a list of the versions published in a channel by running the following command:

      $ opm render <catalog_registry_url>:<tag> \
        | jq -s '.[] | select( .package == "<package_name>" ) \
        | select( .schema == "olm.channel" ) \
        | select( .name == "<channel_name>" ) | .entries \
        | .[] | .name'

      Example command

      $ opm render registry.redhat.io/redhat/redhat-operator-index:v5.0 \
        | jq -s '.[] | select( .package == "openshift-pipelines-operator-rh" ) \
        | select( .schema == "olm.channel" ) | select( .name == "latest" ) \
        | .entries | .[] | .name'

      Example output

      "openshift-pipelines-operator-rh.v1.15.0"
      "openshift-pipelines-operator-rh.v1.16.0"
      "openshift-pipelines-operator-rh.v1.17.0"
      "openshift-pipelines-operator-rh.v1.17.1"

  2. Find out what version or channel is specified in your Operator or extension’s CR by running the following command:

    $ oc get clusterextension <operator_name> -o yaml

    Example command

    $ oc get clusterextension pipelines-operator -o yaml

    Example output

    apiVersion: v1
    items:
    - apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"olm.operatorframework.io/v1","kind":"ClusterExtension","metadata":{"annotations":{},"name":"pipes"},"spec":{"namespace":"pipelines","source":{"catalog":{"packageName":"openshift-pipelines-operator-rh","version":"1.14.x"},"sourceType":"Catalog"}}}
        creationTimestamp: "2025-02-18T21:48:13Z"
        finalizers:
        - olm.operatorframework.io/cleanup-unpack-cache
        - olm.operatorframework.io/cleanup-contentmanager-cache
        generation: 1
        name: pipelines-operator
        resourceVersion: "72725"
        uid: e18b13fb-a96d-436f-be75-a9a0f2b07993
      spec:
        namespace: pipelines
        source:
          catalog:
            packageName: openshift-pipelines-operator-rh
            upgradeConstraintPolicy: CatalogProvided
            version: 1.14.x
          sourceType: Catalog
      status:
        conditions:
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: Deprecated
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: PackageDeprecated
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: ChannelDeprecated
        - lastTransitionTime: "2025-02-18T21:48:13Z"
          message: ""
          observedGeneration: 1
          reason: Deprecated
          status: "False"
          type: BundleDeprecated
        - lastTransitionTime: "2025-02-18T21:48:16Z"
          message: Installed bundle registry.redhat.io/openshift-pipelines/pipelines-operator-bundle@sha256:f7b19ce26be742c4aaa458d37bc5ad373b5b29b20aaa7d308349687d3cbd8838
            successfully
          observedGeneration: 1
          reason: Succeeded
          status: "True"
          type: Installed
        - lastTransitionTime: "2025-02-18T21:48:16Z"
          message: desired state reached
          observedGeneration: 1
          reason: Succeeded
          status: "True"
          type: Progressing
        install:
          bundle:
            name: openshift-pipelines-operator-rh.v1.14.5
            version: 1.14.5
    kind: List
    metadata:
      resourceVersion: ""

  3. Edit your CR by using one of the following methods:

    • If you want to pin your Operator or extension to specific version, such as 1.15.0, edit your CR similar to the following example:

      Example pipelines-operator.yaml CR

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: pipelines-operator
      spec:
        namespace: pipelines
        source:
          sourceType: Catalog
          catalog:
            packageName: openshift-pipelines-operator-rh
            version: "1.15.0"

      This example updates the version from 1.14.x to 1.15.0.

    • If you want to define a range of acceptable update versions, edit your CR similar to the following example:

      Example CR with a version range specified

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: pipelines-operator
      spec:
        namespace: pipelines
        source:
          sourceType: Catalog
          catalog:
            packageName: openshift-pipelines-operator-rh
            version: ">1.15, <1.17"

      The spec.source.catalog.version value specifies that the desired version range is greater than version 1.15 and less than 1.17.

    • If you want to update to the latest version that can be resolved from a channel, edit your CR similar to the following example:

      Example CR with a specified channel

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: pipelines-operator
      spec:
        namespace: pipelines
        source:
          sourceType: Catalog
          catalog:
            packageName: openshift-pipelines-operator-rh
            channels:
              - latest

      The spec.source.catalog.channels value installs the latest release that can be resolved from the specified channel. Updates to the channel are automatically installed. Enter values as an array.

    • If you want to specify a channel and version or version range, edit your CR similar to the following example:

      Example CR with a specified channel and version range

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: pipelines-operator
      spec:
        namespace: pipelines
        source:
          sourceType: Catalog
          catalog:
            packageName: openshift-pipelines-operator-rh
            channels:
              - latest
            version: "<1.16"

      For more information, see "Example custom resources (CRs) that specify a target version".

  4. Apply the update to the cluster by running the following command:

    $ oc apply -f pipelines-operator.yaml

    Example output

    clusterextension.olm.operatorframework.io/pipelines-operator configured

Verification

  • Verify that the channel and version updates have been applied by running the following command:

    $ oc get clusterextension pipelines-operator -o yaml

    Example output

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"olm.operatorframework.io/v1","kind":"ClusterExtension","metadata":{"annotations":{},"name":"pipes"},"spec":{"namespace":"pipelines","source":{"catalog":{"packageName":"openshift-pipelines-operator-rh","version":"\u003c1.16"},"sourceType":"Catalog"}}}
      creationTimestamp: "2025-02-18T21:48:13Z"
      finalizers:
      - olm.operatorframework.io/cleanup-unpack-cache
      - olm.operatorframework.io/cleanup-contentmanager-cache
      generation: 2
      name: pipes
      resourceVersion: "90693"
      uid: e18b13fb-a96d-436f-be75-a9a0f2b07993
    spec:
      namespace: pipelines
      source:
        catalog:
          packageName: openshift-pipelines-operator-rh
          upgradeConstraintPolicy: CatalogProvided
          version: <1.16
        sourceType: Catalog
    status:
      conditions:
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: Deprecated
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: PackageDeprecated
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: ChannelDeprecated
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: BundleDeprecated
      - lastTransitionTime: "2025-02-18T21:48:16Z"
        message: Installed bundle registry.redhat.io/openshift-pipelines/pipelines-operator-bundle@sha256:8a593c1144709c9aeffbeb68d0b4b08368f528e7bb6f595884b2474bcfbcafcd
          successfully
        observedGeneration: 2
        reason: Succeeded
        status: "True"
        type: Installed
      - lastTransitionTime: "2025-02-18T21:48:16Z"
        message: desired state reached
        observedGeneration: 2
        reason: Succeeded
        status: "True"
        type: Progressing
      install:
        bundle:
          name: openshift-pipelines-operator-rh.v1.15.2
          version: 1.15.2

Troubleshooting

  • If you specify a target version or channel that is deprecated or does not exist, you can run the following command to check the status of your extension:

    $ oc get clusterextension <operator_name> -o yaml

    Example output for a version that does not exist

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"olm.operatorframework.io/v1","kind":"ClusterExtension","metadata":{"annotations":{},"name":"pipes"},"spec":{"namespace":"pipelines","source":{"catalog":{"packageName":"openshift-pipelines-operator-rh","version":"9.x"},"sourceType":"Catalog"}}}
      creationTimestamp: "2025-02-18T21:48:13Z"
      finalizers:
      - olm.operatorframework.io/cleanup-unpack-cache
      - olm.operatorframework.io/cleanup-contentmanager-cache
      generation: 3
      name: pipes
      resourceVersion: "93334"
      uid: e18b13fb-a96d-436f-be75-a9a0f2b07993
    spec:
      namespace: pipelines
      source:
        catalog:
          packageName: openshift-pipelines-operator-rh
          upgradeConstraintPolicy: CatalogProvided
          version: 9.x
        sourceType: Catalog
    status:
      conditions:
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: Deprecated
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: PackageDeprecated
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: ChannelDeprecated
      - lastTransitionTime: "2025-02-18T21:48:13Z"
        message: ""
        observedGeneration: 2
        reason: Deprecated
        status: "False"
        type: BundleDeprecated
      - lastTransitionTime: "2025-02-18T21:48:16Z"
        message: Installed bundle registry.redhat.io/openshift-pipelines/pipelines-operator-bundle@sha256:8a593c1144709c9aeffbeb68d0b4b08368f528e7bb6f595884b2474bcfbcafcd
          successfully
        observedGeneration: 3
        reason: Succeeded
        status: "True"
        type: Installed
      - lastTransitionTime: "2025-02-18T21:48:16Z"
        message: 'error upgrading from currently installed version "1.15.2": no bundles
          found for package "openshift-pipelines-operator-rh" matching version "9.x"'
        observedGeneration: 3
        reason: Retrying
        status: "True"
        type: Progressing
      install:
        bundle:
          name: openshift-pipelines-operator-rh.v1.15.2
          version: 1.15.2

5.2.6. Deleting an Operator

You can delete an Operator and its custom resource definitions (CRDs) by deleting the ClusterExtension custom resource (CR).

Prerequisites

  • You have a catalog installed.
  • You have an Operator installed.

Procedure

  • Delete an Operator and its CRDs by running the following command:

    $ oc delete clusterextension <operator_name>

    Example output

    clusterextension.olm.operatorframework.io "<operator_name>" deleted

Verification

  • Verify that the extension CR no longer exists by running the following command:

    $ oc get clusterextension <operator_name>

    The API server returns a NotFound error. A namespace that you created before installing the extension remains on the cluster.

5.2.7. Downloading the bundle manifests of an extension

Download the bundle manifests of an extension with the opm CLI tool. Review the resources and runtime permissions in the manifests before approving the extension for installation.

Prerequisites

  • You have access to an OpenShift Container Platform cluster using an account with cluster-admin permissions.
  • You have decided which extension you want to install.
  • You have installed the opm CLI tool.

Procedure

  1. Inspect the available versions and images of the extension you want to install by running the following command:

    $ opm render <registry_url>:<tag_or_version> | \
      jq -cs '.[] | select( .schema == "olm.bundle" ) | \
      select( .package == "<extension_name>") | \
      {"name":.name, "image":.image}'

    Example command

    $ opm render registry.redhat.io/redhat/redhat-operator-index:v5.0 | \
      jq -cs '.[] | select( .schema == "olm.bundle" ) | \
      select( .package == "openshift-pipelines-operator-rh") | \
      {"name":.name, "image":.image}'

    Example output

    {"name":"openshift-pipelines-operator-rh.v1.14.5","image":"registry.redhat.io/openshift-pipelines/pipelines-operator-bundle@sha256:f7b19ce26be742c4aaa458d37bc5ad373b5b29b20aaa7d308349687d3cbd8838"}

  2. Make a directory to extract the image of the bundle that you want to install by running the following command:

    $ mkdir <new_dir>
  3. Change into the directory by running the following command:

    $ cd <new_dir>
  4. Find the image reference of the version that you want to install and run the following command:

    $ oc image extract <full_path_to_registry_image>@sha256:<sha>

    Example command

    $ oc image extract registry.redhat.io/openshift-pipelines/pipelines-operator-bundle@sha256:f7b19ce26be742c4aaa458d37bc5ad373b5b29b20aaa7d308349687d3cbd8838

  5. Change into the manifests directory by running the following command:

    $ cd manifests
  6. View the contents of the manifests directory by entering the following command. The output lists the manifests of the resources required to install, manage, and operate your extension.

    $ tree

    Example output

    .
    ├── manifests
    │   ├── config-logging_v1_configmap.yaml
    │   ├── openshift-pipelines-operator-monitor_monitoring.coreos.com_v1_servicemonitor.yaml
    │   ├── openshift-pipelines-operator-prometheus-k8s-read-binding_rbac.authorization.k8s.io_v1_rolebinding.yaml
    │   ├── openshift-pipelines-operator-read_rbac.authorization.k8s.io_v1_role.yaml
    │   ├── openshift-pipelines-operator-rh.clusterserviceversion.yaml
    │   ├── operator.tekton.dev_manualapprovalgates.yaml
    │   ├── operator.tekton.dev_openshiftpipelinesascodes.yaml
    │   ├── operator.tekton.dev_tektonaddons.yaml
    │   ├── operator.tekton.dev_tektonchains.yaml
    │   ├── operator.tekton.dev_tektonconfigs.yaml
    │   ├── operator.tekton.dev_tektonhubs.yaml
    │   ├── operator.tekton.dev_tektoninstallersets.yaml
    │   ├── operator.tekton.dev_tektonpipelines.yaml
    │   ├── operator.tekton.dev_tektonresults.yaml
    │   ├── operator.tekton.dev_tektontriggers.yaml
    │   ├── tekton-config-defaults_v1_configmap.yaml
    │   ├── tekton-config-observability_v1_configmap.yaml
    │   ├── tekton-config-read-rolebinding_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml
    │   ├── tekton-config-read-role_rbac.authorization.k8s.io_v1_clusterrole.yaml
    │   ├── tekton-operator-controller-config-leader-election_v1_configmap.yaml
    │   ├── tekton-operator-info_rbac.authorization.k8s.io_v1_rolebinding.yaml
    │   ├── tekton-operator-info_rbac.authorization.k8s.io_v1_role.yaml
    │   ├── tekton-operator-info_v1_configmap.yaml
    │   ├── tekton-operator_v1_service.yaml
    │   ├── tekton-operator-webhook-certs_v1_secret.yaml
    │   ├── tekton-operator-webhook-config-leader-election_v1_configmap.yaml
    │   ├── tekton-operator-webhook_v1_service.yaml
    │   ├── tekton-result-read-rolebinding_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml
    │   └── tekton-result-read-role_rbac.authorization.k8s.io_v1_clusterrole.yaml
    ├── metadata
    │   ├── annotations.yaml
    │   └── properties.yaml
    └── root
        └── buildinfo
            ├── content_manifests
            │   └── openshift-pipelines-operator-bundle-container-v1.16.2-3.json
            └── Dockerfile-openshift-pipelines-pipelines-operator-bundle-container-v1.16.2-3

5.3. Configuring cluster extensions

You can customize Operator installations to control namespace scope and manage deployment behavior including resource allocation, node placement, and pod scheduling.

Important

Configuring cluster extensions is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

5.3.1. Extension configuration

Configure the namespace an extension watches by using the .spec.config field in the ClusterExtension resource.

Important

OLM v1 configuration API is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

Extensions watch all namespaces by default. Some Operators support only namespace-scoped watching based on OLM (Classic) install modes. Configure the .spec.config.inline.watchNamespace field to install these Operators.

Whether you must configure this field depends on the install modes supported by the bundle.

5.3.1.1. Configuration API structure

The configuration API uses an opaque structure. The bundle validates the configuration values, not OLM v1. Operator authors can define their own configuration requirements.

Currently, the Inline configuration type is the only supported type:

Example inline configuration

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: <extension_name>
...
spec:
  namespace: <installation_namespace>
  config:
    configType: Inline
    inline:
      watchNamespace: <watch_namespace>

where:

<installation_namespace>
Specifies the namespace where the extension components run.
config.configType
Specifies the configuration type. Currently, Inline is the only supported type.
<watch_namespace>
Specifies the namespace where the extension watches for custom resources. The watch namespace can match or differ from the installation namespace, depending on the install modes supported by the bundle.

5.3.2. Watch namespace configuration requirements

Avoid installation failures by using the correct watchNamespace value for the install modes supported by your bundle. Requirements vary based on whether the bundle supports AllNamespaces, OwnNamespace, and SingleNamespace install modes.

OLM (Classic) registry+v1 bundles declare the install modes they support. These install modes control whether watchNamespace configuration is required or optional, and what values are valid.

Note

OLM v1 does not support multi-tenancy. You cannot install the same extension more than once on a cluster. As a result, the MultiNamespace install mode is not supported.

AllNamespaces
Watches resources across all namespaces in the cluster.
OwnNamespace
Watches resources only in the installation namespace.
SingleNamespace
Watches resources in a single namespace that differs from the installation namespace.

Whether the .spec.config.inline.watchNamespace field is required depends on the install modes that the bundle supports.

Table 5.4. Watch namespace requirements by bundle capability
Bundle install mode supportwatchNamespace fieldValid values

AllNamespaces mode only

Not applicable

The watchNamespace field is not supported. Extensions watch all namespaces.

OwnNamespace mode only

Required

Must match .spec.namespace field

SingleNamespace mode only

Required

Must differ from .spec.namespace field

Both OwnNamespace and SingleNamespace install modes

Required

Can match or differ from .spec.namespace field

AllNamespaces install mode with one or both of the OwnNamespace and SingleNamespace install modes

Optional

Omit to watch all namespaces, or specify a namespace to watch only that namespace

Important

OLM v1 validates the watchNamespace value based on the install mode support that is declared by the bundle. The installation fails with a validation error if you specify an invalid value or omit a required field.

5.3.3. Discovering bundle install modes

You can render the bundle metadata to find which install modes a bundle supports.

Prerequisites

  • You have installed the jq CLI tool.
  • You have installed the opm CLI tool.

Procedure

  1. Render the bundle metadata by running the following command:

    $ opm render <bundle_image> -o json | \
      jq 'select(.schema == "olm.bundle") | .properties[] | select(.type == "olm.bundle.object")'

    Example output

    {
      "type": "olm.bundle.object",
      "value": {
        "data": "...",
        "ref": "olm.csv"
      }
    }

  2. Decode the base64-encoded CSV data to view install mode declarations:

    $ echo "<base64_data>" | base64 -d | jq '.spec.installModes'

    Example output

    [
      {
        "type": "OwnNamespace",
        "supported": true
      },
      {
        "type": "SingleNamespace",
        "supported": true
      },
      {
        "type": "MultiNamespace",
        "supported": false
      },
      {
        "type": "AllNamespaces",
        "supported": false
      }
    ]

    In this example, the bundle supports both OwnNamespace and SingleNamespace modes. The .spec.config.inline.watchNamespace field is required and can match or differ from the .spec.namespace field.

5.3.4. Configure a watch namespace for a cluster extension (Technology Preview)

You can configure the watch namespace for extensions that support namespace-scoped resource watching.

Important

Configuring watch namespace for a cluster extension is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

Prerequisites

  • You have access to an OpenShift Container Platform cluster using an account with cluster-admin permissions.
  • You have enabled the TechPreviewNoUpgrade feature set on the cluster.
  • You have created the installation namespace.
  • You have verified the supported install modes for the extension and determined the required watchNamespace configuration.

Procedure

  1. Create a custom resource (CR) based on where you want the extension to watch for resources:

    • To configure the extension to watch its own installation namespace:

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: <extension_name>
      spec:
        namespace: <installation_namespace>
        config:
          configType: Inline
          inline:
            watchNamespace: <installation_namespace>
        source:
          sourceType: Catalog
          catalog:
            packageName: <package_name>
            version: <version>
            upgradeConstraintPolicy: CatalogProvided

      where:

      config.inline.watchNamespace
      Specifies the namespace to watch for resources. For requirements and valid values, see "Extension configuration".
    • To configure the extension to watch a different namespace:

      apiVersion: olm.operatorframework.io/v1
      kind: ClusterExtension
      metadata:
        name: <extension_name>
      spec:
        namespace: <installation_namespace>
        config:
          configType: Inline
          inline:
            watchNamespace: <watched_namespace>
        source:
          sourceType: Catalog
          catalog:
            packageName: <package_name>
            version: <version>
            upgradeConstraintPolicy: CatalogProvided
  2. Apply the CR to the cluster by running the following command:

    $ oc apply -f <cluster_extension_cr>.yaml

Verification

  • Verify that the extension installed successfully by running the following command:

    $ oc get clusterextension <extension_name> -o yaml

    Example output

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      name: <extension_name>
    spec:
      namespace: <installation_namespace>
      config:
        configType: Inline
        inline:
          watchNamespace: <installation_namespace>
    status:
      conditions:
      - type: Installed
        status: "True"
        reason: Succeeded

5.3.4.1. Watch namespace configuration examples

To configure the watchNamespace field correctly for your bundle’s install mode, see the following examples. These show valid configurations for Operators that support the AllNamespaces, OwnNamespace, and SingleNamespace install modes.

Example AllNamespaces install mode

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: example-extension
spec:
  namespace: openshift-operators
  source:
    sourceType: Catalog
    catalog:
      packageName: example-operator

  • The config field is omitted. The extension watches all namespaces by default.

Example OwnNamespace install mode

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: example-extension
spec:
  namespace: example-operators
  config:
    configType: Inline
    inline:
      watchNamespace: example-operators
  source:
    sourceType: Catalog
    catalog:
      packageName: example-operator

  • You must set the watchNamespace field to use the OwnNamespace install mode.
  • The watchNamespace value must match the spec.namespace field value.

Example SingleNamespace install mode

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: example-extension
spec:
  namespace: example-operators
  config:
    configType: Inline
    inline:
      watchNamespace: production
  source:
    sourceType: Catalog
    catalog:
      packageName: example-operator

  • You must set the watchNamespace field to use the SingleNamespace install mode.
  • The watchNamespace value must differ from the spec.namespace field value.
  • In this example, the extension runs in the example-operators namespace but watches resources in the production namespace.

5.3.4.2. Watch namespace validation errors

Validation errors occur when the watchNamespace field is omitted or contains an invalid value for the install modes supported by the bundle.

Table 5.5. Common watchNamespace field validation errors
ErrorCauseResolution

Required field missing

The bundle requires the watchNamespace field but it is omitted.

Add the watchNamespace field with a value that matches the install modes supported by the bundle.

OwnNamespace validation error

The bundle only supports OwnNamespace mode but the watchNamespace value does not match the .spec.namespace field.

Set the watchNamespace field to the same value as the .spec.namespace field.

SingleNamespace validation error

The bundle only supports SingleNamespace mode but the watchNamespace value matches the .spec.namespace field.

Set the watchNamespace field to a different namespace than the .spec.namespace field.

Invalid configuration

The .spec.config structure is malformed or has unsupported fields.

Verify the configuration follows the correct API structure with configType: Inline and valid inline fields.

5.3.5. deploymentConfig API

The deploymentConfig API controls Operator pod runtime settings such as resources, node placement, and environment variables, providing feature parity with OLM (Classic) Subscription configuration.

Important

OLM v1 deploymentConfig API is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

Provides feature parity with the Subscription.spec.config configuration of the OLM (Classic). Configure resources, node placement, storage, environment variables, and other deployment settings.

5.3.5.1. deploymentConfig structure

Configure how the Operator deploys in the spec.config.inline.deploymentConfig field as a JSON object.

Example deploymentConfig object

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: <extension_name>
spec:
  namespace: <installation_namespace>
  source:
    sourceType: Catalog
    catalog:
      packageName: <package_name>
  config:
    configType: Inline
    inline:
      deploymentConfig:
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
        nodeSelector:
          node-role.kubernetes.io/infra: ""
        tolerations:
        - key: node-role.kubernetes.io/infra
          operator: Exists
          effect: NoSchedule

where:

source:
Specifies the package source configuration.
deploymentConfig:
Specifies the object for customizing the deployment.
resources:
Specifies the CPU and memory requests and limits.
nodeSelector:
Specifies the node placement selector.
tolerations:
Specifies the node taint tolerations.

5.3.5.2. Supported configuration fields

Environment variables
Add or override environment variables with env. Values are merged with existing container environment variables, with deploymentConfig values taking precedence.
Environment variable sources
Add environment variable sources with envFrom. Sources are appended to existing sources; duplicates are skipped.
Resource requirements
Specify CPU and memory requests and limits with resources. Replaces existing resource requirements.
Node selector
Control pod node placement with nodeSelector. Replaces existing node selector.
Tolerations
Schedule pods on nodes with taints by using tolerations. Appended to existing tolerations.
Affinity rules
Define pod affinity and anti-affinity rules with affinity. Non-nil fields replace corresponding bundle fields.
Volumes and volume mounts
Add volumes and volume mounts. Volumes with the same name as existing bundle volumes are overridden; new volumes are appended.
Annotations
Add custom pod annotations. Merged with existing annotations. Annotations already set by the bundle cannot be overridden.

5.3.5.3. Configuration validation

OLM v1 validates configuration against a JSON schema generated from Kubernetes API definitions. The schema derives from the SubscriptionConfig type used in OLM (Classic), providing consistent validation across versions.

Invalid configurations prevent installation and report errors in the ClusterExtension resource’s Progressing condition. Common validation errors include:

  • Unknown field errors when using unsupported configuration options
  • Type mismatch errors when field values do not match the expected type
  • Required field errors when mandatory nested fields are missing
Note

OLM v1 applies configurations during the ClusterObjectSet deployment process, modifying Operator manifests before organizing them into phases.

5.3.5.4. Converting from OLM (Classic)

Transfer existing Subscription.spec.config settings to the deploymentConfig object. The YAML structure is the same, but some merge behaviors differ from OLM (Classic).

Note

volumes and volumeMounts with the same name override existing entries in OLM v1 rather than appending as in OLM (Classic).

Example OLM (Classic) subscription configuration

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: my-operator
spec:
  name: my-operator
  channel: stable
  config:
    nodeSelector:
      node-role.kubernetes.io/infra: ""
    tolerations:
    - key: node-role.kubernetes.io/infra
      operator: Exists
      effect: NoSchedule

Equivalent OLM v1 cluster extension configuration

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: my-operator
spec:
  namespace: my-operator-ns
  config:
    configType: Inline
    inline:
      deploymentConfig:
        nodeSelector:
          node-role.kubernetes.io/infra: ""
        tolerations:
        - key: node-role.kubernetes.io/infra
          operator: Exists
          effect: NoSchedule
  source:
    sourceType: Catalog
    catalog:
      packageName: my-operator

5.3.6. ClusterObjectSets deployment mechanism

ClusterObjectSets deploy cluster extensions through ordered phases, enabling safe upgrades by maintaining both old and new revisions until the new version succeeds.

Important

OLM v1 ClusterObjectSets is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

ClusterObjectSets are cluster-scoped APIs representing versioned resource sets organized into ordered phases. OLM v1 uses ClusterObjectSets to deploy Operator resources sequentially.

5.3.6.1. Benefits

Phased rollouts
Resources deploy in a defined order by kind. For example, Custom Resource Definitions (CRDs) are created before deployments that use them.
Safe upgrades
Both old and new revisions remain active until the new version succeeds, mitigating service disruption.
Immutable revision records
Immutable revisions provide a clear deployment record.
Large bundle support
References externalized secrets to bypass the etcd 1.5 MiB size limit, enabling large bundle deployments.

5.3.6.2. Relationship to the deploymentConfig API

OLM v1 applies deploymentConfig settings during the ClusterObjectSet process, modifying Operator manifests before organizing them into phases.

5.3.6.3. Deployment phases

Phases are system-determined groups that organize resources into ordered deployment stages based on their API group and kind. Objects are automatically assigned to well-known phases.

Note

All objects within a phase are applied in no particular order. The next phase begins only after all objects in the current phase pass their readiness probes.

The system assigns resources to the following phases in order:

namespaces
Namespace objects.
policies
NetworkPolicy, PodDisruptionBudget, and PriorityClass objects.
identity
ServiceAccount objects.
configuration
Secret and ConfigMap objects.
storage
PersistentVolume, PersistentVolumeClaim, and StorageClass objects.
crds
CustomResourceDefinition objects.
roles
ClusterRole and Role objects.
bindings
ClusterRoleBinding and RoleBinding objects.
infrastructure
Service, Issuer, and Certificate objects.
deploy
Deployment objects.
scaling
VerticalPodAutoscaler objects.
publish
PrometheusRule, ServiceMonitor, PodMonitor, Ingress, Route, and console resources.
admission
ValidatingWebhookConfiguration and MutatingWebhookConfiguration objects.

5.3.7. Inspect ClusterObjectSets

Monitor and troubleshoot cluster extension deployments by viewing ClusterObjectSet phases, resource status, and revision history.

Procedure

  1. List all ClusterObjectSets in the cluster by entering the following command:

    $ oc get clusterobjectsets
  2. List ClusterObjectSets for a specific extension by running the following command:

    $ oc get clusterobjectsets -l olm.operatorframework.io/owner-name=<extension_name>

    Replace <extension_name> with your ClusterExtension name.

  3. View the details of a specific ClusterObjectSet by running the following command:

    $ oc get clusterobjectset <clusterobjectset_name> -o yaml

    Shows deployment phases, resource status, and conditions.

  4. Check the ClusterExtension status to see active revisions by running the following command:

    $ oc get clusterextension <extension_name> -o jsonpath='{.status.activeRevisions}{"\n"}'

    Shows the active revisions currently deployed.

5.3.8. Customize operator deployments

Customize Operator pod deployments to meet production requirements by configuring resource allocation, node placement, and pod tolerations through the ClusterExtension resource.

Important

OLM v1 deploymentConfig API is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

Prerequisites

  • You have access to an OpenShift Container Platform cluster using an account with cluster-admin permissions.
  • You have enabled the TechPreviewNoUpgrade feature set on the cluster.
  • You have created the installation namespace.
  • You have installed the OpenShift CLI (oc).
  • You have identified the operator you want to install and customize.

Procedure

  1. Create a ClusterExtension resource with deploymentConfig customizations:

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      name: my-operator
    spec:
      namespace: my-operator-ns
      config:
        configType: Inline
        inline:
          deploymentConfig:
            resources:
              requests:
                cpu: 100m
                memory: 128Mi
              limits:
                cpu: 500m
                memory: 512Mi
            nodeSelector:
              node-role.kubernetes.io/infra: ""
            tolerations:
            - key: node-role.kubernetes.io/infra
              operator: Exists
              effect: NoSchedule
      source:
        sourceType: Catalog
        catalog:
          packageName: my-operator
          version: 1.0.0

    where:

    resources:
    Specifies CPU and memory resource requests and limits for the Operator pod.
    nodeSelector:
    Specifies pod scheduling restrictions to infrastructure nodes.
    tolerations:
    Specifies pod tolerations that allow scheduling on nodes with the specified taint.
  2. Apply the ClusterExtension resource:

    $ oc apply -f my-operator.yaml
  3. Verify the installation:

    $ oc get clusterextension my-operator -o yaml

Verification

  • Verify that the deploymentConfig settings were applied:

    $ oc get deployment -n my-operator-ns -l olm.operatorframework.io/owner-name=my-operator -o yaml

    Check the deployment specification for your configured settings such as resource limits, node selectors, tolerations, and volumes.

5.3.9. deploymentConfig examples

Customize Operator deployments using resource limits, node placement, custom volumes, environment variables, and combined configurations.

Important

OLM v1 deploymentConfig API is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

5.3.9.1. Environment variables

Add environment variables for runtime configuration.

Adding environment variables

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: kmm-operator
spec:
  namespace: openshift-kmm
  config:
    configType: Inline
    inline:
      deploymentConfig:
        env:
        - name: KMM_MANAGED
          value: "1"
  source:
    sourceType: Catalog
    catalog:
      packageName: kernel-module-management

where:

KMM_MANAGED
Specifies the environment variable used when deploying the Kernel Module Management Operator in a hub-and-spoke configuration.

5.3.9.2. Custom volumes

Mount a custom CA certificate for HTTPS communication through a proxy.

Mounting a custom CA certificate

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: my-operator
spec:
  namespace: my-operator-ns
  config:
    configType: Inline
    inline:
      deploymentConfig:
        volumes:
        - name: trusted-ca
          configMap:
            name: trusted-ca
            items:
            - key: ca-bundle.crt
              path: tls-ca-bundle.pem
        volumeMounts:
        - name: trusted-ca
          mountPath: /etc/pki/ca-trust/extracted/pem
          readOnly: true
  source:
    sourceType: Catalog
    catalog:
      packageName: my-operator

where:

volumes:
Specifies a volume created from the trusted-ca config map.
volumeMounts:
Specifies the volume mount to the Operator container at the specified path.
mountPath:
Specifies the path where the certificate bundle is available inside the container.

5.3.9.3. Pod anti-affinity

Spread Operator pods across nodes for high availability.

Pod anti-affinity for high availability

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: my-operator
spec:
  namespace: my-operator-ns
  config:
    configType: Inline
    inline:
      deploymentConfig:
        affinity:
          podAntiAffinity:
            preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: app.kubernetes.io/name
                    operator: In
                    values:
                    - my-operator
                topologyKey: kubernetes.io/hostname
  source:
    sourceType: Catalog
    catalog:
      packageName: my-operator

where:

podAntiAffinity:
Specifies anti-affinity rules for the Operator pod.
preferredDuringSchedulingIgnoredDuringExecution:
Specifies soft constraints that the scheduler tries to enforce but does not guarantee.
topologyKey
Specifies the topology key that groups nodes by hostname to ensure pods are spread across different nodes.

5.3.9.4. Multiple customizations

Combine multiple deployment customizations.

Production Operator with combined customizations

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: production-operator
spec:
  namespace: production-operators
  config:
    configType: Inline
    inline:
      deploymentConfig:
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 1000m
            memory: 1Gi
        env:
        - name: LOG_LEVEL
          value: info
        - name: ENABLE_METRICS
          value: "true"
        nodeSelector:
          node-role.kubernetes.io/infra: ""
        tolerations:
        - key: node-role.kubernetes.io/infra
          operator: Exists
          effect: NoSchedule
        annotations:
          monitoring.openshift.io/scrape: "true"
          monitoring.openshift.io/port: "8080"
  source:
    sourceType: Catalog
    catalog:
      packageName: production-operator
      version: 2.1.0

where:

resources:
Specifies memory and CPU requests and limits for the Operator pod.
env:
Specifies environment variables for the Operator.
nodeSelector:
Specifies that the pod runs on infrastructure nodes.
tolerations:
Specifies pod tolerations that allow scheduling on nodes with the specified taint.
annotations:
Specifies Prometheus monitoring annotations for the pod.

5.3.10. deploymentConfig field reference

Field reference for the deploymentConfig API including OLM (Classic) to OLM v1 field mappings and merge behavior for each configuration option.

Important

OLM v1 deploymentConfig API is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

5.3.10.1. Field mapping from OLM (Classic) to OLM v1

Field conversion from OLM (Classic) to OLM v1:

Table 5.6. OLM (Classic) to OLM v1 configuration field mapping
OLM (Classic) field pathOLM v1 field pathNotes

spec.config.env

spec.config.inline.deploymentConfig.env

Environment variables are merged. OLM v1 values take precedence over bundle values.

spec.config.envFrom

spec.config.inline.deploymentConfig.envFrom

Environment variable sources are appended to bundle sources. Duplicates are skipped.

spec.config.resources

spec.config.inline.deploymentConfig.resources

Resource specifications completely replace bundle resource requirements.

spec.config.nodeSelector

spec.config.inline.deploymentConfig.nodeSelector

Node selectors completely replace bundle node selectors.

spec.config.tolerations

spec.config.inline.deploymentConfig.tolerations

Tolerations are appended to bundle tolerations.

spec.config.affinity

spec.config.inline.deploymentConfig.affinity

Affinity rules selectively override bundle affinity. Non-nil fields replace corresponding bundle fields.

spec.config.volumes

spec.config.inline.deploymentConfig.volumes

Volumes override existing bundle volumes with the same name; new volumes are appended.

spec.config.volumeMounts

spec.config.inline.deploymentConfig.volumeMounts

Volume mounts override existing bundle volume mounts with the same name; new mounts are appended.

spec.config.annotations

spec.config.inline.deploymentConfig.annotations

Annotations are merged with bundle annotations. Bundle annotations take precedence on conflicts.

spec.config.selector

Not supported

The selector field from OLM (Classic) is not supported in OLM v1. This field was never used in OLM (Classic).

5.3.10.2. Merge and override behavior

Configuration fields have different merge behaviors:

Replace
Completely replaces bundle values. Applies to: resources, nodeSelector
Append
Adds to existing bundle values. Applies to: tolerations, envFrom
Override and append
Overrides existing values with the same name; new values are appended. Applies to: volumes, volumeMounts
Merge with precedence
Merges with bundle values. deploymentConfig values take precedence on conflicts. Applies to: env
Merge with bundle precedence
Merges with bundle values. Bundle takes precedence on conflicts. Applies to: annotations
Selective override
Non-nil fields replace corresponding bundle fields. Applies to: affinity

5.3.10.3. Environment variable fields

env

Specifies an array of environment variable objects. Merged with existing container environment variables, with deploymentConfig values taking precedence. Each object has:

  • name: Environment variable name (string, required).
  • value: Environment variable value (string, optional).
  • valueFrom: Reference to a secret or config map key (object, optional).
envFrom

Specifies an array of environment variable source objects merged with existing sources. Each object can reference:

  • configMapRef: Config map containing environment variables.
  • secretRef: Secret containing environment variables.

5.3.10.4. Resource requirements fields

resources

Specifies compute resource requirements that completely replace existing bundle resource requirements. Contains:

  • requests: Minimum resources required.

    • cpu: CPU request (string, for example, "100m", "0.5").
    • memory: Memory request (string, for example, "128Mi", "1Gi").
  • limits: Maximum resources allowed.

    • cpu: CPU limit (string).
    • memory: Memory limit (string).

5.3.10.5. Node placement fields

nodeSelector

Specifies a map of key-value pairs for node selection. Completely replaces any existing node selector. Pods schedule only on nodes with all specified labels.

Example node selector

nodeSelector:
  node-role.kubernetes.io/infra: ""
  disktype: ssd

tolerations

Specifies an array of toleration objects appended to existing bundle tolerations. Each toleration has:

  • key: Taint key (string).
  • operator: Operator (string: Exists, Equal).
  • value: Taint value (string, required if operator is Equal).
  • effect: Taint effect (string: NoSchedule, PreferNoSchedule, NoExecute).
  • tolerationSeconds: Time before pod eviction for NoExecute effect (integer).
affinity

Specifies an affinity rules object. Non-nil fields replace corresponding bundle fields. Contains:

  • nodeAffinity: Node label-based scheduling rules.
  • podAffinity: Pod label-based scheduling rules.
  • podAntiAffinity: Pod spreading rules across nodes.

5.3.10.6. Storage fields

volumes
Specifies an array of volume objects. Volumes with the same name as existing bundle volumes are overridden; new volumes are appended. All Kubernetes volume types are supported. Each volume requires a name field (string).
volumeMounts

Specifies an array of volume mount objects. Volume mounts with the same name as existing bundle volume mounts are overridden; new mounts are appended. Each mount has:

  • name: Volume name to mount (string, required).
  • mountPath: The path within the container (string, required).
  • readOnly: Whether the volume is read-only (boolean, optional).
  • subPath: A path within the volume (string, optional).

5.3.10.7. Metadata fields

annotations

Specifies a map of key-value pairs for deployment and pod annotations. Annotations are applied to both the deployment metadata and the pod template metadata. Annotations from deploymentConfig are merged with bundle annotations. When keys conflict, bundle annotations take precedence.

Example annotations

annotations:
  monitoring.openshift.io/scrape: "true"
  monitoring.openshift.io/port: "8080"

5.3.11. Troubleshoot deploymentConfig

Common deploymentConfig issues include validation errors, configuration verification problems, and annotation conflicts that can prevent successful Operator installation.

Important

OLM v1 deploymentConfig API is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.

For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.

5.3.11.1. Validation errors

Check the Progressing condition for validation errors when installation fails:

$ oc get clusterextension <extension_name> -o jsonpath='{.status.conditions[?(@.type=="Progressing")].message}'

Common validation errors and resolutions:

Unknown field
Configuration includes an unsupported field. Remove unsupported fields.
Type mismatch
Field value does not match the expected type. Verify field types match Kubernetes specifications.
Required field missing
Mandatory nested field is missing. Complete all required fields in nested structures.

5.3.11.2. Verifying applied configuration

Inspect the Operator deployment to verify applied configurations:

$ oc get deployment -n <namespace> -l olm.operatorframework.io/owner-name=<extension_name> -o yaml

Configuration locations in the deployment specification:

  • Environment variables: spec.template.spec.containers[].env and spec.template.spec.containers[].envFrom
  • Resources: spec.template.spec.containers[].resources
  • Node selector: spec.template.spec.nodeSelector
  • Tolerations: spec.template.spec.tolerations
  • Affinity: spec.template.spec.affinity
  • Volumes: spec.template.spec.volumes and spec.template.spec.containers[].volumeMounts
  • Annotations: metadata.annotations and spec.template.metadata.annotations

5.3.11.3. Annotation conflicts

Bundle annotations take precedence over deploymentConfig annotations when keys conflict. View the installed bundle information:

$ oc get clusterextension <extension_name> -o jsonpath='{.status.install.bundle}'

This returns the bundle name and version. To see the annotations applied to the Operator pod template:

$ oc get deployment -n <namespace> -l olm.operatorframework.io/owner-name=<extension_name> -o jsonpath='{.items[0].spec.template.metadata.annotations}'

To override a bundle annotation, modify the bundle or accept the bundle value.

5.4. User access to extension resources

After you install a cluster extension managed by Operator Lifecycle Manager (OLM) v1, the extension might provide CustomResourceDefinition (CRD) objects that expose new cluster APIs. While cluster administrators automatically have full access to these resources, regular users usually require additional permissions.

OLM v1 does not automatically configure or manage role-based access control (RBAC) for regular users to interact with the APIs provided by installed extensions. Cluster administrators must define the required RBAC policy to create, view, or edit these custom resources (CRs) for such users.

Note

The RBAC permissions described for user access to extension resources are separate from access to the ClusterExtension API used to install and manage extensions.

5.4.1. Common default cluster roles for users

An installed cluster extension can include default cluster roles that grant regular users role-based access control (RBAC) to the extension’s API resources.

Cluster extensions commonly include the following default cluster role policies:

view cluster role
Grants read-only access to custom resource (CR) objects for specified API resources across the cluster. This role provides resource visibility without permission to modify resources, which is ideal for monitoring and viewing.
edit cluster role
Grants permissions to create, update, and delete CR objects across the cluster. This role is intended for users who manage resources but do not manage RBAC or cluster permissions.
admin cluster role
Grants full administrative permissions, including create, update, and delete actions, over all CR objects for specified API resources across the cluster.

5.4.2. Find API groups and resources exposed by a cluster extension

To create appropriate RBAC policies for user access to cluster extension resources, you must know which API groups and resources the extension exposes. You can inspect installed CRDs by using the OpenShift CLI (oc).

Prerequisites

  • A cluster extension has been installed on your cluster.

Procedure

  • To list installed CRDs while specifying a label selector targeting a specific cluster extension by name to find only CRDs owned by that extension, run the following command:

    $ oc get crds -l 'olm.operatorframework.io/owner-kind=ClusterExtension,olm.operatorframework.io/owner-name=<cluster_extension_name>'
  • Alternatively, you can search through all installed CRDs and individually inspect them by CRD name:

    1. List all available custom resource definitions (CRDs) currently installed on the cluster by running the following command:

      $ oc get crds

      Find the CRD you are looking for in the output.

    2. Inspect the individual CRD further to find its API groups by running the following command:

      $ oc get crd <crd_name> -o yaml

5.4.3. Grant user access to extension resources by using custom role bindings

As a cluster administrator, you can manually create and configure role-based access control (RBAC) policies to grant user access to extension resources by using custom role bindings.

Prerequisites

  • A cluster extension has been installed on your cluster.
  • You have a list of API groups and resource names, as described in "Finding API groups and resources exposed by a cluster extension".

Procedure

  1. If the installed cluster extension does not provide default cluster roles, manually create one or more roles:

    1. Consider the use cases for the set of roles described in "Common default cluster roles for users".

      For example, create one or more of the following ClusterRole object definitions, replacing <cluster_extension_api_group> and <cluster_extension_custom_resource> with the actual API group and resource names provided by the installed cluster extension:

      Example view-custom-resource.yaml file

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: view-custom-resource
      rules:
      - apiGroups:
        - <cluster_extension_api_group>
        resources:
        - <cluster_extension_custom_resources>
        verbs:
        - get
        - list
        - watch

      Example edit-custom-resource.yaml file

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: edit-custom-resource
      rules:
      - apiGroups:
        - <cluster_extension_api_group>
        resources:
        - <cluster_extension_custom_resources>
        verbs:
        - get
        - list
        - watch
        - create
        - update
        - patch
        - delete

      Example admin-custom-resource.yaml file

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRole
      metadata:
        name: admin-custom-resource
      rules:
      - apiGroups:
        - <cluster_extension_api_group>
        resources:
        - <cluster_extension_custom_resources>
        verbs:
        - '*'

      Setting a wildcard (*) in the rules.verbs field allows all actions on the specified resources.

    2. Create the cluster roles by running the following command for any YAML files you created:

      $ oc create -f <filename>.yaml
  2. Associate a cluster role to specific users or groups to grant them the necessary permissions for the resource by binding the cluster roles to individual user or group names:

    1. Create an object definition for either a cluster role binding to grant access across all namespaces or a role binding to grant access within a specific namespace:

      • The following example cluster role bindings grant read-only view access to the custom resource across all namespaces:

        Example ClusterRoleBinding object for a user

        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRoleBinding
        metadata:
          name: view-custom-resource-binding
        subjects:
        - kind: User
          name: <user_name>
        roleRef:
          kind: ClusterRole
          name: view-custom-resource
          apiGroup: rbac.authorization.k8s.io

        Example ClusterRoleBinding object for a user

        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRoleBinding
        metadata:
          name: view-custom-resource-binding
        subjects:
        - kind: Group
          name: <group_name>
        roleRef:
          kind: ClusterRole
          name: view-custom-resource
          apiGroup: rbac.authorization.k8s.io

      • The following role binding restricts edit permissions to a specific namespace:

        Example RoleBinding object for a user

        apiVersion: rbac.authorization.k8s.io/v1
        kind: RoleBinding
        metadata:
          name: edit-custom-resource-edit-binding
          namespace: <namespace>
        subjects:
        - kind: User
          name: <username>
        roleRef:
          kind: Role
          name: custom-resource-edit
          apiGroup: rbac.authorization.k8s.io

    2. Save your object definition to a YAML file.
    3. Create the object by running the following command:

      $ oc create -f <filename>.yaml

5.4.4. Grant user access to extension resources by using aggregated cluster roles

As a cluster administrator, you can configure role-based access control (RBAC) policies to grant user access to extension resources by using aggregated cluster roles.

Note

To automatically extend existing default cluster roles, you can add aggregation labels by adding one or more of the following labels to a ClusterRole object:

# ..
metadata:
  labels:
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
    rbac.authorization.k8s.io/aggregate-to-view: "true"
# ..

This allows users who already have view, edit, or admin roles to interact with the custom resource specified by the ClusterRole object without requiring additional role or cluster role bindings to specific users or groups.

Prerequisites

  • A cluster extension has been installed on your cluster.
  • You have a list of API groups and resource names, as described in "Finding API groups and resources exposed by a cluster extension".

Procedure

  1. Create an object definition for a cluster role that specifies the API groups and resources provided by the cluster extension and add an aggregation label to extend one or more existing default cluster roles:

    Example ClusterRole object with an aggregation label

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: view-custom-resource-aggregated
      labels:
        rbac.authorization.k8s.io/aggregate-to-view: "true"
    rules:
      - apiGroups:
          - <cluster_extension_api_group>
        resources:
          - <cluster_extension_custom_resource>
        verbs:
          - get
          - list
          - watch

    You can create similar ClusterRole objects for edit and admin with appropriate verbs, such as create, update, and delete. By using aggregation labels, the permissions for the custom resources are added to the default roles.

  2. Save your object definition to a YAML file.
  3. Create the object by running the following command:

    $ oc create -f <filename>.yaml

5.5. Update paths

Operator Lifecycle Manager (OLM) v1 supports OLM (Classic) semantics for update paths, also known as upgrade edges or upgrade constraints. Support includes replaces, skips, and skipRange directives, with a few noted differences.

By supporting OLM (Classic) semantics, OLM v1 accurately reflects the update graph from catalogs.

OLM v1 differs from the original OLM (Classic) implementation in the following ways:

  • If there are multiple possible successors, OLM v1 behavior differs in the following ways:

    • In OLM (Classic), the successor closest to the channel head is chosen.
    • In OLM v1, the successor with the highest semantic version (semver) is chosen.
  • Consider the following set of file-based catalog (FBC) channel entries:

    # ...
    - name: example.v3.0.0
      skips: ["example.v2.0.0"]
    - name: example.v2.0.0
      skipRange: ">=1.0.0 <2.0.0"

    If 1.0.0 is installed, OLM v1 behavior differs in the following ways:

    • OLM (Classic) will not detect an update path to v2.0.0 because v2.0.0 is skipped and not on the replaces chain.
    • OLM v1 will detect the update path because OLM v1 does not have a concept of a replaces chain. OLM v1 finds all entries that have a replace, skip, or skipRange value that covers the currently installed version.

5.5.1. Support for version ranges

In Operator Lifecycle Manager (OLM) v1, you can specify a version range in an Operator or extension’s custom resource (CR). OLM v1 installs or updates to the latest version that can be resolved within the specified range.

The resolved version workflow includes the following steps:

  • The resolved version is the latest version of the Operator that satisfies the constraints of the Operator and the environment.
  • An Operator update within the specified range is automatically installed if it is resolved successfully.
  • An update is not installed if it is outside of the specified range or if it cannot be resolved successfully.

5.5.2. Version comparison strings

To define a version range for a cluster extension, add a comparison string to the custom resource (CR) of the extension.

A comparison string is a list of space- or comma-separated values and one or more comparison operators enclosed in double quotation marks ("). You can add another comparison string by including an OR, or double vertical bar (||), comparison operator between the strings.

Table 5.7. Basic comparisons
Comparison operatorDefinition

=

Equal to

!=

Not equal to

>

Greater than

<

Less than

>=

Greater than or equal to

<=

Less than or equal to

You can specify a version range in an Operator or extension’s CR by using a range comparison similar to the following example:

Example version range comparison

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: <clusterextension_name>
spec:
  namespace: <installed_namespace>
  source:
    sourceType: Catalog
    catalog:
      packageName: <package_name>
      version: ">=1.11, <1.13"

You can use wildcard characters in all types of comparison strings. OLM v1 accepts x, X, and asterisks (*) as wildcard characters. When you use a wildcard character with the equal sign (=) comparison operator, you define a comparison at the patch or minor version level.

Table 5.8. Example wildcard characters in comparison strings
Wildcard comparisonMatching string

1.11.x

>=1.11.0, <1.12.0

>=1.12.X

>=1.12.0

<=2.x

<3

*

>=0.0.0

You can make patch release comparisons by using the tilde (~) comparison operator. Patch release comparisons specify a minor version up to the next major version.

Table 5.9. Example patch release comparisons
Patch release comparisonMatching string

~1.11.0

>=1.11.0, <1.12.0

~1

>=1, <2

~1.12

>=1.12, <1.13

~1.12.x

>=1.12.0, <1.13.0

~1.x

>=1, <2

You can use the caret (^) comparison operator to make a comparison for a major release. If you make a major release comparison before the first stable release is published, the minor versions define the API’s level of stability. In the semantic versioning (semver) specification, the first stable release is published as the 1.0.0 version.

Table 5.10. Example major release comparisons
Major release comparisonMatching string

^0

>=0.0.0, <1.0.0

^0.0

>=0.0.0, <0.1.0

^0.0.3

>=0.0.3, <0.0.4

^0.2

>=0.2.0, <0.3.0

^0.2.3

>=0.2.3, <0.3.0

^1.2.x

>= 1.2.0, < 2.0.0

^1.2.3

>= 1.2.3, < 2.0.0

^2.x

>= 2.0.0, < 3

^2.3

>= 2.3, < 3

5.5.3. Example custom resources (CRs) that specify a target version

In Operator Lifecycle Manager (OLM) v1, cluster administrators can declaratively set the target version of an Operator or extension in the custom resource (CR).

You can define a target version by specifying any of the following fields:

  • Channel
  • Version number
  • Version range

If you specify a channel in the CR, OLM v1 installs the latest version of the Operator or extension that can be resolved within the specified channel. When updates are published to the specified channel, OLM v1 automatically updates to the latest release that can be resolved from the channel.

Example CR with a specified channel

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: <clusterextension_name>
spec:
  namespace: <installed_namespace>
  source:
    sourceType: Catalog
    catalog:
      packageName: <package_name>
      channels:
        - latest

Installs the latest release that can be resolved from the specified channel. Updates to the channel are automatically installed. Specify the value of the channels parameter as an array. This field is optional

If you specify the Operator or extension’s target version in the CR, OLM v1 installs the specified version. When the target version is specified in the CR, OLM v1 does not change the target version when updates are published to the catalog.

If you want to update the version of the Operator that is installed on the cluster, you must manually edit the Operator’s CR. Specifying an Operator’s target version pins the Operator’s version to the specified release.

Example CR with the target version specified

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: <clusterextension_name>
spec:
  namespace: <installed_namespace>
  source:
    sourceType: Catalog
    catalog:
      packageName: <package_name>
      version: "1.11.1"

Specifies the target version. If you want to update the version of the Operator or extension that is installed, you must manually update this field the CR to the desired target version. This field is optional.

If you want to define a range of acceptable versions for an Operator or extension, you can specify a version range by using a comparison string. When you specify a version range, OLM v1 installs the latest version of an Operator or extension that can be resolved by the Operator Controller.

Example CR with a version range specified

apiVersion: olm.operatorframework.io/v1
kind: ClusterExtension
metadata:
  name: <clusterextension_name>
spec:
  namespace: <installed_namespace>
  source:
    sourceType: Catalog
    catalog:
      packageName: <package_name>
      version: ">1.11.1"

Specifies that the desired version range is greater than version 1.11.1. This field is optional.

After you create or update a CR, apply the configuration file by running the following command:

Command syntax

$ oc apply -f <extension_name>.yaml

5.5.4. Forcing an update or rollback

OLM v1 does not support automatic updates to the next major version or rollbacks to an earlier version. If you want to perform a major version update or rollback, you must verify and force the update manually.

Warning

You must verify the consequences of forcing a manual update or rollback. Failure to verify a forced update or rollback might have catastrophic consequences such as data loss.

Prerequisites

  • You have a catalog installed.
  • You have an Operator or extension installed.

Procedure

  1. Edit the custom resource (CR) of your Operator or extension as shown in the following example:

    Example CR

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      name: <clusterextension_name>
    spec:
      namespace: <installed_namespace>
      source:
        sourceType: Catalog
        catalog:
          packageName: <package_name>
          channels:
            - <channel_name>
          version: <version_or_version_range>
          upgradeConstraintPolicy: SelfCertified

    where:

    spec.namespace
    Specifies the namespace where you want the bundle installed, such as pipelines or my-extension. Extensions are still cluster-scoped and might contain resources that are installed in different namespaces.
    spec.source.catalog.channels
    Specifies channel names as an array, such as pipelines-1.14 or latest. This field is optional.
    spec.source.catalog.version
    Specifies the version or version range, such as 1.14.0, 1.14.x, or >=1.16, of the package you want to install or update. This field is optional.
    spec.source.catalog.upgradeConstraintPolicy
    Specifies the upgrade constraint policy. To force an update or rollback, set the field to SelfCertified. If unspecified, the default setting is CatalogProvided. The CatalogProvided setting only updates if the new version satisfies the upgrade constraints set by the package author. This field is optional.
  2. Apply the changes to your Operator or extensions CR by running the following command:

    $ oc apply -f <extension_name>.yaml

5.5.5. Compatibility with OpenShift Container Platform versions

Before cluster administrators can update their OpenShift Container Platform cluster to its next minor version, they must ensure that all installed Operators are updated to a bundle version that is compatible with the cluster’s next minor version (4.y+1).

For example, Kubernetes periodically deprecates certain APIs that are removed in subsequent releases. If an extension is using a deprecated API, it might no longer work after the OpenShift Container Platform cluster is updated to the Kubernetes version where the API has been removed.

If an Operator author knows that a specific bundle version is not supported and will not work correctly, for any reason, on OpenShift Container Platform later than a certain cluster minor version, they can configure the maximum version of OpenShift Container Platform that their Operator is compatible with.

In the Operator project’s cluster service version (CSV), authors can set the olm.maxOpenShiftVersion annotation to prevent administrators from updating the cluster before updating the installed Operator to a compatible version.

Example CSV with olm.maxOpenShiftVersion annotation

apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  annotations:
    "olm.properties": '[{"type": "olm.maxOpenShiftVersion", "value": "<cluster_version>"}]'

+ Replace <cluster_version> with the latest minor version of OpenShift Container Platform (4.y) that an Operator is compatible with. For example, setting value to 5.0 prevents cluster updates to minor versions later than 5.0 when this bundle is installed on a cluster.

If the olm.maxOpenShiftVersion field is omitted, cluster updates are not blocked by this Operator.

Note

When determining a cluster’s next minor version (4.y+1), OLM v1 only considers major and minor versions (x and y) for comparisons. It ignores any z-stream versions (4.y.z), also known as patch releases, or pre-release versions.

For example, if the cluster’s current version is 5.0.0, the next minor version is 5.1. If the current version is 5.0.0-rc1, the next minor version is still 5.1.

5.5.5.1. Cluster updates blocked by olm cluster Operator

If an installed Operator’s olm.maxOpenShiftVersion field is set and a cluster administrator attempts to update their cluster to a version that the Operator does not provide a valid update path for, the cluster update fails and the Upgradeable status for the olm cluster Operator is set to False.

To resolve the issue, the cluster administrator must either update the installed Operator to a version with a valid update path, if one is available, or they must uninstall the Operator. Then, they can attempt the cluster update again.

5.6. Custom resource definition (CRD) upgrade safety

When you update a custom resource definition (CRD) provided by a cluster extension, Operator Lifecycle Manager (OLM) v1 runs a CRD upgrade safety preflight check to ensure compatibility with earlier versions.

The CRD update must pass the validation checks before the change is allowed to progress on a cluster.

5.6.1. Prohibited CRD upgrade changes

To avoid making a modification that does not validate, review the custom resource definiton (CRD) changes that are blocked by the upgrade safety preflight check.

The CRD upgrade safety preflight check blocks an upgrade if it detects any of the following changes to an existing CRD:

  • Adding a new required field to an existing version
  • Removing an existing field from an existing version
  • Changing an existing field type in an existing version
  • Adding a default value to a field that did not previously have one
  • Changing the default value of an existing field
  • Removing the default value of an existing field
  • Adding enum restrictions to a field that did not previously have them
  • Removing existing enum values from an existing field
  • Increasing the minimum value of an existing field in an existing version
  • Decreasing the maximum value of an existing field in an existing version
  • Adding minimum or maximum constraints to a field that did not previously have them
Note

Rules for minimum and maximum values apply to the minimum, minLength, minProperties, minItems, maximum, maxLength, maxProperties, and maxItems constraints.

The preflight check also blocks an upgrade for the following structural changes, which are handled by the Kubernetes API server:

  • Changing the CRD scope between Cluster and Namespace
  • Removing an existing stored version of the CRD

If the CRD upgrade safety preflight check detects any prohibited change, it logs an error for each violation.

Tip

If a CRD change is neither explicitly allowed nor categorized as a known prohibited change, the preflight check blocks the upgrade and logs an "unknown change" error.

5.6.2. Allowed CRD upgrade changes

Reference which custom resource definition (CRD) changes are compatible with earlier versions to avoid unexpected halts during the upgrade safety preflight check.

The following CRD changes are compatible with earlier versions and pass the upgrade safety preflight check:

  • Adding new values to an existing enum field
  • Changing an existing required field to optional in an existing version
  • Decreasing the minimum value of an existing field in an existing version
  • Increasing the maximum value of an existing field in an existing version
  • Adding a new version of the CRD without modifying existing versions

5.6.3. Disabling the CRD upgrade safety preflight check

You can disable the custom resource definition (CRD) upgrade safety preflight check. In the ClusterExtension object that provides the CRD, set the install.preflight.crdUpgradeSafety.enforcement field with the value of None.

Warning

Disabling the CRD upgrade safety preflight check could break backwards compatibility with stored versions of the CRD and cause other unintended consequences on the cluster.

You cannot disable individual field validators. If you disable the CRD upgrade safety preflight check, you disable all field validators.

Note

If you disable the CRD upgrade safety preflight check in Operator Lifecycle Manager (OLM) v1, the Kubernetes API server still prevents the following operations:

  • Changing scope from Cluster to Namespace or from Namespace to Cluster
  • Removing an existing stored version of the CRD

Prerequisites

  • You have a cluster extension installed.

Procedure

  1. Edit the ClusterExtension object of the CRD:

    $ oc edit clusterextension <clusterextension_name>
  2. Set the install.preflight.crdUpgradeSafety.enforcement field to None:

    Example ClusterExtension object

    apiVersion: olm.operatorframework.io/v1
    kind: ClusterExtension
    metadata:
      name: clusterextension-sample
    spec:
      namespace: default
      source:
        sourceType: "Catalog"
        catalog:
          packageName: argocd-operator
          version: 0.6.0
      install:
        preflight:
          crdUpgradeSafety:
            enforcement: None

5.6.4. Examples of unsafe CRD changes

Review the example unsafe custom resource definition (CRD) changes to recognize modifications that trigger the CRD upgrade safety preflight check.

The following examples use this baseline CustomResourceDefinition object:

Example CRD object

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: v0.13.0
  name: example.test.example.com
spec:
  group: test.example.com
  names:
    kind: Sample
    listKind: SampleList
    plural: samples
    singular: sample
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        properties:
          apiVersion:
            type: string
          kind:
            type: string
          metadata:
            type: object
          spec:
            type: object
          status:
            type: object
          pollInterval:
            type: string
        type: object
    served: true
    storage: true
    subresources:
      status: {}

5.6.4.1. Scope change

The following example changes the spec.scope field from Namespaced to Cluster:

Example scope change in a CRD

spec:
  group: test.example.com
  names:
    kind: Sample
    listKind: SampleList
    plural: samples
    singular: sample
  scope: Cluster
  versions:
  - name: v1alpha1

Example error output

validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "NoScopeChange" validation failed: scope changed from "Namespaced" to "Cluster"

5.6.4.2. Removal of a stored version

The following example removes the existing stored version, v1alpha1:

Example removal of a stored version in a CRD

versions:
- name: v1alpha2
  schema:
    openAPIV3Schema:
      properties:
        apiVersion:
          type: string
        kind:
          type: string
        metadata:
          type: object
        spec:
          type: object
        status:
          type: object
        pollInterval:
          type: string
      type: object

Example error output

validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "NoStoredVersionRemoved" validation failed: stored version "v1alpha1" removed

5.6.4.3. Removal of an existing field

The following example removes the pollInterval property field from the v1alpha1 schema:

Example removal of an existing field in a CRD

versions:
- name: v1alpha1
  schema:
    openAPIV3Schema:
      properties:
        apiVersion:
          type: string
        kind:
          type: string
        metadata:
          type: object
        spec:
          type: object
        status:
          type: object
      type: object

Example error output

validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "NoExistingFieldRemoved" validation failed: crd/test.example.com version/v1alpha1 field/^.spec.pollInterval may not be removed

5.6.4.4. Addition of a required field

The following example changes the pollInterval property to a required field:

Example addition of a required field in a CRD

versions:
- name: v1alpha2
  schema:
    openAPIV3Schema:
      properties:
        apiVersion:
          type: string
        kind:
          type: string
        metadata:
          type: object
        spec:
          type: object
        status:
          type: object
        pollInterval:
          type: string
      type: object
      required:
      - pollInterval

Example error output

validating upgrade for CRD "test.example.com" failed: CustomResourceDefinition test.example.com failed upgrade safety validation. "ChangeValidator" validation failed: version "v1alpha1", field "^": new required fields added: [pollInterval]

Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

Red Hat ドキュメントについて

Legal Notice

Theme

© 2026 Red Hat
トップに戻る