Skip to content

Commit 01efb83

Browse files
committed
LOG-7572: NetworkPolicy for ClusterLogForwarder
1 parent d87d486 commit 01efb83

16 files changed

+415
-16
lines changed

api/observability/v1/output_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ type Kafka struct {
744744
Brokers []BrokerURL `json:"brokers,omitempty"`
745745
}
746746

747-
// +kubebuilder:validation:XValidation:rule="self == '' || (isURL(self) && (self.startsWith('tcp://') || self.startsWith('tls://')))",message="each broker must be a valid URL with a tcp or tls scheme"
747+
// +kubebuilder:validation:XValidation:rule="isURL(self) && (self.startsWith('tcp://') || self.startsWith('tls://'))",message="each broker must be a valid URL with a tcp or tls scheme"
748748
type BrokerURL string
749749

750750
type LokiTuningSpec struct {

bundle/manifests/cluster-logging.clusterserviceversion.yaml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ metadata:
8282
categories: OpenShift Optional, Logging & Tracing, Observability
8383
certified: "false"
8484
containerImage: quay.io/openshift-logging/cluster-logging-operator:latest
85-
createdAt: "2025-07-29T17:44:27Z"
85+
createdAt: "2025-09-03T01:08:59Z"
8686
description: The Red Hat OpenShift Logging Operator for OCP provides a means for
8787
configuring and managing log collection and forwarding.
8888
features.operators.openshift.io/cnf: "false"
@@ -215,15 +215,15 @@ spec:
215215
216216
Examples:
217217
218-
- `.kubernetes.namespace_name`
218+
- `.kubernetes.namespace_id`
219219
220-
- `.log_type`
220+
- `.hostname`
221221
222222
- '.kubernetes.labels.foobar'
223223
224224
- `.kubernetes.labels."foo-bar/baz"`
225225
226-
NOTE1: `In` CANNOT contain `.log_type` or `.message` as those fields are required and cannot be pruned.
226+
NOTE1: `In` CANNOT contain `.log_type`, `.log_source` or `.message` as those fields are required and cannot be pruned.
227227
228228
NOTE2: If this filter is used in a pipeline with GoogleCloudLogging, `.hostname` CANNOT be added to this list as it is a required field.
229229
displayName: Fields to be dropped
@@ -243,11 +243,13 @@ spec:
243243
244244
- `.log_type`
245245
246-
- '.kubernetes.labels.foobar'
246+
- '.log_source'
247+
248+
- '.message'
247249
248250
- `.kubernetes.labels."foo-bar/baz"`
249251
250-
NOTE1: `NotIn` MUST contain `.log_type` and `.message` as those fields are required and cannot be pruned.
252+
NOTE1: `NotIn` MUST contain `.log_type`, `.log_source` and `.message` as those fields are required and cannot be pruned.
251253
252254
NOTE2: If this filter is used in a pipeline with GoogleCloudLogging, `.hostname` MUST be added to this list as it is a required field.
253255
displayName: Fields to be kept
@@ -1991,6 +1993,9 @@ spec:
19911993
verbs:
19921994
- create
19931995
- delete
1996+
- list
1997+
- get
1998+
- watch
19941999
- apiGroups:
19952000
- observability.openshift.io
19962001
resources:

bundle/manifests/observability.openshift.io_clusterlogforwarders.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,8 +2535,7 @@ spec:
25352535
x-kubernetes-validations:
25362536
- message: each broker must be a valid URL with a tcp
25372537
or tls scheme
2538-
rule: self == '' || (isURL(self) && (self.startsWith('tcp://')
2539-
|| self.startsWith('tls://')))
2538+
rule: isURL(self) && (self.startsWith('tcp://') || self.startsWith('tls://'))
25402539
type: array
25412540
topic:
25422541
description: |-

config/crd/bases/observability.openshift.io_clusterlogforwarders.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,8 +2535,7 @@ spec:
25352535
x-kubernetes-validations:
25362536
- message: each broker must be a valid URL with a tcp
25372537
or tls scheme
2538-
rule: self == '' || (isURL(self) && (self.startsWith('tcp://')
2539-
|| self.startsWith('tls://')))
2538+
rule: isURL(self) && (self.startsWith('tcp://') || self.startsWith('tls://'))
25402539
type: array
25412540
topic:
25422541
description: |-

config/rbac/role.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ rules:
7878
verbs:
7979
- create
8080
- delete
81+
- list
82+
- get
83+
- watch
8184
- apiGroups:
8285
- observability.openshift.io
8386
resources:

docs/features/collection.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ a|
9595

9696
|https://issues.redhat.com/browse/LOG-3270[TLS Security Profile Compliance]
9797
|Comply with OCP cluster-wide cryptographic profiles for internal communication and allow configuration of outbound connection profiles. See link:./tls_security_profile.adoc[details]
98+
|https://issues.redhat.com/browse/LOG-7571[Network Policy]| Network policy in place for the collectors that allows all egress and ingress.
9899
|======
99100

100101
=== Tuning

docs/features/network_policy.adoc

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
= NetworkPolicy for Collector Pods
2+
3+
The Cluster Logging Operator automatically creates and manages a `NetworkPolicy` for its collector pods to ensure they function in restrictive network environments, even if a cluster-wide `AdminNetworkPolicy` would otherwise block their traffic.
4+
5+
== Overview
6+
7+
When a `ClusterLogForwarder` is deployed, the operator creates a permissive `NetworkPolicy` that allows all ingress and egress traffic for the collector pods. This ensures that log collection can function properly even when:
8+
9+
* Restrictive default `NetworkPolicies` are in place
10+
* `AdminNetworkPolicy` configurations limit pod communications
11+
* Namespace-level network restrictions are applied
12+
13+
The `NetworkPolicy` is automatically created and removed along with the collector deployment lifecycle.
14+
15+
The `NetworkPolicy` can directly be edited by the cluster administrator and won't be reconciled by the operator upon updates.
16+
17+
== NetworkPolicy Configuration
18+
19+
The operator creates a `NetworkPolicy` for the collector with the following characteristics:
20+
21+
```yaml
22+
apiVersion: networking.k8s.io/v1
23+
kind: NetworkPolicy
24+
metadata:
25+
name: <COLLECTOR-INSTANCE-NAME>
26+
namespace: <COLLECTOR-NAMESPACE>
27+
labels:
28+
app.kubernetes.io/name: vector
29+
app.kubernetes.io/instance: <COLLECTOR-INSTANCE-NAME>
30+
app.kubernetes.io/component: collector
31+
app.kubernetes.io/part-of: cluster-logging
32+
app.kubernetes.io/managed-by: cluster-logging-operator
33+
app.kubernetes.io/version: <CLO-VERSION>
34+
spec:
35+
podSelector:
36+
matchLabels:
37+
app.kubernetes.io/name: vector
38+
app.kubernetes.io/instance: <COLLECTOR-INSTANCE-NAME>
39+
app.kubernetes.io/component: collector
40+
app.kubernetes.io/part-of: cluster-logging
41+
app.kubernetes.io/managed-by: cluster-logging-operator
42+
policyTypes:
43+
- Ingress
44+
- Egress
45+
ingress:
46+
- {} # Allow all ingress traffic
47+
egress:
48+
- {} # Allow all egress traffic
49+
```
50+
51+
== AdminNetworkPolicy Delegation
52+
53+
When an `AdminNetworkPolicy` (ANP) is used in your cluster to enforce network restrictions, you may need to configure delegation to allow the collector's `NetworkPolicy` to take precedence for log collection traffic.
54+
55+
=== Understanding the Hierarchy
56+
57+
OpenShift network policy precedence (highest to lowest priority):
58+
59+
1. **AdminNetworkPolicy** - Cluster-admin controlled, highest priority
60+
2. **BaselineAdminNetworkPolicy** - Default fallback rules
61+
3. **NetworkPolicy** - Namespace-level policies (where collector policies reside)
62+
63+
=== Delegation Configuration
64+
65+
To ensure collector pods can communicate properly when an `AdminNetworkPolicy` is blocking traffic, create an `AdminNetworkPolicy` rule that delegates to `NetworkPolicy` for collector traffic:
66+
67+
==== Example: Delegating Collector Traffic
68+
69+
```yaml
70+
apiVersion: policy.networking.k8s.io/v1alpha1
71+
kind: AdminNetworkPolicy
72+
metadata:
73+
name: allow-logging-collector-delegation
74+
spec:
75+
priority: 50 # Adjust based on your cluster's ANP priority scheme. Lower number means higher priority
76+
subject:
77+
pods: # Target the collector pods
78+
namespaceSelector:
79+
matchLabels:
80+
kubernetes.io/metadata.name: openshift-logging # or collector namespace
81+
podSelector:
82+
matchLabels:
83+
app.kubernetes.io/name: vector
84+
app.kubernetes.io/instance: my-clf # or collector instance name
85+
app.kubernetes.io/managed-by: cluster-logging-operator
86+
app.kubernetes.io/part-of: cluster-logging
87+
app.kubernetes.io/component: collector
88+
ingress:
89+
- name: "delegate-to-collector-ingress"
90+
action: "Pass" # Pass to collector NetworkPolicy
91+
from:
92+
- {} # Delegate decisions for traffic coming from any source
93+
egress:
94+
- name: "delegate-to-collector-egress"
95+
action: "Pass" # Pass to collector NetworkPolicy
96+
to:
97+
- {} # Delegate decisions for traffic going to any destination
98+
```
99+
100+
== References
101+
102+
- https://docs.redhat.com/en/documentation/openshift_container_platform/4.19/html/network_security/admin-network-policy#adminnetworkpolicy_ovn-k-anp[Openshift AdminNetworkPolicy]
103+
- https://docs.openshift.com/container-platform/latest/networking/network_policy/about-network-policy.html[OpenShift Network Policy]
104+
- https://kubernetes.io/docs/concepts/services-networking/network-policies/[Kubernetes NetworkPolicy Documentation]

docs/reference/operator/api_observability_v1.adoc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,15 +1238,15 @@ If segments contain characters outside of this range, the segment must be quoted
12381238

12391239
Examples:
12401240

1241-
- `.kubernetes.namespace_name`
1241+
- `.kubernetes.namespace_id`
12421242

1243-
- `.log_type`
1243+
- `.hostname`
12441244

12451245
- &#39;.kubernetes.labels.foobar&#39;
12461246

12471247
- `.kubernetes.labels.&#34;foo-bar/baz&#34;`
12481248

1249-
NOTE1: `In` CANNOT contain `.log_type` or `.message` as those fields are required and cannot be pruned.
1249+
NOTE1: `In` CANNOT contain `.log_type`, `.log_source` or `.message` as those fields are required and cannot be pruned.
12501250

12511251
NOTE2: If this filter is used in a pipeline with GoogleCloudLogging, `.hostname` CANNOT be added to this list as it is a required field.
12521252

@@ -1264,11 +1264,13 @@ Examples:
12641264

12651265
- `.log_type`
12661266

1267-
- &#39;.kubernetes.labels.foobar&#39;
1267+
- &#39;.log_source&#39;
1268+
1269+
- &#39;.message&#39;
12681270

12691271
- `.kubernetes.labels.&#34;foo-bar/baz&#34;`
12701272

1271-
NOTE1: `NotIn` MUST contain `.log_type` and `.message` as those fields are required and cannot be pruned.
1273+
NOTE1: `NotIn` MUST contain `.log_type`, `.log_source` and `.message` as those fields are required and cannot be pruned.
12721274

12731275
NOTE2: If this filter is used in a pipeline with GoogleCloudLogging, `.hostname` MUST be added to this list as it is a required field.
12741276

internal/controller/observability/clusterlogforwarder_controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
99
appsv1 "k8s.io/api/apps/v1"
10+
networkingv1 "k8s.io/api/networking/v1"
1011
rbacv1 "k8s.io/api/rbac/v1"
1112
"k8s.io/apimachinery/pkg/types"
1213
"sigs.k8s.io/controller-runtime/pkg/builder"
@@ -206,6 +207,7 @@ func (r *ClusterLogForwarderReconciler) SetupWithManager(mgr ctrl.Manager) error
206207
Owns(&corev1.ConfigMap{}).
207208
Owns(&appsv1.DaemonSet{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
208209
Owns(&appsv1.Deployment{}).
210+
Owns(&networkingv1.NetworkPolicy{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})).
209211
Owns(&rbacv1.Role{}).
210212
Owns(&rbacv1.RoleBinding{}).
211213
Owns(&corev1.Secret{}).

internal/controller/observability/collector.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package observability
22

33
import (
4+
"fmt"
45
"strings"
56
"time"
67

@@ -139,6 +140,12 @@ func ReconcileCollector(context internalcontext.ForwarderContext, pollInterval,
139140
return err
140141
}
141142

143+
// Reconcile NetworkPolicy for the collector daemonset
144+
if err := network.ReconcileNetworkPolicy(context.Client, context.Forwarder.Namespace, fmt.Sprintf("%s-%s", constants.CollectorName, resourceNames.CommonName), context.Forwarder.Name, ownerRef, collectorFactory.CommonLabelInitializer); err != nil {
145+
log.Error(err, "collector.ReconcileNetworkPolicy")
146+
return err
147+
}
148+
142149
// Reconcile resources to support metrics gathering
143150
if err := network.ReconcileService(context.Client, context.Forwarder.Namespace, resourceNames.CommonName, context.Forwarder.Name, constants.CollectorName, collector.MetricsPortName, resourceNames.SecretMetrics, collector.MetricsPort, ownerRef, collectorFactory.CommonLabelInitializer); err != nil {
144151
log.Error(err, "collector.ReconcileService")

0 commit comments

Comments
 (0)