Docs:
-
Operator SDK docs: https://sdk.operatorframework.io/docs/olm-integration/
-
OLM GitHub: https://github.com/operator-framework/operator-lifecycle-manager
On the top of the operator container image OLM integration requires two other images to be created:
-
Bundle: An installation package for the operator. It contains the required yaml files and meta information to install the Operator.
-
Catalog: An index of available bundle versions. It can be used in a CatalogSource resource to make a set of Operators available on a K8s cluster.
The Makefile
contains commands to create the required resources:
-
make bundle
: Generate manifest files required for a bundle. -
make bundle-build bundle-push
: Build and push the bundle container image. -
make catalog-build catalog-push
: Build and push the catalog container image.
OLM is expecting semantic versioning for the images, so make sure that the VERSION
make parameter is set accoringly like 0.1.2
.
First we need to generate the required filed for the bundle:
$ make bundle
...
Display name for the operator (required):
> BSzeti Memcached
Description for the operator (required):
> My Test Operator
Provider's name for the operator (required):
> myprovider
Any relevant URL for the provider name (optional):
> https://medium.com/@bszeti
Comma-separated list of keywords for your operator (required):
> memcached,example
Comma-separated list of maintainers and their emails (e.g. 'name1:email1, name2:email2') (required):
> bszeti:me@mycompany.com
...
INFO[0000] Creating bundle/metadata/annotations.yaml
INFO[0000] Creating bundle.Dockerfile
INFO[0000] Bundle metadata generated suceessfully
operator-sdk bundle validate ./bundle
INFO[0000] Found annotations file bundle-dir=bundle container-tool=docker
INFO[0000] Could not find optional dependencies file bundle-dir=bundle container-tool=docker
INFO[0000] All validation tests have completed successfully
The tasks runs a couple of steps:
-
Creates
config/manifests
directory to record the answers and a kustomize script to collects the required manifests for the deployment of the operator. -
Operator image url can be set in
IMG
parameter -
Create
bundle
directory to contain the resources required in the bundle image (using theconfig/manifests
dir to get CRD, SA, roles, etc…). Notebundle/manifests/memcached-operator.clusterserviceversion.yaml
with theClusterServiceVersion
that describes the operator’s metadata and also contains the permissions and deployment of the operator. -
Generate
bundle.Dockerfile
for the docker build
Note
|
Modify the generated content in |
Build and push the bundle image to an image registry:
$ make bundle-build bundle-push BUNDLE_IMG=quay.io/bszeti/memcached-operator-bundle:v0.0.1
For testing purpuses the bundle can be installed directly on a K8s cluster without building a Catalog image using operator-sdk run bundle…
. This creates a temporary Pod in the current namespace that acts as a catalog image (serving a catalog index having the bundle). It also installs the Operator using the bundle automatically, so the a Pod of our operator image should be running.
$ operator-sdk run bundle quay.io/bszeti/memcached-operator-bundle:v0.0.1
INFO[0014] Successfully created registry pod: quay-io-bszeti-memcached-operator-bundle-v0-0-1
INFO[0014] Created CatalogSource: memcached-operator-catalog
INFO[0014] OperatorGroup "operator-sdk-og" created
INFO[0015] Created Subscription: memcached-operator-v0-0-1-sub
INFO[0019] Approved InstallPlan install-zghhn for the Subscription: memcached-operator-v0-0-1-sub
INFO[0019] Waiting for ClusterServiceVersion "default/memcached-operator.v0.0.1" to reach 'Succeeded' phase
INFO[0019] Waiting for ClusterServiceVersion "default/memcached-operator.v0.0.1" to appear
INFO[0030] Found ClusterServiceVersion "default/memcached-operator.v0.0.1" phase: Pending
INFO[0032] Found ClusterServiceVersion "default/memcached-operator.v0.0.1" phase: Installing
INFO[0063] Found ClusterServiceVersion "default/memcached-operator.v0.0.1" phase: Succeeded
INFO[0063] OLM has successfully installed "memcached-operator.v0.0.1"
# Verify that the new temporary CatalogSource was created in the current namespace
$ oc get CatalogSource
NAME DISPLAY TYPE PUBLISHER AGE
memcached-operator-catalog memcached-operator grpc operator-sdk 1m
# Verify that the test catalog and operator Pod is running
oc get pods
NAME READY STATUS RESTARTS AGE
ac095a4638d1696a13777bac081eaa9a0acb339453c13aed762ffabf12ntg89 0/1 Completed 0 1m -> Job to create test catalog
quay-io-bszeti-memcached-operator-bundle-v0-0-1 1/1 Running 0 1m -> Test catalog
bszeti-operator-controller-manager-bb7984f77-gs7lc 1/1 Running 0 1m -> Operator
# Cleanup this test bundle deployment
$ operator-sdk cleanup memcached-operator
INFO[0002] subscription "memcached-operator-v0-0-1-sub" deleted
INFO[0002] clusterserviceversion "memcached-operator.v0.0.1" deleted
INFO[0002] catalogsource "memcached-operator-catalog" deleted
INFO[0002] operatorgroup "operator-sdk-og" deleted
INFO[0002] Operator "memcached-operator" uninstalled
A Catalog image that contains an index of different operator bunlde versions can be created with the make catalog-build catalog-push
command,that uses opm CLI (make sure to use a newer version on Mac).
$ make catalog-build catalog-push CATALOG_IMG=quay.io/bszeti/memcached-operator-catalog:v0.0.1
./bin/opm index add --container-tool docker --mode semver --tag quay.io/bszeti/memcached-operator-catalog:v0.0.1 --bundles quay.io/bszeti/memcached-operator-bundle:v0.0.1
INFO[0000] building the index bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0000] running /usr/local/bin/docker pull quay.io/bszeti/memcached-operator-bundle:v0.0.1 bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0001] running docker create bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0001] running docker cp bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0002] running docker rm bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0002] Could not find optional dependencies file file=bundle_tmp881324843/metadata load=annotations with=bundle_tmp881324843
INFO[0002] Could not find optional properties file file=bundle_tmp881324843/metadata load=annotations with=bundle_tmp881324843
INFO[0002] Generating dockerfile bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0002] writing dockerfile: index.Dockerfile827664081 bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0002] running docker build bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
INFO[0002] [docker build -f index.Dockerfile827664081 -t quay.io/bszeti/memcached-operator-catalog:v0.0.1 .] bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.1]"
/Library/Developer/CommandLineTools/usr/bin/make docker-push IMG=quay.io/bszeti/memcached-operator-catalog:v0.0.1
docker push quay.io/bszeti/memcached-operator-catalog:v0.0.1
...
The catalog can be added to a K8s cluster with a CatalogSource
resource (use namespace openshift-operators
to make it visible in the whole cluster):
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: bszeti-test-catalog
namespace: openshift-operators
spec:
sourceType: grpc
image: quay.io/bszeti/memcached-operator-catalog:v0.0.1
displayName: BSzeti Test Catalog
updateStrategy:
registryPoll:
interval: 10m0s
Aftewards we should see a Pod providing the catalog endpoint (port 50051) and a new Catalog with our operator versions to install (bundles).
A catalog can be extended by using the opm
tool. In this example we create catalog v1.0.0
by extending the earlier catalog v0.0.1
image with adding bundle version v0.0.2
and v0.0.3
.
$ export BUNDLE_IMGS=quay.io/bszeti/memcached-operator-bundle:v0.0.2,quay.io/bszeti/memcached-operator-bundle:v0.0.3
$ export CATALOG_BASE_IMG=quay.io/bszeti/memcached-operator-catalog:v0.0.1
$ make catalog-build catalog-push CATALOG_IMG=quay.io/bszeti/memcached-operator-catalog:v1.0.0
$ ./bin/opm index add --container-tool docker --mode semver --tag quay.io/bszeti/memcached-operator-catalog:v1.0.0 --bundles quay.io/bszeti/memcached-operator-bundle:v0.0.2,quay.io/bszeti/memcached-operator-bundle:v0.0.3 --from-index quay.io/bszeti/memcached-operator-catalog:v0.0.1
INFO[0000] building the index bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0000] Pulling previous image quay.io/bszeti/memcached-operator-catalog:v0.0.1 to get metadata bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0000] running /usr/local/bin/docker pull quay.io/bszeti/memcached-operator-catalog:v0.0.1 bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0001] running /usr/local/bin/docker pull quay.io/bszeti/memcached-operator-catalog:v0.0.1 bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0003] Getting label data from previous image bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0003] running docker inspect bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0003] running docker create bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0003] running docker cp bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0005] running docker rm bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0007] running /usr/local/bin/docker pull quay.io/bszeti/memcached-operator-bundle:v0.0.2 bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0009] running docker create bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0010] running docker cp bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0013] running docker rm bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0016] running /usr/local/bin/docker pull quay.io/bszeti/memcached-operator-bundle:v0.0.3 bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0019] running docker create bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0022] running docker cp bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0024] running docker rm bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0027] Could not find optional dependencies file file=bundle_tmp323266634/metadata load=annotations with=bundle_tmp323266634
INFO[0027] Could not find optional properties file file=bundle_tmp323266634/metadata load=annotations with=bundle_tmp323266634
INFO[0027] Could not find optional dependencies file file=bundle_tmp689119521/metadata load=annotations with=bundle_tmp689119521
INFO[0027] Could not find optional properties file file=bundle_tmp689119521/metadata load=annotations with=bundle_tmp689119521
INFO[0027] Generating dockerfile bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0027] writing dockerfile: index.Dockerfile077247320 bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0027] running docker build bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
INFO[0027] [docker build -f index.Dockerfile077247320 -t quay.io/bszeti/memcached-operator-catalog:v1.0.0 .] bundles="[quay.io/bszeti/memcached-operator-bundle:v0.0.2 quay.io/bszeti/memcached-operator-bundle:v0.0.3]"
$ make catalog-push CATALOG_IMG=quay.io/bszeti/memcached-operator-catalog:v1.0.0
Update the earlier CatalogSource to use the new image quay.io/bszeti/memcached-operator-catalog:v1.0.0
.
Note
|
The bundle’s version number must be changed in its ClusterServiceVersion ( |
The OLM UI will only show the latest version within each channel (alpha
by default) for the operator bundles indexed in the catalog, but it’s possible to install any operator (bundle) version from the index. For example:
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: memcached-operator
namespace: openshift-operators
spec:
channel: alpha
installPlanApproval: Manual
name: memcached-operator
source: bszeti-test-catalog
sourceNamespace: openshift-marketplace
startingCSV: memcached-operator.v0.0.1
Copy a secret from one namespace to another one. Convert kubernetes.io/dockercfg
secret to kubernetes.io/dockerconfigjson
.
PULL_SECRET=$(oc extract -n source-ns secret/dockercfg-secret --to=- --keys=".dockercfg")
REGISTRY_HOST=$( echo $PULL_SECRET | jq --raw-output 'keys[0] | ltrimstr("https://")')
echo $REGISTRY_HOST
REGISTRY_AUTH=$( echo $PULL_SECRET | jq '.[]' )
# Create kubernetes.io/dockercfg Secret
oc apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: dockercfg-secret
namespace: target-ns
type: kubernetes.io/dockercfg
stringData:
.dockercfg: '$PULL_SECRET'
EOF
# Create kubernetes.io/dockerconfigjson Secret
oc apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: dockerconfigjson-secret
namespace: target-ns
type: kubernetes.io/dockerconfigjson
stringData:
.dockerconfigjson: '{"auths":{"$REGISTRY_HOST": $REGISTRY_AUTH }}'
EOF