Working with bundle images

    The Operator bundle format is the default packaging method for Operator SDK and Operator Lifecycle Manager (OLM). You can get your Operator ready for use on OLM by using the Operator SDK to build and push your Operator project as a bundle image.

    Prerequisites

    • Operator SDK CLI installed on a development workstation

    • OpenShift CLI () v4.8+ installed

    • Operator project initialized by using the Operator SDK

    • If your Operator is Go-based, your project must be updated to use supported images for running on OKD

    Procedure

    1. Run the following make commands in your Operator project directory to build and push your Operator image. Modify the IMG argument in the following steps to reference a repository that you have access to. You can obtain an account for storing containers at repository sites such as Quay.io.

      1. Build the image:

      2. Push the image to a repository:

        1. $ make docker-push IMG=<registry>/<user>/<operator_image_name>:<tag>
    2. Update your Makefile by setting the IMG URL to your Operator image name and tag that you pushed:

      1. $ # Image URL to use all building/pushing image targets
      2. IMG ?= <registry>/<user>/<operator_image_name>:<tag>

      This value is used for subsequent operations.

    3. Create your Operator bundle manifest by running the make bundle command, which invokes several commands, including the Operator SDK generate bundle and bundle validate subcommands:

      1. $ make bundle

      Bundle manifests for an Operator describe how to display, create, and manage an application. The make bundle command creates the following files and directories in your Operator project:

      • A bundle manifests directory named bundle/manifests that contains a ClusterServiceVersion object

      • A bundle metadata directory named bundle/metadata

      • All custom resource definitions (CRDs) in a config/crd directory

      • A Dockerfile bundle.Dockerfile

      These files are then automatically validated by using operator-sdk bundle validate to ensure the on-disk bundle representation is correct.

    4. Build and push your bundle image by running the following commands. OLM consumes Operator bundles using an index image, which reference one or more bundle images.

      1. Build the bundle image. Set BUNDLE_IMG with the details for the registry, user namespace, and image tag where you intend to push the image:

        1. $ make bundle-build BUNDLE_IMG=<registry>/<user>/<bundle_image_name>:<tag>
      2. Push the bundle image:

        1. $ docker push <registry>/<user>/<bundle_image_name>:<tag>

    Deploying an Operator with Operator Lifecycle Manager

    Operator Lifecycle Manager (OLM) helps you to install, update, and manage the lifecycle of Operators and their associated services on a Kubernetes cluster. OLM is installed by default on OKD and runs as a Kubernetes extension so that you can use the web console and the OpenShift CLI (oc) for all Operator lifecycle management functions without any additional tools.

    The Operator bundle format is the default packaging method for Operator SDK and OLM. You can use the Operator SDK to quickly run a bundle image on OLM to ensure that it runs properly.

    Prerequisites

    • Operator SDK CLI installed on a development workstation

    • Operator bundle image built and pushed to a registry

    • OLM installed on a Kubernetes-based cluster (v1.16.0 or later if you use apiextensions.k8s.io/v1 CRDs, for example OKD 4.8)

    • Logged in to the cluster with oc using an account with cluster-admin permissions

    • If your Operator is Go-based, your project must be updated to use supported images for running on OKD

    Procedure

    1. Check the status of OLM on your cluster by using the following Operator SDK command:

      1. $ operator-sdk olm status \
      2. --olm-namespace=openshift-operator-lifecycle-manager
    2. Run the Operator on your cluster by using the OLM integration in Operator SDK:

      1. $ operator-sdk run bundle \
      2. [-n <namespace>] \(1)
      3. <registry>/<user>/<bundle_image_name>:<tag>

      This command performs the following actions:

      • Create an index image referencing your bundle image. The index image is opaque and ephemeral, but accurately reflects how a bundle would be added to a catalog in production.

      • Create a catalog source that points to your new index image, which enables OperatorHub to discover your Operator.

    To install and manage Operators, Operator Lifecycle Manager (OLM) requires that Operator bundles are listed in an index image, which is referenced by a catalog on the cluster. As an Operator author, you can use the Operator SDK to create an index containing the bundle for your Operator and all of its dependencies. This is useful for testing on remote clusters and publishing to container registries.

    The Operator SDK uses the opm CLI to facilitate index image creation. Experience with the opm command is not required. For advanced use cases, the opm command can be used directly instead of the Operator SDK.

    Prerequisites

    • Operator SDK CLI installed on a development workstation

    • Operator bundle image built and pushed to a registry

    • OLM installed on a Kubernetes-based cluster (v1.16.0 or later if you use apiextensions.k8s.io/v1 CRDs, for example OKD 4.8)

    • Logged in to the cluster with oc using an account with cluster-admin permissions

    Procedure

    1. Run the following make command in your Operator project directory to build an index image containing your Operator bundle:

      1. $ make catalog-build CATALOG_IMG=<registry>/<user>/<index_image_name>:<tag>

      where the CATALOG_IMG argument references a repository that you have access to. You can obtain an account for storing containers at repository sites such as Quay.io.

    2. Push the built index image to a repository:

        You can use Operator SDK make commands together if you would rather perform multiple actions in sequence at once. For example, if you had not yet built a bundle image for your Operator project, you can build and push both a bundle image and an index image with the following syntax:

        Alternatively, you can set the IMAGE_TAG_BASE field in your Makefile to an existing repository:

        1. IMAGE_TAG_BASE=quay.io/example/my-operator

        You can then use the following syntax to build and push images with automatically-generated names, such as quay.io/example/my-operator-bundle:v0.0.1 for the bundle image and quay.io/example/my-operator-catalog:v0.0.1 for the index image:

      1. Define a CatalogSource object that references the index image you just generated, and then create the object by using the oc apply command or web console:

        Example CatalogSource YAML

        1. apiVersion: operators.coreos.com/v1alpha1
        2. kind: CatalogSource
        3. metadata:
        4. name: cs-memcached
        5. namespace: default
        6. spec:
        7. displayName: My Test
        8. publisher: Company
        9. sourceType: grpc
        10. image: quay.io/example/memcached-catalog:v0.0.1 (1)
        11. updateStrategy:
        12. registryPoll:
        13. interval: 10m
        1Set image to the image pull spec you used previously with the CATALOG_IMG argument.
      2. Check the catalog source:

        1. $ oc get catalogsource

        Example output

        1. NAME DISPLAY TYPE PUBLISHER AGE
        2. cs-memcached My Test grpc Company 4h31m

      Verification

      1. Install the Operator using your catalog:

        1. Define an OperatorGroup object and create it by using the oc apply command or web console:

          Example OperatorGroup YAML

          1. apiVersion: operators.coreos.com/v1
          2. kind: OperatorGroup
          3. metadata:
          4. name: my-test
          5. namespace: default
          6. spec:
          7. targetNamespaces:
          8. - default
        2. Define a Subscription object and create it by using the oc apply command or web console:

          Example Subscription YAML

          1. apiVersion: operators.coreos.com/v1alpha1
          2. kind: Subscription
          3. metadata:
          4. name: catalogtest
          5. namespace: default
          6. spec:
          7. channel: "alpha"
          8. installPlanApproval: Manual
          9. name: catalog
          10. source: cs-memcached
          11. sourceNamespace: default
          12. startingCSV: memcached-operator.v0.0.1
      2. Verify the installed Operator is running:

        1. Check the Operator group:

          1. $ oc get og

          Example output

          1. NAME AGE
          2. my-test 4h40m
        2. Check the cluster service version (CSV):

          Example output

          1. NAME DISPLAY VERSION REPLACES PHASE
        3. Check the pods for the Operator:

          1. $ oc get pods

          Example output

          1. NAME READY STATUS RESTARTS AGE
          2. 9098d908802769fbde8bd45255e69710a9f8420a8f3d814abe88b68f8ervdj6 0/1 Completed 0 4h33m
          3. catalog-controller-manager-7fd5b7b987-69s4n 2/2 Running 0 4h32m
          4. cs-memcached-7622r 1/1 Running 0 4h33m

      Additional resources

      • See for details on direct usage of the opm CLI for more advanced use cases.

      Testing an Operator upgrade on Operator Lifecycle Manager

      You can quickly test upgrading your Operator by using Operator Lifecycle Manager (OLM) integration in the Operator SDK, without requiring you to manually manage index images and catalog sources.

      The run bundle-upgrade subcommand automates triggering an installed Operator to upgrade to a later version by specifying a bundle image for the later version.

      Prerequisites

      • Operator installed with OLM either by using the run bundle subcommand or with traditional OLM installation

      Procedure

      1. If your Operator has not already been installed with OLM, install the earlier version either by using the run bundle subcommand or with traditional OLM installation.

        For example, you can use the following run bundle subcommand for a Memcached Operator by specifying the earlier bundle image:

        1. $ operator-sdk run bundle <registry>/<user>/memcached-operator:v0.0.1

        Example output

        1. INFO[0009] Successfully created registry pod: quay-io-demo-memcached-operator-v0-0-1
        2. INFO[0009] Created CatalogSource: memcached-operator-catalog
        3. INFO[0010] OperatorGroup "operator-sdk-og" created
        4. INFO[0010] Created Subscription: memcached-operator-v0-0-1-sub
        5. INFO[0013] Approved InstallPlan install-bqggr for the Subscription: memcached-operator-v0-0-1-sub
        6. INFO[0013] Waiting for ClusterServiceVersion "my-project/memcached-operator.v0.0.1" to reach 'Succeeded' phase
        7. INFO[0013] Waiting for ClusterServiceVersion "my-project/memcached-operator.v0.0.1" to appear
        8. INFO[0019] Found ClusterServiceVersion "my-project/memcached-operator.v0.0.1" phase: Succeeded
      2. Upgrade the installed Operator by specifying the bundle image for the later Operator version:

        1. $ operator-sdk run bundle-upgrade <registry>/<user>/memcached-operator:v0.0.2

        Example output

        1. INFO[0002] Found existing subscription with name memcached-operator-v0-0-1-sub and namespace my-project
        2. INFO[0002] Found existing catalog source with name memcached-operator-catalog and namespace my-project
        3. INFO[0009] Successfully created registry pod: quay-io-demo-memcached-operator-v0-0-2
        4. INFO[0009] Updated catalog source memcached-operator-catalog with address and annotations
        5. INFO[0010] Deleted previous registry pod with name "quay-io-demo-memcached-operator-v0-0-1"
        6. INFO[0041] Approved InstallPlan install-gvcjh for the Subscription: memcached-operator-v0-0-1-sub
        7. INFO[0042] Waiting for ClusterServiceVersion "my-project/memcached-operator.v0.0.2" to reach 'Succeeded' phase
        8. INFO[0042] Found ClusterServiceVersion "my-project/memcached-operator.v0.0.2" phase: InstallReady
        9. INFO[0043] Found ClusterServiceVersion "my-project/memcached-operator.v0.0.2" phase: Installing
        10. INFO[0044] Found ClusterServiceVersion "my-project/memcached-operator.v0.0.2" phase: Succeeded
        11. INFO[0044] Successfully upgraded to "memcached-operator.v0.0.2"
      3. Clean up the installed Operators:

        1. $ operator-sdk cleanup memcached-operator

      Additional resources

      Kubernetes periodically deprecates certain APIs that are removed in subsequent releases. If your Operator is using a deprecated API, it might no longer work after the OKD cluster is upgraded to the Kubernetes version where the API has been removed.

      As an Operator author, it is strongly recommended that you review the Deprecated API Migration Guide in Kubernetes documentation and keep your Operator projects up to date to avoid using deprecated and removed APIs. Ideally, you should update your Operator before the release of a future version of OKD that would make the Operator incompatible.

      When an API is removed from an OKD version, Operators running on that cluster version that are still using removed APIs will no longer work properly. As an Operator author, you should plan to update your Operator projects to accommodate API deprecation and removal to avoid interruptions for users of your Operator.

      You can check the event alerts of your Operators running on OKD 4.8 and later to find whether there are any warnings about APIs currently in use. The following alerts fire when they detect an API in use that will be removed in the next release:

        APIRemovedInNextReleaseInUse

        APIs that will be removed in the next OKD release.

        APIRemovedInNextEUSReleaseInUse

        APIs that will be removed in the next OKD release.

      If a cluster administrator has installed your Operator, before they upgrade to the next version of OKD, they must ensure a version of your Operator is installed that is compatible with that next cluster version. While it is recommended that you update your Operator projects to no longer use deprecated or removed APIs, if you still need to publish your Operator bundles with removed APIs for continued use on earlier versions of OKD, ensure that the bundle is configured accordingly.

      The following procedure helps prevent administrators from installing versions of your Operator on an incompatible version of OKD. These steps also prevent administrators from upgrading to a newer version of OKD that is incompatible with the version of your Operator that is currently installed on their cluster.

      This procedure is also useful when you know that the current version of your Operator will not work well, for any reason, on a specific OKD version. By defining the cluster versions where the Operator should be distributed, you ensure that the Operator does not appear in a catalog of a cluster version which is outside of the allowed range.

      Operators that use deprecated APIs can adversely impact critical workloads when cluster administrators upgrade to a future version of OKD where the API is no longer supported. If your Operator is using deprecated APIs, you should configure the following settings in your Operator project as soon as possible.

      Prerequisites

      • An existing Operator project

      Procedure

      1. If you know that a specific bundle of your Operator is not supported and will not work correctly on OKD later than a certain cluster version, configure the maximum version of OKD that your Operator is compatible with. In your Operator project’s cluster service version (CSV), set the olm.maxOpenShiftVersion annotation to prevent administrators from upgrading their cluster before upgrading the installed Operator to a compatible version:

        Example CSV with olm.maxOpenShiftVersion annotation

        1. apiVersion: operators.coreos.com/v1alpha1
        2. kind: ClusterServiceVersion
        3. metadata:
        4. annotations:
        5. "olm.properties": '[{"type": "olm.maxOpenShiftVersion", "value": "<cluster_version>"}]' (1)
      2. If your bundle is intended for distribution in a Red Hat-provided Operator catalog, configure the compatible versions of OKD for your Operator by setting the following properties. This configuration ensures your Operator is only included in catalogs that target compatible versions of OKD:

        This step is only valid when publishing Operators in Red Hat-provided catalogs. If your bundle is only intended for distribution in a custom catalog, you can skip this step. For more details, see “Red Hat-provided Operator catalogs”.

        1. Set the com.redhat.openshift.versions annotation in your project’s bundle/metadata/annotations.yaml file:

          Example bundle/metadata/annotations.yaml file with compatible versions

          1Set to a range or single version.
        2. To prevent your bundle from being carried on to an incompatible version of OKD, ensure that the index image is generated with the proper com.redhat.openshift.versions label in your Operator’s bundle image. For example, if your project was generated using the Operator SDK, update the bundle.Dockerfile file:

          Example bundle.Dockerfile with compatible versions

          1. LABEL com.redhat.openshift.versions="<versions>" (1)
          1Set to a range or single version, for example, . This setting defines the cluster versions where the Operator should be distributed, and the Operator does not appear in a catalog of a cluster version which is outside of the range.

      You can now bundle a new version of your Operator and publish the updated version to a catalog for distribution.

      Additional resources

      Additional resources