Skip to content

Commit cb8d55a

Browse files
authoredJan 24, 2020
Merge pull request operator-framework#149 from kevinrizza/opm-docs
Add `opm` docs
2 parents 093283e + 86898f2 commit cb8d55a

File tree

2 files changed

+146
-50
lines changed

2 files changed

+146
-50
lines changed
 

‎README.md

+44-50
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Operator Registry runs in a Kubernetes or OpenShift cluster to provide operator
77

88
This project provides the following binaries:
99

10+
* `opm`, which generates and updates registry databases as well as the index images that encapsulate them.
1011
* `initializer`, which takes as an input a directory of operator manifests and outputs a sqlite database containing the same data for querying.
1112
* `registry-server`, which takes a sqlite database loaded with manifests, and exposes a gRPC interface to it.
1213
* `configmap-server`, which takes a kubeconfig and a configmap reference, and parses the configmap into the sqlite database before exposing it via the same interface as `registry-server`.
@@ -17,82 +18,75 @@ And libraries:
1718
* `pkg/api` - providing low-level client libraries for the gRPC interface exposed by `registry-server`.
1819
* `pkg/registry` - providing basic registry types like Packages, Channels, and Bundles.
1920
* `pkg/sqlite` - providing interfaces for building sqlite manifest databases from `ConfigMap`s or directories, and for querying an existing sqlite database.
21+
* `pkg/lib` - providing external interfaces for interacting with this project as an api that defines a set of standards for operator bundles and indexes.
22+
* `pkg/containertools` - providing an interface to interact with and shell out to common container tooling binaries (if installed on the environment)
2023

2124
# Manifest format
2225

2326

24-
We refer to a directory of files with one ClusterServiceVersion as a "bundle". A bundle is typically just a ClusterServiceVersion and the CRDs that define the owned APIs of the CSV, though additional objects may be included.
27+
We refer to a directory of files with one ClusterServiceVersion as a "bundle". A bundle typically includes a ClusterServiceVersion and the CRDs that define the owned APIs of the CSV in its manifest directory, though additional objects may be included. It also includes an annotations file in its metadata folder which defines some higher level aggregate data that helps to describe the format and package information about how the bundle should be added into an index of bundles.
2528

2629
```
2730
# example bundle
28-
0.6.1
29-
├── etcdcluster.crd.yaml
30-
└── etcdoperator.clusterserviceversion.yaml
31+
etcd
32+
├── manifests
33+
│ ├── etcdcluster.crd.yaml
34+
│ └── etcdoperator.clusterserviceversion.yaml
35+
└── metadata
36+
└── annotations.yaml
3137
```
3238

3339
When loading manifests into the database, the following invariants are validated:
3440

35-
* Every package has at least one channel
36-
* Every ClusterServiceVersion pointed to by a channel in a package exists
41+
* The bundle must have at least one channel defined in the annotations.
3742
* Every bundle has exactly one ClusterServiceVersion.
3843
* If a ClusterServiceVersion `owns` a CRD, that CRD must exist in the bundle.
39-
* If a ClusterServiceVersion `replaces` another, both the old and the new must exist in the package.
4044

4145
Bundle directories are identified solely by the fact that they contain a ClusterServiceVersion, which provides an amount of freedom for layout of manifests.
4246

43-
It's recommended to follow a layout that makes it clear which bundles are part of which package, as in [manifests](manifests):
47+
Check out the [operator bundle design](docs/design/operator-bundle.md) for more detail on the bundle format.
4448

