Disconnected Catalogs and Operators

A part from Openshift services, there are pods which are continuosly updating. They are the Operators Catalogs. These are pod where are defined the Operators that you can see, for example, in the Operator Hub.

$ oc get catalogsource -A
NAMESPACE               NAME                  DISPLAY               TYPE   PUBLISHER   AGE
openshift-marketplace   certified-operators   Certified Operators   grpc   Red Hat     17h
openshift-marketplace   community-operators   Community Operators   grpc   Red Hat     17h
openshift-marketplace   redhat-marketplace    Red Hat Marketplace   grpc   Red Hat     17h
openshift-marketplace   redhat-operators      Red Hat Operators     grpc   Red Hat     17h

Before these catalogs/pods were sqlite-based catalogs. A sqlite database storaged all information about Operators, Channels, Versions, dependencies,…​ Now in 4.11+ the sqlite database has been replaced by a file base. All methods we had to create new custom catalogs it’s not valid (opm, for example). Following, the options we have in a disconnected installation:

There are 3 options for catalogs in disconnected:

  1. Default catalogs with images mirrored and registry mirror config

  2. Default catalogs with images mirrored and Custom catalogs

  3. Build a custom catalog

But apart from the catalogs themself, we would need the images that Operators need to get run. Here, nowadays we have 2 options for mirroring of images from operators.

  1. with command oc

  2. with oc-mirror

Firstly, the Catalogs Sources:

Disconnected Catalogs

We have our new disconnected Openshift deployment. Export KUBECONFIG variable to point to it:

export KUBECONFIG=/root/.kcli/clusters/lab-test-disconnected/auth/kubeconfig

If you check the operator catalogs pods in your cluster you will see:

$ oc get pod -n openshift-marketplace
NAME                                    READY   STATUS             RESTARTS   AGE
certified-operators-dh7kf               0/1     ImagePullBackOff   0          20h
certified-operators-f5xcm               0/1     ImagePullBackOff   0          18h
community-operators-6lw8k               0/1     ImagePullBackOff   0          20h
community-operators-jrdl4               0/1     ImagePullBackOff   0          18h
marketplace-operator-7696c9454c-b4zwl   1/1     Running            2          18h

All pods are in ImagePullBackOff status. Let’s see how to solve it:

Default catalogs with images mirrored and registry mirror config

