github.com/operator-framework/operator-lifecycle-manager@v0.30.0/doc/design/building-your-csv.md (about)

     1  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
     2  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
     3  **Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*
     4  
     5  - [Building a Cluster Service Version (CSV) for the Operator Framework](#building-a-cluster-service-version-csv-for-the-operator-framework)
     6    - [What is a Cluster Service Version (CSV)?](#what-is-a-cluster-service-version-csv)
     7    - [CSV Metadata](#csv-metadata)
     8    - [Your Custom Resource Definitions](#your-custom-resource-definitions)
     9      - [Owned CRDs](#owned-crds)
    10      - [Required CRDs](#required-crds)
    11    - [CRD Templates](#crd-templates)
    12    - [Your API Services](#your-api-services)
    13      - [Owned APIServices](#owned-apiservices)
    14      - [APIService Resource Creation](#apiservice-resource-creation)
    15      - [APIService Serving Certs](#apiservice-serving-certs)
    16      - [Required APIServices](#required-apiservices)
    17    - [Operator Metadata](#operator-metadata)
    18    - [Operator Install](#operator-install)
    19    - [Full Examples](#full-examples)
    20  
    21  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
    22  
    23  # Building a Cluster Service Version (CSV) for the Operator Framework
    24  
    25  This guide is intended to guide an Operator author to package a version of their Operator to run with the [Operator Lifecycle Manager](https://github.com/operator-framework/operator-lifecycle-manager). This will be a manual method that will walk through each section of the file, what it’s used for and how to populate it.
    26  
    27  ## What is a Cluster Service Version (CSV)?
    28  
    29  A CSV is the metadata that accompanies your Operator container image. It can be used to populate user interfaces with info like your logo/description/version and it is also a source of technical information needed to run the Operator, like the RBAC rules it requires and which Custom Resources it manages or depends on.
    30  
    31  The Lifecycle Manager will parse this and do all of the hard work to wire up the correct Roles and Role Bindings, ensure that the Operator is started (or updated) within the desired namespace and check for various other requirements, all without the end users having to do anything.
    32  
    33  You can read about the [full architecture in more detail](architecture.md#what-is-a-clusterserviceversion).
    34  
    35  ## CSV Metadata
    36  
    37  The object has the normal Kubernetes metadata. Since the CSV pertains to the specific version, the naming scheme is the name of the Operator + the semantic version number, eg `mongodboperator.v0.3`.
    38  
    39  The namespace is used when a CSV will remain private to a specific namespace. Only users of that namespace will be able to view or instantiate the Operator. If you plan on distributing your Operator to many namespaces or clusters, you may want to explore bundling it into a [Catalog](architecture.md#catalog-registry-design).
    40  
    41  The namespace listed in the CSV within a catalog is actually a placeholder, so it is common to simply list `placeholder`. Otherwise, loading a CSV directly into a namespace requires that namespace, of course.
    42  
    43  ```yaml
    44  apiVersion: operators.coreos.com/v1alpha1
    45  kind: ClusterServiceVersion
    46  metadata:
    47    name: mongodboperator.v0.3
    48    namespace: placeholder
    49  ```
    50  
    51  ## Your Custom Resource Definitions
    52  There are two types of CRDs that your Operator may use, ones that are “owned” by it and ones that it depends on, which are “required”.
    53  ### Owned CRDs
    54  
    55  The CRDs owned by your Operator are the most important part of your CSV. This establishes the link between your Operator and the required RBAC rules, dependency management and other under-the-hood Kubernetes concepts.
    56  
    57  It’s common for your Operator to use multiple CRDs to link together concepts, such as top-level database configuration in one object and a representation of replica sets in another. List out each one in the CSV file.
    58  
    59  **DisplayName**: A human readable version of your CRD name, eg. “MongoDB Standalone”
    60  
    61  **Description**: A short description of how this CRD is used by the Operator or a description of the functionality provided by the CRD.
    62  
    63  **Group**: The API group that this CRD belongs to, eg. database.example.com
    64  
    65  **Kind**: The machine readable name of your CRD
    66  
    67  **Name**: The full name of your CRD
    68  
    69  The next two sections require more explanation.
    70  
    71  **Resources**:
    72  Your CRDs will own one or more types of Kubernetes objects. These are listed in the resources section to inform your end-users of the objects they might need to troubleshoot or how to connect to the application, such as the Service or Ingress rule that exposes a database.
    73  
    74  It’s recommended to only list out the objects that are important to a human, not an exhaustive list of everything you orchestrate. For example, ConfigMaps that store internal state that shouldn’t be modified by a user shouldn’t appear here.
    75  
    76  **SpecDescriptors, StatusDescriptors, and ActionDescriptors**:
    77  These are a way to hint UIs with certain inputs or outputs of your Operator that are most important to an end user. If your CRD contains the name of a Secret or ConfigMap that the user must provide, you can specify that here. These items will be linked and highlighted in compatible UIs.
    78  
    79  There are three types of descriptors:
    80  
    81  ***SpecDescriptors***: A reference to fields in the `spec` block of an object.
    82  
    83  ***StatusDescriptors***: A reference to fields in the `status` block of an object.
    84  
    85  ***ActionDescriptors***: A reference to actions that can be performed on an object.
    86  
    87  All Descriptors accept the following fields:
    88  
    89  **DisplayName**: A human readable name for the Spec, Status, or Action.
    90  
    91  **Description**: A short description of the Spec, Status, or Action and how it is used by the Operator.
    92  
    93  **Path**: A dot-delimited path of the field on the object that this descriptor describes.
    94  
    95  **X-Descriptors**: Used to determine which "capabilities" this descriptor has and which UI component to use. A canonical list of React UI X-Descriptors for OpenShift can be found [here](https://github.com/openshift/console/blob/master/frontend/packages/operator-lifecycle-manager/src/components/descriptors/types.ts).
    96  
    97  More information on Descriptors can be found [here](https://github.com/openshift/console/tree/master/frontend/packages/operator-lifecycle-manager/src/components/descriptors).
    98  
    99  Below is an example of a MongoDB “standalone” CRD that requires some user input in the form of a Secret and ConfigMap, and orchestrates Services, StatefulSets, Pods and ConfigMaps.
   100  
   101  ```yaml
   102        - displayName: MongoDB Standalone
   103          group: mongodb.com
   104          kind: MongoDbStandalone
   105          name: mongodbstandalones.mongodb.com
   106          resources:
   107            - kind: Service
   108              name: ''
   109              version: v1
   110            - kind: StatefulSet
   111              name: ''
   112              version: v1beta2
   113            - kind: Pod
   114              name: ''
   115              version: v1
   116            - kind: ConfigMap
   117              name: ''
   118              version: v1
   119          specDescriptors:
   120            - description: Credentials for Ops Manager or Cloud Manager.
   121              displayName: Credentials
   122              path: credentials
   123              x-descriptors:
   124                - 'urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Secret'
   125            - description: Project this deployment belongs to.
   126              displayName: Project
   127              path: project
   128              x-descriptors:
   129                - 'urn:alm:descriptor:com.tectonic.ui:selector:core:v1:ConfigMap'
   130            - description: MongoDB version to be installed.
   131              displayName: Version
   132              path: version
   133              x-descriptors:
   134                - 'urn:alm:descriptor:com.tectonic.ui:label'
   135          statusDescriptors:
   136            - description: The status of each of the Pods for the MongoDB cluster.
   137              displayName: Pod Status
   138              path: pods
   139              x-descriptors:
   140                - 'urn:alm:descriptor:com.tectonic.ui:podStatuses'
   141          version: v1
   142          description: >-
   143            MongoDB Deployment consisting of only one host. No replication of
   144            data.
   145  ```
   146  
   147  ### Required CRDs
   148  
   149  Relying on other “required” CRDs is completely optional and only exists to reduce the scope of individual Operators and provide a way to compose multiple Operators together to solve an end-to-end use case. An example of this is an Operator that might set up an application and install an etcd cluster (from an etcd Operator) to use for distributed locking and a Postgres database (from a Postgres Operator) for data storage.
   150  
   151  The Lifecycle Manager will check against the available CRDs and Operators in the cluster to fulfill these requirements. If suitable versions are found, the Operators will be started within the desired namespace and a Service Account created for each Operator to create/watch/modify the Kubernetes resources required.
   152  
   153  **Name**: The full name of the CRD you require
   154  
   155  **Version**: The version of that object API
   156  
   157  **Kind**: The Kubernetes object kind
   158  
   159  **DisplayName**: A human readable version of the CRD
   160  
   161  **Description**: A summary of how the component fits in your larger architecture
   162  
   163  ```yaml
   164      required:
   165      - name: etcdclusters.etcd.database.coreos.com
   166        version: v1beta2
   167        kind: EtcdCluster
   168        displayName: etcd Cluster
   169        description: Represents a cluster of etcd nodes.
   170  ```
   171  ## CRD Templates
   172  Users of your Operator will need to be aware of which options are required vs optional. You can provide templates for each of your CRDs with a minimum set of configuration as an annotation named `alm-examples`. Metadata for each template, for example an expanded description, can be included in an annotation named `alm-examples-metadata`, which should be a hash indexed with the `metadata.name` of the example in the `alm-examples` list. Compatible UIs will pre-enter the `alm-examples` template for users to further customize, and use the `alm-examples-metadata` to help users decide which template to select.
   173  
   174  The annotation consists of a list of the `kind`, eg. the CRD name, and the corresponding `metadata` and `spec` of the Kubernetes object. Here’s a full example that provides templates for `EtcdCluster`, `EtcdBackup` and `EtcdRestore`:
   175  
   176  ```yaml
   177  metadata:
   178    annotations:
   179      alm-examples-metadata: >-
   180        {"example-etcd-cluster":{"description":"Example EtcdCluster CR"},"example-etcd-restore":{"description":"Example EtcdRestore CR that restores data from S3"},"example-etcd-backup":{"description":"Example EtcdBackup CR that stores backups on S3"}}
   181      alm-examples: >-
   182        [{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example-etcd-cluster","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-restore"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"<full-s3-path>","awsSecret":"<aws-secret>"}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-backup"},"spec":{"etcdEndpoints":["<etcd-cluster-endpoints>"],"storageType":"S3","s3":{"path":"<full-s3-path>","awsSecret":"<aws-secret>"}}}]
   183  ```
   184  
   185  ## Your API Services
   186  As with CRDs, there are two types of APIServices that your Operator may use, “owned” and "required".
   187  
   188  ### Owned APIServices
   189  
   190  When a CSV owns an APIService, it is responsible for describing the deployment of the extension api-server that backs it and the group-version-kinds it provides.
   191  
   192  An APIService is uniquely identified by the group-version it provides and can be listed multiple times to denote the different kinds it is expected to provide.
   193  
   194  **DisplayName**: A human readable version of your APIService name, eg. “MongoDB Standalone”
   195  
   196  **Description**: A short description of how this APIService is used by the Operator or a description of the functionality provided by the APIService.
   197  
   198  **Group**: Group that the APIService provides, eg. database.example.com.
   199  
   200  **Version**: Version of the APIService, eg v1alpha1
   201  
   202  **Kind**: A kind that the APIService is expected to provide.
   203  
   204  **DeploymentName**:
   205  Name of the deployment defined by your CSV that corresponds to your APIService (required for owned APIServices). During the CSV pending phase, the OLM Operator will search your CSV's InstallStrategy for a deployment spec with a matching name, and if not found, will not transition the CSV to the install ready phase.
   206  
   207  **Resources**:
   208  Your APIServices will own one or more types of Kubernetes objects. These are listed in the resources section to inform your end-users of the objects they might need to troubleshoot or how to connect to the application, such as the Service or Ingress rule that exposes a database.
   209  
   210  It’s recommended to only list out the objects that are important to a human, not an exhaustive list of everything you orchestrate. For example, ConfigMaps that store internal state that shouldn’t be modified by a user shouldn’t appear here.
   211  
   212  **SpecDescriptors, StatusDescriptors, and ActionDescriptors**:
   213  Essentially the same as for owned CRDs.
   214  
   215  ### APIService Resource Creation
   216  The Lifecycle Manager is responsible for creating or replacing the Service and APIService resources for each unique owned APIService.
   217  * Service pod selectors are copied from the CSV deployment matching the APIServiceDescription's DeploymentName.
   218  * A new CA key/cert pair is generated for for each installation and the base64 encoded CA bundle is embedded in the respective APIService resource.
   219  
   220  ### APIService Serving Certs
   221  The Lifecycle Manager handles generating a serving key/cert pair whenever an owned APIService is being installed. The serving cert has a CN containing the host name of the generated Service resource and is signed by the private key of the CA bundle embedded in the corresponding APIService resource. The cert is stored as a type `kubernetes.io/tls` Secret in the deployment namespace and a Volume named "apiservice-cert" is automatically appended to the Volumes section of the deployment in the CSV matching the APIServiceDescription's `DeploymentName` field. If one does not already exist, a VolumeMount with a matching name is also appended to all containers of that deployment. This allows users to define a VolumeMount with the expected name to accommodate any custom path requirements. The generated VolumeMount's path defaults to `/apiserver.local.config/certificates` and any existing VolumeMounts with the same path are replaced.
   222  
   223  ### Required APIServices
   224  
   225  The Lifecycle Manager will ensure all required CSVs have an APIService that is available and all expected group-version-kinds are discoverable before attempting installation. This allows a CSV to rely on specific kinds provided by APIServices it does not own.
   226  
   227  **DisplayName**: A human readable version of your APIService name, eg. “MongoDB Standalone”
   228  
   229  **Description**: A short description of how this APIService is used by the Operator or a description of the functionality provided by the APIService.
   230  
   231  **Group**: Group that the APIService provides, eg. database.example.com.
   232  
   233  **Version**: Version of the APIService, eg v1alpha1
   234  
   235  **Kind**: A kind that the APIService is expected to provide.
   236  
   237  ## Operator Metadata
   238  The metadata section contains general metadata around the name, version and other info that aids users in discovery of your Operator.
   239  
   240  **DisplayName**: Human readable name that describes your Operator and the CRDs that it implements
   241  
   242  **Keywords**: A list of categories that your Operator falls into. Used for filtering within compatible UIs.
   243  
   244  **Provider**: The name of the publishing entity behind the Operator
   245  
   246  **Maturity**: Level of maturity the Operator has achieved at this version, eg. planning, pre-alpha, alpha, beta, stable, mature, inactive, or deprecated.
   247  
   248  **Version**: The semanic version of the Operator. This value should be incremented each time a new Operator image is published.
   249  
   250  **Icon**: a base64 encoded image of the Operator logo or the logo of the publisher. The `base64data` parameter contains the data and the `mediatype` specifies the type of image, eg. `image/png` or `image/svg+xml`.
   251  
   252  **Links**: A list of relevant links for the Operator. Common links include documentation, how-to guides, blog posts, and the company homepage.
   253  
   254  **Maintainers**: A list of names and email addresses of the maintainers of the Operator code. This can be a list of individuals or a shared email alias, eg. support@example.com.
   255  
   256  **Description**: A markdown blob that describes the Operator. Important information to include: features, limitations and common use-cases for the Operator. If your Operator manages different types of installs, eg. standalone vs clustered, it is useful to give an overview of how each differs from each other, or which ones are supported for production use.
   257  
   258  **MinKubeVersion**: A minimum version of Kubernetes that server is supposed to have so operator(s) can be deployed. The Kubernetes version must be in "Major.Minor.Patch" format (e.g: 1.11.0).
   259  
   260  **Labels** (optional): Any key/value pairs used to organize and categorize this CSV object.
   261  
   262  **Selectors** (optional): A label selector to identify related resources. Set this to select on current labels applied to this CSV object (if applicable).
   263  
   264  **InstallModes**: A set of `InstallMode`s that tell OLM which `OperatorGroup`s an Operator can belong to. Belonging to an `OperatorGroup` means that OLM provides the set of targeted namespaces as an annotation on the Operator's CSV and any deployments defined therein. These deployments can then utilize [the Downward API](https://kubernetes.io/docs/tasks/inject-data-application/downward-api-volume-expose-pod-information/#the-downward-api) to inject the list of namespaces into their container(s). An `InstallMode` consists of an `InstallModeType` field and a boolean `Supported` field. There are four `InstallModeTypes`:
   265  * `OwnNamespace`: If supported, the operator can be a member of an `OperatorGroup` that selects its own namespace
   266  * `SingleNamespace`: If supported, the operator can be a member of an `OperatorGroup` that selects one namespace
   267  * `MultiNamespace`: If supported, the operator can be a member of an `OperatorGroup` that selects more than one namespace
   268  * `AllNamespaces`: If supported, the operator can be a member of an `OperatorGroup` that selects all namespaces (target namespace set is the empty string "")
   269  
   270  Here's an example:
   271  
   272  ```yaml
   273     keywords: ['etcd', 'key value', 'database', 'coreos', 'open source']
   274     version: 0.9.2
   275     maturity: alpha
   276     replaces: etcdoperator.v0.9.0
   277     maintainers:
   278     - name: CoreOS, Inc
   279       email: support@coreos.com
   280     provider:
   281       name: CoreOS, Inc
   282     labels:
   283       alm-owner-etcd: etcdoperator
   284       operated-by: etcdoperator
   285     selector:
   286       matchLabels:
   287         alm-owner-etcd: etcdoperator
   288         operated-by: etcdoperator
   289     links:
   290     - name: Blog
   291       url: https://coreos.com/etcd
   292     - name: Documentation
   293       url: https://coreos.com/operators/etcd/docs/latest/
   294     - name: etcd Operator Source Code
   295       url: https://github.com/coreos/etcd-operator
   296     icon:
   297     - base64data: <base64-encoded-data>
   298       mediatype: image/png
   299     installModes:
   300     - type: OwnNamespace
   301       supported: true
   302     - type: SingleNamespace
   303       supported: true
   304     - type: MultiNamespace
   305       supported: false
   306     - type: AllNamespaces
   307       supported: true
   308  ```
   309  
   310  ## Operator Install
   311  The install block is how the Lifecycle Manager will instantiate the Operator on the cluster. There are two subsections within install: one to describe the `deployment` that will be started within the desired namespace and one that describes the Role `permissions` required to successfully run the Operator.
   312  
   313  Ensure that the `serviceAccountName` used in the `deployment` spec matches one of the Roles described under `permissions`.
   314  
   315  Multiple Roles should be described to reduce the scope of any actions needed containers that the Operator may run on the cluster. For example, if you have a component that generates a TLS Secret upon start up, a Role that allows `create` but not `list` on Secrets is more secure than using a single all-powerful Service Account.
   316  
   317  It is also possible to set custom labels for Deployment in addition to the system labels set by the OLM. This labels should be present in the `label` fields of the `deployments` section.  
   318  
   319  Here’s a full example:
   320  
   321  ```yaml
   322    install:
   323      spec:
   324        deployments:
   325          - name: example-operator
   326            label:
   327              application: example-operator
   328              technology: general
   329            spec:
   330              replicas: 1
   331              selector:
   332                matchLabels:
   333                  k8s-app: example-operator
   334              template:
   335                metadata:
   336                  labels:
   337                    k8s-app: example-operator
   338                spec:
   339                  containers:
   340                      image: 'quay.io/example/example-operator:v0.0.1'
   341                      imagePullPolicy: Always
   342                      name: example-operator
   343                      resources:
   344                        limits:
   345                          cpu: 200m
   346                          memory: 100Mi
   347                        requests:
   348                          cpu: 100m
   349                          memory: 50Mi
   350                  imagePullSecrets:
   351                    - name: ''
   352                  nodeSelector:
   353                    kubernetes.io/os: linux
   354                  serviceAccountName: example-operator
   355        permissions:
   356          - serviceAccountName: example-operator
   357            rules:
   358              - apiGroups:
   359                  - ''
   360                resources:
   361                  - configmaps
   362                  - secrets
   363                  - services
   364                verbs:
   365                  - get
   366                  - list
   367                  - create
   368                  - update
   369                  - delete
   370              - apiGroups:
   371                  - apps
   372                resources:
   373                  - statefulsets
   374                verbs:
   375                  - '*'
   376              - apiGroups:
   377                  - apiextensions.k8s.io
   378                resources:
   379                  - customresourcedefinitions
   380                verbs:
   381                  - get
   382                  - list
   383                  - watch
   384                  - create
   385                  - delete
   386              - apiGroups:
   387                  - mongodb.com
   388                resources:
   389                  - '*'
   390                verbs:
   391                  - '*'
   392          - serviceAccountName: example-operator-list
   393            rules:
   394              - apiGroups:
   395                  - ''
   396                resources:
   397                  - services
   398                verbs:
   399                  - get
   400                  - list
   401      strategy: deployment
   402  ```
   403  
   404  ## Full Examples
   405  
   406  Several [complete examples of CSV files](https://github.com/operator-framework/community-operators) are stored in Github.