Maestro leverages CloudEvents to transport Kubernetes resources to target clusters and relay the resource status back. These resources and their statuses are stored and updated in a database. The system is composed of two main parts: the Maestro server and the Maestro agent.
The Maestro Server includes various components to fulfill its functions, as illustrated in the diagram below.
To enable gRPC server-side TLS, specify your server cert and key with --grpc-tls-cert-file and --grpc-tls-key-file.
For authorization, the gRPC server uses a mock authorizer by default. To enable real authorization, set --grpc-authn-type to either mtls or token. Depending on the authorizer type, you will need to create authorization rule resources, which are standard Kubernetes RBAC resources.
- mTLS-Based Authorization
For mTLS-based authorization, specify the client CA file using --grpc-client-ca-file. The server will validate the client certificate against this CA.
Then create authorization rules based on the CN (Common Name) or O (Organization) in the client certificate, representing the user or group. For example, to allow the user "Alice" to publish and subscribe to the policy source, use the following Kubernetes RBAC configuration:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: policy-pub-sub
rules:
- nonResourceURLs:
- /sources/policy
verbs:
- pub
- sub
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: policy-pub-sub
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: policy-pub-sub
subjects:
- kind: User
name: Alice
apiGroup: rbac.authorization.k8s.ioOn the gRPC client side, configure the gRPC options with the client certificate and key files, as follows:
grpcOptions = grpcoptions.NewGRPCOptions()
grpcOptions.URL = grpcServerAddr
grpcOptions.CAFile = grpcServerCAFile
grpcOptions.ClientCertFile = grpcClientCertFile
grpcOptions.ClientKeyFile = grpcClientKeyFileThe grpcClientCertFile and grpcClientKeyFile should contain the certificate signed by the client CA. For the example above, the CN must be "Alice".
- Token-Based Authorization
For token-based authorization, the gRPC server authenticates the client using a Kubernetes service account token. The service account is expected to be created by the gRPC client.
Create authorization rules based on the service account associated with the token. For example, to allow the service account open-cluster-management/policy-controller to publish and subscribe to the policy source, use the following Kubernetes RBAC configuration:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: policy-pub-sub
rules:
- nonResourceURLs:
- /sources/policy
verbs:
- pub
- sub
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: policy-pub-sub
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: policy-pub-sub
subjects:
- kind: ServiceAccount
name: policy-controller
namespace: open-cluster-managementOn the gRPC client side, configure the gRPC options with the token file, as follows:
grpcOptions = grpcoptions.NewGRPCOptions()
grpcOptions.URL = grpcServerAddr
grpcOptions.CAFile = grpcServerCAFile
grpcOptions.TokenFile = grpcClientTokenFileThe grpcClientTokenFile stores the token for the corresponding service account. In the example above, it holds the token for the open-cluster-management/policy-controller service account.
- See this example for how to use the gRPC client to publish and subscribe to
CloudEvents. - See this example for how to use the
MaestroGRPCSourceWorkClientclient to publish and subscribe toManifestWorks.
-
The consumer (e.g., ClustersService) uses the
MaestroGRPCSourceWorkClientto create aManifestWork.{ "apiVersion": "work.open-cluster-management.io/v1", "kind": "ManifestWork", "metadata": { "name": "e44ec579-9646-549a-b679-db8d19d6da37", ... }, "spec": { "workload": { "manifests": [ { "kind": "Deployment", "apiVersion": "apps/v1", "metadata": { "name": "maestro-e2e-upgrade-test", "namespace": "default" }, ... } ] } } }The CS uses the
uuid.NewSHA1(uuid.NameSpaceOID, manifests[0].Name + manifests[0].Namespace + manifests[0].GVK)to generate theManifestWorkname. -
The
MaestroGRPCSourceWorkClientsends thisManifestWorkas aCloudEventto the Maestro server via gRPC.{ "source": "mw-client-example", "type": "io.open-cluster-management.works.v1alpha1.manifestbundles.spec.create_request", "datacontenttype": "application/json", "data": {...}, "metadata": "{\"name\":\"e44ec579-9646-549a-b679-db8d19d6da37\",\"uid\":\"55c61e54-a3f6-563d-9fec-b1fe297bdfdb\",...}", "resourceid": "55c61e54-a3f6-563d-9fec-b1fe297bdfdb", ... }- The
MaestroGRPCSourceWorkClientgenerates a UID (uuid.NewSHA1(uuid.NameSpaceOID, sourceID + manifestwork.GR + manifestwork.Namespace + manifestwork.Name)) for thisManifestWorkand set theCloudEventresourceidextension attribute to this UID.
- The
-
The Maestro server receives this
CloudEvent, creates a correspondingResourcerecord in its database.- Maestro server sets the
resourceidas theResourcerecord ID - Maestro server sets the
CloudEventas theResourcerecord payload
- Maestro server sets the
-
After persisting the record, the Maestro server publishes a CloudEvent representing the stored Resource to Maestro agent.
- Maestro server uses the
Resourcerecord ID as theManifestWorkname.
- Maestro server uses the
-
The Maestro agent receives this CloudEvent, converts it back into a
ManifestWork, and applies it to the target Kubernetes cluster. After applied, there is a corresponding appliedmanifestwork created on the agent side.
-
The Maestro agent watches applied manifest status changes.
-
The Maestro agent updates the corresponding ManifestWork status and publishes a CloudEvent representing it.
-
The Maestro server receives the ManifestWork status and updates the corresponding
Resourcerecord status in its database (Maestro server finds the corresponding Resource via CloudEvent resourceid). -
The Maestro server sends this update using a CloudEvent.
-
The MaestroGRPCSourceWorkClient receives this CloudEvent and converts it back to a ManifestWork.
-
The Consumer watches this updated ManifestWork.