This option is based on mirroring of catalog images, and then use a registry mirror config with a machineConfig object. We do not use ImageContentSourcePolicy because catalog are using tags reference in the images instead of digest:

  • Mirror catalogs images using oc-mirror. Create a imageset file (7-imageset-config-catalogs.yaml):

    kind: ImageSetConfiguration
    apiVersion: mirror.openshift.io/v1alpha2
    archiveSize: 10
    storageConfig:
      registry:
        imageURL: registry.dsal:8443/imagetset/mirror-catalog:metadata
        skipTLS: true
    mirror:
      additionalImages:
      - name: registry.redhat.io/redhat/redhat-operator-index:v4.11
      - name: registry.redhat.io/redhat/redhat-marketplace-index:v4.11
      - name: registry.redhat.io/redhat/community-operator-index:v4.11
      - name: registry.redhat.io/redhat/certified-operator-index:v4.11
  • Run mirror command

    oc-mirror --config=./7-imageset-config-catalogs.yaml  docker://registry.dsal:8443/mirror
  • Create a new registry-conf-operators.txt file because these images (catalog images) references are tags instead of digest:

    [[registry]]
      prefix = ""
      location = "registry.redhat.io/redhat"
      mirror-by-digest-only = false
    
    [[registry.mirror]]
    location = "registry.dsal:8443/mirror/redhat"
  • Get base64 from this file:

    cat registry-conf-operators.txt | base64 -w0
    W1tyZWdpc3RyeV1dCiAgcHJlZml4ID0gIiIKICBsb2NhdGlvbiA9ICJyZWdpc3RyeS5yZWRoYXQuaW8vcmVkaGF0IgogIG1pcnJvci1ieS1kaWdlc3Qtb25seSA9IGZhbHNlCgpbW3JlZ2lzdHJ5Lm1pcnJvcl1dCmxvY2F0aW9uID0gInJlZ2lzdHJ5LmRzYWw6ODQ0My9taXJyb3IvcmVkaGF0Igo=
  • Create machine-config file 7-mc-99-operators-registries.yaml:

    apiVersion: machineconfiguration.openshift.io/v1
    kind: MachineConfig
    metadata:
      labels:
        machineconfiguration.openshift.io/role: master
      name: 99-operators-registries
    spec:
      config:
        ignition:
          version: 3.1.0
        storage:
          files:
          - contents:
              source: data:text/plain;charset=utf-8;base64,W1tyZWdpc3RyeV1dCiAgcHJlZml4ID0gIiIKICBsb2NhdGlvbiA9ICJyZWdpc3RyeS5yZWRoYXQuaW8vcmVkaGF0IgogIG1pcnJvci1ieS1kaWdlc3Qtb25seSA9IGZhbHNlCgpbW3JlZ2lzdHJ5Lm1pcnJvcl1dCmxvY2F0aW9uID0gInJlZ2lzdHJ5LmRzYWw6ODQ0My9taXJyb3IvcmVkaGF0Igo=
            filesystem: root
            mode: 420
            path: /etc/containers/registries.conf.d/99-operators-registries.conf
  • and apply it

    oc apply -f 7-mc-99-operators-registries.yaml

    Now, wait for MachineConfigPool to be updated in all nodes (It will reboot node(s)).

  • Delete pods from openshift-markeplace namespace to force update

    oc delete --all pods -n openshift-marketplace

    Wait some seconds to see pod running again:

    $ oc get pod -n openshift-marketplace
    NAME                                    READY   STATUS    RESTARTS   AGE
    certified-operators-fg98d               1/1     Running   0          15s
    community-operators-qf9jm               1/1     Running   0          15s
    marketplace-operator-6f9748c96f-bwlkq   1/1     Running   0          17s
    redhat-marketplace-nb7hw                1/1     Running   0          14s
    redhat-operators-qx9rd                  1/1     Running   0          14s

Now we have all our catalogs running with mirrored images. Let’s go to the next method:

Default catalogs with images mirrored and custom catalogs

The second method would be creating custom catalogs based on default ones.

