From 4914f5298237b46e6d26ff4ed1b157cf1645325a Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 7 Sep 2026 11:02:06 +0200 Subject: [PATCH 1/3] fix: add Redis egress NP and allow metrics from openshift-user-workload-monitoring Add allow-redis-egress NetworkPolicy (port 6379, broad; no pod/namespace selector) for production Redis caching. Redis is part of the recommended checklist for production deployments but is not deployed OOTB; users bring their own in any namespace or as an external managed service. Also add openshift-user-workload-monitoring to the allow-metrics-ingress NP. User-deployed ServiceMonitors are scraped by the Prometheus in that namespace, not by the platform Prometheus in openshift-monitoring. Assisted-by: Claude --- .../rhdh/default-config/networkpolicy.yaml | 25 +++++++++++++++++++ pkg/model/networkpolicy_test.go | 8 +++--- .../default-config/networkpolicy.yaml | 18 +++++++++++++ .../default-config/networkpolicy.yaml | 18 +++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/config/profile/rhdh/default-config/networkpolicy.yaml b/config/profile/rhdh/default-config/networkpolicy.yaml index 84b4fa68e..b58ba4016 100644 --- a/config/profile/rhdh/default-config/networkpolicy.yaml +++ b/config/profile/rhdh/default-config/networkpolicy.yaml @@ -53,6 +53,27 @@ spec: - port: 443 protocol: TCP +--- +# Redis is part of the recommended checklist for production deployments +# (see https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.10/html/setting_up_and_configuring_your_first_red_hat_developer_hub_instance/checklist-to-run-your-first-rhdh-instance-in-production_setting-up-and-configuring-your-first-red-hat-developer-hub-instance). +# RHDH does not deploy Redis OOTB; users bring their own, which could be in the same +# namespace, a different namespace, or an external managed service. The rule therefore +# has no pod or namespace selector. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-redis-egress +spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage # replaced at runtime with 'backstage-' + policyTypes: + - Egress + egress: + - ports: + - port: 6379 + protocol: TCP + --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -92,6 +113,10 @@ spec: matchLabels: # OpenShift platform monitoring kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + # OpenShift user workload monitoring (scrapes user-deployed ServiceMonitors) + kubernetes.io/metadata.name: openshift-user-workload-monitoring - namespaceSelector: matchLabels: # GKE Standard: Google Managed Prometheus diff --git a/pkg/model/networkpolicy_test.go b/pkg/model/networkpolicy_test.go index 049014cca..6ac383d76 100644 --- a/pkg/model/networkpolicy_test.go +++ b/pkg/model/networkpolicy_test.go @@ -33,7 +33,7 @@ func TestDefaultNetworkPolicies(t *testing.T) { assert.NotNil(t, obj) mo := obj.Object().(*multiobject.MultiObject) - assert.Equal(t, 9, len(mo.Items), "expected 6 backend + 3 DB NPs") + assert.Equal(t, 10, len(mo.Items), "expected 7 backend + 3 DB NPs") backendLabel := utils.BackstageAppLabelValue(bs.Name) dbLabel := utils.BackstageDbAppLabelValue(bs.Name) @@ -48,7 +48,7 @@ func TestDefaultNetworkPolicies(t *testing.T) { backendCount++ } } - assert.Equal(t, 6, backendCount, "expected 6 backend NPs") + assert.Equal(t, 7, backendCount, "expected 7 backend NPs") assert.Equal(t, 3, dbCount, "expected 3 DB NPs") } @@ -63,7 +63,7 @@ func TestNetworkPoliciesWithoutLocalDb(t *testing.T) { assert.NotNil(t, obj) mo := obj.Object().(*multiobject.MultiObject) - assert.Equal(t, 6, len(mo.Items), "expected only 6 backend NPs when localDb is disabled") + assert.Equal(t, 7, len(mo.Items), "expected only 7 backend NPs when localDb is disabled") backendLabel := utils.BackstageAppLabelValue(testObj.backstage.Name) for _, item := range mo.Items { @@ -218,7 +218,7 @@ func TestNetworkPolicyFlavourMergePreservesNamespaceWidePodSelector(t *testing.T assert.NotNil(t, obj) mo := obj.Object().(*multiobject.MultiObject) - assert.Equal(t, 7, len(mo.Items), "expected 6 backend + 1 flavour NP (DB NPs filtered out)") + assert.Equal(t, 8, len(mo.Items), "expected 7 backend + 1 flavour NP (DB NPs filtered out)") backendLabel := utils.BackstageAppLabelValue(testObj.backstage.Name) var foundNamespaceWide bool diff --git a/pkg/model/testdata/default-config/networkpolicy.yaml b/pkg/model/testdata/default-config/networkpolicy.yaml index 914bc874b..3af990a9f 100644 --- a/pkg/model/testdata/default-config/networkpolicy.yaml +++ b/pkg/model/testdata/default-config/networkpolicy.yaml @@ -48,6 +48,21 @@ spec: --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy +metadata: + name: allow-redis-egress +spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage + policyTypes: + - Egress + egress: + - ports: + - port: 6379 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy metadata: name: allow-psql-egress spec: @@ -80,6 +95,9 @@ spec: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-user-workload-monitoring - namespaceSelector: matchLabels: kubernetes.io/metadata.name: gmp-system diff --git a/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml b/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml index 914bc874b..3af990a9f 100644 --- a/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml +++ b/pkg/model/testdata/testflavours/default-config/networkpolicy.yaml @@ -48,6 +48,21 @@ spec: --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy +metadata: + name: allow-redis-egress +spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage + policyTypes: + - Egress + egress: + - ports: + - port: 6379 + protocol: TCP +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy metadata: name: allow-psql-egress spec: @@ -80,6 +95,9 @@ spec: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: openshift-user-workload-monitoring - namespaceSelector: matchLabels: kubernetes.io/metadata.name: gmp-system From 7c9cc3f583364ab3097ad27386704cd204daceec Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 7 Sep 2026 11:03:16 +0200 Subject: [PATCH 2/3] chore: regen bundle manifests --- ...kstage-operator.clusterserviceversion.yaml | 2 +- ...kstage-operator.clusterserviceversion.yaml | 2 +- .../rhdh-default-config_v1_configmap.yaml | 25 +++++++++++++++++++ dist/rhdh/install.yaml | 25 +++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) diff --git a/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml b/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml index 124eaa412..89678f03b 100644 --- a/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml +++ b/bundle/backstage.io/manifests/backstage-operator.clusterserviceversion.yaml @@ -25,7 +25,7 @@ metadata: } } ] - createdAt: "2026-09-01T21:03:46Z" + createdAt: "2026-09-07T09:02:32Z" description: Backstage Operator operators.operatorframework.io/builder: operator-sdk-v1.42.2 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 diff --git a/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml b/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml index 3f9f17313..e8e103351 100644 --- a/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml +++ b/bundle/rhdh/manifests/backstage-operator.clusterserviceversion.yaml @@ -29,7 +29,7 @@ metadata: categories: Developer Tools certified: "true" containerImage: registry.redhat.io/rhdh/rhdh-rhel9-operator:2.0 - createdAt: "2026-09-01T21:03:48Z" + createdAt: "2026-09-07T09:02:33Z" description: Red Hat Developer Hub is a Red Hat supported version of Backstage. It comes with pre-built plug-ins and configuration settings, supports use of an external database, and can help streamline the process of setting up a self-managed diff --git a/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml b/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml index 1c09e8bbb..e7eda3c0c 100644 --- a/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml +++ b/bundle/rhdh/manifests/rhdh-default-config_v1_configmap.yaml @@ -431,6 +431,27 @@ data: - port: 443 protocol: TCP + --- + # Redis is part of the recommended checklist for production deployments + # (see https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.10/html/setting_up_and_configuring_your_first_red_hat_developer_hub_instance/checklist-to-run-your-first-rhdh-instance-in-production_setting-up-and-configuring-your-first-red-hat-developer-hub-instance). + # RHDH does not deploy Redis OOTB; users bring their own, which could be in the same + # namespace, a different namespace, or an external managed service. The rule therefore + # has no pod or namespace selector. + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-redis-egress + spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage # replaced at runtime with 'backstage-' + policyTypes: + - Egress + egress: + - ports: + - port: 6379 + protocol: TCP + --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -470,6 +491,10 @@ data: matchLabels: # OpenShift platform monitoring kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + # OpenShift user workload monitoring (scrapes user-deployed ServiceMonitors) + kubernetes.io/metadata.name: openshift-user-workload-monitoring - namespaceSelector: matchLabels: # GKE Standard: Google Managed Prometheus diff --git a/dist/rhdh/install.yaml b/dist/rhdh/install.yaml index a6065aa76..adead7cad 100644 --- a/dist/rhdh/install.yaml +++ b/dist/rhdh/install.yaml @@ -3024,6 +3024,27 @@ data: - port: 443 protocol: TCP + --- + # Redis is part of the recommended checklist for production deployments + # (see https://docs.redhat.com/en/documentation/red_hat_developer_hub/1.10/html/setting_up_and_configuring_your_first_red_hat_developer_hub_instance/checklist-to-run-your-first-rhdh-instance-in-production_setting-up-and-configuring-your-first-red-hat-developer-hub-instance). + # RHDH does not deploy Redis OOTB; users bring their own, which could be in the same + # namespace, a different namespace, or an external managed service. The rule therefore + # has no pod or namespace selector. + apiVersion: networking.k8s.io/v1 + kind: NetworkPolicy + metadata: + name: allow-redis-egress + spec: + podSelector: + matchLabels: + rhdh.redhat.com/app: backstage # replaced at runtime with 'backstage-' + policyTypes: + - Egress + egress: + - ports: + - port: 6379 + protocol: TCP + --- apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -3063,6 +3084,10 @@ data: matchLabels: # OpenShift platform monitoring kubernetes.io/metadata.name: openshift-monitoring + - namespaceSelector: + matchLabels: + # OpenShift user workload monitoring (scrapes user-deployed ServiceMonitors) + kubernetes.io/metadata.name: openshift-user-workload-monitoring - namespaceSelector: matchLabels: # GKE Standard: Google Managed Prometheus From 4975ae4369d8f2693de38c829000f599f0df2b2f Mon Sep 17 00:00:00 2001 From: Armel Soro Date: Mon, 14 Sep 2026 17:45:33 +0200 Subject: [PATCH 3/3] docs: document allow-redis-egress and allow-metrics-ingress network policies Add the two new default NetworkPolicy entries to configuration.md (Metadata Generation section) and add a NetworkPolicy note plus troubleshooting guidance to monitoring.md for OpenShift user-workload monitoring scrapes. Co-authored-by: Fortune Ndlovu Assisted-by: Claude --- docs/configuration.md | 2 ++ docs/monitoring.md | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 77e487192..2df468032 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -229,6 +229,8 @@ For example, Backstage CR named **mybackstage** will create K8s Deployment resou - The placeholder value in `podSelector.matchLabels` (`backstage` vs `backstage-psql`) determines whether a policy targets the backend or the database at runtime - DB-scoped policies are filtered out when `spec.database.enableLocalDb` is `false` - When local DB is disabled, the `allow-psql-egress` policy allows egress on port 5432 to any destination (for external databases) + - The `allow-redis-egress` policy allows egress on port 6379 TCP to any destination (Redis is not deployed by the operator; users bring their own) + - The `allow-metrics-ingress` policy allows ingress on port 9464 from `openshift-monitoring`, `openshift-user-workload-monitoring`, GKE GMP namespaces (`gmp-system`, `gke-gmp-system`), and `monitoring` (kube-prometheus-stack convention) - On OpenShift, the `allow-router-ingress` policy's `namespaceSelector` is set to `policy-group.network.openshift.io/ingress: ""` ### Multi objects diff --git a/docs/monitoring.md b/docs/monitoring.md index 8d270d0ec..3f3e29f21 100644 --- a/docs/monitoring.md +++ b/docs/monitoring.md @@ -117,6 +117,8 @@ When monitoring is disabled, the operator will automatically clean up any existi To enable metrics monitoring on OpenShift, ensure you have enabled [monitoring for user-defined projects](https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/monitoring/configuring-user-workload-monitoring#preparing-to-configure-the-monitoring-stack-uwm) for the metrics to be ingested by the built-in Prometheus instances. +**NetworkPolicy note:** When monitoring is enabled, the default `allow-metrics-ingress` NetworkPolicy allows Prometheus in `openshift-user-workload-monitoring` to scrape `/metrics` on port 9464. Platform Prometheus in `openshift-monitoring` does not scrape user-deployed ServiceMonitors. + #### Complete Example Here's a complete example of a Backstage Custom Resource with monitoring enabled: @@ -269,6 +271,10 @@ If the ServiceMonitor is not being created automatically: $ oc get crd servicemonitors.monitoring.coreos.com ``` +### Scrapes fail after enabling monitoring on OpenShift + +If scrapes fail after enabling `spec.monitoring.enabled: true`, confirm the `allow-metrics-ingress` NetworkPolicy includes `kubernetes.io/metadata.name: openshift-user-workload-monitoring` in its namespace selectors. The default policy already includes this, but if you have overridden it via raw configuration, the user-workload-monitoring namespace must be present for Prometheus to reach port 9464. + ### Metrics Not Appearing in Prometheus If metrics are not appearing in Prometheus: