├── docs ├── intro.md ├── why-olm.md ├── what-is-an-operator.md ├── what-does-olm-enable.md ├── openshift │ ├── coming-soon.md │ ├── faq.md │ ├── important-changes-by-release.md │ └── operator-marketplace.md ├── list-available-operators.md ├── when-to-update-my-operator.md ├── multiarch.md ├── uninstall-an-operator.md ├── how-do-i-install-my-operator-with-olm.md ├── discover-operator-presence.md ├── uninstall-olm.md ├── install-olm.md ├── operator-dependencies-and-requirements.md ├── subscriptions.md ├── validate-package.md ├── glossary.md ├── snapshot-appr-registry.md ├── operator-scoping.md ├── troubleshooting.md └── packaging-an-operator.md ├── .gitignore ├── .travis.yml ├── README.md ├── index.md └── LICENSE /docs/intro.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | -------------------------------------------------------------------------------- /docs/why-olm.md: -------------------------------------------------------------------------------- 1 | # Why would I use OLM? -------------------------------------------------------------------------------- /docs/what-is-an-operator.md: -------------------------------------------------------------------------------- 1 | # What is an Operator? 2 | 3 | -------------------------------------------------------------------------------- /docs/what-does-olm-enable.md: -------------------------------------------------------------------------------- 1 | # What does OLM enable me to do? 2 | 3 | OLM enables management of operators in a cluster. 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - 1.34.0 4 | cache: cargo 5 | script: 6 | - cargo install --force --git https://github.com/crawford/marker.git 7 | - marker 8 | -------------------------------------------------------------------------------- /docs/openshift/coming-soon.md: -------------------------------------------------------------------------------- 1 | # Coming Soon... 2 | 3 | The topic you are looking for is currently being worked on. The document will be updated soon. 4 | 5 | 6 | # Contributing 7 | 8 | If you are interested in knowing more about **Operator Lifecycle Manager** and want to contribute, do checkout our [OLM repo](https://github.com/operator-framework/operator-lifecycle-manager) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Operator Lifecycle Book 2 | 3 | ## Adding a new page 4 | 5 | - Clone this repo 6 | - Make a new markdown doc in `docs` 7 | - Example: `docs/what-does-olm-enable.md` 8 | - Update or create a new link in `index.md` to point to the doc in `docs` 9 | - The link should be `https://operator-framework.github.io/olm-book/docs/` + doc name (no `.md`) 10 | - Example: `[What does OLM enable](https://operator-framework.github.io/olm-book/docs/what-does-olm-enable)`? 11 | - Make a PR with both changes 12 | - See the updated links in https://operator-framework.github.io/olm-book 13 | 14 | You can also use the in-browser editor to make PRs! 15 | -------------------------------------------------------------------------------- /docs/openshift/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ (OpenShift Specific) 2 | 3 | This FAQ is reserved for questions specifically pertaining to using OLM on OpenShift. 4 | 5 | ## Developing an Operator 6 | 7 | ### Q: I'm developing a new version of an operator already published to one of the default catalogs (redhat-operators, certified-operators, or community-operators). How can I hide the published versions from OLM and the OperatorHub UI? 8 | 9 | Deleting the default `OperatorSource` and `CatalogSource` of the catalog your operator exists in will prevent OLM and the OperatorHub UI from using it. However, default `OperatorSources` are regenerated upon deletion. Instructions to disable regeneration can be found in the [`marketplace-operator` configuration section](operator-marketplace.md#configuration). 10 | -------------------------------------------------------------------------------- /docs/openshift/important-changes-by-release.md: -------------------------------------------------------------------------------- 1 | # Important Changes by OCP Release 2 | 3 | ## 4.2 4 | 5 | ### New Global Catalog Namespace 6 | 7 | The default _GCN_ (global catalog namespace) has been changed from OLM's namespace, `openshift-operator-lifecycle-manager`, to `operator-marketplace`. As a quick refresher, the GCN is a special namespace that contains operator catalogs that can be subscribed to from any namespace in the cluster. The important positive implication of this change is that default catalogs in the `operator-marketplace` namespace (`redhat-operators`, `certified-operators`, etc...) can be subscribed to from all namespaces without further configuration. The negative implication is that any subscriptions to catalogs in the `openshift-operator-lifecycle-manager` namespace must be co-located in that namespace. 8 | -------------------------------------------------------------------------------- /docs/list-available-operators.md: -------------------------------------------------------------------------------- 1 | # How do I list Operators available to install? 2 | 3 | There is an extension API in OLM named `PackageManifest` that contains information about existing `CatalogSources`, which is essentially a repository of CSVs, CRDs, and packages that define an operator in the cluster. By querying that API, you can see the list of available operators. 4 | 5 | There are two different types of `CatalogSource` in OLM: global and namespaced `CatalogSource`. The global `CatalogSource` contains operators that will be available for all namespaces while namespaced `CatalogSource` only contains operators that are only available for a specific namespace. 6 | 7 | ## PackageManifest Commands 8 | 9 | You can use these example commands via kubectl CLI (kubectl) to list available operators in a specific namespace. `PackageManifest` will return the union of global, which are available globally, and namespaced operators in namespace you're requesting. 10 | ```bash 11 | $ kubectl get packagemanifest -n 12 | ``` 13 | 14 | The list of available operators will be displayed as an output of those above commands: 15 | ```bash 16 | $ kubectl get packagemanifest 17 | NAME CATALOG AGE 18 | cassandra-operator Community Operators 26m 19 | etcd Community Operators 26m 20 | postgres-operator Community Operators 26m 21 | prometheus Community Operators 26m 22 | wildfly Community Operators 26m 23 | ``` 24 | -------------------------------------------------------------------------------- /docs/when-to-update-my-operator.md: -------------------------------------------------------------------------------- 1 | # When do I need to update my operator 2 | 3 | When you install an operator from a catalog such as [quay.io/operator-framework/upstream-community-operator](https://quay.io/repository/operator-framework/upstream-community-operators), updated versions of one of more operators are pushed to the container image by rebuilding the catalog. If you have an older image of the catalog in your cluster, you can get the updates to your operators by fetching the latest release of the catalog's container image. 4 | 5 | If the image used to build the `Catalogsource` uses a versioned tag, update the tag version of the image to fetch updates to operators in the `Catalogsource`. 6 | 7 | For example: 8 | 9 | ``` 10 | $ oc get catsrc operatorhubio-catalog -n olm -o yaml | grep image: 11 | 12 | image: quay.io/operator-framework/upstream-community-operators:0.0.1 13 | 14 | $ kubectl patch catsrc operatorhubio-catalog -n olm --type=merge -p '{"spec": {"image": "quay.io/operator-framework/upstream-community-operators:0.0.2"}}' 15 | 16 | ``` 17 | 18 | If the image used to build the `Catalogsource` uses the `latest` tag, simply delete the pod corresponding to the `CatalogSource`. When the pod is recreated, it will be recreated with the latest image of the catalog, which will contain updates to the operators in that catalog. 19 | 20 | For example: 21 | 22 | ``` 23 | $ kubectl delete pods -n olm -l olm.catalogSource=operatorhubio-catalog 24 | 25 | ``` 26 | The operators that were installed from the catalog will be updated automatically or manually, depending on the value of `installPlanApproval` in the Subscription for the operator. For more information on approving manual updates to operators, please see [How do I approve an update?](openshift/coming-soon.md) -------------------------------------------------------------------------------- /docs/multiarch.md: -------------------------------------------------------------------------------- 1 | # How do I ship an operator that supports multiple node architectures? 2 | 3 | It is assumed that all operators run on linux hosts, but can be configured to manage workloads on other architectures if worker nodes are available. 4 | 5 | Which os/arches are supported by the operator can be indicated by adding labels to the ClusterServiceVersion providing the operator. 6 | 7 | ## Supported Labels 8 | 9 | Labels indicating supported os and arch are defined by: 10 | 11 | ```yaml 12 | labels: 13 | operatorframework.io/arch.: supported 14 | operatorframework.io/os.: supported 15 | ``` 16 | 17 | Where `` and `` are one of the values [listed here](https://github.com/golang/go/blob/master/src/go/build/syslist.go). 18 | 19 | ## Multiple Architectures 20 | 21 | Some operators may support multiple node architectures or oses. In this case, multiple labels can be added. For example, an operator that support both windows and linux workloads: 22 | 23 | ```yaml 24 | labels: 25 | operatorframework.io/os.windows: supported 26 | operatorframework.io/os.linux: supported 27 | ``` 28 | 29 | ## Defaults 30 | 31 | If a ClusterServiceVersion does not include an `os` label, it is treated as if it has the following label: 32 | 33 | ```yaml 34 | labels: 35 | operatorframework.io/os.linux: supported 36 | ``` 37 | 38 | 39 | If a ClusterServiceVersion does not include an `arch` label, it is treated as if it has the following label: 40 | 41 | ```yaml 42 | labels: 43 | operatorframework.io/arch.amd64: supported 44 | ``` 45 | 46 | ## Filtering available operators by os or arch 47 | 48 | Only windows: 49 | 50 | ```sh 51 | $ kubectl get packagemanifests -l operatorframework.io/os.windows=supported 52 | ``` 53 | 54 | ## Caveats 55 | 56 | Only the labels on the [HEAD of the default channel](glossary.md#channel-head) are considered for filtering PackageManifests by label. 57 | 58 | This means, for example, that providing an alternate architecture for an operator in the non-default channel is possible, but will not be available for filtering in the PackageManifest API. 59 | -------------------------------------------------------------------------------- /docs/uninstall-an-operator.md: -------------------------------------------------------------------------------- 1 | # How to uninstall an Operator? 2 | 3 | In order to uninstall an operator, you need to delete the following resources: 4 | 5 | - Subscription 6 | - ClusterServiceVersion (CSV) 7 | 8 | Both `Subscription` and `CSV` are namespaced objects meaning you need to delete a `Subscription` and a `CSV` in a specific namespace where you install the operator into. 9 | 10 | ## Delete a Subscription 11 | 12 | If you wish to look up a list of `Subscription` in a specific namespace to see which `Subscription` you want to delete, you can use the following `kubectl` command: 13 | ```bash 14 | $ kubectl get subscription -n 15 | ``` 16 | 17 | You can delete the `Subscription` in the namespace that the operator was installed into using this command: 18 | ```bash 19 | $ kubectl delete subscription -n 20 | ``` 21 | 22 | ## Delete a ClusterServiceVersion (CSV) 23 | 24 | If you wish to look up a list of `ClusterServiceVersion` in a specific namespace to see which `ClusterServiceVersion` you need to delete, you can use the example `kubectl` command: 25 | 26 | ```bash 27 | $ kubectl get clusterserviceversion -n 28 | ``` 29 | 30 | You can delete the `ClusterServiceVersion` in the namespace that the operator was installed into using this command: 31 | 32 | ```bash 33 | $ kubectl delete clusterserviceversion -n 34 | ``` 35 | 36 | By deleting `ClusterServiceVersion`, it will delete the operator's resources that OLM created for the operator such as deployment, pod(s), RBAC, and others. However, `CustomResourceDefinition` (CRD), that is installed by the operator, won't get deleted during uninstalling process. Deleting `CRD` will resolve into deleting all instances of that `CRD` which may be used by other operators. `CRD` can be deleted manually if needed. Furthermore, deleting a `CSV` also deletes any corresponding CSVs that OLM "Copied" into other namespaces watched by the operator. 37 | 38 | Alternatively, you can delete both `Subscription` and its `CSV` using a sequence of commands: 39 | ```bash 40 | $ CSV=kubectl delete subscription -n -o json | jq '.status.installedCSV' 41 | $ kubectl delete subscription -n 42 | $ kubectl delete csv $CSV -n 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/how-do-i-install-my-operator-with-olm.md: -------------------------------------------------------------------------------- 1 | # How do I install my operator with OLM? 2 | 3 | [Once you've made your operator available in a catalog](openshift/coming-soon.md), [or you've chosen an operator from an existing catalog](openshift/coming-soon.md), you can install your operator by creating a Subscription to a specific channel. 4 | ```yaml 5 | apiVersion: operators.coreos.com/v1alpha1 6 | kind: Subscription 7 | metadata: 8 | name: 9 | namespace: 10 | spec: 11 | channel: 12 | name: 13 | source: 14 | sourceNamespace: 15 | ``` 16 | For example, if you want to install an operator named `my-operator`, from a catalog named `my-catalog` that is in the namespace `olm`, and you want to subscribe to the channel `stable`, your subscription yaml would look like this: 17 | 18 | ```yaml 19 | apiVersion: operators.coreos.com/v1alpha1 20 | kind: Subscription 21 | metadata: 22 | name: subs-to-my-operator 23 | namespace: olm 24 | spec: 25 | channel: stable 26 | name: my-operator 27 | source: my-catalog 28 | sourceNamespace: olm 29 | ``` 30 | 31 | Once you have the subscription yaml, `kubectl apply -f Subscription.yaml` to install your operator. 32 | 33 | You can inspect your Subscription with `kubectl get subs -n `. 34 | 35 | To ensure the operator installed successfully, check for the ClusterServiceVersion and the operator deployment in the namespace it was installed in. 36 | 37 | ``` 38 | $ kubectl get csv -n 39 | 40 | NAME DISPLAY VERSION REPLACES PHASE 41 | Succeeded 42 | ``` 43 | ``` 44 | $ kubectl get deployments -n 45 | NAME READY UP-TO-DATE AVAILABLE AGE 46 | 1/1 1 1 9m48s 47 | ``` 48 | 49 | If the ClusterServiceVersion fails to show up or does not reach the `Succeeded` phase, please check the [troubleshooting documentation](openshift/coming-soon.md)) to debug your installation. 50 | -------------------------------------------------------------------------------- /docs/discover-operator-presence.md: -------------------------------------------------------------------------------- 1 | # How do I discover the presence/availability of an Operator? 2 | 3 | ## Discovering installed operators 4 | Checking the presence of custom installed operators in the cluster is simply a matter of checking all the 5 | `ClusterServiceVersions` (CSV) that are available in the cluster. Every operator installed by OLM has a corresponding CSV 6 | associated with it that that contains all the details of the operator. Running `kubectl get csvs -A` 7 | would return all CSVs across all namespaces and provide a high-level view of all custom installed operators. 8 | 9 | If the ClusterServiceVersion fails to show up or does not reach the `Succeeded` phase, please check the [troubleshooting documentation](openshift/coming-soon.md) to debug your installation. 10 | 11 | ## Finding available operators 12 | Operators are available from a variety of sources, or catalogs. Some catalogs are bundled in the default installation of 13 | OLM, and there are also online catalogs of operators available to install within the cluster. 14 | 15 | ### Installing operators from within the cluster 16 | A collection of operators come packaged with the default OLM installation and can be examined by querying the packageserver. 17 | These operators come from the community as well as officially supported Red Hat operators. The package server is an 18 | [apiserver extension](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/) 19 | that aggregates information on all operators available to install from catalog sources in the cluster. To see available 20 | packages run `kubectl get packagemanifests`. 21 | 22 | To get more information about a particular operator installed within the cluster from a catalogsource, run 23 | `kubectl describe packagemanifests `. This will provide some detailed information about the operator such as 24 | its intended use, applicable CRDs, and resources for support with that particular operator. 25 | 26 | ### Finding operators to install 27 | A great resource to find all available operators is [OperatorHub](https://operatorhub.io/), an online catalog 28 | of installable operators. There are over 80 available operators available to install, with details around the installation process, 29 | the upgrade process, and operator support information. Installing operators from OperatorHub is seamless if OLM is installed. 30 | 31 | -------------------------------------------------------------------------------- /docs/uninstall-olm.md: -------------------------------------------------------------------------------- 1 | # How do I uninstall OLM? 2 | 3 | You can symmetrically uninstall OLM as you did to install it. Specifically all OLM resources in [crds.yaml](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/deploy/upstream/quickstart/crds.yaml) and [olm.yaml](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/deploy/upstream/quickstart/olm.yaml) should be deleted. The `apiservices` should be removed as the first step, preventing it from becoming a dangling resource. 4 | 5 | Uninstalling OLM does not necessarily clean up the operators it maintained. Please clean up installed operator resources before uninstalling OLM, especially for resources that do not have an owner reference. 6 | 7 | ## Uninstall Released OLM 8 | 9 | For uninstalling release versions of OLM, you can use the following commands: 10 | 11 | ```bash 12 | export OLM_RELEASE= 13 | kubectl delete apiservices.apiregistration.k8s.io v1.packages.operators.coreos.com 14 | kubectl delete -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${OLM_RELEASE}/crds.yaml 15 | kubectl delete -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${OLM_RELEASE}/olm.yaml 16 | ``` 17 | 18 | > NOTE: You can identify which version of OLM you are using by inspecting the version of the packageserver CSV. 19 | 20 | > ```bash 21 | > export OLM_NAMESPACE= 22 | > kubectl -n $OLM_NAMESPACE get csvs 23 | > NAME DISPLAY VERSION REPLACES PHASE 24 | > packageserver Package Server 0.13.0 Succeeded 25 | > ``` 26 | 27 | ## Uninstall From Git Repository Master Branch 28 | 29 | You can also uninstall OLM from the master branch of the [operator-framework/operator-lifecycle-manager](https://github.com/operator-framework/operator-lifecycle-manager/) repository with the following: 30 | 31 | ```bash 32 | kubectl delete apiservices.apiregistration.k8s.io v1.packages.operators.coreos.com 33 | kubectl delete -f https://raw.githubusercontent.com/operator-framework/operator-lifecycle-manager/master/deploy/upstream/quickstart/crds.yaml 34 | kubectl delete -f https://raw.githubusercontent.com/operator-framework/operator-lifecycle-manager/master/deploy/upstream/quickstart/olm.yaml 35 | ``` 36 | 37 | ## Verify OLM Uninstall 38 | 39 | Primarily, you can check that OLM has been uninstalled by checking the OLM namespace. 40 | 41 | ```bash 42 | kubectl get namespace $OLM_NAMESPACE 43 | Error from server (NotFound): namespaces "$OLM_NAMESPACE" not found 44 | ``` 45 | 46 | More specifically, you can verify that OLM has been uninstalled successfully by making sure that OLM **owned** `CustomResourceDefinitions` are removed: 47 | 48 | ```bash 49 | kubectl get crd | grep operators.coreos.com 50 | ``` 51 | 52 | You can also check that the OLM `deployments` are terminated: 53 | 54 | ```bash 55 | kubectl get deploy -n $OLM_NAMESPACE 56 | No resources found. 57 | ``` 58 | 59 | The `role` and `rolebinding` in the OLM namespace are removed: 60 | 61 | ```bash 62 | kubectl get role -n $OLM_NAMESPACE 63 | No resources found. 64 | ``` 65 | 66 | ```bash 67 | kubectl get rolebinding -n $OLM_NAMESPACE 68 | No resources found. 69 | ``` 70 | 71 | At last, the OLM namespace should also be terminated. 72 | -------------------------------------------------------------------------------- /docs/install-olm.md: -------------------------------------------------------------------------------- 1 | # How do I install OLM? 2 | 3 | The OLM is installable on Kubernetes clusters. For the following instructions to work, you must have a Kubernetes cluster running and the `kubectl` is able to communicate with the API server of that cluster. For more information about configuring `kubectl`, please visit [here](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/). 4 | 5 | Note: The OLM can be tested locally with a [minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/) cluster, currently supporting version 1.16.0. For more information see [Makefile](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/Makefile). 6 | 7 | ## Install Released OLM 8 | For installing release versions of OLM, for example version 0.12.0, you can use the following command: 9 | 10 | ```bash 11 | export olm_release=0.12.0 12 | kubectl apply -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${olm_release}/crds.yaml 13 | kubectl apply -f https://github.com/operator-framework/operator-lifecycle-manager/releases/download/${olm_release}/olm.yaml 14 | ``` 15 | 16 | Learn more about available releases [here](https://github.com/operator-framework/operator-lifecycle-manager/releases). 17 | 18 | ## Install From Git Repository Master Branch 19 | 20 | You can install OLM from the master branch of the [operator-framework/operator-lifecycle-manager](https://github.com/operator-framework/operator-lifecycle-manager/) repository with the following: 21 | 22 | ```bash 23 | kubectl create -f https://raw.githubusercontent.com/operator-framework/operator-lifecycle-manager/master/deploy/upstream/quickstart/crds.yaml 24 | kubectl create -f https://raw.githubusercontent.com/operator-framework/operator-lifecycle-manager/master/deploy/upstream/quickstart/olm.yaml 25 | ``` 26 | You can also clone the entire git repository and use the [Makefile](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/Makefile) for deploying OLM locally on [minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/) for development purposes. 27 | 28 | ```bash 29 | git clone https://github.com/operator-framework/operator-lifecycle-manager.git 30 | cd operator-lifecycle-manager 31 | make run-local 32 | ``` 33 | 34 | ## Verify OLM Install 35 | 36 | You can verify the necessary CustomResourceDefinitions are created from applying the `crds.yaml` file with the following: 37 | 38 | ```bash 39 | $ kubectl get crd 40 | NAME CREATED AT 41 | catalogsources.operators.coreos.com 2019-10-21T18:15:27Z 42 | clusterserviceversions.operators.coreos.com 2019-10-21T18:15:27Z 43 | installplans.operators.coreos.com 2019-10-21T18:15:27Z 44 | operatorgroups.operators.coreos.com 2019-10-21T18:15:27Z 45 | subscriptions.operators.coreos.com 2019-10-21T18:15:27Z 46 | ``` 47 | You can also visualize OLM deployments from applying `olm.yaml` file with the following: 48 | 49 | ```bash 50 | $ kubectl get deploy -n olm 51 | NAME READY UP-TO-DATE AVAILABLE AGE 52 | catalog-operator 1/1 1 1 5m52s 53 | olm-operator 1/1 1 1 5m52s 54 | packageserver 2/2 2 2 5m43s 55 | ``` -------------------------------------------------------------------------------- /docs/openshift/operator-marketplace.md: -------------------------------------------------------------------------------- 1 | # Operator Marketplace 2 | 3 | On OpenShift clusters, the [marketplace-operator](https://github.com/operator-framework/operator-marketplace) makes off-cluster Quay Appregistry type catalogs available to OLM. It is installed by default with OpenShift. 4 | 5 | ## Pulling Catalogs From Appregistry 6 | 7 | The marketplace-operator can be told to pull a catalog from Appregistry by creating an `OperatorSource`: 8 | 9 | ```yaml 10 | apiVersion: operators.coreos.com/v1 11 | kind: OperatorSource 12 | metadata: 13 | name: my-operators 14 | namespace: openshift-marketplace 15 | spec: 16 | type: appregistry 17 | endpoint: https://quay.io/cnr 18 | registryNamespace: my-operators 19 | displayName: "My Operators" 20 | publisher: "Me, Myself, and I" 21 | ``` 22 | 23 | - `type` is the registry type (`appregistry` being the only supported type) 24 | - `endpoint` is the Appregistry endpoint 25 | - `registryNamespace` is the name of your Appregistry namespace 26 | - `displayName` and `publisher` are optional and only needed for UI purposes 27 | 28 | The creation of an `OperatorSource` results in the creation of an OLM `CatalogSource` in the same namespace the marketplace-operator is running in. This `CatalogSource` will be populated with operators from the `OperatorSource` ready to be managed by OLM. 29 | 30 | In versions of OpenShift > 4.2, all `CatalogSources` generated by the marketplace-operator in the `openshift-marketplace` namespace are available for use in all namespaces. 31 | 32 | ## Configuration 33 | 34 | The marketplace-operator is installed by default into the `openshift-marketplace` namespace along with three Red Hat provided `OperatorSources`; `redhat-operators`, `certified-operators`, and `community-operators`, which represent operators published by redhat, ISVs (Independent Software Vendors), and upstream community members respectively. 35 | 36 | In versions of OpenShift > 4.2, The default behavior of the marketplace-operator ensures these `OperatorSources` always exist on a cluster, even if they are manually deleted. 37 | 38 | You can manually configure which `OperatorSources` the `marketplace-operator` recreates by creating an `OperatorHub` resource: 39 | 40 | ```yaml 41 | apiVersion: config.openshift.io/v1 42 | kind: OperatorHub 43 | metadata: 44 | name: cluster 45 | spec: 46 | sources: 47 | - name: "community-operators" 48 | disabled: true 49 | ``` 50 | 51 | Alternatively, to disable all default `OperatorSources`, you can use the `disableAllDefaultSources` attribute: 52 | 53 | ```yaml 54 | apiVersion: config.openshift.io/v1 55 | kind: OperatorHub 56 | metadata: 57 | name: cluster 58 | spec: 59 | disableAllDefaultSources: true 60 | ``` 61 | 62 | _**Note:** `sources` takes precedent over `disableAllDefaultSources` if it has entries defined._ 63 | 64 | Once an `OperatorSource` is disabled, the `marketplace-operator` will automatically delete it if present. 65 | 66 | In OpenShift 4.1, recreation of the default `OperatorSources` is controlled by [CVO (cluster-version-operator)](https://github.com/openshift/cluster-version-operator/tree/release-4.1) and can be disabled by [setting them as unmanaged resources](https://github.com/openshift/cluster-version-operator/blob/release-4.1/docs/dev/clusterversion.md#setting-objects-unmanaged): 67 | 68 | ```sh 69 | $ cat <version-patch.yaml 70 | - op: add 71 | path: /spec/overrides/- 72 | value: 73 | kind: OperatorSource 74 | name: community-operators 75 | namespace: openshift-marketplace 76 | unmanaged: true 77 | EOF 78 | $ kubectl patch clusterversion version --type json -p "$(cat version-patch.yaml)" 79 | ... 80 | ``` 81 | 82 | _**Note:** In OpenShift 4.1, default `OperatorSources` won't be deleted automatically when disabled. 83 | -------------------------------------------------------------------------------- /docs/operator-dependencies-and-requirements.md: -------------------------------------------------------------------------------- 1 | # Operator Dependency and Requirement Resolution 2 | 3 | ## Overview on Dependency Principles 4 | 5 | OLM manages the dependency resolution and upgrade lifecycle of running operators. 6 | 7 | Dependencies within OLM exist when an operator will not function as intended if a second operator is not present on cluster and are often introduced when installing or updating an operator. 8 | 9 | OLM does not allow an operator to define a dependency on a specific version (e.g. `etcd-operator v0.9.0`) or instance (e.g. `etcd v3.2.1`) of an operator. Instead, an operator may define a dependency on a specific (Group, Version, Kind) of an API provided by a seperate operator. This encourages operator authors to depend on the interface and not the implementation; thereby allowing operators to update on individual release cycles. 10 | 11 | If a dependency is ever discovered, OLM will attempt to resolve said dependency by searching through known `CatalogSources` for an operator that `owns` the API. If an operator is found that `owns`the `required` API, OLM will attempt to deploy the operator that `owns` the API. If no `owner` is found, OLM will fail to deploy the operator with the dependency. 12 | 13 | ### Similarity with Package Managers 14 | 15 | OLM manages operator dependency resolution very similarily to OS package managers, such as apt/dkpg and yum/rpm. However, given that operators are always running, OLM attempts to ensure that it never deploys a combination of operators that do not work with each other. 16 | 17 | This means that OLM will never: 18 | 19 | * install a set of operators that require APIs that can't be provided 20 | * update an operator in a way that breaks another that depends upon it 21 | 22 | ### OLM Dependency Resolution Specifics 23 | 24 | Dependency resolution begins when a `Subscription` is reconciled by OLM. 25 | 26 | When resolving a `Subscription`, OLM will look at all `Subscription` in the namespace and identify the next offering of each operator based on the upgrade graph. By updating all `Subscriptions` in the namespace, OLM avoids version deadlock that could be introduced when two operators have dependencies on each other. 27 | 28 | Once OLM has identified the list of operator that should be installed in the namespace, OLM will attempt to resolve any required APIs that are missing from the cluster by querying known `CatalogSources`. 29 | 30 | Rather than returning the first `CatalogSource` that contains the missing API, OLM will attempt to identify a prioritized `CatalogSource` - one that provided an operator that depends on the missing API. If the prioritized `CatalogSource` does not contain the API, OLM will search through the remaining `CatalogSources` in the namespace for the API. If an operator is found that provides the API, OLM will create a `Subscription` for the operator using that `CatalogSource`. 31 | 32 | If the required API cannot be resolved, OLM will not install operators that rely on that API. 33 | 34 | ## Defining a Dependency 35 | 36 | An operator can define dependencies within its `ClusterServiceVersion (CSV)``. An operator can specify: 37 | 38 | * A `required` CRD by adding it to the `spec.customresourcedefinitions.required` field. 39 | * A `required` API Service by adding it to the `spec.apiservicedefinitions.required` field. 40 | 41 | > Note: If your operator defines a dependency, packaging it in the same `CatalogSource` as the operator that fulfills the dependency ensures that OLM will always resolve the dependency. 42 | 43 | ## Defining Ownership over an API 44 | 45 | An operator can define which APIs it owns within its CSV. An operator can specify: 46 | 47 | * An `owned` CRD by adding it to the `spec.customresourcedefinitions.owned` field. 48 | * An `owned` API Service by adding it to the `spec.apiservicedefinitions.owned` field. 49 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | # Operator Lifecycle Book 2 | 3 | - [Introduction](docs/intro.md) 4 | 5 | - [Glossary](docs/glossary.md) 6 | 7 | ## Foundational Concepts 8 | 9 | - [What is an Operator?](docs/what-is-an-operator.md) 10 | - [Why would I use OLM?](docs/openshift/coming-soon.md) 11 | - [What does OLM enable?](docs/what-does-olm-enable.md) 12 | - [Operators on cluster](docs/openshift/coming-soon.md) 13 | 14 | ## Under the hood 15 | 16 | - [Operands](docs/openshift/coming-soon.md) 17 | - [Operator bundles](docs/openshift/coming-soon.md) 18 | - [Operator catalogs](docs/openshift/coming-soon.md) 19 | - [Subscriptions](docs/subscriptions.md) 20 | - [Operator dependencies and requirements](docs/operator-dependencies-and-requirements.md) 21 | - [Operator update graphs and channels](docs/openshift/coming-soon.md) 22 | - [Operator versioning and release strategies](docs/openshift/coming-soon.md) 23 | - [Operand support matrices](docs/openshift/coming-soon.md) 24 | - [Operator install modes](docs/openshift/coming-soon.md) 25 | - [Operator scoping](docs/operator-scoping.md) 26 | 27 | ## Basic Use Cases 28 | 29 | - [How do I install OLM?](docs/install-olm.md) 30 | - [How do I package my Operator for OLM?](docs/packaging-an-operator.md) 31 | - [How do I validate the package?](docs/validate-package.md) 32 | - [How do I make my Operator part of a catalog?](docs/openshift/coming-soon.md) 33 | - [How do I install my Operator with OLM?](docs/how-do-i-install-my-operator-with-olm.md) 34 | - [How do I list Operators available to install?](docs/list-available-operators.md) 35 | - [How do I uninstall an Operator?](docs/uninstall-an-operator.md) 36 | - [How do I discover the presence/availability of an Operator?](docs/discover-operator-presence.md) 37 | - [How do I uninstall OLM?](docs/uninstall-olm.md) 38 | 39 | ## Advanced Use Cases 40 | 41 | - [When do I need to update my Operator?](docs/when-to-update-my-operator.md) 42 | - [How do I create an updated version of my Operator?](docs/openshift/coming-soon.md) 43 | - [How do I test an update before shipping?](docs/openshift/coming-soon.md) 44 | - [How do I ship an updated version of my Operator?](docs/openshift/coming-soon.md) 45 | - [How do I approve an update?](docs/openshift/coming-soon.md) 46 | - [How do I scope down an Operator?](docs/openshift/coming-soon.md) 47 | - [How can I install an Operator when I am not cluster admin?](docs/openshift/coming-soon.md) 48 | - [How do I rely on other Operators with my Operator?](docs/openshift/coming-soon.md) 49 | - [How can I configure / customize my Operator deployment?](docs/openshift/coming-soon.md) 50 | - [How can I set / override defaults to amend runtime behavior of my Operator?](docs/openshift/coming-soon.md) 51 | - [What annotations can I use to drive UIs?](docs/openshift/coming-soon.md) 52 | - [How do I change which users are able to use an Operator?](docs/openshift/coming-soon.md) 53 | - [How do I “hide” particular CRDs not intended for consumption by an end-user?](docs/openshift/coming-soon.md) 54 | - [How do I ship webhooks?](docs/openshift/coming-soon.md) 55 | - [When and how should a running Operator express that it is not upgradeable?](docs/openshift/coming-soon.md) 56 | - [When should an Operator upgrade its Operands?](docs/openshift/coming-soon.md) 57 | - [How should an Operator Author create and package an Operator for a singleton operand?](docs/openshift/coming-soon.md) 58 | - [How do I snapshot a Quay Appregistry operator catalog?](docs/snapshot-appr-registry.md) 59 | - [How do I ship an operator that supports multiple node architectures?](docs/multiarch.md) 60 | 61 | ## Troubleshooting 62 | 63 | - [Troubleshoot OLM installation](docs/openshift/coming-soon.md) 64 | - [Troubleshoot operator installation with OLM](docs/troubleshooting.md) 65 | 66 | ## OLM on OCP (OpenShift Container Platform) 67 | 68 | - [FAQ](docs/openshift/faq.md) 69 | - [Important changes by OCP release](docs/openshift/important-changes-by-release.md) 70 | - [Operator Marketplace](docs/openshift/operator-marketplace.md) 71 | -------------------------------------------------------------------------------- /docs/subscriptions.md: -------------------------------------------------------------------------------- 1 | # Subscriptions 2 | 3 | Subscriptions are Custom Resources that relate an operator to a CatalogSource. Subscriptions describe which channel of an operator package to subscribe to and whether to perform updates automatically or manually. If set to automatic, the Subscription ensures OLM will manage and upgrade the operator to ensure the latest version is always running in the cluster. 4 | 5 | Here's an example of a Subscription definition: 6 | 7 | ```yaml 8 | apiVersion: operators.coreos.com/v1alpha1 9 | kind: Subscription 10 | metadata: 11 | name: my-operator 12 | namespace: openshift-operators 13 | spec: 14 | channel: stable 15 | name: my-operator 16 | source: redhat-operators 17 | sourceNamespace: openshift-marketplace 18 | ``` 19 | 20 | This Subscription object defines the name and namespace of the operator, as well as the catalog from which the operator data can be found. The channel (such as alpha, beta, or stable) helps determine which stream of the operator should be installed from the CatalogSource. 21 | 22 | ## Manually Approving Upgrades via Subscriptions 23 | 24 | By default, OLM will automatically approve updates to an operator as new versions become available via a CatalogSource. When creating a subscription, it is possible to disable automatic updates by setting the `approval` field to `Manual` like so: 25 | 26 | ```yaml 27 | apiVersion: operators.coreos.com/v1alpha1 28 | kind: Subscription 29 | metadata: 30 | name: my-operator 31 | namespace: openshift-operators 32 | spec: 33 | channel: stable 34 | name: my-operator 35 | source: redhat-operators 36 | sourceNamespace: openshift-marketplace 37 | approval: Manual 38 | ``` 39 | 40 | Setting the `approval` field to manual will prevent OLM from automatically installing the operator. As such, you will need to approve the installPlan which can be done with the following commands: 41 | 42 | ```bash 43 | kubectl -n openshift-operators get installplans 44 | NAME CSV APPROVAL APPROVED 45 | install-bfmxd my-operator.v0.1.0 Manual false 46 | 47 | $ kubectl -n default patch installplan install-bfmxd -p '{"spec":{"approved":true}}' --type merge 48 | installplan.operators.coreos.com/install-bfmxd patched 49 | 50 | $ kubectl -n openshift-operators get installplans 51 | NAME CSV APPROVAL APPROVED 52 | install-bfmxd my-operator.v0.1.0 Manual true 53 | ``` 54 | 55 | Now that the `install-bfmxd` installPlan is in the approved state, OLM will install the operator defined by the `my-operator.v0.1.0` CSV. 56 | 57 | When the CatalogSource is updated with a newer version of that operator in the channel you selected, a new installPlan will be created in the namespace that you installed the operator to, as shown below: 58 | 59 | ```bash 60 | $ kubectl -n openshift-operators get installplans 61 | NAME CSV APPROVAL APPROVED 62 | install-bfmxd my-operator.v0.1.0 Manual true 63 | install-svojy my-operator.v0.2.0 Manual false 64 | ``` 65 | 66 | From here, you can approve `install-svojy` using the patch command shown earlier. 67 | 68 | With the new installPlan in the approve state, the `my-operator.v0.2.0` CSV will be deployed to the cluster and if the CSV reaches the `Succeeded` state the old CSV will be deleted. If the new CSV fails to reach the `Succeeded` state, both CSVs will continue to exist and it is up to the user to resolve the failure. In either case, OLM will not delete old installPlans as they act as a record of CSVs that were installed on your cluster. 69 | 70 | ## How do I know when an update is available for an operator 71 | 72 | It is possible to identify when there is a newer version of an operator available by inspecting the status of the operator's subscription. The value associated with the `currentCSV` field is the newest version that is known to OLM, and `installedCSV` is the version that is installed on the cluster. -------------------------------------------------------------------------------- /docs/validate-package.md: -------------------------------------------------------------------------------- 1 | # How do I validate the package? 2 | 3 | Once you've [created your operator's package manifests](packaging-an-operator.md), you will want to ensure that your package is valid and in the correct format. To ensure this, you should take several steps to ensure that your package can be used to install your operator in OLM. We will publish the package into a catalog, install that catalog onto a Kube cluster, and then install the operator onto that cluster. If all of that succeeds and your operator is behaving as expected, your package is valid. 4 | 5 | ## Linting 6 | 7 | You can perform some basic static verification on your package by using [`operator-courier`](https://github.com/operator-framework/operator-courier). 8 | 9 | ``` 10 | $ pip3 install operator-courier 11 | $ operator-courier verify manifests/my-operator-package 12 | ``` 13 | 14 | You can also use `operator-courier` to verify that your operator will be displayed properly on [OperatorHub.io](https://operatorhub.io/). 15 | 16 | ``` 17 | $ operator-courier verify --ui_validate_io manifests/my-operator-package 18 | ``` 19 | 20 | ## Add your package to a catalog 21 | 22 | The [operator-registry project](https://github.com/operator-framework/operator-registry) defines a format for storing sets of operators and exposing them to make them available on a cluster. As part of adding your package to an operator-registry catalog, the operator-registry tools will verify that your operator is packaged properly ("Does it have a valid CSV of the correct format?", "Does my CRD properly reference my CSVs?", etc.). The simplest way to test that your package can be added to a catalog is by actually attempting to create a catalog that includes your operator. 23 | 24 | To create a catalog that includes your package, simply build a container image that uses the operator-registry command line tools to generate a registry and serve it. For example, create a file in the root of your project called `registry.Dockerfile` 25 | 26 | ```Dockerfile 27 | FROM quay.io/operator-framework/upstream-registry-builder as builder 28 | 29 | COPY manifests manifests 30 | RUN ./bin/initializer -o ./bundles.db 31 | 32 | FROM scratch 33 | COPY --from=builder /build/bundles.db /bundles.db 34 | COPY --from=builder /build/bin/registry-server /registry-server 35 | COPY --from=builder /bin/grpc_health_probe /bin/grpc_health_probe 36 | EXPOSE 50051 37 | ENTRYPOINT ["/registry-server"] 38 | CMD ["--database", "bundles.db"] 39 | ``` 40 | 41 | This Dockerfile assumes that your package is in a directory called `./manifests/` similar to [this example](https://github.com/operator-framework/operator-registry/tree/master/manifests). It copies your manifests into the builder image, runs `initializer`, then copies the output into the final scratch image and defines the run command to serve the operator-registry. 42 | 43 | Then just use your favorite container tooling to build the container image and push it to a registry: 44 | 45 | ``` 46 | docker build -t example-registry:latest -f registry-Dockerfile . 47 | docker push example-registry:latest 48 | ``` 49 | 50 | Your catalog is published and we are ready to use it on your cluster. 51 | 52 | ## Install your operator 53 | 54 | Now that you have created an operator-registry image that hosts your operator's package, add that catalog to your cluster: 55 | 56 | ```yaml 57 | apiVersion: operators.coreos.com/v1alpha1 58 | kind: CatalogSource 59 | metadata: 60 | name: example-manifests 61 | namespace: your-namespace 62 | spec: 63 | sourceType: grpc 64 | image: example-registry:latest 65 | ``` 66 | 67 | This will cause OLM to pull your image and create a pod in the designated namespace (`your-namespace`) that hosts your package. Your Catalog is now installed onto your cluster and your package is available! 68 | 69 | Once the catalog has been loaded, your Operators package definitions are read by the `package-server`, a component of OLM. Watch your Operator packages become available: 70 | 71 | ``` 72 | $ kubectl get packagemanifests -n your-namespace 73 | 74 | NAME AGE 75 | your-operator 13m 76 | ``` 77 | 78 | Once loaded, you can query a particular package for its Operators that it serves across multiple channels. To obtain the default channel run: 79 | 80 | ``` 81 | $ kubectl get packagemanifests your-operator -o jsonpath='{.status.defaultChannel}' -n your-namespace 82 | 83 | alpha 84 | ``` 85 | 86 | With this information, the operators package name, the channel and the name and namespace of your catalog you can now [install your operator with OLM](how-do-i-install-my-operator-with-olm.md) 87 | 88 | Now that your operator is installed from your package, poke around and ensure that it is working as you expect. If so, your package is valid! 89 | -------------------------------------------------------------------------------- /docs/glossary.md: -------------------------------------------------------------------------------- 1 | # OLM Glossary 2 | 3 | A list of OLM terms, with definitions and common Aliases. 4 | 5 | ## CustomResourceDefinitions (CRDs) 6 | 7 | The following [CustomResourceDefinitions](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/) are defined by the OLM. 8 | 9 | ### ClusterServiceVersion 10 | 11 | **Definition**: The ClusterServiceVersion represents a particular version of a ClusterService and its operator. It includes metadata such as name, description, version, repository link, labels, icon, etc. It declares `owned`/`required` CRDs, cluster requirements, and install strategy that tells OLM how to create required resources and set up the operator as a [deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/). 12 | 13 | **Aliases**: CSV(s) 14 | 15 | ### CatalogSources 16 | 17 | **Definition**: The CatalogSource represents a repository of bundles, which are collections of resources that must contain [CSVs](#ClusterServiceVersion), [CRDs](#CustomResourceDefinitions), and package definitions. There are multiple implementations of a CatalogSource backend, the current recommendation is to use a [registry image](#Index). 18 | 19 | **Aliases**: CatSrc(s) 20 | 21 | ### InstallPlans 22 | 23 | **Definition**: The InstallPlan defines a set of resources to be created in order to install or upgrade to a specific version of a ClusterService defined by a CSV. 24 | 25 | **Aliases**: IP(s) 26 | 27 | ### OperatorGroups 28 | 29 | **Definition**: The OperatorGroup selects a set of target namespaces in which to generate required RBAC access for its member Operators. 30 | 31 | **Aliases**: OG(s) 32 | 33 | ### OperatorSources 34 | 35 | **Definition**: The OperatorSources are a way of pointing to external app registry namespaces that contain a catalog of operators. Applying an OperatorSource to a cluster makes the operators in that OperatorSource available for installation in that cluster. 36 | 37 | **Aliases**: OpSrc(s) 38 | 39 | ### Subscriptions 40 | 41 | **Definition**: The Subscription defines the channel and the source of Operator updates and is used to keep the CSV updated by binding with a channel in a package. 42 | 43 | **Aliases**: Subs(s) 44 | 45 | ## OLM Concepts 46 | 47 | ### Bundle 48 | 49 | **Definition**: A collection of Operator [CSV](#ClusterServiceVersion), manifests, and metadata which together form a unique version of an Operator that can be installed onto the cluster. 50 | 51 | ### Bundle Image 52 | 53 | **Definition**: An image of a bundle is built from operator manifests and contains exactly one [bundle](#Bundle). The bundle images are stored and distributed by OCI spec container registries such as Quay.io or DockerHub. 54 | 55 | ### Channel 56 | 57 | **Definition**: The channel defines a stream of updates for an operator and is used to roll out updates for subscribers. The head points at the latest version of that channel. For example, a stable channel would have all stable versions of an operator arranged from the earliest to the latest. An operator can have several channels, and a subscription binding to a certain channel would only look for updates in that channel. 58 | 59 | ### Channel Head 60 | 61 | **Definition**: Head refers to the latest known update in a particular [channel](#Channel). 62 | 63 | ### Catalog Image 64 | 65 | **Definition**: A catalog image is a containerized datastore that describes a set of operator and update metadata that can be installed onto a cluster via OLM. 66 | 67 | **Aliases**: OPM Index 68 | 69 | ### Dependency 70 | 71 | **Definition**: An Operator may have a dependency on another Operator being present in the cluster. For example, the Vault Operator has a dependency on the Etcd Operator for its data persistence layer. OLM resolves these dependencies by ensuring all specified versions of Operators and CRDs are installed on the cluster during the installation phase. This dependency is resolved by finding and installing an Operator in a Catalog that satisfies the required CRD API, and not related to [packages](#Packages)/[bundles](#Bundles). 72 | 73 | **Aliases**: Operator Dependency, GVK Dependency, API Dependency, Required CRD 74 | 75 | ### Index 76 | 77 | **Definition**: The Index refers to an image of a database (a database snapshot) that contains information about Operator bundles including CSVs, CRDs, etc of all versions. This index can host a history of used operators on a cluster and be maintained by adding or removing operators. 78 | 79 | **Aliases**: Registry DB, Catalog DB, OPM registry 80 | 81 | ### Package 82 | 83 | **Definition**: A package is a directory that encloses all released history of an Operator with each version contained 84 | in the bundle format. A released version of an Operator is described in a ClusterServiceVersion manifest alongside the CustomResourceDefinitions. 85 | 86 | ### Registry 87 | 88 | **Definition**: A database which stores [Bundle Images](#Bundle-Image) of Operators, each with all of its latest/historical versions in all [channels](#Channel). 89 | 90 | ### Upgrade Graph 91 | 92 | **Definition**: An upgrade graph links versions of [CSV](#ClusterServiceVersions) together, similar to the upgrade graph of any other packaged software. Operators can be installed sequentially, or certain versions can be skipped. The update graph is expected to grow only at the head with newer versions being added. This is automatically resolved as part of [index](#Index). 93 | -------------------------------------------------------------------------------- /docs/snapshot-appr-registry.md: -------------------------------------------------------------------------------- 1 | # How do I snapshot a Quay Appregistry operator catalog? 2 | 3 | ## What in tarnation is a _snapshot_? 4 | 5 | For the purposes of this document, a _snapshot_ is: 6 | 7 | - a point-in-time export of an Appregistry (appr) type catalog's content 8 | - the result of converting an appr catalog to a container image type catalog 9 | - an immutable artifact 10 | 11 | ## When/Why would I need a snapshot? 12 | 13 | OLM always installs from the latest version of an appr catalog. As appr catalogs are updated, the latest versions of operators change, and older versions may be removed or altered. This behavior can cause problems maintaining reproducible installs over time. 14 | 15 | As of OCP 4.3, Red Hat provided operators are distributed via appr catalogs. Creating a snapshot provides a simple way to use this content without incurring the aforementioned issues. 16 | 17 | ## Prerequisites 18 | 19 | - Linux 20 | - A version `oc` that has the `oc catalog build`, such as [this one for OCP `4.3`](https://openshift-release-artifacts.svc.ci.openshift.org/4.3/) 21 | - A container image registry that supports [Docker v2-2](https://docs.docker.com/registry/spec/manifest-v2-2/) 22 | - [grpcurl](https://github.com/fullstorydev/grpcurl) (optional, for testing) 23 | 24 | ## Setup 25 | 26 | Users should authenticate with the target image registry. By default, `oc adm catalog build` uses `~/.docker/config.json` to determine credentials. 27 | 28 | ## Taking a snapshot 29 | 30 | Snapshot `redhat-operators` as `quay.io/my/redhat-operators:snapshot-0`. 31 | 32 | ```sh 33 | $ oc adm catalog build --appregistry-endpoint https://quay.io/cnr --appregistry-org redhat-operators --to=quay.io/my/redhat-operators:snapshot-0 34 | INFO[0013] loading Bundles dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605 35 | INFO[0013] directory dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605 file=manifests-829192605 load=bundles 36 | INFO[0013] directory dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605 file=3scale-operator load=bundles 37 | INFO[0013] found csv, loading bundle dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605 file=3scale-operator.v0.3.0.clusterserviceversion.yaml load=bundles 38 | INFO[0013] loading bundle file dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605/3scale-operator file=3scale-operator.package.yaml load=bundle 39 | INFO[0013] loading bundle file dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605/3scale-operator file=3scale-operator.v0.3.0.clusterserviceversion.yaml load=bundle 40 | ... 41 | Uploading ... 244.9kB/s 42 | Pushed sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3 to quay.io/my/redhat-operators:snapshot-0 43 | ``` 44 | 45 | Sometimes invalid manifests are accidentally introduced into Red Hat's catalogs, when this happens you may see some errors. 46 | 47 | ```sh 48 | ... 49 | INFO[0014] directory dir=/var/folders/st/9cskxqs53ll3wdn434vw4cd80000gn/T/300666084/manifests-829192605 file=4.2 load=package 50 | W1114 19:42:37.876180 34665 builder.go:141] error building database: error loading package into db: fuse-camel-k-operator.v7.5.0 specifies replacement that couldn't be found 51 | Uploading ... 244.9kB/s 52 | ... 53 | ``` 54 | 55 | These errors are usually non-fatal, and if the operator package mentioned doesn't contain an operator you plan to install or a dependency of one, then they can be ignored. 56 | 57 | ## Testing a snapshot 58 | 59 | You can validate snapshot content by running it as a container and querying its gRPC API: 60 | 61 | Pull a snapshot image. 62 | 63 | ```sh 64 | $ docker pull quay.io/my/redhat-operators:snapshot-0 65 | ... 66 | ``` 67 | 68 | Run the snapshot image. 69 | 70 | ```sh 71 | $ docker run -p -p 50051:50051 -it quay.io/my/redhat-operators:snapshot-0 72 | ... 73 | ``` 74 | 75 | Query the running snapshot for available packages using `grpcurl`. 76 | 77 | ```sh 78 | $ grpcurl -plaintext localhost:50051 api.Registry/ListPackages 79 | { 80 | "name": "3scale-operator" 81 | } 82 | { 83 | "name": "amq-broker" 84 | } 85 | { 86 | "name": "amq-online" 87 | } 88 | ... 89 | ``` 90 | 91 | Get the latest bundle in a channel. 92 | 93 | ```sh 94 | $ grpcurl -plaintext -d '{"pkgName":"kiali-ossm","channelName":"stable"}' localhost:50051 api.Registry/GetBundleForChannel 95 | { 96 | "csvName": "kiali-operator.v1.0.7", 97 | "packageName": "kiali-ossm", 98 | "channelName": "stable", 99 | ... 100 | ``` 101 | 102 | ## Using a snapshot 103 | 104 | You can resolve OLM `Subscriptions` with a snapshot image by referencing it in a `CatalogSource`: 105 | 106 | Pull a snapshot image. 107 | 108 | ```sh 109 | $ docker pull quay.io/my/redhat-operators:snapshot-0 110 | ... 111 | ``` 112 | 113 | Get the digest of the snapshot image. 114 | 115 | ```sh 116 | $ docker inspect --format='{{index .RepoDigests 0}}' quay.io/my/redhat-operators:snapshot-0 117 | quay.io/my/redhat-operators@sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3 118 | ``` 119 | 120 | Assuming an `OperatorGroup` exists in namespace `my-ns` that supports your operator and its dependencies, create a `CatalogSource` using the snapshot digest. 121 | 122 | ```yaml 123 | apiVersion: operators.coreos.com/v1alpha1 124 | kind: CatalogSource 125 | metadata: 126 | name: redhat-operators-snapshot 127 | namespace: my-ns 128 | spec: 129 | sourceType: grpc 130 | image: quay.io/my/redhat-operators@sha256:f73d42950021f9240389f99ddc5b0c7f1b533c054ba344654ff1edaf6bf827e3 131 | displayName: Red Hat Operators Snapshot 132 | ``` 133 | 134 | Create a `Subscription` that resolves the latest available `servicemeshoperator` and its dependencies from the snapshot. 135 | 136 | ```yaml 137 | apiVersion: operators.coreos.com/v1alpha1 138 | kind: Subscription 139 | metadata: 140 | name: servicemeshoperator 141 | namespace: my-ns 142 | spec: 143 | source: redhat-operators-snapshot 144 | sourceNamespace: my-ns 145 | name: servicemeshoperator 146 | channel: 1.0 147 | ``` 148 | 149 | Updates to Red Hat's appr catalog's can be captured by a new snapshot, tested, and introduced to existing clusters by swapping out the `CatalogSource's` `spec.image` field with the new snapshot digest. 150 | 151 | ## My snapshot build succeeded, but the final image doesn't contain any operators!? 152 | 153 | This can occur if the image repository specified by `--to` does not have Docker v2-2 enabled. As of November 2019, only select Quay namespaces have v2-2 enabled. The OLM team keeps a [redhat-operators snapshot repo](https://quay.io/repository/operator-framework/redhat-operators) available and manually adds snapshots upon request. If you need a new snapshot taken and do not have access to a v2-2 enabled repo, please reach out to `@olm-dev` in [#forum-operator-fw](https://coreos.slack.com/archives/C3VS0LV41). 154 | -------------------------------------------------------------------------------- /docs/operator-scoping.md: -------------------------------------------------------------------------------- 1 | # Operator Scoping 2 | 3 | OLM runs with cluster-admin privileges and is capable of granting permissions to operators that it deploys. By default, an operator can specify any set of permission(s) in the CSV and OLM will consequently grant it to the operator. In effect, an operator can achieve cluster-scoped privilege(s) which may not always be desired. 4 | 5 | OLM introduces the concept of `OperatorGroups` to enable cluster admins complete control over the permissions that OLM grants operators that it deploys. An admin may create a single `OperatorGroup` in a given namespace. Any CSV created in that namespace is said to be a member operator of that `OperatorGroup`. With `OperatorGroups`, a cluster admin can: 6 | 7 | * Define the set of permissions that OLM may grant to member operators 8 | * Define the set of namespaces that OLM may grant namespaced permissions in. 9 | 10 | ## Configuring OperatorGroups 11 | 12 | ### Scoping Member Operators to Specific Namespaces 13 | 14 | Using an `OperatorGroup`, a cluster admin can scope member operators' namespaced permissions to specific namespaces in two ways: 15 | 16 | * Using a predefined list of namespaces 17 | * Using a label selector. 18 | 19 | #### Defining a set of namespaces 20 | 21 | The set of namespaces can be hardcoded setting the `spec.targetNamespaces` of an `OperatorGroup` like so: 22 | 23 | ```yaml 24 | apiVersion: operators.coreos.com/v1alpha2 25 | kind: OperatorGroup 26 | metadata: 27 | name: my-group 28 | namespace: my-namespace 29 | spec: 30 | targetNamespaces: 31 | - my-namespace 32 | - my-other-namespace 33 | - my-other-other-namespace 34 | ``` 35 | 36 | In the example above, member operator will be scoped to the following namespaces: 37 | 38 | * my-namespace 39 | * my-other-namespace 40 | * my-other-other-namespace 41 | 42 | #### Defining a set of namespaces with a label selector 43 | 44 | Cluster admins may not know in advance which namespaces member operators should be scoped to. In this case, it may make sense to use a label selector to identify which namespaces permissions should be granted in. A namespace selector can be defined for an `OpearatorGroup` like so: 45 | 46 | ```yaml 47 | apiVersion: operators.coreos.com/v1alpha2 48 | kind: OperatorGroup 49 | metadata: 50 | name: my-group 51 | namespace: my-namespace 52 | spec: 53 | selector: 54 | cool.io/prod: "true" 55 | ``` 56 | 57 | In the example above, member operators will be scoped to any namespaces with the `cool.io/prod: true` label. If no namespaces exist with the `cool.io/prod: true` label, OLM will fail to install any member operators. 58 | 59 | >Note: In the case that both a selector and a list of namespaces are provided, the selector is ignored. 60 | 61 | #### TargetNamespaces and their realationship to InstallModes 62 | 63 | When creating `OperatorGroups` it is important to keep in mind that an operator may not support all namespace configurations. For example, an operator that is designed to run at the cluster level shouldn't be expected to work in an `OperatorGroup` that defines a single targetNamespace. 64 | 65 | Operator authors are responsible for defining which `InstallModes` their operator supports within its `ClusterServiceVersion (CSV)`. There are four `InstallModes` that an operator can support: 66 | 67 | * **OwnNamespace**: If supported, the operator can be configured to watch for events in the namespace it is deployed in. 68 | * **SingleNamespace**: If supported, the operator can be configured to watch for events in a single namespace that the operator is not deployed in. 69 | * **MultiNamespace**: If supported, the operator can be configured to watch for events in more than one namespace. 70 | * **AllNamespaces**: If supported, the operator can be configured to watch for events in all namespaces. 71 | 72 | >Note: If a CSV's spec omits an entry of InstallModeType, that type is considered unsupported unless support can be inferred by an existing entry that implicitly supports it. 73 | 74 | Cluster admins cannot override which `InstallModes` an operator supports, and so should understand how to create an `OperatorGroup` that supports each `InstallMode`. Let's look at an example of an `OperatorGroup` implementing each type of installMode: 75 | 76 | ##### OwnNamespace 77 | 78 | ```yaml 79 | apiVersion: operators.coreos.com/v1alpha2 80 | kind: OperatorGroup 81 | metadata: 82 | name: own-namespace-operator-group 83 | namespace: own-namespace 84 | spec: 85 | targetNamespaces: 86 | - own-namespace 87 | ``` 88 | 89 | ##### SingleNamespace 90 | 91 | ```yaml 92 | apiVersion: operators.coreos.com/v1alpha2 93 | kind: OperatorGroup 94 | metadata: 95 | name: single-namespace-operator-group 96 | namespace: own-namespace 97 | spec: 98 | targetNamespaces: 99 | - some-other-namespace 100 | ``` 101 | 102 | ##### MultiNamespace 103 | 104 | ```yaml 105 | apiVersion: operators.coreos.com/v1alpha2 106 | kind: OperatorGroup 107 | metadata: 108 | name: multi-namespace-operator-group 109 | namespace: own-namespace 110 | spec: 111 | targetNamespaces: 112 | - own-namespace 113 | - some-other-namespace 114 | ``` 115 | 116 | ##### AllNamespaces 117 | 118 | ```yaml 119 | apiVersion: operators.coreos.com/v1alpha2 120 | kind: OperatorGroup 121 | metadata: 122 | name: all-namespaces-operator-group 123 | namespace: own-namespace 124 | ``` 125 | 126 | ### Scoping Member Operator Permissions 127 | 128 | When creating an `OperatorGroup`, cluster admins may specify a `ServiceAccount` that defines the set of permissions that may be granted to all member operators. OLM will ensure that when an operator is installed its privileges are confined to that of the `ServiceAccount` specified. 129 | 130 | As a result a cluster-admin can limit an operator to a pre-defined set of RBAC rules. The Operator will not be able to do anything that is not explicitly permitted by these permissions. This enables self-sufficient installation of Operators by non-cluster-admin users with a limited scope. 131 | 132 | #### Defining a ServiceAccount for an OperatorGroup 133 | 134 | A `ServiceAccount` may be defined within an `OperatorGroup` like so: 135 | 136 | ```yaml 137 | apiVersion: operators.coreos.com/v1alpha2 138 | kind: OperatorGroup 139 | metadata: 140 | name: scoped-permissions-operator-group 141 | namespace: own-namespace 142 | spec: 143 | serviceAccountName: member-operator-servicee-account 144 | targetNamespaces: 145 | - own-namespace 146 | ``` 147 | 148 | Any operator tied to this `OperatorGroup` will now be confined to the permission(s) granted to the specified `ServiceAccount`. If the operator asks for permission(s) that are outside the scope of the `ServiceAccount` the install will fail with appropriate error(s). 149 | 150 | An example of scoping an operator can be found [here](openshift/coming-soon.md). 151 | 152 | ### Configuring the End User Experience 153 | 154 | ### Making Operators Available 155 | 156 | Once a cluster admin has successfully created an `OperatorGroup`, he or she then has the opportunity to decide which operators should be offered as a part of that group. This is an important phase in configuring the cluster, as most users may not have the ability to install an operator into an `OperatorGroup`. 157 | 158 | A cluster admin can add an operator to an `OperatorGroup` by creating a `Subscription` in the same namespace. An operator can be added and removed from an `OperatorGroup` at anytime. 159 | 160 | Keep in mind that this process can be repeated for any number of `OperatorGroups`. This means that a cluster admin can decide for a set of operator to watch for events in one set of namespaces while defining a seperate set of operators that watch for events in a seperate set of namespaces. 161 | 162 | ### Enabling a User to use an Operator 163 | 164 | Once a cluster admin has decided which operators are available on a cluster, it is now time to decide which user(s) may take advantage of an available operator. 165 | 166 | Users interact with operators by creating a resource in a namespace that an operator is watching. As such, by tuning RBAC privileges a cluster admin has complete control over the set of users that may interact with an operator along with the set of APIs that user may take advantage of. 167 | 168 | For example, if an operator were available that offered two APIs, a cluster admin may provide a user with full RBAC privileges over one API but not grant the user any privileges with the second API. 169 | -------------------------------------------------------------------------------- /docs/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | This document focuses on troubleshooting unexpected behavior when installing and managing operators with OLM. This document contains 3 sections where we highlight how to troubleshoot specific OLM components: 4 | 5 | * [Troubleshooting the `CatalogSource`](#catalogsource-troubleshooting) 6 | * [Troubleshooting the `Subscription`](#subscription-troubleshooting) 7 | * [Troubleshooting the `ClusterServiceVersion (CSV)`](#clusterserviceversion-troubleshooting) 8 | 9 | ## Prereqs 10 | 11 | Some of the commands listed below assume that you have [yq](https://github.com/mikefarah/yq) installed on your system. While `yq` is not required, it is a useful tool when parsing yaml. You can install `yq` by following the [official installation steps](https://github.com/mikefarah/yq#install). 12 | 13 | ## CatalogSource Troubleshooting 14 | 15 | ### How to debug a failing CatalogSource 16 | 17 | The Catalog operator will constantly update the `Status` of `CatalogSources` to reflect its current state. You can check the `Status` of your `CatalogSource` with the following command: 18 | 19 | `$ kubectl -n my-namespace get catsrc my-catalog -o yaml | yq r - status` 20 | 21 | >Note: It is possible that the `Status` is missing, which suggests that the Catalog operator is encountering an issue when processing the `CatalogSource` in a very early stage. 22 | 23 | If the `Status` block does not provide enough information, check the [Catalog operator's logs](#how-to-view-the-catalog-operator-logs). 24 | 25 | If you are still unable to identify the cause of the failure, check if a pod was created for the `CatalogSource`. If a pod exists, review the pod's yaml and logs: 26 | 27 | ```bash 28 | $ kubectl -n my-namespace get pods 29 | NAME READY STATUS RESTARTS AGE 30 | my-catalog-ltdlp 1/1 Running 0 8m31s 31 | 32 | $ kubectl -n my-namespace get pod my-catalog-ltdlp -o yaml 33 | ... 34 | 35 | $ kubectl -n my-namespace logs my-catalog-ltdlp 36 | ... 37 | ``` 38 | 39 | ### I'm not sure if a specific version of an operator is available in a CatalogSource 40 | 41 | First verify that the `CatalogSource` contains the operator that you want to install: 42 | 43 | ```bash 44 | $ kubectl -n my-namespace get packagemanifests 45 | NAME CATALOG AGE 46 | ... 47 | portworx My Catalog Source 14m 48 | postgres-operator My Catalog Source 14m 49 | postgresql My Catalog Source 14m 50 | postgresql-operator-dev4devs-com My Catalog Source 14m 51 | prometheus My Catalog Source 14m 52 | ... 53 | ``` 54 | 55 | If the operator is present, check if the version you want is available: 56 | 57 | `$ kubectl -n my-namespace get packagemanifests my-operator -o yaml` 58 | 59 | ### My CatalogSource cannot pull images from a private registry 60 | 61 | If you are attempting to pull images from a private registry, make sure to specify a secret key in the `CatalogSource.Spec.Secrets` field. 62 | 63 | ## Subscription Troubleshooting 64 | 65 | This section assumes that you have a working `CatalogSource`. 66 | 67 | ### How to debug a failing Subscription 68 | 69 | The Catalog operator will constantly update the `Status` of `Subscription` to reflect its current state. You can check the `Status` of your `Subscription` with the following command: 70 | 71 | `$ kubectl -n my-namespace get subscriptions my-subscription -o yaml | yq r - status` 72 | 73 | >Note: It is possible that the `Status` is missing, which suggests that the Catalog operator is encountering an issue when processing the `Subscription` in a very early stage. 74 | 75 | If the `Status` block does not provide enough information, check the [Catalog operator's logs](#how-to-view-the-catalog-operator-logs). 76 | 77 | ### A subscription in namespace X can't install operators from a CatalogSource in namespace Y 78 | 79 | `Subscriptions` cannot install operators provided by `CatalogSources` that are not in the same namespace unless the `CatalogSource` is created in the `olm` namespace. 80 | 81 | ### Why does a single failing subscription cause all subscriptions in a namespace to fail? 82 | 83 | Each Subscription in a namespace acts as a part of a set of operators for the namespace - think of a Subscription as an entry in a python `requirements.txt`. If OLM is unable to resolve part of the set, it knows that resolving the entire set will fail, so it will bail out of the installation of operators for that particular namespace. Subscriptions are separate objects but within a namespace they are all synced and resolved together. 84 | 85 | ## ClusterServiceVersion Troubleshooting 86 | 87 | ### How to debug a failing CSV 88 | 89 | If the OLM operator encounters an unrecoverable error when attempting to install the operator the `CSV` will be placed in the `failed` phase. The OLM operator will constantly update the `Status` with useful information regarding the state of the `CSV`. You can check the `Status` of your `CSV` with the following command: 90 | 91 | `$ kubectl -n my-catalogsource-namespace get csv prometheusoperator.0.32.0 -o yaml | yq r - status` 92 | 93 | >Note: It is possible that the Status is missing, which suggests that the OLM operator is encountering an issue when processing the `CSV` in a very early stage. You should respond by reviewing the logs of the OLM operator. 94 | 95 | You should typically pay special attention to the information within the `status.reason` and `status.message` fields. Please look in the [failed CSV reasons](#failed-csv-reasons) 96 | 97 | If the `Status` block does not provide enough information, check the [OLM operator's logs](#how-to-view-the-olm-operator-logs). 98 | 99 | ### Failed CSV Reasons 100 | 101 | #### Reason: NoOperatorGroup 102 | 103 | The `CSV` failed to install because it has been deployed in a namespace that does not include an `OperatorGroup`. For more information about `OperatorGroups` see [operator-scoping.md](operator-scoping.md). 104 | 105 | #### Reason: UnsupportedOperatorGroup 106 | 107 | The `CSV` is failing to install because it does not support he `OperatorGroup` defined in the namespace. For more information about `OperatorGroups` see [operator-scoping.md](operator-scoping.md). 108 | 109 | ### Failed CSV Messages 110 | 111 | #### Messages Ending with "field is immutable" 112 | 113 | The `CSV` is failing because its install strategy changes some immutable field of an existing `Deployment`. This usually happens on upgrade, after an operator author publishes a new version of the operator containing such a change. In this case, the issue can be resolved by publishing a new version of the operator that uses a different `Deployment` name, which will cause OLM to generate a completely new `Deployment` instead of attempting to patch any existing one. 114 | 115 | ## Debugging the OLM or Catalog operators 116 | 117 | ### How to enable verbose logging on the OLM and Catalog operators 118 | 119 | Both the OLM and Catalog operators have `-debug` flags available that display much more useful information when diagnosing a problem. If necessary, add this flag to their deployments and perform the action that is showing undersired behavior. 120 | 121 | ### How to view the Catalog operator logs 122 | 123 | To view the Catalog Operator logs, use the following commands: 124 | 125 | ```bash 126 | $ kubectl -n olm get pods 127 | NAME READY STATUS RESTARTS AGE 128 | catalog-operator-5bdc79c56b-zbqbl 1/1 Running 0 5m30s 129 | olm-operator-6999db5767-5r5zs 1/1 Running 0 5m31s 130 | operatorhubio-catalog-ltdlp 1/1 Running 0 5m28s 131 | packageserver-5c76df75bb-mq4qd 1/1 Running 0 5m26s 132 | 133 | $ kubectl -n olm logs catalog-operator-5bdc79c56b-zbqbl 134 | ... 135 | ``` 136 | 137 | ### How to view the OLM operator logs 138 | 139 | To view the OLM Operator logs, use the following commands: 140 | 141 | ```bash 142 | $ kubectl -n olm get pods 143 | NAME READY STATUS RESTARTS AGE 144 | catalog-operator-5bdc79c56b-zbqbl 1/1 Running 0 5m30s 145 | olm-operator-6999db5767-5r5zs 1/1 Running 0 5m31s 146 | operatorhubio-catalog-ltdlp 1/1 Running 0 5m28s 147 | packageserver-5c76df75bb-mq4qd 1/1 Running 0 5m26s 148 | 149 | $ kubectl -n olm logs olm-operator-6999db5767-5r5zs 150 | ... 151 | ``` 152 | -------------------------------------------------------------------------------- /docs/packaging-an-operator.md: -------------------------------------------------------------------------------- 1 | # How do I package an Operator for OLM? 2 | 3 | OLM requires you to provide metadata about your operator in order to ensure that it can be kept running safely on a cluster, and to provide information about how updates should be applied as you publish new versions of your operator. 4 | 5 | This is very similar to packaging software for a traditional operating system - think of the packaging step for OLM as the stage at which you make your `rpm`, `dep`, or `apk` bundle. 6 | 7 | ## Writing your Operator Manifests 8 | 9 | OLM uses an api called `ClusterServiceVersion` (CSV) to describe a single instance of a version of an operator. This is the main entrypoint for packaging an operator for OLM. 10 | 11 | There are two important ways to think about the CSV: 12 | 13 | 1. Like an `rpm` or `deb`, it collects metadata about the operator that is required to install it onto the cluster. 14 | 2. Like a `Deployment` that can stamp out `Pod`s from a template, the `ClusterServiceVersion` describes a template for the operator `Deployment` and can stamp them out. 15 | 16 | This is all in service of ensuring that when a user installs an operator from OLM, they can understand what changes are happening to the cluster, and OLM can ensure that installing the operator is a safe operation. 17 | 18 | ### Starting from an existing set of operator manifests 19 | 20 | For this example, we'll use the example manifests from [the example memcached operator](https://github.com/operator-framework/operator-sdk-samples/tree/master/go/memcached-operator/deploy). 21 | 22 | These manifests consist of: 23 | 24 | - **CRDs** that define the APIs your operator will manage 25 | - **Operator** (`operator.yaml`), containing the`Deployment` that runs your operator pods 26 | - **RBAC** (`role.yaml`, `role_binding.yaml`, `service_account.yaml`) that configures the service account permissions your operator requires. 27 | 28 | Building a minimal `ClusterServiceVersion` from these requires transplanting the contents of the Operator definition and the RBAC definitions into a CSV. Together, your CSV and CRDs will form the package that you give to OLM to install an operator. 29 | 30 | #### Basic Metadata (Optional) 31 | 32 | Let's start with a CSV that only contains some descriptive metadata: 33 | 34 | ```yaml 35 | apiVersion: operators.coreos.com/v1alpha1 36 | kind: ClusterServiceVersion 37 | metadata: 38 | annotations: 39 | name: memcached-operator.v0.10.0 40 | spec: 41 | description: This is an operator for memcached. 42 | displayName: Memcached Operator 43 | keywords: 44 | - memcached 45 | - app 46 | maintainers: 47 | - email: corp@example.com 48 | name: Some Corp 49 | maturity: alpha 50 | provider: 51 | name: Example 52 | url: www.example.com 53 | version: 0.10.0 54 | ``` 55 | 56 | Most of these fields are optional, but they provide an opportunity to describe your operator to potential or current users. 57 | 58 | #### Installation Metadata (Required) 59 | 60 | The next section to add to the CSV is the Install Strategy - this tells OLM about the runtime components of your operator and their requirements. 61 | 62 | Here is an example of the basic structure of an install strategy: 63 | 64 | ```yaml 65 | apiVersion: operators.coreos.com/v1alpha1 66 | kind: ClusterServiceVersion 67 | metadata: 68 | annotations: 69 | name: memcached-operator.v0.10.0 70 | spec: 71 | install: 72 | # strategy indicates what type of deployment artifacts are used 73 | strategy: deployment 74 | # spec for the deployment strategy is a list of deployment specs and required permissions - similar to a pod template used in a deployment 75 | spec: 76 | permissions: 77 | - serviceAccountName: memcached-operator 78 | rules: 79 | - apiGroups: 80 | - "" 81 | resources: 82 | - pods 83 | verbs: 84 | - '*' 85 | # the rest of the rules 86 | # permissions required at the cluster scope 87 | clusterPermissions: 88 | - serviceAccountName: memcached-operator 89 | rules: 90 | - apiGroups: 91 | - "" 92 | resources: 93 | - serviceaccounts 94 | verbs: 95 | - '*' 96 | # the rest of the rules 97 | deployments: 98 | - name: memcached-operator 99 | spec: 100 | replicas: 1 101 | # the rest of a deployment spec 102 | ``` 103 | 104 | `deployments` is an array - your operator may be composed of several seperate components that should all be deployed and versioned together. 105 | 106 | It's also important to tell OLM the ways in which your operator can be deployed, or its `installModes`. InstallModes indicate if your operator can be configured to watch, one, some, or all namespaces. Please see the [document on install modes]() and `OperatorGroups` for more information. 107 | 108 | ```yaml 109 | apiVersion: operators.coreos.com/v1alpha1 110 | kind: ClusterServiceVersion 111 | metadata: 112 | name: memcached-operator.v0.10.0 113 | spec: 114 | # ... 115 | installModes: 116 | - supported: true 117 | type: OwnNamespace 118 | - supported: true 119 | type: SingleNamespace 120 | - supported: false 121 | type: MultiNamespace 122 | - supported: true 123 | type: AllNamespaces 124 | ``` 125 | 126 | **Using `faq` to build an install strategy from an existing deployment and rbac** 127 | 128 | `faq` is a wrapper around `jq` that can handle multiple input and output formats, like the yaml we're working with now. The following example requires that [faq be installed](https://github.com/jzelinskie/faq#installation) and references [the example memcached operator](https://github.com/operator-framework/operator-sdk-samples/tree/master/go/memcached-operator/deploy). 129 | 130 | Here is a simple `faq` script that can generate an install strategy from a single deployment: 131 | 132 | ```sh 133 | $ faq -f yaml '{install: {strategy: "deployment", spec:{ deployments: [{name: .metadata.name, template: .spec }] }}}' operator.yaml 134 | ``` 135 | 136 | If you have an existing CSV `csv.yaml` (refer to the example from Basic Metadata) and you'd like to insert or update an install strategy from a deployment `operator.yaml`, a role `role.yaml`, and a service account `service_account.yaml`, that is also possible: 137 | 138 | ```sh 139 | $ faq -f yaml -o yaml --slurp '.[0].spec.install = {strategy: "deployment", spec:{ deployments: [{name: .[1].metadata.name, template: .[1].spec }], permissions: [{serviceAccountName: .[3].metadata.name, rules: .[2].rules }]}} | .[0]' csv.yaml operator.yaml role.yaml service_account.yaml 140 | ``` 141 | 142 | #### Defining APIs (Required) 143 | 144 | By definition, operators are programs that can talk to the Kubernetes API. Often, they are also programs that *extend* the Kubernetes API, by providing an interface via `CustomResourceDefinition`s or, less frequently, `APIService`s. 145 | 146 | ##### Owned APIs 147 | 148 | Exactly which APIs are used and which APIs are watched or owned is important metadata for OLM. OLM uses this information to determine if dependencies are met and ensure that no two operators fight over the same resources in a cluster. 149 | 150 | ```yaml 151 | apiVersion: operators.coreos.com/v1alpha1 152 | kind: ClusterServiceVersion 153 | metadata: 154 | name: memcached-operator.v0.10.0 155 | spec: 156 | # ... 157 | customresourcedefinitions: 158 | owned: 159 | # a list of CRDs that this operator owns 160 | # name is the metadata.name of the CRD 161 | - name: cache.example.com 162 | # version is the version of the CRD (one per entry) 163 | version: v1alpha1 164 | # spec.names.kind from the CRD 165 | kind: Memcached 166 | ``` 167 | 168 | ##### Required APIs 169 | 170 | Similarly, there is a section `spec.customresourcedefinitions.required`, where dependencies can be specified. The operators that provide those APIs will be discovered and installed by OLM if they have not been installed. 171 | 172 | ```yaml 173 | apiVersion: operators.coreos.com/v1alpha1 174 | kind: ClusterServiceVersion 175 | metadata: 176 | name: other-operator.v1.0 177 | spec: 178 | # ... 179 | customresourcedefinitions: 180 | required: 181 | # a list of CRDs that this operator requires 182 | - name: cache.example.com 183 | version: v1alpha1 184 | kind: Memcached 185 | ``` 186 | 187 | Dependency resolution and ownership is discussed more in depth in our [registry documentation](). 188 | 189 | ```yaml 190 | apiVersion: operators.coreos.com/v1alpha1 191 | kind: ClusterServiceVersion 192 | metadata: 193 | name: memcached-operator.v0.10.0 194 | spec: 195 | # ... 196 | customresourcedefinitions: 197 | owned: 198 | # a list of CRDs that this operator owns 199 | # name is the metadata.name of the CRD 200 | - name: cache.example.com 201 | # version is the version of the CRD (one per entry) 202 | version: v1alpha1 203 | # spec.names.kind from the CRD 204 | kind: Memcached 205 | ``` 206 | 207 | ##### NativeAPIs (recommended) 208 | 209 | There are often cases where you wish to depend on an API that is either provided natively by the platform (i.e. `Pod`) or sometimes by another operator that is outside the control of OLM. 210 | 211 | In those cases, those dependencies can be described in the CSV as well, via `nativeAPIs` 212 | 213 | ```yaml 214 | apiVersion: operators.coreos.com/v1alpha1 215 | kind: ClusterServiceVersion 216 | metadata: 217 | name: other-operator.v1.0 218 | spec: 219 | nativeAPIs: 220 | - group: "" 221 | version: v1 222 | kind: Pod 223 | ``` 224 | 225 | The absence of any required `nativeAPIs` from a cluster will pause the installation of the operator, and `OLM` will write a status into the `CSV` indicating the missing APIs. 226 | 227 | TODO: example status 228 | 229 | `nativeAPIs` is an optional field, but the more information you give OLM about the context in which your operator should be run, the more informed decisions OLM can make. 230 | 231 | ##### Extension apiservers and APIServices 232 | 233 | Please see the document on [extension apiservers]() if your operator does not rely on CRDs to provide its API. 234 | 235 | #### Operator SDK 236 | 237 | TODO: link to SDK csv generation 238 | 239 | #### Advanced and Optional features 240 | 241 | Please see the documentation for [advanced operator configuration]() which includes additional suggestions for further integration with OLM. 242 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------