49+
# Bundle images
50+
51+
Using [OCI spec](https://github.com/opencontainers/image-spec/blob/master/spec.md) container images as a method of storing the manifest and metadata contents of individual bundles, `opm` interacts directly with these images to generate and incrementally update the database. Once you have your [manifests defined](https://operator-framework.github.io/olm-book/docs/packaging-an-operator.html#writing-your-operator-manifests) and have created a directory in the format defined above, building the image is as simple as defining a [Dockerfile](docs/design/operator-bundle.md#Bundle-Dockerfile) and building that image:
52+
53+
54+
```sh
55+
podman build -t quay.io/my-container-registry-namespace/my-manifest-bundle:latest -f bundle.Dockerfile .
4556
```
46-
manifests
47-
├── etcd
48-
│   ├── 0.6.1
49-
│   │   ├── etcdcluster.crd.yaml
50-
│   │   └── etcdoperator.clusterserviceversion.yaml
51-
│   ├── 0.9.0
52-
│   │   ├── etcdbackup.crd.yaml
53-
│   │   ├── etcdcluster.crd.yaml
54-
│   │   ├── etcdoperator.v0.9.0.clusterserviceversion.yaml
55-
│   │   └── etcdrestore.crd.yaml
56-
│   ├── 0.9.2
57-
│   │   ├── etcdbackup.crd.yaml
58-
│   │   ├── etcdcluster.crd.yaml
59-
│   │   ├── etcdoperator.v0.9.2.clusterserviceversion.yaml
60-
│   │   └── etcdrestore.crd.yaml
61-
│   └── etcd.package.yaml
62-
└── prometheus
63-
├── 0.14.0
64-
│   ├── alertmanager.crd.yaml
65-
│   ├── prometheus.crd.yaml
66-
│   ├── prometheusoperator.0.14.0.clusterserviceversion.yaml
67-
│   ├── prometheusrule.crd.yaml
68-
│   └── servicemonitor.crd.yaml
69-
├── 0.15.0
70-
│   ├── alertmanager.crd.yaml
71-
│   ├── prometheus.crd.yaml
72-
│   ├── prometheusoperator.0.15.0.clusterserviceversion.yaml
73-
│   ├── prometheusrule.crd.yaml
74-
│   └── servicemonitor.crd.yaml
75-
├── 0.22.2
76-
│   ├── alertmanager.crd.yaml
77-
│   ├── prometheus.crd.yaml
78-
│   ├── prometheusoperator.0.22.2.clusterserviceversion.yaml
79-
│   ├── prometheusrule.crd.yaml
80-
│   └── servicemonitor.crd.yaml
81-
└── prometheus.package.yaml
57+
58+
Once you have built the container, you can publish it like any other container image:
59+
60+
```sh
61+
podman push quay.io/my-container-registry-namespace/my-manifest-bundle:latest
8262
```
8363

84-
# Building a catalog of Operators using `operator-registry`
64+
Of course, this build step can be done with any other OCI spec container tools like `docker`, `buildah`, `libpod`, etc.
65+
66+
# Building an index of Operators using `opm`
8567

86-
The [Dockerfile](upstream-example.Dockerfile) provides an example of using the `initializer` and `registry-server` to build a minimal container that provides a `gRPC` API over the example manifests in [manifests](manifests).
68+
Now that you have published the container image containing your manifests, how do you actually make that bundle available to other users' Kubernetes clusters so that the Operator Lifecycle Manager can install the operator? This is where the meat of the `operator-registry` project comes in. OLM has the concept of [CatalogSources](https://operator-framework.github.io/olm-book/docs/glossary.html#catalogsources) which define a reference to what packages are available to install onto a cluster. To make your bundle available, you can add the bundle to a container image which the CatalogSource points to. This image contains a database of pointers to bundle images that OLM can pull and extract the manifests from in order to install an operator. So, to make your operator available to OLM, you can generate an index image via opm with your bundle reference included:
8769

8870
```sh
89-
docker build -t example-registry:latest -f upstream-example.Dockerfile .
90-
docker push example-registry:latest
71+
opm index add --bundles quay.io/my-container-registry-namespace/my-manifest-bundle:0.0.1 --tag quay.io/my-container-registry-namespace/my-index:1.0.0
72+
podman push quay.io/my-container-registry-namespace/my-index:1.0.0
9173
```
9274

93-
# Using the catalog with Operator Lifecycle Manager
75+
The resulting image is referred to as an "Index". It is an image which contains a database of pointers to operator manifest content that is easily queriable via an included API that is served when the container image is run.
76+
77+
Now that image is available for clusters to use and reference with CatalogSources on their cluster.
78+
79+
Index images are additive, so you can add a new version of your operator bundle when you publish a new version:
80+
81+
```sh
82+
opm index add --bundles quay.io/my-container-registry-namespace/my-manifest-bundle:0.0.2 --from-index quay.io/my-container-registry-namespace/my-index:1.0.0 --tag quay.io/my-container-registry-namespace/my-index:1.0.1
83+
```
84+
85+
For more detail on using `opm` to generate index images, take a look at the [documentation](docs/design/opm-tooling.md).
86+
87+
# Using the index with Operator Lifecycle Manager
9488

95-
To add a catalog packaged with `operator-registry` to your cluster for use with [Operator Lifecycle Manager](https://github.com/operator-framework/operator-lifecycle-manager) (OLM) create a `CatalogSource` referencing the image you created and pushed above:
89+
To add an index packaged with `operator-registry` to your cluster for use with [Operator Lifecycle Manager](https://github.com/operator-framework/operator-lifecycle-manager) (OLM) create a `CatalogSource` referencing the image you created and pushed above:
9690

9791
```yaml
9892
apiVersion: operators.coreos.com/v1alpha1

‎docs/design/opm-tooling.md

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Operator Registry Tooling
2+
3+
When compiled, the `operator-registry` project results in a collection of tools that in aggregate define a way of packaging and delivering operator manifests to Kubernetes clusters. Historically, this is done with multiple tools. For example, you can use `initializer` to generate an immutable database and then use `registry-serve` to serve the database via an API. We have added the `opm` tool that aggregates these functions togeother and allows a user to interact with container images and tooling directly to generate and update registry databases in a mutable way.
4+
5+
The following document describes the tooling that `opm` provides along with descriptions of how to use them including each command's purpose, their inputs and outputs, and some examples.
6+
7+
## opm
8+
9+
`opm` (Operator Package Manager) is a tool that is used to generate and interact with operator-registry catalogs, both the underlying databases (generally referred to as the `registry`) and their images (the `index`). This is divided into two main commands: `registry` which is used to initialize, update and serve an API of the underlying database of manifests and references and `index` which is used to interact with an OCI container runtime to generate the registry database and package it in a container image.
10+
11+
### registry
12+
13+
`opm registry` generates and updates registry database objects.
14+
15+
#### add
16+
17+
First, let's look at adding a version of an operator bundle to a registry database. For example:
18+
19+
`opm registry add -b "quay.io/operator-framework/operator-bundle-prometheus:0.14.0" -d "test-registry.db"`
20+
21+
Dissecting this command, we called `opm registry add` to pull a container image that includes the manifests for the 0.14.0 version of the `prometheus` operator. We then unpacked those manifests from the container image and attempted to insert them into the registry database `test-registry.db`. Since that database file didn't currently exist on disk, the database was initialized first and then prometheus 0.14.0 was added to the empty database.
22+
23+
Now imagine that the 0.15.0 version of the `prometheus operator` was just released. We can add that operator to our existing database by calling add again and pointing to the new container image:
24+
25+
`opm registry add -b "quay.io/operator-framework/operator-bundle-prometheus:0.15.0" -d "test-registry.db"`
26+
27+
Great! The existing `test-registry.db` file is updated. Now we have a registry that contains two versions of the operator and defines an update graph that, when added to a cluster, will signal to the Operator Lifecycle Manager that if you have already installed version `0.14.0` that `0.15.0` can be used to upgrade your installation.
28+
29+
#### rm
30+
31+
`opm` also currently supports removing entire packages from a registry. For example:
32+
33+
`opm registry rm -o "prometheus" -d "test-registry.db"`
34+
35+
Calling this on our existing test registry removes all versions of the prometheus operator entirely from the database.
36+
37+
#### serve
38+
39+
`opm` also includes a command to connect to an existing database and serve a `gRPC` API that handles requests for data about the registry:
40+
41+
`opm registry serve -d "test-registry.db" -p 50051`
42+
43+
### index
44+
45+
`opm index` is, for the most part, a wrapper for `opm registry` that abstracts the underlying database interaction to instead make it easier to speak about the container images that are actually shipped to clusters directly. In particular, this makes it easy to say "given my operator index image, I want to add a new version of my operator and get an updated container image that I can automatically ship to clusters".
46+
47+
#### add
48+
49+
Index add works much the same way as registry add. For example:
50+
51+
`opm index add --bundles quay.io/operator-framework/operator-bundle-prometheus:0.14.0 --tag quay.io/operator-framework/monitoring-index:1.0.0`
52+
53+
Just like `opm registry add`, this command pulls a given container bundle and attempts to put it into a registry. The real difference is that the result is more than just a database file. By default, this command actually builds a container image and, looking at the `--tag` flag, will tag the output image as `quay.io/operator-framework/monitoring-index:1.0.0`. The resulting image has the database and the opm binary in it and, when run, calls the `registry serve` command on the database that was generated.
54+
55+
Just like registry add command, the updates are cumulative. In this case, rather than pointing at a database file, we can use the `--from-index` flag to specify a previous index to build off of a previous registry:
56+
57+
`opm index add --bundles quay.io/operator-framework/operator-bundle-prometheus:0.15.0 --from-index quay.io/operator-framework/monitoring:1.0.0 --tag quay.io/operator-framework/monitoring:1.0.1`
58+
59+
This results in a fresh image that includes the updated prometheus operator in the prometheus package's update graph.
60+
61+
At a high level, this command operates by wrapping `registry add` around some additional interaction with pulling and building container images. To that end, the last thing it does is actually shell out to a container CLI tool to build the resulting container (by default, `podman build`). It does this by generating a dockerfile and then passing that file to the shell command. For example:
62+
63+
```dockerfile
64+
FROM quay.io/operator-framework/upstream-registry-builder AS builder
65+
66+
FROM scratch
67+
LABEL operators.operatorframework.io.index.database.v1=./index.db
68+
COPY database ./
69+
COPY --from=builder /build/bin/opm /opm
70+
COPY --from=builder /bin/grpc_health_probe /bin/grpc_health_probe
71+
EXPOSE 50051
72+
ENTRYPOINT ["/opm"]
73+
CMD ["registry", "serve", "--database", "index.db"]
74+
```
75+
76+
Of note here is that we use a builder image to get the latest upstream released version of opm in order to call `opm registry serve` to host the gRPC API. If a developer or CI system would prefer to point to a different version of `opm` to serve their operator (perhaps one in a private release or a fork) then they just need to deliver their own version in a container and then use the `--binary-image` command. ex:
77+
78+
`opm index add --bundles quay.io/operator-framework/operator-bundle-prometheus:0.14.0 --tag quay.io/operator-framework/monitoring-index:1.0.0 --binary-image quay.io/$user/my-opm-source`
79+
80+
This will update the above dockerfile and replace the builder image with the image specified in the `--binary-image` flag.
81+
82+
We are aware of the fact that, in many cases, users will want to make other changes to this dockerfile (adding additional labels, adding other binaries for metrics, using a different port, etc.). For these more complex use cases, we have added the `--generate` and `--out-dockerfile` flags. Adding `--generate` will skip the container build command entirely and instead write a Dockerfile to the local filesystem. By default this file is called `index.Dockerfile` and is put in the directory you run `opm` from. If you want to rename this generated dockerfile and write it somewhere else, just specify the `--out-dockerfile` flag:
83+
84+
`opm index add --bundles quay.io/operator-framework/operator-bundle-prometheus:0.14.0 --generate --out-dockerfile "my.Dockerfile"`
85+
86+
Running this command will still generate the updated registry database, but it will store it locally and additionally write `my.Dockerfile` which can be modified as needed.
87+
88+
#### rm
89+
90+
Like `opm registry rm`, this command will remove all versions an entire operator package from the index and results in a container image that does not include that package. It supports virtually all of the same options and flags as `opm index add` with the exception of replacing `--bundles` with `--operators`. Ex:
91+
92+
`opm index rm --operators prometheus --tag quay.io/operator-framework/monitoring-index:1.0.2 --binary-image quay.io/$user/my-opm-source`
93+
94+
This will result in the tagged container image `quay.io/operator-framework/monitoring-index:1.0.2` with a registry that no longer contains the `prometheus` operator at all.
95+
96+
### Container Tooling
97+
98+
Of note, many of these commands require some form of shelling to common container tooling (in the general case at least to pull the bundle image and extract the contents to update the registry). By default, the container tool that `opm` shells to is [podman](https://podman.io/). However, we also support overriding this via the `--container-tool` flag in all of these commands:
99+
100+
`opm registry add -b "quay.io/operator-framework/operator-bundle-prometheus:0.14.0" -d "test-registry.db" --container-tool docker`
101+
102+
This will run `opm registry add` via the docker runtime.

0 commit comments

Comments
 (0)
Please sign in to comment.