Skip to content

Commit 933673b

Browse files
committed
docs: add operator policy guide
ref: https://redhat.atlassian.net/browse/ACM-10409 Signed-off-by: Janelle Law <jalaw@redhat.com>
1 parent a4c8ad9 commit 933673b

3 files changed

Lines changed: 293 additions & 0 deletions

File tree

content/en/docs/getting-started/integration/policy-controllers/_index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,9 @@ View the following sections to learn more about the Policy Add-on:
3434
Gatekeeper is a validating webhook with auditing capabilities that can enforce custom resource definition-based
3535
policies that are run with the Open Policy Agent (OPA). Gatekeeper `ConstraintTemplates` and constraints can be
3636
provided in an OCM `Policy` to sync to managed clusters that have Gatekeeper installed on them.
37+
38+
- #### [Operator policy]({{< ref "docs/getting-started/integration/policy-controllers/operator-policy" >}})
39+
40+
The `OperatorPolicy` is provided by OCM and defines a desired state for operators managed by Operator Lifecycle Manager (OLM)
41+
on managed clusters. It enables automated installation, configuration, and lifecycle management of operators across your
42+
cluster fleet using the same policy framework as `ConfigurationPolicy`.
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
---
2+
title: Operator Policy
3+
weight: 5
4+
hide_summary: true
5+
---
6+
7+
The `OperatorPolicy` defines a desired state for operators managed by the Operator Lifecycle Manager (OLM) on managed clusters. The Operator policy controller is provided by Open Cluster Management and runs on managed clusters as part of the `config-policy-controller` deployment.
8+
9+
View the [Policy API concepts]({{< ref "docs/getting-started/integration/policy-controllers/policy#managed-cluster-policy-controllers" >}}) page to learn more about the `OperatorPolicy` API.
10+
11+
## Prerequisites
12+
13+
You must meet the following prerequisites to use the Operator policy controller:
14+
15+
- Ensure [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl) and [`kustomize`](https://kubectl.docs.kubernetes.io/installation/kustomize/) are installed.
16+
17+
- Ensure [Golang](https://golang.org/doc/install) is installed, if you are planning to install from the source.
18+
19+
- Ensure the `open-cluster-management` _policy framework_ is installed. See [Policy Framework]({{< ref "docs/getting-started/integration/policy-controllers/policy-framework" >}}) for more information.
20+
21+
- Ensure Operator Lifecycle Manager (OLM) is installed on the managed clusters where you plan to deploy operators. See the [OLM Quick Start guide](https://olm.operatorframework.io/docs/getting-started/) for installation instructions.
22+
23+
## Installing the operator policy controller
24+
25+
The operator policy controller and the configuration policy controller run in the same `config-policy-controller` pod on managed clusters. The operator policy controller is disabled by default.
26+
27+
Steps 1 and 2 will install the configuration policy controller, matching the steps in [Installing the configuration policy controller]({{< ref "docs/getting-started/integration/policy-controllers/configuration-policy">}}).
28+
29+
If configuration policy controller is already installed, complete Step 3 onwards.
30+
31+
### Deploy via Clusteradm CLI
32+
33+
Ensure `clusteradm` CLI is installed and is newer than v0.3.0. Download and extract the [clusteradm binary](https://github.com/open-cluster-management-io/clusteradm/releases/latest). For more details see the [clusteradm GitHub page](https://github.com/open-cluster-management-io/clusteradm/blob/main/README.md#quick-start).
34+
35+
1. Deploy the configuration policy controller (which includes the operator policy controller) to the managed clusters:
36+
37+
```Shell
38+
$ clusteradm addon enable addon --names config-policy-controller --clusters <cluster_name> --context ${CTX_HUB_CLUSTER}
39+
Deploying config-policy-controller add-on to namespaces open-cluster-management-agent-addon of managed cluster: <cluster_name>
40+
```
41+
42+
2. Ensure the pod is running on the managed cluster with the following command:
43+
44+
```Shell
45+
$ kubectl get pods -n open-cluster-management-agent-addon --context ${CTX_MANAGED_CLUSTER}
46+
NAME READY STATUS RESTARTS AGE
47+
config-policy-controller-7f8fb64d8c-pmfx4 1/1 Running 0 44s
48+
```
49+
50+
3. To enable operator policy controller on managed cluster `cluster1`, annotate the ManagedClusterAddon in the hub cluster:
51+
52+
```Shell
53+
$ kubectl annotate -n cluster1 managedclusteraddon config-policy-controller operator-policy-disabled=false --context ${CTX_HUB_CLUSTER}
54+
managedclusteraddon.addon.open-cluster-management.io/config-policy-controller annotated
55+
```
56+
57+
4. On the managed cluster, confirm the operator policy controller was enabled by examining the `config-policy-controller` pod container arguments:
58+
59+
```Shell
60+
$ kubectl get pods -n open-cluster-management-agent-addon --context ${CTX_MANAGED_CLUSTER}
61+
NAME READY STATUS RESTARTS AGE
62+
config-policy-controller-5888b6cbc5-lvwdj 1/1 Running 0 30s
63+
64+
$ kubectl describe pod config-policy-controller-5888b6cbc5-lvwdj -n open-cluster-management-agent-addon --context ${CTX_MANAGED_CLUSTER} | grep enable-operator-policy
65+
- --enable-operator-policy=true
66+
```
67+
68+
## Sample operator policy
69+
70+
After a successful deployment, test the policy framework and operator policy controller with a sample policy.
71+
72+
For more information on how to use an `OperatorPolicy`, read the [Policy API concept section]({{< ref "docs/getting-started/integration/policy-controllers/policy-framework#policy" >}}).
73+
74+
### Example: Deploy an external secrets operator
75+
76+
The following example deploys an external secrets operator to a managed cluster using an `OperatorPolicy`. The ESO operator was chosen arbitrarily for the example.
77+
78+
1. Create a Policy in Inform mode to scan for an external secrets operator in managed cluster `cluster1` in the `default` namespace. The `Policy` remediation action of `inform` will override the remediation action of the `OperatorPolicy`:
79+
80+
```Yaml
81+
apiVersion: policy.open-cluster-management.io/v1
82+
kind: Policy
83+
metadata:
84+
name: policy-eso
85+
spec:
86+
remediationAction: inform
87+
disabled: false
88+
policy-templates:
89+
- objectDefinition:
90+
apiVersion: policy.open-cluster-management.io/v1beta1
91+
kind: OperatorPolicy
92+
metadata:
93+
name: policy-eso
94+
spec:
95+
remediationAction: inform
96+
severity: medium
97+
complianceType: musthave
98+
upgradeApproval: None
99+
operatorGroup:
100+
namespace: default
101+
name: external-secrets-operator-group
102+
targetNamespaces:
103+
- default
104+
subscription:
105+
namespace: default
106+
name: external-secrets-operator
107+
channel: alpha
108+
source: operatorhubio-catalog
109+
sourceNamespace: olm
110+
startingCSV: external-secrets-operator.v0.11.0
111+
versions:
112+
- external-secrets-operator.v0.11.0
113+
---
114+
apiVersion: policy.open-cluster-management.io/v1
115+
kind: PlacementBinding
116+
metadata:
117+
name: binding-policy-eso
118+
placementRef:
119+
name: placement-policy-eso
120+
kind: Placement
121+
apiGroup: cluster.open-cluster-management.io
122+
subjects:
123+
- name: policy-eso
124+
kind: Policy
125+
apiGroup: policy.open-cluster-management.io
126+
---
127+
apiVersion: cluster.open-cluster-management.io/v1beta1
128+
kind: Placement
129+
metadata:
130+
name: placement-policy-eso
131+
spec:
132+
predicates:
133+
- requiredClusterSelector:
134+
celSelector:
135+
celExpressions:
136+
- managedCluster.metadata.name == "cluster1"
137+
```
138+
139+
2. Apply the policy to the hub cluster:
140+
141+
```Shell
142+
$ kubectl apply -n default -f policy-eso.yaml --context ${CTX_HUB_CLUSTER}
143+
policy.policy.open-cluster-management.io/policy-eso created
144+
placementbinding.policy.open-cluster-management.io/binding-policy-eso created
145+
placement.cluster.open-cluster-management.io/placement-policy-eso created
146+
```
147+
148+
3. Ensure the `default` namespace has a `ManagedClusterSetBinding` for a `ManagedClusterSet` with at least one managed cluster resource. See [Bind ManagedClusterSet to a namespace]({{< ref "docs/concepts/cluster-inventory/managedclusterset#bind-managedclusterset-to-a-namespace" >}}) for more information.
149+
150+
4. Verify the managed cluster is selected by the `Placement`:
151+
152+
```Shell
153+
$ kubectl get -n default placementdecision placement-policy-eso-decision-1 -o yaml --context ${CTX_HUB_CLUSTER}
154+
155+
...
156+
status:
157+
decisions:
158+
- clusterName: cluster1
159+
```
160+
161+
The output shows the managed cluster `cluster1` is selected.
162+
163+
5. Verify the Policy was propagated to the managed cluster:
164+
165+
```Shell
166+
$ kubectl get policy -A --context ${CTX_MANAGED_CLUSTER}
167+
NAMESPACE NAME REMEDIATION ACTION COMPLIANCE STATE AGE
168+
cluster1 default.policy-eso inform NonCompliant 11s
169+
```
170+
171+
6. The policy is `NonCompliant`. Inspect the policy status:
172+
173+
```Shell
174+
$ kubectl describe policy default.policy-eso --context ${CTX_MANAGED_CLUSTER} -n cluster1
175+
...
176+
Status:
177+
Compliant: NonCompliant
178+
Details:
179+
Compliant: NonCompliant
180+
History:
181+
Event Name: default.policy-eso.18ab8e1a8ff67343
182+
Last Timestamp: 2026-05-01T21:25:22Z
183+
Message: NonCompliant; the policy spec is valid, ... the Subscription required by the policy was not found ...
184+
```
185+
186+
The policy is in `NonCompliant` state because the external secrets operator was not found on the managed cluster in the `default` namespace.
187+
188+
7. To automatically install the operator on the managed cluster, patch the policy remediation action to `enforce`. Note the top-level Policy remediation action `enforce` will override the OperatorPolicy remediation action.
189+
190+
```Shell
191+
$ kubectl patch policy policy-eso -n default --context ${CTX_HUB_CLUSTER} --type=merge -p '{"spec": {"remediationAction": "enforce"}}'
192+
policy.policy.open-cluster-management.io/policy-eso patched
193+
```
194+
195+
8. Verify the external secrets operator subscription was created:
196+
197+
```Shell
198+
$ kubectl get subscription -n default --context ${CTX_MANAGED_CLUSTER}
199+
NAME PACKAGE SOURCE CHANNEL
200+
external-secrets-operator external-secrets-operator operatorhubio-catalog alpha
201+
```
202+
203+
The output shows the external secrets operator subscription is active.
204+
205+
9. Verify the external secrets operator deployment is running:
206+
207+
```Shell
208+
$ kubectl get deployment -n default --context ${CTX_MANAGED_CLUSTER}
209+
NAME READY UP-TO-DATE AVAILABLE AGE
210+
external-secrets-operator-controller-manager 1/1 1 1 10m
211+
```
212+
213+
The output shows the external secrets operator is deployed and running.
214+
215+
### Cleanup: Remove the example operator
216+
217+
By default, the operator policy controller will delete most of the objects created by the policy when the OperatorPolicy `spec.complianceType` is changed to `mustnothave` AND the policy `remediationAction` is set to `enforce`.
218+
219+
1. Optional: edit the OperatorPolicy `spec.removalBehavior` to customize the objects to keep or delete. The default settings are:
220+
221+
```Yaml
222+
removalBehavior:
223+
clusterServiceVersions: Delete
224+
customResourceDefinitions: Keep
225+
subscriptions: Delete
226+
operatorGroups: DeleteIfUnused
227+
```
228+
229+
2. Edit the `complianceType` to `mustnothave` in the OperatorPolicy spec, then re-apply the policy:
230+
231+
```Yaml
232+
apiVersion: policy.open-cluster-management.io/v1
233+
kind: Policy
234+
metadata:
235+
name: policy-eso
236+
spec:
237+
remediationAction: enforce # Ensure remediationAction is set to `enforce`
238+
disabled: false
239+
policy-templates:
240+
- objectDefinition:
241+
apiVersion: policy.open-cluster-management.io/v1beta1
242+
kind: OperatorPolicy
243+
metadata:
244+
name: policy-eso
245+
spec:
246+
complianceType: mustnothave # Edit this line to `mustnothave`
247+
```
248+
249+
```Shell
250+
$ kubectl apply -n default -f policy-eso.yaml --context ${CTX_HUB_CLUSTER}
251+
policy.policy.open-cluster-management.io/policy-eso configured
252+
placementbinding.policy.open-cluster-management.io/binding-policy-eso unchanged
253+
placement.cluster.open-cluster-management.io/placement-policy-eso unchanged
254+
```
255+
256+
3. Verify the external secrets operator and all other objects created by the Policy were deleted in the managed cluster:
257+
258+
```Shell
259+
$ kubectl get deployment -n default --context ${CTX_MANAGED_CLUSTER}
260+
No resources found in default namespace.
261+
262+
$ kubectl get subscription -n default --context ${CTX_MANAGED_CLUSTER}
263+
No resources found in default namespace.
264+
265+
# repeat for other objects
266+
```
267+
268+
4. Delete the Policy on the hub cluster.
269+
270+
```Shell
271+
$ kubectl delete -n default policy policy-eso --context ${CTX_HUB_CLUSTER}
272+
policy.policy.open-cluster-management.io "policy-eso" deleted
273+
```
274+
275+
## Additional resources
276+
277+
- [Policy API Concepts]({{< ref "docs/getting-started/integration/policy-controllers/policy" >}})
278+
- [Policy Collection - Community examples](https://github.com/open-cluster-management-io/policy-collection)
279+
- [Operator Lifecycle Manager (OLM) documentation](https://olm.operatorframework.io/docs/)
280+
- [OperatorHub.io registry](https://operatorhub.io/)

content/en/docs/getting-started/integration/policy-controllers/policy.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ controller on the managed cluster. The policy framework supports delivering the
187187
the page on [Configuration Policy]({{< ref "docs/getting-started/integration/policy-controllers/configuration-policy" >}}) for more
188188
information.
189189

190+
- Operator policy
191+
192+
The `OperatorPolicy` is provided by OCM and defines a desired state for operators managed by Operator Lifecycle Manager (OLM)
193+
on managed clusters. It enables declarative lifecycle management of operators, including installation, configuration, upgrades,
194+
and removal across your cluster fleet. See the page on [Operator Policy]({{< ref "docs/getting-started/integration/policy-controllers/operator-policy" >}}) for more
195+
information.
196+
190197
- Open Policy Agent Gatekeeper
191198

192199
Gatekeeper is a validating webhook with auditing capabilities that can enforce custom resource definition-based

0 commit comments

Comments
 (0)