In the first method we did a mirror of the catalog images. We already have the images copied to our private registry, so we can simply create catalogs that point to these images. Follow the next steps:

  • Disable default catalogs:

    oc patch OperatorHub cluster --type json \
        -p '[{"op": "add", "path": "/spec/disableAllDefaultSources", "value": true}]'
  • Create new catalogs files 7-default-catalogsources.yaml, just replacing public images for mirrored images in registry.dsal:8443/mirror registry:

    apiVersion: v1
    kind: List
    metadata:
      resourceVersion: ""
      selfLink: ""
    items:
    - apiVersion: operators.coreos.com/v1alpha1
      kind: CatalogSource
      metadata:
        name: mirror-certified-operators
        namespace: openshift-marketplace
      spec:
        displayName: Mirror Certified Operators
        grpcPodConfig:
          nodeSelector:
            kubernetes.io/os: linux
            node-role.kubernetes.io/master: ""
          tolerations:
          - effect: NoSchedule
            key: node-role.kubernetes.io/master
            operator: Exists
          - effect: NoExecute
            key: node.kubernetes.io/unreachable
            operator: Exists
            tolerationSeconds: 120
          - effect: NoExecute
            key: node.kubernetes.io/not-ready
            operator: Exists
            tolerationSeconds: 120
        image: registry.dsal:8443/mirror/redhat/certified-operator-index:v4.11
        publisher: Custom
        sourceType: grpc
        updateStrategy:
          registryPoll:
            interval: 10m0s
    - apiVersion: operators.coreos.com/v1alpha1
      kind: CatalogSource
      metadata:
        name: mirror-community-operators
        namespace: openshift-marketplace
      spec:
        displayName: Mirror Community Operators
        grpcPodConfig:
          nodeSelector:
            kubernetes.io/os: linux
            node-role.kubernetes.io/master: ""
          priorityClassName: system-cluster-critical
          tolerations:
          - effect: NoSchedule
            key: node-role.kubernetes.io/master
            operator: Exists
          - effect: NoExecute
            key: node.kubernetes.io/unreachable
            operator: Exists
            tolerationSeconds: 120
          - effect: NoExecute
            key: node.kubernetes.io/not-ready
            operator: Exists
            tolerationSeconds: 120
        image: registry.dsal:8443/mirror/redhat/community-operator-index:v4.11
        publisher: Custom
        sourceType: grpc
        updateStrategy:
          registryPoll:
            interval: 10m0s
    - apiVersion: operators.coreos.com/v1alpha1
      kind: CatalogSource
      metadata:
        name: mirror-redhat-marketplace
        namespace: openshift-marketplace
      spec:
        displayName: Mirror Red Hat Marketplace
        grpcPodConfig:
          nodeSelector:
            kubernetes.io/os: linux
            node-role.kubernetes.io/master: ""
          tolerations:
          - effect: NoSchedule
            key: node-role.kubernetes.io/master
            operator: Exists
          - effect: NoExecute
            key: node.kubernetes.io/unreachable
            operator: Exists
            tolerationSeconds: 120
          - effect: NoExecute
            key: node.kubernetes.io/not-ready
            operator: Exists
            tolerationSeconds: 120
        image: registry.dsal:8443/mirror/redhat/redhat-marketplace-index:v4.11
        publisher: Custom
        sourceType: grpc
        updateStrategy:
          registryPoll:
            interval: 10m0s
    - apiVersion: operators.coreos.com/v1alpha1
      kind: CatalogSource
      metadata:
        name: mirror-redhat-operators
        namespace: openshift-marketplace
      spec:
        displayName: Mirror Red Hat Operators
        grpcPodConfig:
          nodeSelector:
            kubernetes.io/os: linux
            node-role.kubernetes.io/master: ""
          tolerations:
          - effect: NoSchedule
            key: node-role.kubernetes.io/master
            operator: Exists
          - effect: NoExecute
            key: node.kubernetes.io/unreachable
            operator: Exists
            tolerationSeconds: 120
          - effect: NoExecute
            key: node.kubernetes.io/not-ready
            operator: Exists
            tolerationSeconds: 120
        image: registry.dsal:8443/mirror/redhat/redhat-operator-index:v4.11
        publisher: Custom
        sourceType: grpc
        updateStrategy:
          registryPoll:
            interval: 10m0s
  • and then apply:

    oc apply -f 7-default-catalogsources.yaml

Now, we can see our custom catalogs based on default catalogs running:

$ oc get pod -n openshift-marketplace
NAME                                    READY   STATUS    RESTARTS   AGE
marketplace-operator-6f9748c96f-bwlkq   1/1     Running   0          10m
mirror-certified-operators-6dnw9        1/1     Running   0          71s
mirror-community-operators-cx84l        1/1     Running   0          71s
mirror-redhat-marketplace-ct22n         1/1     Running   0          71s
mirror-redhat-operators-4n2q8           1/1     Running   0          71s

$ oc get catalogsource -A
NAMESPACE               NAME                         DISPLAY                      TYPE   PUBLISHER   AGE
openshift-marketplace   mirror-certified-operators   Mirror Certified Operators   grpc   Custom      91s
openshift-marketplace   mirror-community-operators   Mirror Community Operators   grpc   Custom      91s
openshift-marketplace   mirror-redhat-marketplace    Mirror Red Hat Marketplace   grpc   Custom      91s
openshift-marketplace   mirror-redhat-operators      Mirror Red Hat Operators     grpc   Custom      91s
Take note our catalogs have prefix mirror-*

Let’s go to the third method:

Custom catalog

