Skip to content

Commit 5c65c6b

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

4 files changed

Lines changed: 299 additions & 1 deletion

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`.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Ensure `clusteradm` CLI is installed and is newer than v0.3.0. Download and extr
3535

3636
```Shell
3737
# Deploy the configuration policy controller
38-
clusteradm addon enable addon --names config-policy-controller --clusters <cluster_name> --context ${CTX_HUB_CLUSTER}
38+
clusteradm addon enable --names config-policy-controller --clusters <cluster_name> --context ${CTX_HUB_CLUSTER}
3939
```
4040

4141
2. Ensure the pod is running on the managed cluster with the following command:
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
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 --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+
tolerations:
138+
- key: cluster.open-cluster-management.io/unreachable
139+
operator: Equal
140+
- key: cluster.open-cluster-management.io/unavailable
141+
operator: Equal
142+
```
143+
144+
2. Apply the policy to the hub cluster:
145+
146+
```Shell
147+
$ kubectl apply -n default -f policy-eso.yaml --context ${CTX_HUB_CLUSTER}
148+
policy.policy.open-cluster-management.io/policy-eso created
149+
placementbinding.policy.open-cluster-management.io/binding-policy-eso created
150+
placement.cluster.open-cluster-management.io/placement-policy-eso created
151+
```
152+
153+
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.
154+
155+
4. Verify the managed cluster is selected by the `Placement`:
156+
157+
```Shell
158+
$ kubectl get -n default placementdecision placement-policy-eso-decision-1 -o yaml --context ${CTX_HUB_CLUSTER}
159+
160+
...
161+
status:
162+
decisions:
163+
- clusterName: cluster1
164+
```
165+
166+
The output shows the managed cluster `cluster1` is selected.
167+
168+
5. Verify the Policy was propagated to the managed cluster:
169+
170+
```Shell
171+
$ kubectl get policy -A --context ${CTX_MANAGED_CLUSTER}
172+
NAMESPACE NAME REMEDIATION ACTION COMPLIANCE STATE AGE
173+
cluster1 default.policy-eso inform NonCompliant 11s
174+
```
175+
176+
6. The policy is `NonCompliant`. Inspect the policy status:
177+
178+
```Shell
179+
$ kubectl describe policy default.policy-eso --context ${CTX_MANAGED_CLUSTER} -n cluster1
180+
...
181+
Status:
182+
Compliant: NonCompliant
183+
Details:
184+
Compliant: NonCompliant
185+
History:
186+
Event Name: default.policy-eso.18ab8e1a8ff67343
187+
Last Timestamp: 2026-05-01T21:25:22Z
188+
Message: NonCompliant; the policy spec is valid, ... the Subscription required by the policy was not found ...
189+
```
190+
191+
The policy is in `NonCompliant` state because the external secrets operator was not found on the managed cluster in the `default` namespace.
192+
193+
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.
194+
195+
```Shell
196+
$ kubectl patch policy policy-eso -n default --context ${CTX_HUB_CLUSTER} --type=merge -p '{"spec": {"remediationAction": "enforce"}}'
197+
policy.policy.open-cluster-management.io/policy-eso patched
198+
```
199+
200+
8. Verify the external secrets operator subscription was created:
201+
202+
```Shell
203+
$ kubectl get subscription -n default --context ${CTX_MANAGED_CLUSTER}
204+
NAME PACKAGE SOURCE CHANNEL
205+
external-secrets-operator external-secrets-operator operatorhubio-catalog alpha
206+
```
207+
208+
The output shows the external secrets operator subscription is active.
209+
210+
9. Verify the external secrets operator deployment is running:
211+
212+
```Shell
213+
$ kubectl get deployment -n default --context ${CTX_MANAGED_CLUSTER}
214+
NAME READY UP-TO-DATE AVAILABLE AGE
215+
external-secrets-operator-controller-manager 1/1 1 1 10m
216+
```
217+
218+
The output shows the external secrets operator is deployed and running.
219+
220+
### Cleanup: Remove the example operator
221+
222+
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`.
223+
224+
1. Optional: edit the OperatorPolicy `spec.removalBehavior` to customize the objects to keep or delete. The default settings are:
225+
226+
```Yaml
227+
removalBehavior:
228+
clusterServiceVersions: Delete
229+
customResourceDefinitions: Keep
230+
subscriptions: Delete
231+
operatorGroups: DeleteIfUnused
232+
```
233+
234+
2. Edit the `complianceType` to `mustnothave` in the OperatorPolicy spec, then re-apply the policy:
235+
236+
```Yaml
237+
apiVersion: policy.open-cluster-management.io/v1
238+
kind: Policy
239+
metadata:
240+
name: policy-eso
241+
spec:
242+
remediationAction: enforce # Ensure remediationAction is set to `enforce`
243+
disabled: false
244+
policy-templates:
245+
- objectDefinition:
246+
apiVersion: policy.open-cluster-management.io/v1beta1
247+
kind: OperatorPolicy
248+
metadata:
249+
name: policy-eso
250+
spec:
251+
complianceType: mustnothave # Edit this line to `mustnothave`
252+
```
253+
254+
```Shell
255+
$ kubectl apply -n default -f policy-eso.yaml --context ${CTX_HUB_CLUSTER}
256+
policy.policy.open-cluster-management.io/policy-eso configured
257+
placementbinding.policy.open-cluster-management.io/binding-policy-eso unchanged
258+
placement.cluster.open-cluster-management.io/placement-policy-eso unchanged
259+
```
260+
261+
3. Verify the external secrets operator and all other objects created by the Policy were deleted in the managed cluster:
262+
263+
```Shell
264+
$ kubectl get deployment -n default --context ${CTX_MANAGED_CLUSTER}
265+
No resources found in default namespace.
266+
267+
$ kubectl get subscription -n default --context ${CTX_MANAGED_CLUSTER}
268+
No resources found in default namespace.
269+
270+
# repeat for other objects
271+
```
272+
273+
4. Delete the Policy on the hub cluster.
274+
275+
```Shell
276+
$ kubectl delete -n default policy policy-eso --context ${CTX_HUB_CLUSTER}
277+
policy.policy.open-cluster-management.io "policy-eso" deleted
278+
```
279+
280+
## Additional resources
281+
282+
- [Policy API Concepts]({{< ref "docs/getting-started/integration/policy-controllers/policy" >}})
283+
- [Policy Collection - Community examples](https://github.com/open-cluster-management-io/policy-collection)
284+
- [Operator Lifecycle Manager (OLM) documentation](https://olm.operatorframework.io/docs/)
285+
- [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)