This gist demonstrates using
Red Hat OpenShift GitOps
(read: ArgoCD) with the policy framework in
Red Hat Advanced Cluster Management for Kubernetes
(RHACM, with a community at open-cluster-management.io). In particular it shows how the
OperatorPolicy
kind provides a more gitops-friendly surface for managing OLM operators, compared
to managing Subscriptions, ClusterServiceVersions, InstallPlans (and more) directly.
For more information on OperatorPolicy from a non-GitOps view, I have written a separate article: https://developers.redhat.com/articles/2024/08/08/getting-started-operatorpolicy.
Although this document will not cover how to install RHACM, it includes zz_gitops-policy.yaml
to
install the Openshift GitOps operator with the RHACM Policy Framework. The policy should work
out-of-the-box by directly applying it on the hub cluster, but it can also be copied into the Policy
"wizard" in the RHACM console and then customized to apply to specific clusters in the fleet.
Without modifications it will apply to all managed clusters.
After the operator installation is complete (gated by policy dependencies), the policy will also configure the ArgoCD object on the cluster to use healthchecks specific to the policy types, and will create a Role and RoleBinding so that ArgoCD can sync the policy types.
Those policies can be viewed and managed in ArgoCD by creating an Application like this:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: gitops-policy
namespace: openshift-gitops
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
directory:
include: zz_gitops-policy.yaml
jsonnet: {}
path: .
repoURL: https://gist.github.com/5b810888609e9dace5c63c443fee6ad9.git
targetRevision: HEAD
This Application is also a nice example of viewing RHACM resources in ArgoCD, since it includes many different types.
Ideally, installing an operator is as simple as creating a single subscription. We will use the quay operator as an example throughout this gist:
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: quay-operator
namespace: openshift-operators
spec:
channel: stable-3.11
installPlanApproval: Automatic
name: quay-operator
source: redhat-operators
sourceNamespace: openshift-marketplace
Warning
The actual functionality of the example operator installations has not been verified here, only that it appears to correctly install.
This Subscription will install the latest 3.11.z
version, and keep it automatically updated...
However, it is not possible in this resource to declare more specifically which exact version of the
operator we want to maintain on the cluster. There is the spec.startingCSV
, but this does not
control the current/active version of the operator. This subscription specifies Automatic
approval of future InstallPlans, and the only alternative is Manual
. The manual setting affects
all other operators in that namespace, and requires users to parse and approve InstallPlans that
are not predictably named.
One option for approving these InstallPlans is to periodically create a Job which can look up all InstallPlans and approve some or all. One implementation of this is at https://github.com/redhat-cop/gitops-catalog/tree/main/installplan-approver
Another option is to use OperatorPolicy, which became generally available in RHACM 2.11. To install
specifically the 3.11.1
version of the quay operator, and allow for controlled upgrades in the
future, you can create this OperatorPolicy:
apiVersion: policy.open-cluster-management.io/v1beta1
kind: OperatorPolicy
metadata:
name: quay-operator
namespace: local-cluster
spec:
complianceType: musthave
remediationAction: enforce
severity: high
subscription:
name: quay-operator
channel: stable-3.11
startingCSV: quay-operator.v3.11.1
upgradeApproval: Automatic
versions:
- quay-operator.v3.11.1
To follow along with this "demo", create an Application like this, with a pinned revision that can be updated to advance through the steps:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: quay-operator
namespace: openshift-gitops
spec:
destination:
server: https://kubernetes.default.svc
project: default
source:
directory:
include: quay-operator-policy.yaml
jsonnet: {}
path: .
repoURL: https://gist.github.com/5b810888609e9dace5c63c443fee6ad9.git
targetRevision: d28ee80edcf50420bc1cdb2aca16e297f36db57c
Thanks to the healthchecks we've configured, the application will report itself as Degraded while the operator is installing. Once that process is complete, it will become Healthy, and we can see more information in the health message:
# kubectl get application.argoproj -n openshift-gitops quay-operator
status:
resources:
- group: policy.open-cluster-management.io
health:
message: Compliant; the policy spec is valid, the policy does not specify an
OperatorGroup but one already exists in the namespace - assuming that OperatorGroup
is correct, the Subscription matches what is required by the policy, an InstallPlan
to update to [quay-operator.v3.11.4] is available for approval but approval
for [quay-operator.v3.11.4] is required, ClusterServiceVersion (quay-operator.v3.11.1)
- install strategy completed with no errors, there are CRDs present for the
operator, all operator Deployments have their minimum availability, CatalogSource
was found
status: Healthy
kind: OperatorPolicy
name: quay-operator
At the time of writing this, quay-operator.v3.11.4
was the latest version in the stable-3.11
channel, and OLM has prepared a new InstallPlan to upgrade to that version. The spec.versions
list
in the OperatorPolicy does not include that version as allowed, so the policy controller will not
approve that InstallPlan.
Tip
By default, the OperatorPolicy only reports the upgrade as available - the Policy is Compliant and
the Application is Healthy. The spec.complianceConfig.upgradesAvailable
field configures this
behavior: it can be set to NonCompliant
to make the Policy NonCompliant and the Application
Degraded, to draw extra attention to the situation.
Assuming the role of a responsible adminstrator, say we've noticed that an update is available, and we've confirmed that this new version will work on the cluster. Traditionally we would need to approve the InstallPlan, but the name of that resource will vary between clusters. With OperatorPolicy, we can simply add this version to the spec:
@@ -14,3 +14,4 @@ spec:
upgradeApproval: Automatic
versions:
- quay-operator.v3.11.1
+ - quay-operator.v3.11.4
The policy controller will then approve the InstallPlan (as long as it does not include any
unapproved updates to other operators) and the Application should become healthy again once the
new Deployment is available. Note that if there is a newer version available in the stable-3.11
channel, perhaps v3.11.5
, then this update will not approve the InstallPlan for that version.
Unfortunately, that means that the operator will remain at version v3.11.1
. To allow any version
on that channel, set the versions
field to an empty list, which provides a similar behavior to the
traditional installPlanApproval: Automatic
Subscription setting:
@@ -12,6 +12,4 @@ spec:
channel: stable-3.11
startingCSV: quay-operator.v3.11.1
upgradeApproval: Automatic
- versions:
- - quay-operator.v3.11.1
+ versions: []
If you're following along, you can update the quay-operator
Application to targetRevision
fa824a3408a0aec612cfb6dfca778e4e2b4394ed
to only allow v3.11.4
. Or, update to targetRevision
d502b05373ee78152e93262867b4a0a816258ba2
to allow all v3.11.z
versions.
As one other option, if we no longer wanted to allow the previous version - say it has some
vulnerability that we want to avoid - we could update the allowed versions
list to only include
the non-vulnerable version. The application would be marked as Degraded until a "good" version was
running.
Currently, the policy controller only handles OperatorPolicies created in the "managed cluster
namespace". This demo utilized the local-cluster
, which is the canonically correct namespace when
the hub is self-managed by RHACM. When deployed to other clusters, this field would need to be
customized. It might be possible with kustomization
, or the policy framework can be used to
distribute the policies, which will handle setting the correct namespace.
OperatorPolicy relies on the InstallPlans created by OLM, and so it can not orchestrate upgrades
to intermediate versions on the upgrade graph. For example, this demo upgraded from v3.11.1
to
v3.11.4
, since that was the tip of the upgrade graph at the time, and matched the InstallPlan in
the cluster. If the policy was instead set to allow version v3.11.3
, in this case the operator
would have remained at versions v3.11.1
.