The above 2 methods allow us to have all operators available as we have a connected installation, but the third option involves in creating our custom catalog containing only the operators we need.

Now, catalogs are file-based catalogs instead of sqlite-based catalogs, so most of the command from opm binary don’t work. To create a custom catalog follow next steps:

  • Create catalog index dir

    rm -Rf custom-catalog; mkdir -p custom-catalog/configs
  • Extract render index from public image of a public catalog, in our case, the "redhat-operator" catalog index:

    opm render registry.redhat.io/redhat/redhat-operator-index:v4.11 > redhat-operator-index.json

    Take a look to the json file extracted. You can see all info about channels, packages, operators, …​

    if you have space problems in /tmp you can try to extend /tmp LV

    lvresize --resizefs -L+5G rootvg/tmplv
  • Now we will filter operators from the rendered json extracted from catalog executing an script. These is the list of operators:

    • elasticsearch-operator

    • cluster-logging

    • cincinnati-operator

  • The following script extracts the packages and operators related to the list above:

    operators="elasticsearch-operator cluster-logging cincinnati-operator"
    echo "" > custom-catalog/configs/index.json
    for operator in $operators; do
      mkdir -p custom-catalog/configs/$operator
      cat redhat-operator-index.json | jq --arg operator "$operator" 'select( .package == $operator or .name == $operator)' >> custom-catalog/configs/$operator/catalog.json
    done
  • Now, we generate the dockerfile of our catalog image

    opm generate dockerfile custom-catalog/configs

    This command generate a Dockerfile like this:

    $ more custom-catalog/configs.Dockerfile
    # The base image is expected to contain
    # /bin/opm (with a serve subcommand) and /bin/grpc_health_probe
    FROM quay.io/operator-framework/opm:latest
    
    # Configure the entrypoint and command
    ENTRYPOINT ["/bin/opm"]
    CMD ["serve", "/configs", "--cache-dir=/tmp/cache"]
    
    # Copy declarative config root into image at /configs and pre-populate serve cache
    ADD configs /configs
    RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"]
    
    # Set DC-specific label for the location of the DC root directory
    # in the image
    LABEL operators.operatorframework.io.index.configs.v1=/configs
  • Let’s build the catalog image

    cd custom-catalog
    podman build -t registry.dsal:8443/mirror/redhat/custom-redhat-operator-index:v1 -f configs.Dockerfile
    cd ~/
  • And now, push the catalog image to our registry

    podman push --tls-verify=false \
      --authfile ~/pull-secret-all.json \
      registry.dsal:8443/mirror/redhat/custom-redhat-operator-index:v1
  • Delete all catalogs we deploy in the previous method (we had our mirror-* catalogs)

    oc delete catalogsources --all -n openshift-marketplace
  • Create catalogsource 7-custom-catalogsource.yaml

    apiVersion: operators.coreos.com/v1alpha1
    kind: CatalogSource
    metadata:
      name: custom-redhat-operators
      namespace: openshift-marketplace
    spec:
      displayName: Custom Red Hat Operators
      grpcPodConfig:
        nodeSelector:
          kubernetes.io/os: linux
          node-role.kubernetes.io/master: ""
        tolerations:
        - effect: NoSchedule
          key: node-role.kubernetes.io/master
          operator: Exists
        - effect: NoExecute
          key: node.kubernetes.io/unreachable
          operator: Exists
          tolerationSeconds: 120
        - effect: NoExecute
          key: node.kubernetes.io/not-ready
          operator: Exists
          tolerationSeconds: 120
      image: registry.dsal:8443/mirror/redhat/custom-redhat-operator-index:v1
      publisher: Custom
      sourceType: grpc
      updateStrategy:
        registryPoll:
          interval: 10m0s
  • and apply it

    oc apply -f  7-custom-catalogsource.yaml

Now we can see running our pod, catalog and only our operators selected

$ oc get pod -n openshift-marketplace
NAME                                    READY   STATUS    RESTARTS   AGE
custom-redhat-operators-82z9h           1/1     Running   0          59s
marketplace-operator-6f9748c96f-bwlkq   1/1     Running   0          44m

