Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions api/flowcollector/v1beta2/flowcollector_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type FlowCollectorSpec struct {
ConsolePlugin FlowCollectorConsolePlugin `json:"consolePlugin,omitempty"`

// `deploymentModel` defines the desired type of deployment for flow processing. Possible values are:<br>
// - `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet.<br>
// - `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet. Only recommended on small clusters, below 15 nodes.<br>
// - `Service` to make the flow processor listen as a Kubernetes Service, backed by a scalable Deployment.<br>
// - `Kafka` to make flows sent to a Kafka pipeline before consumption by the processor.<br>
// Kafka can provide better scalability, resiliency, and high availability (for more details, see https://www.redhat.com/en/topics/integration/what-is-apache-kafka).<br>
Expand All @@ -90,15 +90,14 @@ type FlowCollectorSpec struct {
Exporters []*FlowCollectorExporter `json:"exporters"`

// `networkPolicy` defines network policy settings for NetObserv components isolation.
// +k8s:conversion-gen=false
// +kubebuilder:default:={enable:true}
NetworkPolicy NetworkPolicy `json:"networkPolicy,omitempty"`
}

type NetworkPolicy struct {
// Deploys network policies on the namespaces used by NetObserv (main and privileged).
// These network policies better isolate the NetObserv components to prevent undesired connections to them.
// This option is enabled by default, disable it to manually manage network policies
// These network policies better isolate the NetObserv components to prevent undesired connections from and to them.
// This option is enabled by default when using with OVNKubernetes, and disabled otherwise (it has not been tested with other CNIs).
// When disabled, you can create manually the network policies for the NetObserv components.
// +optional
Enable *bool `json:"enable,omitempty"`

Expand Down
34 changes: 32 additions & 2 deletions api/flowcollector/v1beta2/flowcollector_validation_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ func (r *FlowCollector) ValidateDelete(_ context.Context, _ runtime.Object) (adm

func (r *FlowCollector) Validate(_ context.Context, fc *FlowCollector) (admission.Warnings, error) {
v := validator{fc: &fc.Spec}
v.validateDeploymentModel()
v.validateNetPol()
v.validateAgent()
v.validateFLP()
v.warnLogLevels()
Expand All @@ -81,16 +83,44 @@ func (v *validator) warnLogLevels() {
}
}

func (v *validator) validateDeploymentModel() {
if CurrentClusterInfo != nil {
n, err := CurrentClusterInfo.GetNbNodes()
if err != nil {
v.warnings = append(v.warnings, fmt.Sprintf("Could not get the number of nodes, cannot validate the deployment model: %s", err.Error()))
} else if n >= 15 && v.fc.DeploymentModel == DeploymentModelDirect {
v.warnings = append(v.warnings, fmt.Sprintf(`The number of nodes is bigger than the recommendation for deployment model "Direct" (%d >= 15), meaning that "flowlogs-pipeline" uses a lot more memory and bandwidth than necessary; it is recommended to use a different deployment model ("Service" or "Kafka").`, n))
}
} else {
v.warnings = append(v.warnings, "Unknown environment, cannot validate the deployment model")
}
}

func (v *validator) validateNetPol() {
if CurrentClusterInfo != nil {
cni, err := CurrentClusterInfo.GetCNI()
if err != nil {
v.warnings = append(v.warnings, fmt.Sprintf("Could not detect CNI: %s", err.Error()))
} else if cni == cluster.OpenShiftSDN && v.fc.NetworkPolicy.Enable != nil && *v.fc.NetworkPolicy.Enable {
v.warnings = append(v.warnings, "OpenShiftSDN detected with unsupported setting: spec.networkPolicy.enable; this setting will be ignored; to remove this warning set spec.networkPolicy.enable to false.")
} else if cni != cluster.OVNKubernetes && v.fc.DeployNetworkPolicyOtherCNI() {
v.warnings = append(v.warnings, "Network policy is enabled via spec.networkPolicy.enable, despite not running OVN-Kubernetes: this configuration has not been tested; to remove this warning set spec.networkPolicy.enable to false.")
}
} else {
v.warnings = append(v.warnings, "Unknown environment, cannot detect the CNI in use")
}
}

func (v *validator) validateAgent() {
for feat, minVersion := range neededOpenShiftVersion {
if slices.Contains(v.fc.Agent.EBPF.Features, feat) {
if CurrentClusterInfo != nil && CurrentClusterInfo.IsOpenShift() {
// Make sure required version of ocp is installed
ok, err := CurrentClusterInfo.IsOpenShiftVersionAtLeast(minVersion)
ok, actual, err := CurrentClusterInfo.IsOpenShiftVersionAtLeast(minVersion)
if err != nil {
v.warnings = append(v.warnings, fmt.Sprintf("Could not detect OpenShift cluster version: %s", err.Error()))
} else if !ok {
v.warnings = append(v.warnings, fmt.Sprintf("The %s feature requires OpenShift %s or above (version detected: %s)", feat, minVersion, CurrentClusterInfo.GetOpenShiftVersion()))
v.warnings = append(v.warnings, fmt.Sprintf("The %s feature requires OpenShift %s or above (version detected: %s)", feat, minVersion, actual))
}
} else {
v.warnings = append(v.warnings, fmt.Sprintf("Unknown environment, cannot detect if the feature %s is supported", feat))
Expand Down
100 changes: 97 additions & 3 deletions api/flowcollector/v1beta2/flowcollector_validation_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ func TestValidateAgent(t *testing.T) {

CurrentClusterInfo = &cluster.Info{}
for _, test := range tests {
CurrentClusterInfo.MockOpenShiftVersion(test.ocpVersion)
CurrentClusterInfo.Mock(test.ocpVersion, "")
v := validator{fc: &test.fc.Spec}
v.validateAgent()
if test.expectedError == "" {
Expand Down Expand Up @@ -528,6 +528,7 @@ func TestValidateConntrack(t *testing.T) {

r := FlowCollector{}
CurrentClusterInfo = &cluster.Info{}
CurrentClusterInfo.Mock("", "")
for _, test := range tests {
warnings, err := r.Validate(context.TODO(), test.fc)
if test.expectedError == "" {
Expand Down Expand Up @@ -733,7 +734,7 @@ func TestValidateFLP(t *testing.T) {
CurrentClusterInfo = &cluster.Info{}
r := FlowCollector{}
for _, test := range tests {
CurrentClusterInfo.MockOpenShiftVersion(test.ocpVersion)
CurrentClusterInfo.Mock(test.ocpVersion, "")
warnings, err := r.Validate(context.TODO(), test.fc)
if test.expectedError == "" {
assert.NoError(t, err, test.name)
Expand Down Expand Up @@ -892,7 +893,7 @@ func TestValidateScheduling(t *testing.T) {
CurrentClusterInfo = &cluster.Info{}
r := FlowCollector{}
for _, test := range tests {
CurrentClusterInfo.MockOpenShiftVersion(test.ocpVersion)
CurrentClusterInfo.Mock(test.ocpVersion, "")
warnings, err := r.Validate(context.TODO(), test.fc)
if test.expectedError == "" {
assert.NoError(t, err, test.name)
Expand Down Expand Up @@ -926,3 +927,96 @@ func TestElligibleMetrics(t *testing.T) {
assert.Equal(t, []string{"namespace_drop_packets_total", "workload_drop_packets_total", "node_drop_packets_total"}, met)
assert.Equal(t, []string{"namespace_ingress_packets_total", "workload_ingress_packets_total", "node_ingress_packets_total", "namespace_egress_packets_total", "workload_egress_packets_total", "node_egress_packets_total"}, tot)
}

func TestValidateNetPol(t *testing.T) {
tests := []struct {
name string
fc *FlowCollector
cni cluster.NetworkType
expectedError string
expectedWarnings admission.Warnings
}{
{
name: "Empty config is valid for ovn-k",
fc: &FlowCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Spec: FlowCollectorSpec{},
},
cni: cluster.OVNKubernetes,
},
{
name: "Empty config is valid for sdn",
fc: &FlowCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Spec: FlowCollectorSpec{},
},
cni: cluster.OpenShiftSDN,
},
{
name: "Empty config is valid for unknown",
fc: &FlowCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Spec: FlowCollectorSpec{},
},
cni: "unknown",
},
{
name: "Enabled netpol is valid for ovn-k",
fc: &FlowCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Spec: FlowCollectorSpec{
NetworkPolicy: NetworkPolicy{Enable: ptr.To(true)},
},
},
cni: cluster.OVNKubernetes,
},
{
name: "Enabled netpol triggers warning for sdn",
fc: &FlowCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Spec: FlowCollectorSpec{
NetworkPolicy: NetworkPolicy{Enable: ptr.To(true)},
},
},
cni: cluster.OpenShiftSDN,
expectedWarnings: admission.Warnings{"OpenShiftSDN detected with unsupported setting: spec.networkPolicy.enable; this setting will be ignored; to remove this warning set spec.networkPolicy.enable to false."},
},
{
name: "Enabled netpol triggers warning for unknown",
fc: &FlowCollector{
ObjectMeta: metav1.ObjectMeta{
Name: "cluster",
},
Spec: FlowCollectorSpec{
NetworkPolicy: NetworkPolicy{Enable: ptr.To(true)},
},
},
cni: "unknown",
expectedWarnings: admission.Warnings{"Network policy is enabled via spec.networkPolicy.enable, despite not running OVN-Kubernetes: this configuration has not been tested; to remove this warning set spec.networkPolicy.enable to false."},
},
}

CurrentClusterInfo = &cluster.Info{}
for _, test := range tests {
CurrentClusterInfo.Mock("4.20.0", test.cni)
v := validator{fc: &test.fc.Spec}
v.validateNetPol()
if test.expectedError == "" {
assert.Empty(t, v.errors, test.name)
} else {
assert.Len(t, v.errors, 1, test.name)
assert.ErrorContains(t, v.errors[0], test.expectedError, test.name)
}
assert.Equal(t, test.expectedWarnings, v.warnings, test.name)
}
}
6 changes: 5 additions & 1 deletion api/flowcollector/v1beta2/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,11 @@ func (spec *FlowCollectorSpec) HasExperimentalAlertsHealth() bool {
return false
}

func (spec *FlowCollectorSpec) DeployNetworkPolicy() bool {
func (spec *FlowCollectorSpec) DeployNetworkPolicyOVN() bool {
return spec.NetworkPolicy.Enable == nil || *spec.NetworkPolicy.Enable
}

func (spec *FlowCollectorSpec) DeployNetworkPolicyOtherCNI() bool {
return spec.NetworkPolicy.Enable != nil && *spec.NetworkPolicy.Enable
}

Expand Down
9 changes: 4 additions & 5 deletions bundle/manifests/flows.netobserv.io_flowcollectors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3220,7 +3220,7 @@ spec:
default: Direct
description: |-
`deploymentModel` defines the desired type of deployment for flow processing. Possible values are:<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet.<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet. Only recommended on small clusters, below 15 nodes.<br>
- `Service` to make the flow processor listen as a Kubernetes Service, backed by a scalable Deployment.<br>
- `Kafka` to make flows sent to a Kafka pipeline before consumption by the processor.<br>
Kafka can provide better scalability, resiliency, and high availability (for more details, see https://www.redhat.com/en/topics/integration/what-is-apache-kafka).<br>
Expand Down Expand Up @@ -4252,8 +4252,6 @@ spec:
and recreate the resource.
rule: self == oldSelf
networkPolicy:
default:
enable: true
description: '`networkPolicy` defines network policy settings for
NetObserv components isolation.'
properties:
Expand All @@ -4268,8 +4266,9 @@ spec:
enable:
description: |-
Deploys network policies on the namespaces used by NetObserv (main and privileged).
These network policies better isolate the NetObserv components to prevent undesired connections to them.
This option is enabled by default, disable it to manually manage network policies
These network policies better isolate the NetObserv components to prevent undesired connections from and to them.
This option is enabled by default when using with OVNKubernetes, and disabled otherwise (it has not been tested with other CNIs).
When disabled, you can create manually the network policies for the NetObserv components.
type: boolean
type: object
processor:
Expand Down
9 changes: 4 additions & 5 deletions config/crd/bases/flows.netobserv.io_flowcollectors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3014,7 +3014,7 @@ spec:
default: Direct
description: |-
`deploymentModel` defines the desired type of deployment for flow processing. Possible values are:<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet.<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet. Only recommended on small clusters, below 15 nodes.<br>
- `Service` to make the flow processor listen as a Kubernetes Service, backed by a scalable Deployment.<br>
- `Kafka` to make flows sent to a Kafka pipeline before consumption by the processor.<br>
Kafka can provide better scalability, resiliency, and high availability (for more details, see https://www.redhat.com/en/topics/integration/what-is-apache-kafka).<br>
Expand Down Expand Up @@ -3901,8 +3901,6 @@ spec:
- message: Namespace is immutable. If you need to change it, delete and recreate the resource.
rule: self == oldSelf
networkPolicy:
default:
enable: true
description: '`networkPolicy` defines network policy settings for NetObserv components isolation.'
properties:
additionalNamespaces:
Expand All @@ -3916,8 +3914,9 @@ spec:
enable:
description: |-
Deploys network policies on the namespaces used by NetObserv (main and privileged).
These network policies better isolate the NetObserv components to prevent undesired connections to them.
This option is enabled by default, disable it to manually manage network policies
These network policies better isolate the NetObserv components to prevent undesired connections from and to them.
This option is enabled by default when using with OVNKubernetes, and disabled otherwise (it has not been tested with other CNIs).
When disabled, you can create manually the network policies for the NetObserv components.
type: boolean
type: object
processor:
Expand Down
9 changes: 4 additions & 5 deletions docs/FlowCollector.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ for these features as a best effort only.
<td>enum</td>
<td>
`deploymentModel` defines the desired type of deployment for flow processing. Possible values are:<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet.<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet. Only recommended on small clusters, below 15 nodes.<br>
- `Service` to make the flow processor listen as a Kubernetes Service, backed by a scalable Deployment.<br>
- `Kafka` to make flows sent to a Kafka pipeline before consumption by the processor.<br>
Kafka can provide better scalability, resiliency, and high availability (for more details, see https://www.redhat.com/en/topics/integration/what-is-apache-kafka).<br>
Expand Down Expand Up @@ -157,8 +157,6 @@ Kafka can provide better scalability, resiliency, and high availability (for mor
<td>object</td>
<td>
`networkPolicy` defines network policy settings for NetObserv components isolation.<br/>
<br/>
<i>Default</i>: map[enable:true]<br/>
</td>
<td>false</td>
</tr><tr>
Expand Down Expand Up @@ -8361,8 +8359,9 @@ configuration, you can disable it and install your own instead.<br/>
<td>boolean</td>
<td>
Deploys network policies on the namespaces used by NetObserv (main and privileged).
These network policies better isolate the NetObserv components to prevent undesired connections to them.
This option is enabled by default, disable it to manually manage network policies<br/>
These network policies better isolate the NetObserv components to prevent undesired connections from and to them.
This option is enabled by default when using with OVNKubernetes, and disabled otherwise (it has not been tested with other CNIs).
When disabled, you can create manually the network policies for the NetObserv components.<br/>
</td>
<td>false</td>
</tr></tbody>
Expand Down
9 changes: 4 additions & 5 deletions helm/crds/flows.netobserv.io_flowcollectors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3018,7 +3018,7 @@ spec:
default: Direct
description: |-
`deploymentModel` defines the desired type of deployment for flow processing. Possible values are:<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet.<br>
- `Direct` (default) to make the flow processor listen directly from the agents using the host network, backed by a DaemonSet. Only recommended on small clusters, below 15 nodes.<br>
- `Service` to make the flow processor listen as a Kubernetes Service, backed by a scalable Deployment.<br>
- `Kafka` to make flows sent to a Kafka pipeline before consumption by the processor.<br>
Kafka can provide better scalability, resiliency, and high availability (for more details, see https://www.redhat.com/en/topics/integration/what-is-apache-kafka).<br>
Expand Down Expand Up @@ -3905,8 +3905,6 @@ spec:
- message: Namespace is immutable. If you need to change it, delete and recreate the resource.
rule: self == oldSelf
networkPolicy:
default:
enable: true
description: '`networkPolicy` defines network policy settings for NetObserv components isolation.'
properties:
additionalNamespaces:
Expand All @@ -3920,8 +3918,9 @@ spec:
enable:
description: |-
Deploys network policies on the namespaces used by NetObserv (main and privileged).
These network policies better isolate the NetObserv components to prevent undesired connections to them.
This option is enabled by default, disable it to manually manage network policies
These network policies better isolate the NetObserv components to prevent undesired connections from and to them.
This option is enabled by default when using with OVNKubernetes, and disabled otherwise (it has not been tested with other CNIs).
When disabled, you can create manually the network policies for the NetObserv components.
type: boolean
type: object
processor:
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/consoleplugin/consoleplugin_objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type builder struct {

func newBuilder(info *reconcilers.Instance, desired *flowslatest.FlowCollectorSpec, name string) builder {
imageToUse := reconcilers.MainImage
needsPF4, err := info.ClusterInfo.IsOpenShiftVersionLessThan("4.15.0")
needsPF4, _, err := info.ClusterInfo.IsOpenShiftVersionLessThan("4.15.0")
if err == nil && needsPF4 {
imageToUse = reconcilers.ConsolePluginCompatImage
}
Expand Down
Loading
Loading