Publish Kubernetes Operator to OperatorHub
In this post I will show you how you can publish your operator to OperatorHub.
I assume you have a pre built and publised docker image with the operator in it.
Install requirement
brew install opm
brew install operator-sdk
Stucture
Your Operator submission can be formatted following the bundle
or packagemanifest
format. he packagemanifest
format is a legacy format which is kept for backwards compatibility only so I will use bundle
format.
tree OLM
OLM
└── 0.0.1
├── manifests
│ ├── trivy-operator.v0.0.1.clusterserviceversion.yaml
│ └── crds.yaml
└── metadata
└── annotations.yaml
Create clusterserviceversion
To add your operator to any of the supported platforms, you will need to submit metadata for your Operator to be used by the Operator Lifecycle Manager
(OLM). This is YAML file called ClusterServiceVersion
which contains references to all of the CRDs, RBAC rules, Deployment and container image needed to install and securely run your Operator.
nano OLM/0.0.1/manifests/trivy-operator.v0.0.1.clusterserviceversion.yaml
First start with a CSV that only contains some descriptive metadata:
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
annotations:
capabilities: Basic Install
description: Trivy Operator for scheduled imagescans and an Admission Control.
certified: "false"
containerImage: devopstales/trivy-operator:0.0.1
name: trivy-operator.v0.0.1
spec:
description: Trivy Operator for scheduled imagescans and an Admission Control.
displayName: Trivy Operator
keywords:
- "devops"
- "tales"
- trivy
- security
maintainers:
- email: devopstales@mydomain.intra
name: devopstales
maturity: alpha
provider:
name: Blog
url: devopstales.hithub.io
version: 0.10.0
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.
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
annotations:
# ...
name: trivy-operator.v0.0.1
spec:
install:
# ...
# strategy indicates what type of deployment artifacts are used
strategy: deployment
# spec for the deployment strategy is a list of deployment specs and required permissions - similar to a pod template used in a deployment
spec:
permissions:
- serviceAccountName: trivy-operator
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- '*'
# the rest of the rules
# permissions required at the cluster scope
clusterPermissions:
- serviceAccountName: trivy-operator
rules:
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- '*'
# the rest of the rules
deployments:
- name: trivy-operator
spec:
replicas: 1
# the rest of a deployment spec
For Openshift you can append SCC to the serviceaccount in the rules section
It’s also important to tell OLM the ways in which your operator can be deployed:
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
annotations:
# ...
name: trivy-operator.v0.0.1
spec:
# ...
installModes:
- supported: true
type: OwnNamespace
- supported: true
type: SingleNamespace
- supported: false
type: MultiNamespace
- supported: true
type: AllNamespaces
By definition, operators are programs that can talk to the Kubernetes API and they are also extend the Kubernetes API, by CustomResourceDefinitions
. Which APIs are watched or owned is important metadata for OLM so we need to define thease too.
apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
annotations:
# ...
alm-examples: |-
[
{
"apiVersion": "trivy-operator.devopstales.io/v1",
"kind": "NamespaceScanner",
"metadata": {
"name": "trivy-operator-main-config"
},
"spec": {
"crontab": "*/5 * * * *",
"namespace_selector": "trivy-scan",
"registry": [
{
"name": "docker.io",
"user": "",
"password": ""
}
]
}
}
]
name: trivy-operator.v0.0.1
spec:
spec:
# ...
customresourcedefinitions:
owned:
# a list of CRDs that this operator owns
# name is the metadata.name of the CRD
- name: namespace-scanners.trivy-operator.devopstales.io
# version is the version of the CRD (one per entry)
version: v1
# spec.names.kind from the CRD
kind: NamespaceScanner
You must place the CustomResourceDefinitions
to the manifests
folder andy any other object like service
what you want to deploy by the Operator Framework
. If you created your `` you can test with OperatorHub’s Operator Preview page.
Test operator
You can test your files with operator-sdk
locally:
operator-sdk bundle validate ./OLM/0.0.1 --select-optional suite=operatorframework
INFO[0000] All validation tests have completed successfully
Generate bundle
To test the functions all working correctly you need first to install the operator with Operato framework. To do so you need a build the bundle
image the the catalog index:
cd OML
opm alpha bundle build -c stable -d 0.0.1/manifests -t devopstales/trivy-operator-bundle:0.0.1 -p trivy-operator
docker push docker.io/devopstales/trivy-operator-bundle:0.0.1
opm index add -b docker.io/devopstales/trivy-operator-bundle:0.0.1 -t docker.io/devopstales/trivy-operator-index:0.0.1 -c docker
docker push docker.io/devopstales/trivy-operator-index:0.0.1
Install OML
To install the operator from your catalog index first you need to install the operator-lifecycle-manager
.
curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/v0.19.1/install.sh | bash -s v0.19.1
Add your index as CatalogSource
nano cs-trivy-operator.yaml
apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
name: devopstales-catalog
namespace: olm
spec:
displayName: devopstales
publisher: devopstales
sourceType: grpc
image: docker.io/devopstales/trivy-operator-index:0.0.1
updateStrategy:
registryPoll:
interval: 1m
kubectl apply -f cs-trivy-operator.yaml
kubectl get catalogsource --all-namespaces
NAMESPACE NAME DISPLAY TYPE PUBLISHER AGE
olm devopstales-catalog devopstales grpc devopstales 13m
olm operatorhubio-catalog Community Operators grpc OperatorHub.io 7h20m
kubectl get packagemanifest | grep trivy
trivy-operator devopstales 6h54m
Subscribe to this operator:
$ cat og.yaml
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: test-og
namespace: default
spec:
targetNamespaces:
- default
$ cat sub_devopstales-catalog.yaml
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: trivy-operator
namespace: default
spec:
channel: alpha
installPlanApproval: Automatic
name: trivy-operator
source: devopstales-catalog
sourceNamespace: olm
startingCSV: trivy-operator.v0.0.1
After create them, you will get the below objects:
$ oc get sub -n default
NAME PACKAGE SOURCE CHANNEL
trivy-operator trivy-operator devopstales-catalog alpha
$ oc get ip -n default
NAME CSV APPROVAL APPROVED
install-tvpq4 trivy-operator.v0.0.1 Automatic true
$ oc get csv -n default
NAME DISPLAY VERSION REPLACES PHASE
trivy-operator.v0.0.1 Trivy Operator 0.0.1 Succeeded
The you can create the Custo Resource to test the functionality.
Publicate operato on OperatoHub
To publish your bundled operator you need to create a pull requuest to the operatorhub community-operators repo or RedHat Opeshift community-operators repo.