$ oc get catalogsource -n openshift-marketplace
NAME                      DISPLAY                    TYPE   PUBLISHER   AGE
custom-redhat-operators   Custom Red Hat Operators   grpc   Custom      71s

$ oc get packagemanifest -n openshift-marketplace
NAME                          CATALOG                    AGE
elasticsearch-operator        Custom Red Hat Operators   91s
cluster-logging               Custom Red Hat Operators   91s
cincinnati-operator           Custom Red Hat Operators   91s

Congratulations!! You are provider of your own operators Catalog :)

Disconnected Operators

Now, we have our custom catalog running in our cluster, and operators "available" to be installed, but, we need images neeeded by those operators to able to be deployed, installed and instanced. Those images are:

  • The bundle image

  • Images used by operator to give that service

We have again 2 methods for mirroring this:

  • with oc

  • with oc-mirror

Let’s start with oc method:

Mirroring with oc

This method, nowadays only works with the default catalog index (not custom ones). With custom index you must use oc-mirror. But we will do a dry-run so you can learn how to do it.

We are NOT going to mirror all images of a public catalog (we don’t have enough space in our private registry), but we can see the manifest (--manifest-only parameter) to understand the process:

Execute command and explore directory mapping.txt and ImageContentSourcePolicy file:

oc adm catalog mirror --dry-run --manifests-only registry.redhat.io/redhat/redhat-operator-index:v4.11 registry.dsal:8443/mirror/redhat

The output of this command will be something like this:

src image has index label for declarative configs path: /configs/
using index path mapping: /configs/:/tmp/3682376003
W0118 10:50:52.582735 1061475 manifest.go:449] Chose linux/amd64 manifest from the manifest list.
wrote declarative configs to /tmp/3682376003
using declarative configs at: /tmp/3682376003
no digest mapping available for registry.redhat.io/redhat/redhat-operator-index:v4.11, skip writing to ImageContentSourcePolicy
wrote mirroring manifests to manifests-redhat-operator-index-1674039050
deleted dir /tmp/3682376003

The resultant files are:

$ tree manifests-redhat-operator-index-1674039050/
manifests-redhat-operator-index-1674039050/
├── catalogSource.yaml
├── imageContentSourcePolicy.yaml
└── mapping.txt

These files are:

  • A catalogsource to import in our cluster

  • A ImageContentSourcePolicy to say our cluster where are the images

  • A mapping.txt in format compatible to mirror with the command "oc mirror". We could use it afterwards to do the mirroring.

The method is with oc-mirror:

Mirroring with oc-mirror

This method we use oc-mirror binary, tool which we have used several times in this workshop. oc-mirror helped us to do mirror of set of openshift release images, mirror of images, and also we can use it for catalogs.

oc-mirror offers 2 options:

  • Mirroring with our custom catalog image already filtered with the operators wished.

  • Mirroring with the public catalog image filtering with the imageset syntax

First option:

ImageSet for custom catalog index

This option, oc-mirror takes our custom catalog and also the source/origin catalog (it’s a requirement), makes the mirror of the operators included in our custom catalog and then give to us all we need to run operators in our cluster. Let’s see:

  • Create imageset config file 7-imageset-mirroring-custom-catalog.yaml:

    kind: ImageSetConfiguration
    apiVersion: mirror.openshift.io/v1alpha2
    archiveSize: 10
    storageConfig:
      registry:
        imageURL: registry.dsal:8443/imagetset/mirror-custom-catalog:metadata
        skipTLS: true
    mirror:
      operators:
      - catalog: registry.dsal:8443/mirror/redhat/custom-redhat-operator-index:v1
        originalRef: registry.redhat.io/redhat/redhat-operator-index:v4.11
    take note we need to specify in the config the source of our custom catalog with the parameter originalRef
  • Run mirror

    oc-mirror --continue-on-error --config=./7-imageset-mirroring-custom-catalog.yaml  docker://registry.dsal:8443/mirror

    It takes some time, be patient. These will be the output:

    ...
    sha256:e72c3703a5be273bd6135626abe6d1a78a3c642eea9c98e508d71cd252d2536a registry.dsal:8443/mirror/openshift-logging/elasticsearch-operator-bundle:33b087fb
    sha256:f6af35418dc282c51902b462c03a6fe62d38d0ec83b9fd7c95cee754377b24af registry.dsal:8443/mirror/openshift-logging/elasticsearch-operator-bundle:a9ad14a9
    sha256:88223a315adef617e57a038cf825ac2b52a255d64e63b7461ab15e1f7683baf5 registry.dsal:8443/mirror/openshift-logging/elasticsearch-operator-bundle:b0cde4fb
    info: Mirroring completed in 4m16.05s (41.98MB/s)
    Rendering catalog image "registry.dsal:8443/mirror/mirror/redhat/custom-redhat-operator-index:v1" with file-based catalog
    Writing image mapping to oc-mirror-workspace/results-1679995563/mapping.txt
    Writing CatalogSource manifests to oc-mirror-workspace/results-1679995563
    Writing ICSP manifests to oc-mirror-workspace/results-1679995563

    The result of this operation will be:

    • Operators from custom catalog images mirrored

    • An ImageContentSourcePolicy file to import into the cluster (oc-mirror-workspace/results-xxxx/imageContentSourcePolicy.yaml)

    • A catalogsource with a copy of our catalogsource (oc-mirror-workspace/results-xxxx/catalogSource-redhat-custom-redhat-operator-index.yaml)

    • A mapping.txt with the list of images mirrored (oc-mirror-workspace/results-xxxx/mapping.txt)

We are not going to configure or apply these configuration/mirroring in the cluster. We will do it later, in the next section, with the other option based on the official catalog filtered:

ImageSet for official catalog filtered

The second method/option is using the feature of oc-mirror to filter operators of a default/official index, and mirror images of them.

  • Create imageset config file 7-imageset-mirroring-default-catalog.yaml:

    kind: ImageSetConfiguration
    apiVersion: mirror.openshift.io/v1alpha2
    archiveSize: 10
    storageConfig:
      registry:
        imageURL: registry.dsal:8443/imagetset/mirror-default-catalog:metadata
        skipTLS: true
    mirror:
      operators:
       - catalog: registry.redhat.io/redhat/redhat-operator-index:v4.11
         packages:
           - name: elasticsearch-operator
           - name: cluster-logging
           - name: cincinnati-operator
  • Now, delete all catalogs deployed and run oc-mirror command:

    oc delete catalogsource --all -n openshift-marketplace
    
    oc-mirror --continue-on-error --config=./7-imageset-mirroring-default-catalog.yaml docker://registry.dsal:8443/mirror
    .........
    .........
    info: Mirroring completed in 2.26s (0B/s)
    Rendering catalog image "registry.dsal:8443/mirror/redhat/redhat-operator-index:v4.11" with file-based catalog
    Writing image mapping to oc-mirror-workspace/results-1674048845/mapping.txt
    Writing CatalogSource manifests to oc-mirror-workspace/results-1674048845
    Writing ICSP manifests to oc-mirror-workspace/results-1674048845
    Make sure to remember the name of the directory that contains your generated results, which should be named results-xxxx. In the provided example, the directory is named oc-mirror-workspace/results-1674048845.

    The result will be:

    • Operators images mirrored

    • An ImageContentSourcePolicy file to import into the cluster (oc-mirror-workspace/results-xxxx/imageContentSourcePolicy.yaml)

    • A CatalogSource file to create the catalog in the cluster(oc-mirror-workspace/results-xxxx/catalogSource-redhat-custom-redhat-operator-index.yaml)

    • A mapping.txt with the list of images mirrored (oc-mirror-workspace/results-xxxx/mapping.txt)

  • Now, we are going to import the new catalog created by oc-mirror and import the ImageContentSourcePolicy object. Import all object in the folder specified in the output of the oc-mirror execution (use your result dir):

    $ oc apply -f oc-mirror-workspace/results-xxxx
    catalogsource.operators.coreos.com/redhat-operator-index created
    imagecontentsourcepolicy.operator.openshift.io/operator-0 created
  • The result of all these operations:

    $ oc get pod,catalogsources,packagemanifest,imagecontentsourcepolicy -n openshift-marketplace
    NAME                                        READY   STATUS    RESTARTS   AGE
    pod/marketplace-operator-6f9748c96f-bwlkq   1/1     Running   0          3h38m
    pod/redhat-operator-index-5vp2s             1/1     Running   0          2m25s
    
    NAME                                                       DISPLAY   TYPE   PUBLISHER   AGE
    catalogsource.operators.coreos.com/redhat-operator-index             grpc               2m25s
    
    NAME                                                                   CATALOG   AGE
    packagemanifest.packages.operators.coreos.com/cincinnati-operator                2m25s
    packagemanifest.packages.operators.coreos.com/elasticsearch-operator             2m25s
    packagemanifest.packages.operators.coreos.com/cluster-logging                    2m25s
    
    NAME                                                            AGE
    imagecontentsourcepolicy.operator.openshift.io/image-policy-0   21h
    imagecontentsourcepolicy.operator.openshift.io/image-policy-1   21h
    imagecontentsourcepolicy.operator.openshift.io/operator-0       2m25s
    For more detail and stay curious take a look to the files generated by oc-mirror command

To test the the catalogs, mirrors and operators, we will install Openshift Logging Operator and ElasticSearch Operator.

  • Create a yaml file 7-operator-openshift-logging.yaml with the namespaces, the operator groups and subscriptions:

    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: openshift-operators-redhat
      annotations:
        openshift.io/node-selector: ""
      labels:
        openshift.io/cluster-monitoring: "true"
    ---
    apiVersion: v1
    kind: Namespace
    metadata:
      name: openshift-logging
      annotations:
        openshift.io/node-selector: ""
      labels:
        openshift.io/cluster-monitoring: "true"
    ---
    apiVersion: operators.coreos.com/v1
    kind: OperatorGroup
    metadata:
      name: openshift-operators-redhat
      namespace: openshift-operators-redhat
    spec: {}
    ---
    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: "elasticsearch-operator"
      namespace: "openshift-operators-redhat"
    spec:
      channel: "stable"
      installPlanApproval: "Automatic"
      source: "redhat-operator-index"
      sourceNamespace: "openshift-marketplace"
      name: "elasticsearch-operator"
    ---
    apiVersion: operators.coreos.com/v1
    kind: OperatorGroup
    metadata:
      name: cluster-logging
      namespace: openshift-logging
    spec:
      targetNamespaces:
      - openshift-logging
    ---
    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: cluster-logging
      namespace: openshift-logging
    spec:
      channel: "stable"
      name: cluster-logging
      source: redhat-operator-index
      sourceNamespace: openshift-marketplace
  • and apply it

    oc apply -f 7-operator-openshift-logging.yaml

    After some time, the operators will be installed

    $ oc get clusterserviceversions -n openshift-logging
    NAME                           DISPLAY                            VERSION   REPLACES   PHASE
    cluster-logging.5.5.5          Red Hat OpenShift Logging          5.5.5                Succeeded
    elasticsearch-operator.5.3.9   OpenShift Elasticsearch Operator   5.3.9                Succeeded
    
    $ oc get pod -n openshift-operators-redhat
    NAME                                      READY   STATUS    RESTARTS   AGE
    elasticsearch-operator-7685d767d9-jzd85   2/2     Running   0          3m17s
    
    $ oc get pod -n openshift-logging
    NAME                                      READY   STATUS    RESTARTS   AGE
    cluster-logging-operator-ddd4f964-xrdzt   1/1     Running   0          5m22s

We are not going to install an instance of openshift-logging for capacity reasons. We only have a small single node :)