-
-# 404 Not Found
-
-Sorry, the page you are looking for doesn't exists.
-
-Go back to [netobserv.io home page](https://netobserv.io)
diff --git a/CNAME b/CNAME
index 4a46747..0f76f9e 100644
--- a/CNAME
+++ b/CNAME
@@ -1 +1,2 @@
-netobserv.io
\ No newline at end of file
+netobserv.io
+
diff --git a/README.md b/README.md
index feeffd4..48f713a 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,44 @@
-# Welcome to [netobserv.io](https://netobserv.io)
+# netobserv.io
-This site is under construction...
+This repository contains the code for the [netobserv.io](https://netobserv.io) web site / blog.
-All sources are available on [github.com/netobserv](https://github.com/netobserv)
-- Network Observability Operator [getting started guide](https://github.com/netobserv/network-observability-operator/blob/main/README.md)
-- Available [blog articles](./documents/blogs/index.md)
-- Extra [documents and hacks](./documents/README.md)
+## How it works
+
+It uses the static site generator [Quarkus Roq](https://pages.quarkiverse.io/quarkus-roq/) to generate a static HTML site based on markdown pages.
+
+Most of the time, writing content simply requires you to drop a new markdown file in [content/posts](./content/posts/), and assets (such as images) in [static/assets](./static/assets/). A few meta-data is also required at the top of the markdown file, such as:
+
+```
+---
+layout: :theme/post
+title: "Your post title"
+description: "The post description"
+tags: Insert,Some,Tags,Here
+authors: [your-name]
+---
+
+```
+
+Then, open a pull-request and the post will be reviewed by maintainers.
+
+First-time contributors should also provide some info about themselves in [data/authors.yml](./data/authors.yml).
+
+## Testing locally
+
+To test locally, the simplest way is to use the [quarkus CLI](https://quarkus.io/guides/cli-tooling).
+
+After you cloned this repository, from its root, run:
+
+```bash
+quarkus dev
+```
+
+And then open http://localhost:8080/
+
+## Deploying on netobserv.io
+
+Deploying on netobserv.io is fully automated after pull-requests are merged. This is all handled via [a github action](./.github/workflows/static.yml) that runs quarkus to generate the static HTML artifact, which is deployed through GitHub pages.
+
+## Contributions
+
+Like all the other NetObserv components, this blog is open-source and we are welcoming external contributions. Feel free to open pull-requests!
diff --git a/content/404.html b/content/404.html
new file mode 100644
index 0000000..6c12b3f
--- /dev/null
+++ b/content/404.html
@@ -0,0 +1,5 @@
+---
+layout: :theme/404
+link: 404.html
+image: iamroq.png
+---
diff --git a/content/about.md b/content/about.md
new file mode 100644
index 0000000..f83d3e6
--- /dev/null
+++ b/content/about.md
@@ -0,0 +1,12 @@
+---
+title: About
+description: |
+ NetObserv aka Network Observability is a set of components used to observe network traffic by generating NetFlows from eBPF agents, enrich those flows using a configurable pipeline that is Kubernetes-aware, export them in various ways (logs, metrics, Kafka, IPFIX...), and finally provide a comprehensive visualization tool for making sense of that data, and a CLI. Those components can be used as standalones or deployed in Kubernetes / OpenShift via an integrated Operator.
+layout: :theme/page
+---
+
+# About NetObserv
+
+NetObserv is a set of components used to observe network traffic by generating NetFlows from [eBPF agents](https://github.com/netobserv/netobserv-ebpf-agent), enriching those flows using [a configurable pipeline](https://github.com/netobserv/flowlogs-pipeline/) which is Kubernetes-aware, exporting them in various ways (logs, metrics, Kafka, IPFIX...), and finally providing a comprehensive [visualization tool](https://github.com/netobserv/network-observability-console-plugin/) for making sense of that data, and [a CLI](https://github.com/netobserv/network-observability-cli). Those components can be used as standalones or deployed in Kubernetes / OpenShift via an [integrated Operator](https://github.com/netobserv/network-observability-operator/).
+
+It is known and distributed in Red Hat OpenShift as the [Network Observability operator](https://docs.openshift.com/container-platform/latest/observability/network_observability/network-observability-operator-release-notes.html).
diff --git a/content/authors.md b/content/authors.md
new file mode 100644
index 0000000..57f6521
--- /dev/null
+++ b/content/authors.md
@@ -0,0 +1,21 @@
+---
+title: Authors
+description: |
+ Authors on this blog.
+layout: :theme/page
+---
+
+# Authors on this blog
+
+
+
+Red Hat OpenShift Container Platform (OCP) has had monitoring capabilities from the start and [Network Observability as Developer Preview](https://cloud.redhat.com/blog/a-guide-to-providing-insight-with-network-observability) since OCP 4.10 release.
+
+Network Observability brings user interfaces in OpenShift web console administration to filter and visualize your cluster network flows as:
+
+- Graph (top 5 flow rates stacked with total example)
+})
+
+- Table (showing sources and destinations sorted by time)
+})
+
+- Topology (using directed graph layout)
+})
+
+If you are interested in Network Observability for your cluster, check [official documentation for installation](https://docs.openshift.com/container-platform/4.12/networking/network_observability/installing-operators.html).
+
+## Network representations
+
+Topology view is a great way to understand how the different components of your cluster interact internally and identify which ones are communicating with the external world. It can also help you define your network policies or highlight potential threats.
+
+To avoid huge and unreadable network graphs, we introduced in Network Observability multiple options to focus on the content you are looking for.
+
+- Time range
+Showing by default the last 5 minutes, it allows you to focus on a particular time window
+
+- Filtering
+To select a particular set of records based on Source and / or Destination criterias such as `IPs`, `Ports`, `Protocol`, `Kind`, `Name` etc
+
+- Level of details (scope display option)
+Allowing you to select from `Node` / `Namespace` / `Owner` / `Resource` aggregating metrics into the specified layer
+
+- Groups
+To arrange components by their ownership
+
+## Example of usage
+
+What happens in your network when you deploy a [httpd sample application](https://github.com/sclorg/httpd-ex) ?
+
+})
+
+You can see that the final deployed pod in blue involved another pod called `httpd-sample-1-build` that pulled the image from `openshift-image-registry` (1), did some DNS resolution for provided image URL (2), pulled it from the resolved external IP (3) before creating our pod through kubernetes services (4).
+
+Finally, some flows are showing between our pod and `openshift-ingress` after opening the hosted page (5).
+
+After moving my time window or waiting a bit, the `httpd-sample-1-build` pod disappears as it's status is now `Completed`.
+
+})
+
+## Complex representations
+
+Sometimes we need to see more than a single application to troubleshoot network issues or to highlight bandwidth usage at cluster level.
+
+2D network topology may start to show its limits as you need to switch between multiple options and never get an overview into a single render.
+
+})
+
+We can do the following observation from this:
+- it is almost impossible to have a good overview of your entire network
+- drawing each connection on a flat representation is hard to read
+- it is difficult to understand ownership and relations between objects without a concrete representation
+
+## Another dimension
+
+Here is where [3D Topology](https://github.com/jpinsonneau/react-three-topology) makes the scene !
+
+3D representations are pretty old and you can find a lot of them online such as [networkmaps](https://github.com/pablomarle/networkmaps), [vagrant-mesh-net](https://github.com/IMPIMBA/vagrant-mesh-net) or even more generic ones such as [splunk-3D-graph-network-topology-viz](https://github.com/splunk/splunk-3D-graph-network-topology-viz). Each of these has its own rendering philosophy to resolve specific use cases.
+
+This is a way to render your network using a representation everybody knows: "buildings".
+```
+To enable this feature in Network Observability, you will need to use Network Observability v1.0 and add "&3d=preview" in the URL.
+Then go to Topology tab -> Show advanced options -> Display options
+From there set Scope option as "Resource" and Layout as "3D".
+```
+
+})
+
+- **Building** drawn by dotted lines represent your `Cluster`
+Every internal communication is inside these lines
+Each floor is represented by a line
+- **Bricks surrounding the building** in a circle shape account for `external ips`
+- **Ground floor** with purple bricks represents your `Nodes`
+You can have multiple nodes all located at ground level
+- **Upper floors** in green shows your `Namespaces`
+Namespaces are aligned between nodes so each floor represent a single namespace
+If a namespace is not carried by a node, you will see an empty space
+- **Rooms** stand for owners such as `Deployments` in dark blue or `StatefulSets` in light blue
+You can have multiple owners per namespaces
+They will repeat on each node + namespace combination if the load is distributed
+- Finally, **rooms contents** depict `Pods`
+These are represented in the proper node + namespace + owner combination according to its kindred
+
+})
+This representation emphasizes the entire ownership chain from `Node` to `Pod` passing by `Namespace`.
+It also pin up how your load is balanced between nodes.
+
+})
+
+The important part of your network traffic is highlighted since lines are less likely to cross than in the 2D view and their size and color differ according to bytes rate.
+A thin black line will represent a smaller amount than a heavy red line.
+
+## Conclusion
+
+We need to identify the various use cases to elaborate proper representations. This is a daily step by step work between internal teams on both engineering and UI / UX and customers. We are likely to implement more views in the future to highlight network issues, health, threats and usage.
+One of the next implementations is going to be [sankey chart](https://observablehq.com/@d3/sankey) that will be useful for connection tracking.
+
+## We need you !
+
+Feel free to contribute by commenting this post, opening issues in [netobserv console plugin](https://github.com/netobserv/network-observability-console-plugin/issues) or opening pull request in any [netobserv component](https://github.com/netobserv)
+
+Tell us more about your expectations, the way you currently solve issues and what could help your daily experience.
+
+})
+})
+})
+})
+})
+})
+})
+})
diff --git a/content/posts/2023-09-12-dns_tracking.md b/content/posts/2023-09-12-dns_tracking.md
new file mode 100644
index 0000000..ec78fec
--- /dev/null
+++ b/content/posts/2023-09-12-dns_tracking.md
@@ -0,0 +1,152 @@
+---
+layout: :theme/post
+title: "Network Observability Per Flow DNS tracking"
+description: "Why? Because it's always DNS"
+tags: eBPF,DNS,Monitoring,Troubleshooting
+authors: [jpinsonneau,memodi,msherif1234]
+---
+
+
+
+})
+
+In today's interconnected digital landscape, Domain Name System (DNS) tracking
+plays a crucial role in networking and security. DNS resolution is a fundamental
+process that translates human-readable domain names into IP addresses, enabling
+communication between devices and servers. It can also be a security vulnerability
+and a tool for firewalling and blocking access to content, depending on how it is
+configured and manipulated. For operations excellence, DNS
+resolution benefits from monitoring and analysis, which can be achieved through
+innovative technologies like eBPF (extended Berkeley Packet Filter). In this
+blog post, we'll delve into the world of DNS tracking using eBPF tracepoint
+hooks, exploring how this powerful combination can be used for various purposes,
+including network monitoring and security enhancement.
+
+## Understanding DNS Resolution
+
+Before diving into the specifics of eBPF tracepoint hooks, let's briefly recap
+how DNS resolution works. In a Kubernetes architecture, DNS plays a critical role
+in enabling communication between various components and services within the cluster.
+Kubernetes uses DNS to facilitate service discovery and to resolve domain names
+to the corresponding IP addresses of pods or services.
+This process involves multiple steps, including querying DNS
+servers, caching responses, obtaining the IP address to establish a connection
+and caching response for future re-occurrence of the same DNS query.
+
+## Utilizing Tracepoint Hooks for DNS Tracking
+
+Tracepoint hooks are predefined points in the Linux kernel where eBPF programs
+can be attached to capture and analyze specific events. For DNS tracking, we
+leveraged tracepoint hooks associated with DNS resolution processes,
+specifically the `tracepoint/net/net_dev_queue` tracepoint. Then we parse the
+DNS header to determine if it is a query or a response, attempt to correlate the
+query or response with a specific DNS transaction, and then record the elapsed time
+to compute DNS latency. Furthermore, DNS network flows are enriched with DNS-related
+fields (id, latency and response codes) to help build graphs
+with aggregated DNS statistics and to help filtering on specific fields for display
+in the Network Observability console.
+
+## Potential Use Cases
+
+DNS tracking with eBPF tracepoint hooks can serve various purposes:
+
+- Network Monitoring: Gain insights into DNS queries and responses, helping
+ network administrators identify unusual patterns, potential bottlenecks, or
+ performance issues.
+
+- Security Analysis: Detect suspicious DNS activities, such as domain name
+ generation algorithms (DGA) used by malware, or identify unauthorized DNS
+ resolutions that might indicate a security breach.
+
+- Troubleshooting: Debug DNS-related issues by tracing DNS resolution steps,
+ tracking latency, and identifying misconfigurations.
+
+## How to enable DNS tracking
+
+By default DNS tracking is disabled because it requires `privileged` access. To
+enable this feature we need to create a flow collector object with the following
+fields enabled in eBPF config section as below:
+
+```yaml
+apiVersion: flows.netobserv.io/v1beta1
+kind: FlowCollector
+metadata:
+ name: cluster
+spec:
+ agent:
+ type: EBPF
+ ebpf:
+ privileged: true
+ features:
+ - DNSTracking
+```
+
+## A quick tour in the UI
+
+Once the `DNSTracking` feature is enabled, the Console plugin will automatically
+adapt to provide additional filters and show informations across views.
+
+Open your OCP Console and move to `Administrator view` -> `Observe` ->
+`Network Traffic` page as usual.
+
+Three new filters, `DNS Id`, `DNS Latency` and `DNS Response Code` will be
+available in the common section:
+
+})
+
+The first one will allow you to filter on a specific DNS Id (found using `dig`
+command or in flow table details) to correlate with your query.
+
+})
+
+The second one helps to identify potential performance issues by looking at DNS
+resolution latency.
+
+})
+
+The third filter surfaces DNS response codes, which can help detect errors or
+unauthorized resolutions.
+
+})
+
+### Overview
+
+New graphs are introduced in the `advanced options` -> `Manage panels` popup:
+
+})
+
+- Top X average DNS latencies
+- Top X DNS response code
+- Top X DNS response code stacked with total
+
+})
+})
+
+### Traffic flows
+
+The table view adds the new DNS columns `Id`, `Latency` and `Response code`,
+which are available from the `advanced options` -> `manage columns` popup.
+
+})
+
+The DNS flows display this information in both the table and the side panel:
+
+})
+
+## Future support
+
+- Adding tracking capability for mDNS
+
+- Adding support for DNS over TCP
+
+- Investigating options to handle DNS over TLS where the DNS header is fully
+ encrypted.
+
+## Feedback
+
+We hope you liked this article !
+
+Netobserv is an OpenSource project [available on github](https://github.com/netobserv).
+Feel free to share your [ideas](https://github.com/netobserv/network-observability-operator/discussions/categories/ideas), [use cases](https://github.com/netobserv/network-observability-operator/discussions/categories/show-and-tell) or [ask the community for help](https://github.com/netobserv/network-observability-operator/discussions/categories/q-a).
diff --git a/content/posts/2023-09-12-packet_drops.md b/content/posts/2023-09-12-packet_drops.md
new file mode 100644
index 0000000..0d65ae0
--- /dev/null
+++ b/content/posts/2023-09-12-packet_drops.md
@@ -0,0 +1,190 @@
+---
+layout: :theme/post
+title: "Network Observability Real-Time Per Flow Packets Drop"
+description: "Monitoring packet drops helps understanding network performance or configuration issues"
+tags: eBPF,Drops,Monitoring,Troubleshooting
+authors: [Amoghrd,jpinsonneau,msherif1234]
+---
+
+
+
+})
+
+In OCP ensuring efficient packet delivery is crucial for maintaining smooth
+communication between applications. However, due to various factors such
+as network congestion, misconfigured systems, or hardware limitations,
+packets might occasionally get dropped. Detecting and diagnosing these
+packet drops is essential for optimizing network performance and
+maintaining a high quality of service.
+
+This is where eBPF (extended Berkeley Packet Filter) comes into play
+as a powerful tool for real-time network performance analysis.
+In this blog, we'll take a detailed look at how network observability
+using eBPF can help in detecting and understanding packet drops,
+enabling network administrators and engineers to proactively
+address network issues.
+
+## Detecting Packet Drops with eBPF
+
+eBPF enables developers to set up tracepoints at key points within the network
+stack. These tracepoints can help intercept packets at specific events,
+such as when they are received, forwarded, or transmitted.
+By analyzing the events around packet drops, you can gain insight into the
+reasons behind them.
+In network observability we are using the `tracepoint/skb/kfree_skb` tracepoint hook
+to detect when packets are dropped, determine the reason why packets drop and reconstruct
+the flow by enriching it with drop metadata such as packets and bytes statistics,
+For TCP, only the latest TCP connection state as well as the TCP connection flags
+are added.
+The packet drops eBPF hook supports TCP, UDP, SCTP, ICMPv4 and ICMPv6 protocols.
+There are two main categories for packet drops. The first category, core
+subsystem drops,covers most of the host drop reasons; for the complete
+list please refer to
+[drop-reason](https://github.com/torvalds/linux/blob/master/include/net/dropreason-core.h).
+Second, there are OVS-based drops, which is a recent kernel enhancement;
+for reference please checkout the following link
+[OVS-drop-reason](https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/openvswitch/drop.h).
+
+## Kernel support
+
+The drop cause tracepoint API is a recent kernel feature only available from RHEL9.2
+kernel version. Older kernel will ignore this feature if its configured.
+
+## How to enable packet drops
+
+By default packets drops detection is disabled because it requires
+`privileged` access to the host kernel. To enable the feature we need
+to create a `FlowCollector` object with the following fields enabled in eBPF config
+section
+
+```yaml
+apiVersion: flows.netobserv.io/v1beta1
+kind: FlowCollector
+metadata:
+ name: cluster
+spec:
+ agent:
+ type: EBPF
+ ebpf:
+ privileged: true
+ features:
+ - PacketDrop
+```
+
+## A quick tour in the UI
+
+Once the `PacketDrop` feature is enabled, the OCP console plugin automatically adapts to provide
+additional filters and show information across Netflow Traffic page views.
+
+Open your OCP Console and move to
+`Administrator view` -> `Observe` -> `Network Traffic` page as usual.
+
+Now, a new query option is available to filter flows by their drop status:
+
+})
+
+- `Fully dropped` shows the flows that have 100% dropped packets
+- `Containing drops` shows the flows having at least one packet dropped
+- `Without drops` show the flows having 0% dropped packets
+- `All` shows all of the above
+
+Two new filters, `Packet drop TCP state` and `Packet drop latest cause` are available
+in the common section:
+
+})
+
+The first one will allow you to set the TCP state filter:
+
+})
+
+- A _LINUX_TCP_STATES_H number like 1, 2, 3
+- A _LINUX_TCP_STATES_H TCP name like `ESTABLISHED`, `SYN_SENT`, `SYN_RECV`
+
+The second one will let you pick causes to filter on:
+
+})
+
+- A _LINUX_DROPREASON_CORE_H number like 2, 3, 4
+- A _LINUX_DROPREASON_CORE_H SKB_DROP_REASON name like
+ `NOT_SPECIFIED`,`NO_SOCKET`, `PKT_TOO_SMALL`
+
+### Overview
+
+New graphs are introduced in the `advanced options` -> `manage panels` popup:
+
+})
+
+- Top X flow dropped rates stacked
+- Total dropped rate
+- Top X dropped state
+- Top X dropped cause
+- Top X flow dropped rates stacked with total
+
+Select the desired graphs to render them in the overview panel:
+
+})
+})
+})
+
+Note that you can compare the top drops against total dropped or total traffic
+in the last graph using the kebab menu
+})
+
+### Traffic flows
+
+The table view shows the number of `bytes` and `packets` sent in green and the
+related numbers dropped in red. Additionally, you can get details about the
+drop in the side panel that brings you to the proper documentation.
+
+})
+
+### Topology
+
+Last but not least, the topology view displays edges containing drops in red.
+That's useful especially when digging on a specific drop reason between two resources.
+
+})
+
+## Potential use-case scenarios
+
+- `NO_SOCKET` drop reason: There might be packet drops observed due to the
+ destination port being not reachable. This can be emulated by running a
+ curl command on a node to an unknown port
+
+```bash
+while : ; do curl :; sleep 5; done
+```
+
+The drops can be observed on the console as seen below:
+
+})
+
+})
+
+- `OVS_DROP_LAST_ACTION` drop reason: OVS packet drops can be observed on
+ RHEL9.2 and above. It can be emulated by running the iperf command with
+ network-policy set to drop on a particular port.
+ These drops can be observed on the console as seen below:
+
+})
+
+})
+
+})
+
+## Resource impact of using PacketDrop
+
+The performance impact of using PacketDrop enabled with the Network
+Observability operator is noticeable on the flowlogs-pipeline(FLP)
+component using ~22% and ~9% more vCPU and memory respectively when
+compared to baseline whereas the impact on other components in not
+significant (less than 3% increase).
+
+## Feedback
+
+We hope you liked this article !
+
+Netobserv is an OpenSource project [available on github](https://github.com/netobserv).
+Feel free to share your [ideas](https://github.com/netobserv/network-observability-operator/discussions/categories/ideas), [use cases](https://github.com/netobserv/network-observability-operator/discussions/categories/show-and-tell) or [ask the community for help](https://github.com/netobserv/network-observability-operator/discussions/categories/q-a).
diff --git a/content/posts/2023-10-02-lokiless.md b/content/posts/2023-10-02-lokiless.md
new file mode 100644
index 0000000..e156366
--- /dev/null
+++ b/content/posts/2023-10-02-lokiless.md
@@ -0,0 +1,292 @@
+---
+layout: :theme/post
+title: "Deploying Network Observability without Loki: an example with ClickHouse"
+description: "Keep your existing infrastructure to integrate with NetObserv"
+tags: Infrastructure,Storage,ClickHouse,Loki
+authors: [jotak]
+---
+
+
+
+This blog post talks about a new feature that comes with Network Observability (NetObserv) 1.4: the ability to deploy it without Loki, coupled with exporting flows to an alternative storage. It clarifies what this change is and what it isn't. Then it demonstrates the optional configuration for consuming flows outside of Loki. Finally, it explores potential avenues for future development that this feature enables.
+
+## A brief history
+
+When we started the NetObserv project, one of the first architectural questions was, as you could expect, which storage solution to adopt. It has to be robust for a write-intensive application, with indexing capabilities on large data sets, scalable, while still allowing to run complex queries. It must be able to store structured logs and to extract time-series from them. Features like full-text indexing or data mutability aren't required. On top of that, the license must be compatible with our needs. We ended up with a shortlist that included Grafana Loki, OpenDistro, Influx and a few others. This was two years ago.
+
+We also talked with other OpenShift teams having similar requirements, such as the Logging and the Distributed Tracing teams, and got some feedback to eventually rule out candidates with supposedly higher operational costs. And since the Logging team had already planned to invest in the Loki Operator, that was a nice opportunity to mutualize some efforts. Ok, let's be honest: that was a huge time saver especially for us, thanks so much folks!
+
+## Why change now?
+
+To be clear, **we aren't actually moving away from Loki**. Loki remains the one and only storage solution that we fully support at the moment, and our console plugin is entirely based on queries to Loki, in its _logql_ format. However, we have seen some people using NetObserv in a way that we didn't expect: for example, deploying it without Loki and configuring flow exporters with Kafka or IPFIX. Why? It turns out that they are more interested in the kube-enriched raw flow data than in the visualizations that NetObserv provides, and dealing with a new backend storage setup and maintenance is undesirable for them. Which, admittedly, is a quite reasonable argument.
+
+To summarize, here's the deal:
+- 💰: you save on operational aspects by not deploying Loki or any storage that would be new to you.
+- 💔: you lose all the fancy dashboards that we build with so much love.
+- 👩🏽🔧: you need to create your own consumer — Kafka or IPFIX — for doing anything with the exported flows: this is on your plate. But you will see below that it's nothing insurmountable.
+
+## What is changed
+
+Before 1.4, NetObserv was designed with Loki as a requirement. If you did not configure the Loki endpoint, our _flowlogs-pipeline_ component still sent flows to a default URL (and failed), and our console plugin still tried to query Loki (and failed). While the latter isn't too annoying for someone who doesn't intend to use the console plugin, the former could be the cause of performance degradation.
+
+So this is what we did: **we "just" added an _enable_ knob for Loki**. With Loki turned off, _flowlogs-pipeline_ obviously doesn't try to send anything to it. And since the console plugin becomes useless without Loki, it isn't deployed anymore in that case.
+
+})
+_NetObserv architecture diagram: before and after 1.4_
+
+As the diagram shows, if we choose to remove Loki, capabilities of the flows pipeline downstream remain:
+
+- The ability to generate Prometheus metrics. Those metrics and their related dashboards are still accessible in the OpenShift Console, independently from our plugin.
+- The ability to set up one or several exporters downstream the pipeline, such as via Kafka or to any IPFIX collector. This is then up to you to consume this data for any purpose.
+
+## Example use case
+
+Enough theory, let's put it into practice: we are going to set up NetObserv to export enriched flows to Kafka, and we will create a very simple consumer that stores them in a [ClickHouse database](https://clickhouse.com/). To do so, we created a sample application: [kafka-clickhouse-example](https://github.com/jotak/kafka-clickhouse-example/).
+
+For simplicity, ClickHouse is deployed locally and [ktunnel](https://github.com/omrikiei/ktunnel) is used for reverse port-forwarding, magically bringing ClickHouse "into" the cluster. Obviously, you won't need `ktunnel` when using a real ClickHouse server.
+
+### Prerequisites
+
+- An OpenShift or Kubernetes cluster
+- [NetObserv operator](https://github.com/netobserv/network-observability-operator) installed (do not install a `FlowCollector` yet).
+- ClickHouse binary: grab it as explained in their [quick install guide](https://clickhouse.com/docs/en/install#quick-install).
+- [ktunnel](https://github.com/omrikiei/ktunnel) binary.
+- Some common tools such as `curl`, `kubectl`, `envsubst`...
+
+> Note: These steps have been tested on a small OCP 4.13 cluster with 3 worker nodes. There is no one-size-fits-all configuration, so you might need to adapt some settings depending on your environment, such as [the Kafka configuration](https://github.com/jotak/kafka-clickhouse-example/blob/main/contrib/kafka.yaml).
+
+### Start ClickHouse with ktunnel
+
+Using the ClickHouse binary that you downloaded, run:
+
+```bash
+./clickhouse server
+```
+
+This starts a ClickHouse server that listens on `:9000` on your machine.
+
+In another terminal, setup ktunnel:
+
+```bash
+ktunnel expose clickhouse 9000:9000
+```
+
+You should see something like this:
+
+```
+INFO[0000] Exposed service's cluster ip is: 172.30.115.68
+INFO[0000] ProgressDeadlineInSeconds is currently 600s. It may take this long to detect a deployment failure.
+INFO[0000] waiting for deployment to be ready
+INFO[0005] deployment "clickhouse" successfully rolled out
+INFO[0005] port forwarding to https://api.yourcluster.com:6443/api/v1/namespaces/default/pods/clickhouse-958f5476f-wwj6g/portforward
+INFO[0005] Waiting for port forward to finish
+INFO[0005] Forwarding from 127.0.0.1:28688 -> 28688
+Forwarding from [::1]:28688 -> 28688
+INFO[2023-09-25 16:45:23.710] starting tcp tunnel from source 9000 to target localhost:9000
+```
+
+It creates a `clickhouse` service in the `default` namespace, bridged to your local server.
+
+### Prepare Kafka
+
+The steps here are very similar to the [Kafka deployment script](https://github.com/netobserv/network-observability-operator/blob/release-1.4/.mk/development.mk#L54-L63) that we use in NetObserv for development and testing purposes. They use [Strimzi](https://strimzi.io/) - the upstream of AMQ Streams for OpenShift - to get Kafka in the cluster, and a topic named "flows-export" is pre-created.
+
+```bash
+# Create a namespace for all the deployments
+kubectl create namespace netobserv
+
+# Install Strimzi (Kafka)
+kubectl apply -f https://strimzi.io/install/latest?namespace=netobserv -n netobserv
+export DEFAULT_SC=$(kubectl get storageclass -o=jsonpath='{.items[?(@.metadata.annotations.storageclass\.kubernetes\.io/is-default-class=="true")].metadata.name}') && echo "Using SC $DEFAULT_SC"
+curl -s -L "https://raw.githubusercontent.com/jotak/kafka-clickhouse-example/main/contrib/kafka.yaml" | envsubst | kubectl apply -n netobserv -f -
+
+# Wait that all pods are up and running, with the KafkaTopic being ready (a few minutes...)
+kubectl wait --timeout=180s --for=condition=ready kafkatopic flows-export -n netobserv
+kubectl get pods -n netobserv
+```
+
+When listing pods, you should see something like this:
+
+```
+NAME READY STATUS RESTARTS AGE
+kafka-cluster-entity-operator-5f5bc5675b-lpmmc 3/3 Running 0 3m33s
+kafka-cluster-kafka-0 1/1 Running 0 4m47s
+kafka-cluster-kafka-1 1/1 Running 0 4m47s
+kafka-cluster-kafka-2 1/1 Running 0 4m47s
+kafka-cluster-zookeeper-0 1/1 Running 0 5m15s
+kafka-cluster-zookeeper-1 1/1 Running 0 5m15s
+kafka-cluster-zookeeper-2 1/1 Running 0 5m15s
+strimzi-cluster-operator-6bdcd796f6-qsc4g 1/1 Running 0 17m
+```
+
+### Prepare NetObserv
+
+Assuming you already installed the operator, now you must create a `FlowCollector` resource to start sending flow logs to Kafka. For the purpose of this article, we don't install and configure Loki but be informed that you can export flows to one or multiple endpoints and save them into Loki in parallel according to your needs.
+
+> Note: we configure here Kafka as an **exporter**, which is unrelated to the `spec.deploymentModel: KAFKA` / `spec.kafka` settings: those ones correspond to NetObserv's internal flows processing configuration (NetObserv being both the producer and the consumer), whereas `spec.exporters` relates to NetObserv being just the producer, leaving up to us how we want to consume that data.
+
+```bash
+cat < Note: all the code snippets below are taken from [this repository](https://github.com/jotak/kafka-clickhouse-example/).
+
+It reads messages from Kafka:
+
+```
+// ... running in a loop ...
+
+ m, err := r.ReadMessage(context.Background())
+ if err != nil {
+ break
+ }
+ if flow, err := decode(m.Value); err != nil {
+ klog.Errorf("failed to decode: %v", err)
+ } else {
+ out <- flow
+ }
+
+// ...
+
+func decode(b []byte) (map[string]interface{}, error) {
+ var rawLine map[string]interface{}
+ err := json.Unmarshal(b, &rawLine)
+ return rawLine, err
+}
+```
+
+It gets fields from deserialized JSON:
+
+```
+ if v, ok := rawFlow[fields.Bytes]; ok {
+ bytes = int(v.(float64))
+ }
+ if v, ok := rawFlow[fields.Packets]; ok {
+ packets = int(v.(float64))
+ }
+ // etc.
+```
+
+And it executes the insert query:
+
+```
+ if err := conn.Exec(
+ context.Background(),
+ "INSERT INTO flows VALUES (?,?,?,?,?,?,?,?,?,?,?,?)",
+ flowStart, flowEnd, srcAddr, dstAddr, srcName, dstName, srcKind, dstKind, srcNamespace, dstNamespace, bytes, packets,
+ ); err != nil {
+ klog.Warnf("Insertion error: %v", err)
+ }
+```
+
+That's about it.
+
+It only maps a subset of the available flow data. You can check the [JSON reference](https://docs.openshift.com/container-platform/latest/networking/network_observability/json-flows-format-reference.html) to learn about all the fields.
+
+If you want to adapt it in a secure environment, you need to configure the [kafka-go client](https://github.com/segmentio/kafka-go#tls-support) for TLS/mTLS/SASL, and the [clickhouse-go client](https://github.com/ClickHouse/clickhouse-go#tlsssl) for TLS and setting up credentials.
+
+## What's next?
+
+We hope that you enjoyed reading this post and that it opens up new horizons about what you can do with NetObserv.
+
+What are our next steps regarding storage? To be honest, nothing yet acted in the roadmap at the time of writing, and this is why we'd love to get your feedback.
+
+Some ideas: we could improve the storage-less experience by still enabling our console plugin, with the same dashboards, flow table, topology as with Loki - the only difference being that it would be limited in terms of querying past data, only live flows would be accessible. That would probably involve using Kafka as a flow forwarder.
+
+We could also investigate other storage options. But as you can imagine, maintaining several options in parallel comes at a cost. Especially as the query languages are far from being standardized in the observability landscape. Well... at least at the moment: we keep an eye on an initiative that could be a game changer for us: [a query standard for observability](https://docs.google.com/document/d/1JRQ4hoLtvWl6NqBu_RN8T7tFaFY5jkzdzsB9H-V370A/edit). Think like OpenTelemetry, but for queries. How nice would it be?
+
+Finally, if you feel inspired by this flow consumer app, but you would expect something directly usable out of the box, production-ready... Then, why not collaborate in the open? We would love to see open-source contributions on this field. We could for instance create new repositories for community-maintained connectors, hosted on NetObserv's GitHub, and would of course provide all the help and expertise that we can, if there is demand for that.
+
+Any other ideas, or something to say? Don't hesitate to comment or ask questions on [our discussion board](https://github.com/netobserv/network-observability-operator/discussions)! A thread has been created specifically for this blog post: [here](https://github.com/netobserv/network-observability-operator/discussions/438).
diff --git a/content/posts/2023-10-02-secondary_interface.md b/content/posts/2023-10-02-secondary_interface.md
new file mode 100644
index 0000000..1d0104a
--- /dev/null
+++ b/content/posts/2023-10-02-secondary_interface.md
@@ -0,0 +1,160 @@
+---
+layout: :theme/post
+title: "Network Observability secondary interface support"
+description: "Are you blind to traffic on secondary interfaces? Of course not"
+tags: Monitoring,Network,Multus,SRIOV
+authors: [msherif1234]
+---
+
+
+
+Network observability for secondary interfaces with Multus and SR-IOV plugins
+in Kubernetes can be a complex task, but it's crucial for monitoring and
+troubleshooting network issues in a Kubernetes cluster.
+
+## Overview of how you can achieve network observability for secondary interface
+
+
+
+
+
+1. **Multus CNI Plugin**: Multus is a CNI (Container Network Interface) plugin
+ for Kubernetes that allows you to attach multiple network interfaces to pods.
+ In Openshift Multus is used to attach SR-IOV vfs to your pods.
+ For reference and more details about Multus CNI please refer to
+ [Multus OCP documentation](https://docs.openshift.com/container-platform/4.13/networking/multiple_networks/understanding-multiple-networks.html)
+
+2. **SR-IOV Plugin**: SR-IOV (Single Root I/O Virtualization) is a technology that
+ enables the partitioning of a single PCIe network adapter into multiple virtual
+ functions (VFs).
+ Pods can then use these VFs as secondary network interfaces, achieving higher
+ network performance and isolation.
+ For reference and more details about SR-IOV pls refer to
+ [SR-IOV OCP documentation](https://docs.openshift.com/container-platform/4.13/networking/hardware_networks/configuring-sriov-device.html)
+
+## Network observability eBPF agent enhancements to support the secondary interface
+
+To ensure network observability for secondary interfaces in this setup, and make
+the eBPF agent network namespace aware, eBPF agents need to implement the
+following steps:
+
+1. Using fsNotify Package:
+ Utilize the fsNotify package to be notified when new network namespaces are created.
+ This allows the eBPF agent to keep track of network namespace creation events.
+
+2. Using netlink Package:
+ Employ the netlink package to register when the network interfaces are created or deleted
+ within each network namespace. This will enable the eBPF agent to monitor the interface
+ changes on a per-namespace basis.
+
+3. Attach/Detach eBPF TC Hooks:
+ Add support to the eBPF agent to attach and detach eBPF Traffic Control (TC) hook
+ for network interfaces in non-default network namespaces. This step is crucial for
+ monitoring and controlling network traffic within these network namespaces.
+
+## Configuring SR-IOV objects
+
+1. Install the SR-IOV operator in the environment.
+2. Identify the SR-IOV capable device on the node.
+3. Label the node which has SR-IOV interface with the label
+ `feature.node.kubernetes.io/network-sriov.capable=true`
+4. Create the `SriovNetworkNodePolicy` object
+
+```yaml
+apiVersion: sriovnetwork.openshift.io/v1
+kind: SriovNetworkNodePolicy
+metadata:
+ name: mypolicy
+ namespace: openshift-sriov-network-operator
+spec:
+ resourceName: netdeviceresource
+ nodeSelector:
+ feature.node.kubernetes.io/network-sriov.capable: "true"
+ priority: 99
+ numVfs: 50
+ nicSelector:
+ pfNames: ["ens7f0np0#25-49"]
+ deviceType: netdevice
+```
+
+5. Create the `SriovNetwork` object. This will create net-attach-def in
+ the `openshift-sriov-network-operator` namespace.
+
+```yaml
+apiVersion: sriovnetwork.openshift.io/v1
+kind: SriovNetwork
+metadata:
+ name: sriov-test
+ namespace: openshift-sriov-network-operator
+spec:
+ resourceName: netdeviceresource
+ networkNamespace: test
+ ipam: '{ "type": "static", "addresses": [{"address": "192.168.122.71/24"}]}'
+```
+
+6. Create a test pod using the `SRIOVNetwork` object created above and
+ denoted by annotation, `k8s.v1.cni.cncf.io/networks: "sriov-test"`
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+ name: httpd-2
+ namespace: openshift-sriov-network-operator
+ labels:
+ app: sriov
+ annotations:
+ k8s.v1.cni.cncf.io/networks: "sriov-test"
+spec:
+ containers:
+ - name: httpd
+ command: ["sleep", "30d"]
+ image: registry.redhat.io/rhel8/support-tools
+ ports:
+ - containerPort: 8080
+ securityContext:
+ allowPrivilegeEscalation: false
+ seccompProfile:
+ type: RuntimeDefault
+ capabilities:
+ drop:
+ - ALL
+```
+
+## Configuring the network observability operator to work with SR-IOV
+
+1. Deploy the network observability operator.
+
+2. Create the `FollowCollector` object with `privileged` set to `true`.
+
+```yaml
+apiVersion: flows.netobserv.io/v1beta1
+kind: FlowCollector
+metadata:
+ name: cluster
+spec:
+ agent:
+ type: EBPF
+ ebpf:
+ privileged: true
+```
+
+Network observability operator will deploy it's components (eBPF agent, flowlogs pipeline and
+console plugin), the eBPF agent will start discovering all the interfaces and attach the eBPF
+hooks, flows start being collected
+
+## Sample Network observability raw flow output by filtering on Pod VF interface `net1`
+
+By opening the console plugin and looking in the Traffic Flows table and filter by
+`Network interface name == net1` like the following for TCP flow
+packets as an example
+
+
+
+## Feedback
+
+Netobserv is an OpenSource project [available on github](https://github.com/netobserv).
+Feel free to share your
+[ideas](https://github.com/netobserv/network-observability-operator/discussions/categories/ideas), [use cases](https://github.com/netobserv/network-observability-operator/discussions/categories/show-and-tell) or [ask the community for help](https://github.com/netobserv/network-observability-operator/discussions/categories/q-a).
\ No newline at end of file
diff --git a/content/posts/2023-10-16-whats_new_1_4.md b/content/posts/2023-10-16-whats_new_1_4.md
new file mode 100644
index 0000000..3d00fcb
--- /dev/null
+++ b/content/posts/2023-10-16-whats_new_1_4.md
@@ -0,0 +1,161 @@
+---
+layout: :theme/post
+title: "What's new in Network Observability 1.4"
+description: "Check out the new features: TCP latency, DNS metrics, drop metrics, SR-IOV and more..."
+tags: What's New,SRIOV,Drops,DNS,Latency
+authors: [stleerh]
+---
+
+
+
+OpenShift Container Platform (OCP) is the leading Kubernetes environment for managing container-based applications. However, this is just the core platform. If you go to **OperatorHub** on the OpenShift web console (UI), you will see hundreds of *optional* operators, which are analogous to extensions for your browser. Buried in this operator gold mine is one called Network Observability.
+
+Network Observability 1.4, as the release number suggests, is not new. The team has put out four feature releases since its first general availability back in January 2023. It has grown significantly since I wrote a [blog about Network Observability 1.0](https://cloud.redhat.com/blog/check-out-the-new-network-observability-support-in-openshift-4.12). This release supports OCP 4.11 and above.
+
+The focus of this blog is the new features in 1.4, but a quick word about Network Observability. It is a tool that collects traffic flows using an eBPF agent and then enriches and stores them as logs and metrics to provide valuable insight and visualization into your network. In case you've been living under a rock (I mean, a gold crystal) in the Linux world, [eBPF](https://en.wikipedia.org/wiki/EBPF) is the technology that allows you to extend the kernel capabilities without having to write a messy kernel module. It uses various probes to get some really cool statistics that would otherwise be difficult to get, which we will dive into later in this blog.
+
+## Features
+
+All of the 1.4 features and enhancements can be put into four categories. They are:
+
+1. Hardware
+ - Support for SR-IOV interfaces
+ - Support on [IBM Z](https://www.ibm.com/z) architecture
+
+2. Traffic
+ - Packet drops
+ - DNS tracking information
+ - Export flows and dashboards without Loki
+ - Enhancements to Network Observability dashboards
+ - Round Trip Time (RTT) { developer preview }
+
+3. UI/UX
+ - Comparison operator field in filtering
+ - "Swap" source and dest
+ - "Back and forth" to include return traffic
+ - Vertical slider for changing scopes in Topology
+
+4. Performance and scalability
+
+Some features require the Network Observability eBPF agent to be configured to enable that particular feature. This is done when you create a Flow Collector instance. After installing the Network Observability operator, click the **Flow Collector** link as shown below.
+
+})
+
+This brings up the **Create FlowCollector** panel. Follow the steps for that feature to enable it.
+
+
+## Hardware
+
+### SR-IOV Interfaces
+
+SR-IOV is a hardware standard to virtualize a NIC. In netdevice mode, the eBPF agent can now provide traffic flows that go through these interfaces. To enable this feature, when creating the FlowCollector instance, you must enable *privileged* mode. This is in the **Create FlowCollector** form view under ***agent > ebpf > privileged***.
+
+})
+
+
+
+### IBM Z
+
+In the last release, we added support for IBM Power and ARM. We now officially support IBM Z as well. Long live the mainframes!
+
+## Traffic
+
+On traffic features, Network Observability is providing additional information that is directly relevant to troubleshooting packet drops, DNS, and latency issues. We plan to publish more details about these features and how to use them in future blogs.
+
+### Packet drops
+
+The eBPF agent can get real-time packet drops per flow for TCP, UDP, SCTP, and ICMPv4/v6 (such as ping). To enable this feature, when creating the FlowCollector instance, you must enable *privileged* mode and the *PacketDrop* feature. This is in the **Create FlowCollector** form view under ***agent > ebpf > privileged*** and ***agent > ebpf > features***.
+
+})
+
+Now decide how you want to filter packet drops. In **Observe > Network Traffic** under **Query options**, select whether to show flows that have all packets dropped, at least one packet dropped, no packets dropped, or no filter. Be careful if you select "no packets dropped", as that means you won't see flows with packet drops. Then in the filter field, there are new filters for the TCP state and the drop cause. See the highlighted red areas below that it's referring to in web console. You also need to be running OCP 4.13 or higher.
+
+})
+
+The **Overview** tab has several new packet drop graphs, two of which are shown below.
+
+})
+
+Click **Show advanced options** (which then becomes *Hide advanced options*) to reveal **Manage panels**. Click this link to choose what graphs to display.
+
+
+
+The **Traffic flows** tab shows the bytes and packet counts of what has been dropped in red. The **Topology** tab displays a red link between vertices where packet drops have occurred.
+
+
+
+
+
+
+### DNS tracking information
+
+DNS is one networking area that is the source of potential problems. This feature provides information on DNS ID, latency, and response code and the ability to filter on these fields. To enable this feature, when creating the FlowCollector instance, you must enable *privileged* mode and the *DNSTracking* feature. This is in the **Create FlowCollector** form view under ***agent > ebpf > privileged*** and ***agent > ebpf > features***. See the screenshot in the **Packet drops** section above on where to configure this.
+
+Like the Packet Drops feature, there are new DNS graphs in the **Overview** tab. See above on how to display them. There are also new DNS columns in the traffic flows table.
+
+})
+
+### Export flows and dashboards without Loki
+
+If you only want to export flows to a Kafka consumer or to an IPFIX collector, it is no longer necessary to install Loki. Without Loki and internal flow storage, the netobserv console plugin is not installed, which means you don't get the **Observe > Network Traffic** panel and hence no Overview graphs, Traffic flows table, and Topology. You will still get flow metrics in **Observe > Dashboards**.
+
+### Enhancements to Network Observability dashboards
+
+Speaking of dashboards, in **Observe > Dashboards, NetObserv / Health** selection, there is a new Flows Overhead graph that shows the percentage of flows generated by Network Observability itself.
+
+})
+
+The dashboard under **NetObserv** was also changed to separate applications and infrastructure.
+
+})
+
+### Round Trip Time (RTT)
+
+Round Trip Time (RTT) is a development preview feature that shows the latency for the TCP handshake process on a per-flow basis. To enable this feature, when creating the FlowCollector instance, you must enable the *FlowRTT* feature. This is in the **Create FlowCollector** form view under ***agent > ebpf > features***. See the screenshot in the **Packet drops** section above on where to configure this. Note the eBPF *privileged* feature is not required. It is also recommended to set sampling to 1 (or a low value) in order to not miss the TCP handshaking packets (SYN and ACK).
+
+The **Overview** tab has two new RTT graphs shown below.
+
+})
+
+The **Traffic flows** tab adds the *Flow RTT* column. In the table below, it filters and displays all flows that take more than 1 millisecond (the value is in nanoseconds).
+
+})
+
+## UI/UX
+
+### Comparison operator field in filtering
+
+To the left of the filter field (see figure above on **Query options**) is a new field for the comparison operator. Previously, the only comparison operator was an implied "equals" comparison. Now, you can filter on "not equals" or "more than" for numeric value comparisons such as DNS latency or Flow RTT.
+
+### "Swap" source and dest
+
+When you click *Swap* in the filter section, it changes all the source values to dest and vice versa. This makes it convenient to do this operation.
+
+
+
+### "Back and forth" to include return traffic
+
+Before this change, **Query options** had a Reporter section where you chose Source, Destination, or Both. For external traffic, you either got half the traffic or all the traffic duplicated depending on your selection. This now gives you two similar options. Choose *One way* (default) to get the traffic exactly in one direction. Choose *Back and forth* to let it figure out and do the right thing for you. You don't have to think about ingress, egress... I digress! The *Direction* column in the flows table will show one of *ingress*, *egress*, or the new *inner*, which indicates inter-node traffic.
+
+
+
+### Vertical slider for changing scopes in Topology
+
+The scope in Topology determines what is shown for the vertices in the graph. The highest level view is to show Kubernetes nodes for the vertices by selecting Node. The next level is Namespace, followed by Owner (typically a Deployment, StatefulSet, or DaemonSet), and finally Resource for the specific pod to pod/service communication. Prior to this, the selection was under **Query options**. Now it is visible as a vertical slider on the topology as shown on the right.
+
+
+## Performance and scalability
+
+We are constantly looking to improve the performance and scalability of the operator at the same time while reducing the resource footprint without compromising on visibility that matters. We have published a set of [guidelines](https://docs.openshift.com/container-platform/4.13/networking/network_observability/configuring-operator.html#network-observability-resources-table_network_observability) on the same, and we are looking to evolve this over a period of time.
+
+
+## Conclusion
+
+I hope you enjoy the new features. This was a high level overview of this release and going forward, we plan to publish other blogs to describe the features in more details. In the meantime, continue mining for that data nugget!
+
+
+---
+
+Special thanks to Julien Pinsonneau, Mohamed Mahmoud, Joel Takvorian, Dave Gordon, Sara Thomas, and Deepthi Dharwar for providing feedback, advice, and ensuring accuracy in this article.
diff --git a/content/posts/2023-12-05-acm.md b/content/posts/2023-12-05-acm.md
new file mode 100644
index 0000000..3401f30
--- /dev/null
+++ b/content/posts/2023-12-05-acm.md
@@ -0,0 +1,263 @@
+---
+layout: :theme/post
+title: "Leveraging NetObserv metrics in RHACM"
+description: "How to get all the NetObserv metrics in a multi-cluster environment"
+tags: ACM,Multicluster,Metrics,Monitoring
+authors: [jotak]
+---
+
+
+
+_Credits: Scott Berens, Sara Thomas, Julien Pinsonneau, Steven Lee, Olivier Cazade: thank you for kindly reviewing_
+
+## What is RHACM?
+
+Red Hat Advanced Cluster Management for Kubernetes (RHACM) provides end-to-end management visibility and control to manage a multi-cluster Kubernetes / OpenShift environment. It can be deployed with an OLM operator and is integrated with the OpenShift Console, with all managed clusters being supervised from a hub cluster console. For more information, see [blog posts](https://cloud.redhat.com/blog/tag/red-hat-advanced-cluster-management) on RHACM , and [documentation](https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.9/html/about/welcome-to-red-hat-advanced-cluster-management-for-kubernetes).
+
+## What is NetObserv?
+
+Network Observability (NetObserv) is a Red Hat operator providing observability over all the network traffic on a cluster by installing eBPF agents per-node which generate flow logs. These flows are collected, stored, converted into metrics, queried from dashboards and so on. More observability blog posts [here](https://cloud.redhat.com/blog/tag/observability), and NetObserv documentation [there](https://docs.openshift.com/container-platform/4.14/network_observability/network-observability-overview.html).
+
+## How to combine them?
+
+RHACM has an Observability add-on that uses Thanos and Prometheus federation to pull some of the metrics from the monitored clusters, automatically injecting cluster name and ID as metric labels. It provides [an API](https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.9/html/observability/customizing-observability#adding-custom-metrics) to configure which additional metrics to pull.
+
+On the other hand, NetObserv generates metrics out of the processed flow logs. They are pulled and stored by Prometheus, in each cluster where NetObserv is installed.
+
+So it seems there could be a match between RHACM and NetObserv?
+
+(Spoiler: yes!) Let's dive into the details and set it up.
+
+### Pre-requisites
+
+- A running OpenShift[*] cluster, configured as a hub with RHACM. In this blog, I am simply installing the Advanced Cluster Management for Kubernetes operator from console Operator Hub, with the default `MultiClusterHub` resource. For full installation guidance, see the [documentation](https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.9/html/install/installing).
+- Other clusters imported in RHACM. To do this, you are well guided when using the OpenShift Console, after selecting "All Clusters" in the top-left dropdown list.
+- NetObserv operator installed and configured on each cluster to monitor. This can also be done entirely from the OpenShift Console, via OperatorHub, or even better, directly piloted via RHACM policies. We [provide some templates](https://github.com/netobserv/documents/tree/main/examples/ACM/policies) that you can install on the hub cluster. If you choose to use them, NetObserv install is triggered by adding a label `netobserv=true` on clusters; but be aware that at the time of writing, it does not cover installing Loki, which means you don't get full-featured NetObserv.
+
+_*: nothing should stop you from doing the same with other Kubernetes flavors, but this blog will focus on OpenShift as it contains a few references to the OpenShift Console, and assumes Prometheus-based monitoring is set up on each cluster like is provided out of the box with OpenShift._
+
+The following instructions have been tested with RHACM 2.8 and 2.9, and NetObserv 1.4.2 and pre-release 1.5.
+
+### Configure NetObserv metrics
+
+By default, NetObserv configures a small set of metrics, namely:
+- `namespace_flows_total`
+- `node_ingress_bytes_total`
+- `workload_ingress_bytes_total`
+
+For the purpose of this blog, we enable more metrics. Note that enabling more metrics may have a noticeable impact on Prometheus. You should monitor Prometheus resource usage when doing so.
+
+If you're running NetObserv 1.4.x or older, edit the `FlowCollector` resource, find property `spec.processor.metrics.ignoreTags` and remove `egress` and `packets`.
+
+If you're running NetObserv 1.5 or above, edit the `FlowCollector` resource, find property `spec.processor.metrics.includeList` and set it up with:
+- `namespace_flows_total`
+- `node_ingress_bytes_total`
+- `workload_ingress_bytes_total`
+- `workload_egress_bytes_total`
+- `workload_egress_packets_total`
+- `workload_ingress_packets_total`
+
+This adds metrics used in later steps. [Take a look](https://github.com/netobserv/network-observability-operator/blob/main/docs/Metrics.md) at the available metrics if you want to customize this setup further.
+
+If you are only interested in metrics, you don't need to install and enable Loki. Read more about that [here](https://cloud.redhat.com/blog/deploying-network-observability-without-loki-an-example-with-clickhouse). But while NetObserv doesn't currently provide an out-of-the-box experience for viewing multi-cluster logs from Loki, these flow logs are still the most detailed and accurate data available when it comes to troubleshooting the network per cluster, providing a finer insight than metrics.
+
+Said differently:
+
+- Metrics are the best for wide angle, aggregated view: ideal for a multi-cluster single pane of glass.
+- Flow logs are the best for zoomed-in, detailed views: ideal for an in-cluster deep dive.
+
+### Start the observability add-on
+
+If you already have observability configured in RHACM, you can skip this section.
+
+Else, follow the instructions [documented here](https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.9/html/observability/enabling-observability-service). This involves configuring access for metrics storage, such as using AWS S3, Google Cloud Storage, ODF or a few others as you can see in the documentation.
+
+Proceed until you have created a `MultiClusterObservability` resource.
+
+Before going further, make sure the observability stack is up and running:
+
+```bash
+kubectl get pods -n open-cluster-management-observability -w
+```
+
+Example output:
+```
+NAME READY STATUS RESTARTS AGE
+observability-alertmanager-0 3/3 Running 0 91s
+observability-alertmanager-1 3/3 Running 0 52s
+observability-alertmanager-2 3/3 Running 0 30s
+observability-grafana-6c9984bd7b-6556s 3/3 Running 0 92s
+observability-grafana-6c9984bd7b-hd8v6 3/3 Running 0 92s
+observability-observatorium-api-8598c7f6d-l7psc 1/1 Running 0 75s
+observability-observatorium-api-8598c7f6d-nq888 1/1 Running 0 75s
+observability-observatorium-operator-55674f7fc8-szh7k 1/1 Running 0 92s
+observability-rbac-query-proxy-7b7dd7cb96-mgpwt 2/2 Running 0 91s
+observability-rbac-query-proxy-7b7dd7cb96-w99xg 2/2 Running 0 90s
+observability-thanos-compact-0 1/1 Running 0 75s
+observability-thanos-query-748f4bb977-7scd6 1/1 Running 0 76s
+observability-thanos-query-748f4bb977-jbwqx 1/1 Running 0 76s
+observability-thanos-query-frontend-5d8b9c878d-btbgm 1/1 Running 0 76s
+observability-thanos-query-frontend-5d8b9c878d-h48mt 1/1 Running 0 75s
+observability-thanos-query-frontend-memcached-0 2/2 Running 0 76s
+observability-thanos-query-frontend-memcached-1 2/2 Running 0 55s
+observability-thanos-query-frontend-memcached-2 2/2 Running 0 54s
+observability-thanos-receive-controller-85bf46b584-l22wp 1/1 Running 0 75s
+observability-thanos-receive-default-0 1/1 Running 0 75s
+observability-thanos-receive-default-1 1/1 Running 0 54s
+observability-thanos-receive-default-2 1/1 Running 0 41s
+observability-thanos-rule-0 2/2 Running 0 76s
+observability-thanos-rule-1 2/2 Running 0 46s
+observability-thanos-rule-2 2/2 Running 0 24s
+observability-thanos-store-memcached-0 2/2 Running 0 75s
+observability-thanos-store-memcached-1 2/2 Running 0 58s
+observability-thanos-store-memcached-2 2/2 Running 0 49s
+observability-thanos-store-shard-0-0 1/1 Running 2 (64s ago) 76s
+observability-thanos-store-shard-1-0 1/1 Running 2 (63s ago) 76s
+observability-thanos-store-shard-2-0 1/1 Running 2 (57s ago) 76s
+```
+
+### Configure pulling NetObserv metrics
+
+This is done with a new ConfigMap that declares all metrics to be pulled from the federated Prometheus, along with recording rules:
+
+```yaml
+kind: ConfigMap
+apiVersion: v1
+metadata:
+ name: observability-metrics-custom-allowlist
+ namespace: open-cluster-management-observability
+data:
+ metrics_list.yaml: |
+ rules:
+ # Namespaces
+ - record: namespace:netobserv_workload_egress_bytes_total:src:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_egress_bytes_total[5m]),\"namespace\",\"$1\",\"SrcK8S_Namespace\",\"(.*)\")) by (namespace)
+ - record: namespace:netobserv_workload_ingress_bytes_total:dst:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_ingress_bytes_total[5m]),\"namespace\",\"$1\",\"DstK8S_Namespace\",\"(.*)\")) by (namespace)
+ - record: namespace:netobserv_workload_egress_packets_total:src:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_egress_packets_total[5m]),\"namespace\",\"$1\",\"SrcK8S_Namespace\",\"(.*)\")) by (namespace)
+ - record: namespace:netobserv_workload_ingress_packets_total:dst:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_ingress_packets_total[5m]),\"namespace\",\"$1\",\"DstK8S_Namespace\",\"(.*)\")) by (namespace)
+
+ # Namespaces / cluster ingress|egress
+ - record: namespace:netobserv_workload_egress_bytes_total:src:unknown_dst:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_egress_bytes_total{ DstK8S_OwnerType=\"\"}[5m]),\"namespace\",\"$1\",\"SrcK8S_Namespace\",\"(.*)\")) by (namespace)
+ - record: namespace:netobserv_workload_ingress_bytes_total:dst:unknown_src:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_ingress_bytes_total{ SrcK8S_OwnerType=\"\"}[5m]),\"namespace\",\"$1\",\"DstK8S_Namespace\",\"(.*)\")) by (namespace)
+ - record: namespace:netobserv_workload_egress_packets_total:src:unknown_dst:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_egress_packets_total{ DstK8S_OwnerType=\"\"}[5m]),\"namespace\",\"$1\",\"SrcK8S_Namespace\",\"(.*)\")) by (namespace)
+ - record: namespace:netobserv_workload_ingress_packets_total:dst:unknown_src:rate5m
+ expr: sum(label_replace(rate(netobserv_workload_ingress_packets_total{ SrcK8S_OwnerType=\"\"}[5m]),\"namespace\",\"$1\",\"DstK8S_Namespace\",\"(.*)\")) by (namespace)
+
+ # Workloads
+ - record: workload:netobserv_workload_egress_bytes_total:src:rate5m
+ expr: sum(label_replace(label_replace(label_replace(rate(netobserv_workload_egress_bytes_total[5m]),\"namespace\",\"$1\",\"SrcK8S_Namespace\",\"(.*)\"),\"workload\",\"$1\",\"SrcK8S_OwnerName\",\"(.*)\"),\"kind\",\"$1\",\"SrcK8S_OwnerType\",\"(.*)\")) by (namespace,workload,kind)
+ - record: workload:netobserv_workload_ingress_bytes_total:dst:rate5m
+ expr: sum(label_replace(label_replace(label_replace(rate(netobserv_workload_ingress_bytes_total[5m]),\"namespace\",\"$1\",\"DstK8S_Namespace\",\"(.*)\"),\"workload\",\"$1\",\"DstK8S_OwnerName\",\"(.*)\"),\"kind\",\"$1\",\"DstK8S_OwnerType\",\"(.*)\")) by (namespace,workload,kind)
+```
+
+Let's take a break here: what are we doing?
+
+This is defining a bunch of [Prometheus recording rules](https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#rule).
+
+RHACM offers two options for pulling custom metrics from the managed clusters:
+
+- By declaring metric names to pull
+- Or by declaring such recording rules
+
+The former is easier to configure but in many cases, this is probably not what you want. When pulling metrics from many sources, the key concept to have in mind is [metrics cardinality](https://www.robustperception.io/cardinality-is-key/). The more metrics you configure, the bigger the impact on Prometheus and Thanos resource usage and performance. "Cardinality" here does not refer to the number of record rules or names that we declare in this configuration - these are called _metric families_ - after all, if you look closely, we only mention four distinct metric families in this config, which isn't a lot. No, what really matters with cardinality is the distinct count of all metric families _and all their combinations of label keys and values_.
+
+Imagine a metric that provides per-pod information: this is a high cardinality. Imagine a metric that provides per-source pod and per-destination pod information: cardinality explodes. Imagine all of that, pulled from hundreds, thousands of clusters: I prefer not to.
+
+Thankfully, in each cluster, NetObserv's metrics aren't per-pod, but per-workload. This is a first degree of aggregation to tackle cardinality. So the cardinality of such metrics grows capped as `N²`, where `N` is the number of workloads in the cluster. For multi-cluster metrics, this is probably still too much, so we filter or aggregate further using recording rules. Also, multi-cluster dashboards don't have to go ultra deep in the level of details, they need to provide overviews, so we can keep the more detailed metrics just per-cluster, possibly with a smaller retention.
+
+In the config shown above, we are reducing the workload metrics cardinality to `2N` by storing independently `ingress` metrics (per destination, without the source) and `egress` metrics (per source, without the destination). We are also creating other metrics more aggregated, per namespace. And finally, there is a set of metrics with special filters dedicated to watching traffic in/out of the cluster.
+
+End of the break, let's continue with our setup.
+
+Create this `ConfigMap` in your hub cluster - the one where the RHACM operator is installed:
+
+```bash
+kubectl apply -f https://raw.githubusercontent.com/netobserv/documents/main/examples/ACM/netobserv-metrics.yaml
+```
+
+Note that, if you are using the NetObserv upstream (community) operator, metrics are only available as "user workload metrics", and the procedure to configure RHACM observability then differs a little bit: the `ConfigMap` must be deployed in a different namespace, and the file key must be `uwl_metrics_list.yaml`. More information [here](https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.9/html/observability/customizing-observability#adding-user-workload-metrics).
+
+This config is immediately picked up by the metrics collector. To make sure everything worked correctly, you can take a look at these logs:
+
+```bash
+kubectl logs -n open-cluster-management-addon-observability -l component=metrics-collector -f
+```
+
+Hopefully you should see an info log such as: `Metrics pushed successfully`. If there are some typos or mistakes in the ConfigMap, you would see an error in these logs.
+
+### Installing the dashboards
+
+We've built two dashboards for the set of metrics configured:
+
+- One showing Clusters Overview
+- Another showing more details per cluster
+
+To install them:
+
+```bash
+kubectl apply -f https://raw.githubusercontent.com/netobserv/documents/main/examples/ACM/dashboards/clusters-overview.yaml
+kubectl apply -f https://raw.githubusercontent.com/netobserv/documents/main/examples/ACM/dashboards/per-cluster.yaml
+```
+
+### Viewing the dashboards
+
+From the hub cluster console, select the "All Clusters" view:
+
+})
+
+Click the Grafana link:
+
+})
+
+The new dashboards are in the "NetObserv" directory:
+
+})
+
+1. NetObserv / Clusters Overview
+
+})
+_Clusters overall in/out stats and top namespaces_
+
+})
+_Clusters in/out external traffic_
+
+2. NetObserv / Per Cluster
+
+})
+_Top namespaces charts_
+
+})
+_Namespaces and Workloads tables_
+
+These dashboards provide high level views on cluster metrics. To dive more in the details, such as for troubleshooting or performance analysis, it is still preferable to use the NetObserv plugin or metrics on a given cluster, via the OpenShift Console: not only the metrics are more accurate there, with less aggregation and a better resolution, but there are also more details available in the raw flow logs that aren't visible in metrics, such as pod/port/IP/interface information per flow and accurate timestamps.
+
+### It's on you
+
+You can customize these dashboards or create new ones. [This documentation](https://access.redhat.com/documentation/en-us/red_hat_advanced_cluster_management_for_kubernetes/2.9/html/observability/using-observability#setting-up-the-grafana-developer-instance) will guide you through the steps of creating your own dashboards.
+
+For instance, do you want to track workloads having external traffic, which we haven't done in this blog (we did only for namespaces)? You can just adapt the rules defined above. If you look at them closely, you'll notice they're all really using the same four metrics under the cover: `netobserv_workload_egress_bytes_total`, `netobserv_workload_ingress_bytes_total` and their equivalent for packets. To track per-workload external traffic, we can use them again, and as for namespaces, filter on empty `SrcK8S_OwnerType` or `DstK8S_OwnerType`. This trick stands for: NetObserv hasn't been able to identify any in-cluster resource corresponding to this source or destination, so this is likely a cluster-external caller or service.
+
+_Update, 2024-11-28: as of today, a more accurate way to filter for cluster-external traffic would be to check for empty [subnet labels](https://docs.openshift.com/container-platform/latest/observability/network_observability/flowcollector-api.html#spec-processor-subnetlabels)._
+
+We would end up with these two new rules:
+
+```yaml
+ - record: workload:netobserv_workload_egress_bytes_total:src:unknown_dst:rate5m
+ expr: sum(label_replace(label_replace(label_replace(rate(netobserv_workload_egress_bytes_total{ DstK8S_OwnerType=\"\"}[5m]),\"namespace\",\"$1\",\"SrcK8S_Namespace\",\"(.*)\"),\"workload\",\"$1\",\"SrcK8S_OwnerName\",\"(.*)\"),\"kind\",\"$1\",\"SrcK8S_OwnerType\",\"(.*)\")) by (namespace,workload,kind)
+ - record: workload:netobserv_workload_ingress_bytes_total:dst:unknown_src:rate5m
+ expr: sum(label_replace(label_replace(label_replace(rate(netobserv_workload_ingress_bytes_total{ SrcK8S_OwnerType=\"\"}[5m]),\"namespace\",\"$1\",\"DstK8S_Namespace\",\"(.*)\"),\"workload\",\"$1\",\"DstK8S_OwnerName\",\"(.*)\"),\"kind\",\"$1\",\"DstK8S_OwnerType\",\"(.*)\")) by (namespace,workload,kind)
+```
+
+Be careful about escaping double-quotes, though it's not very pretty, it is necessary: else you would end up with a parsing error. Also, the `label_replace` chained calls here could be avoided as they look messy, but they make it actually easier to manipulate those metrics later on, in Grafana.
+
+Also, don't forget that NetObserv has [more metrics to show](https://github.com/netobserv/network-observability-operator/blob/main/docs/Metrics.md), especially starting from the coming-soon release 1.5, such as TCP latencies, [packet drop](https://cloud.redhat.com/blog/network-observability-real-time-per-flow-packets-drop) counters and so on. And just for teasing, we are working on a fresh new API in NetObserv that will soon let you build pretty much any metric you want out of flow logs, for even more dashboarding possibilities.
+
+If you want to get in touch with the NetObserv team, you can use our [discussion board](https://github.com/netobserv/network-observability-operator/discussions).
diff --git a/content/posts/2024-01-18-rtt.md b/content/posts/2024-01-18-rtt.md
new file mode 100644
index 0000000..cf627ee
--- /dev/null
+++ b/content/posts/2024-01-18-rtt.md
@@ -0,0 +1,168 @@
+---
+layout: :theme/post
+title: "Network Observability TCP Handshake Round Trip Time"
+description: "Check out how NetObserv helps monitoring TCP latency"
+tags: eBPF,Latency,Network
+authors: [dushyantbehl,jpinsonneau,msherif1234]
+---
+
+
+
+In OpenShift Container Platform (OCP), ensuring efficient packet delivery is
+paramount for maintaining seamless communication between applications.
+However, challenges like network congestion, misconfigured systems,
+or hardware limitations can lead to slow connections, impacting overall
+performance. Round Trip Time (RTT), typically measured in milliseconds,
+plays a crucial role in monitoring network health and diagnosing issues.
+
+## Implementing Smooth Round-Trip Time (SRTT) with eBPF
+
+The RTT is the time it takes for a packet to travel from the sender to the receiver
+and back. In a network, RTT can vary due to factors like network congestion,
+varying route lengths, and other dynamic conditions.
+SRTT is introduced to provide a more consistent and less jittery representation
+of the RTT.
+
+In TCP, RTT is a crucial metric.
+
+Our implementation leverages eBPF to register to `fentry` eBPF hook
+for `tcp_rcv_established()`.
+We extract the SRTT (smooth round-trip time) value from TCP sockets, correlating it
+to existing flows and enriching them with RTT values in nanoseconds.
+
+When a new Netobserv flow is created, and the RTT (Round-Trip Time) feature is enabled,
+an initial RTT of `10usec` is assigned.
+This initial value for RTT may be considered quite low.
+
+Upon triggering the eBPF (Extended Berkeley Packet Filter) socket, the flow RTT
+value is updated to reflect the maximum RTT value for that specific flow.
+
+For more detailed explanation of smoothed RTT estimation, refer to [Karn's algorithm paper](http://ccr.sigcomm.org/archive/1995/jan95/ccr-9501-partridge87.pdf)
+
+})
+
+### Why using `fentry` eBPF hook
+
+The eBPF `fentry` programs have lower overhead as they trigger
+the hook before calling the kernel function of interest.
+
+In our implementation:
+
+1. Register and link `fentry` hook for kernel's `tcp_rcv_established()`
+
+```cgo
+SEC("fentry/tcp_rcv_established")
+int BPF_PROG(tcp_rcv_fentry, struct sock *sk, struct sk_buff *skb) {
+ if (sk == NULL || skb == NULL) {
+ return 0;
+ }
+ return calculate_flow_rtt_tcp(sk, skb);
+}
+```
+
+2. Reconstruct the Netobserv flow key, including incoming interface Layer2, Layer3, and Layer4 info.
+
+3. Match existing flows in the PerCPU hashmap flow table and enrich them with srtt info from TCP sockets. If
+ multiple SRTT values exist for the same flow, we take the maximum value.
+
+Currently, our approach calculates RTT only for the TCP packets so flows which are non-TCP do not show RTT information.
+
+## Potential Use Cases
+
+Flow RTT capture from eBPF `flow_monitor` hookpoint can serve various purposes:
+
+- Network Monitoring: Gain insights into TCP handshakes, helping
+ network administrators identify unusual patterns, potential bottlenecks, or
+ performance issues.
+
+- Troubleshooting: Debug TCP-related issues by tracking latency and identifying
+ misconfigurations.
+
+## How to Enable RTT
+
+To enable this feature we need to create a FlowCollector object with the following
+fields enabled in eBPF config section as below:
+
+```yaml
+apiVersion: flows.netobserv.io/v1beta2
+kind: FlowCollector
+metadata:
+ name: cluster
+spec:
+ agent:
+ type: eBPF
+ ebpf:
+ features:
+ - FlowRTT
+```
+
+## A Quick Tour in the UI
+
+Once the `FlowRTT` feature is enabled, the OCP console plugin automatically adapts
+to provide additional filter and show information across Netflow Traffic page views.
+
+Open your OCP Console and move to
+`Administrator view` -> `Observe` -> `Network Traffic` page as usual.
+
+A new filter, `Flow RTT` is available in the common section:
+
+})
+
+The `FlowRTT` filter will allow you to capture any flow that has an RTT more than a specific time in nanoseconds.
+
+For production users, filtering on the `TCP` protocol, `Ingress` direction,
+and looking for `FlowRTT` values greater than 10,000,000 nanoseconds (10ms)
+can help identify TCP flows with high latency.
+This filtering approach allows users to focus on specific network flows that may
+be experiencing significant delays.
+By setting a threshold of `10ms`, you can efficiently isolate and address potential
+latency issues in your TCP traffic.
+
+### Overview
+
+New graphs are introduced in the `Advanced options` -> `Manage panels` popup:
+
+})
+
+- Top X average TCP handshake Round Trip Time with overall (donut or lines)
+- Bottom X minimum TCP handshake Round Trip Time with overall (donut or lines)
+- Top X maximum TCP handshake Round Trip Time with overall (donut or lines)
+- Top X 90th percentile TCP handshake Round Trip Time with overall (donut or lines)
+- Top X 99th percentile TCP handshake Round Trip Time with overall (donut or lines)
+-
+})
+
+These two graphs can help you to identify the slowest TCP flows and their trends
+over time. Use the filters to drill down into specific pods, namespaces or nodes.
+
+### Traffic flows
+
+The table view shows the `Flow RTT` in both column and side panel.
+
+})
+
+### Topology
+
+Last but not least, the topology view displays min / max / avg / p90 / p99 `RTT`
+latency on edges.
+Clicking on a node or an edge will allow you to see per direction metrics and
+the related graph.
+
+})
+
+### Future improvments
+
+Here is a non exhaustive list of future improvements coming for a full featured
+Round Trip Time analysis:
+
+- Latest RTT in topology view
+- Prometheus metrics and alerting
+
+## Feedback
+
+We hope you liked this article !
+
+Netobserv is an OpenSource project [available on github](https://github.com/netobserv).
+Feel free to share your [ideas](https://github.com/netobserv/network-observability-operator/discussions/categories/ideas), [use cases](https://github.com/netobserv/network-observability-operator/discussions/categories/show-and-tell) or [ask the community for help](https://github.com/netobserv/network-observability-operator/discussions/categories/q-a).
diff --git a/content/posts/2024-02-28-whats_new_1_5.md b/content/posts/2024-02-28-whats_new_1_5.md
new file mode 100644
index 0000000..d4e417e
--- /dev/null
+++ b/content/posts/2024-02-28-whats_new_1_5.md
@@ -0,0 +1,190 @@
+---
+layout: :theme/post
+title: "What's new in Network Observability 1.5"
+description: "Check out the new features: simplified configuration, creating custom metrics, availability zones and more..."
+tags: What's New,Latency,Metrics,Configuration,AZ
+authors: [stleerh]
+---
+
+
+
+Network Observability 1.5 is the new version of the operator from Red Hat that focuses on providing insights into networking. There's an upstream version that runs on plain Kubernetes, but this blog will focus on using OpenShift Container Platform (OCP) and the OpenShift web console for the user interface.
+
+I will highlight the most important new features of this release so if you want a summary of all the changes including bug fixes, check out the [release notes](https://docs.openshift.com/container-platform/4.15/network_observability/network-observability-operator-release-notes.html). If you want some background of this product, read the [OpenShift documentation](https://docs.openshift.com/container-platform/4.15/network_observability/network-observability-overview.html) and various [Red Hat blogs](https://www.redhat.com/en/blog) on this topic, including my blog on the previous [1.4 release](https://www.redhat.com/en/blog/whats-new-in-network-observability-1.4).
+
+To get started, you should have an OpenShift cluster. You will need to log in with a cluster-admin role. Follow the [documentation steps](https://docs.openshift.com/container-platform/4.15/network_observability/installing-operators.html) to install **Network Observability** provided by Red Hat in **OperatorHub** on the OpenShift web console.
+
+## Feature Highlights
+
+Version 1.5 has significant improvements in ease-of-use and a number of features related to graphs and metrics. The Flow Round Trip Time (RTT) feature that was in Technical Preview is now in General Availability (GA), which means it is fully supported.
+
+If you've used Network Observability before, the first thing you might have noticed after installing the operator is that there are two APIs available instead of one (Figure 1).
+
+})
+_
Figure 1: Network Observability Operater and APIs
_
+
+FlowMetrics is a dev preview feature which I will cover at the end, so let's start with FlowCollector.
+
+### FlowCollector API
+
+FlowCollector is the heart of network observability. Creating a FlowCollector instance deploys an [eBPF](https://en.wikipedia.org/wiki/EBPF) agent for generating network flows, optionally supporting Kafka to improve scalability and reliability, a flowlogs pipeline for collecting, enriching, and storing the flow data and metrics, and a UI plugin for OpenShift web console to display graphs, tables, and topology.
+
+In 1.5, the FlowCollector API version was upgraded to *flows.netobserv.io/v1beta2* from v1beta1. In web console, the UI or "Flow view" to create an instance gets a facelift. The custom resource has the following top level categories:
+
+1. Name and Labels
+2. Loki client settings
+3. Console plugin configuration
+4. Namespace
+5. Deployment model
+6. Agent configuration
+7. Processor configuration
+
+The first significant change is in "Loki client settings". When you click and open this, you get the following:
+
+})
+_
Figure 2: Loki client settings
_
+
+One of the new fields is "Mode" where you select how you installed Loki. The most common is "LokiStack", which means you installed the Loki Operator and created a LokiStack instance. Under the "Loki stack" section, make sure the **Name** matches the LokiStack name you gave it. The nice part is that it will go and figure out the LokiStack gateway URL for you and give it proper authorization.
+
+Parameters are now exposed under "Console plugin configuration", particularly "Quick filters" (Figure 3). Network Observability predefines some filters as defaults which can be changed. While this was possible before, now you can do it in the UI.
+
+})
+_
Figure 3: Console plugin configuration
_
+
+Under "Agent configuration", there is no longer an agent type because the only supported agent is *eBPF*. It is still possible to configure *IPFIX* through YAML.
+
+In "Processor configuration", the changes are to enable availability zones, cluster ID, and a "Metrics configuration" section to select a list of predefined metrics under the "include list" (Figure 4).
+
+})
+_
Figure 4: Processor configuration
_
+
+The full list of predefined metrics is [here](https://github.com/netobserv/network-observability-operator/blob/main/docs/Metrics.md). When you include a metric, it stores it in Prometheus and is available as a Prometheus metric prefixed with "netobserv_". For example, if you add the metric *namespace_egress_bytes_total*, then go to **Observe > Metrics** and enter the PromQL `sum(rate(netobserv_namespace_egress_bytes_total[1m]))`. This should display a single line that is the sum of the average number of egress bytes over one-minute intervals. Select a refresh time in the upper right dropdown if you want the graph to be updated periodically.
+
+Availability zones and cluster ID will be covered in the traffic flow table section below.
+
+## UI Changes and Features
+
+The new features and enhancements will be covered by going over the changes in the Network Observability UI, starting with the three tabs in **Observe > Network Traffic**, namely *Overview*, *Network Traffic*, and *Topology*.
+
+### Overview tab
+
+Graphs for Flow RTT and DNS Tracking, including support for DNS TCP (previously only DNS UDP), were added. There are graphs for:
+
+- Top 5 and/or top total graph
+- Top 5 average graph using latest metrics or all metrics
+- Top 5 max graph
+- Top 5 90th percentile graph (P90)
+- Top 5 99th percentile graph (P99)
+- Bottom 5 min graph
+
+#### Manage panels selection
+
+With so many graphs to choose from, the **Manage panels** dialog, found under "Show advanced options", now provides a simple filter (Figure 5). Click one or more buttons to filter on the selection.
+
+})
+_
Figure 5: Manage panels
_
+
+#### Graph types
+
+If you click **⋮** in the upper right corner of the graph, there will be various options depending on the type of graph. For example, the ***TCP handshake Round Trip Time*** graph shows a donut chart but can be changed to use a lines graph (Figure 6).
+
+
+_
Figure 6: Options - Graph type
_
+
+#### Single graph focus
+
+In Overview, it displays all graphs on a scrollable panel. If you click the "Focus" icon in the upper right corner next to **⋮**, it displays one graph and gives a preview of all the other graphs on a scrollable panel on the right side (Figure 7). If you click a preview graph, it becomes the graph in focus. This feature can also be toggled in the "Display options" dropdown.
+
+})
+_
Figure 7: Single graph focus
_
+
+### Traffic flows tab
+
+These are the new labels in the flow data.
+
+1. Differentiated Services Code Point (DSCP)
+This is a 6-bit value in the IP packet header that indicates the priority of a packet to provide quality of service (QoS), particularly for time-sensitive data such as voice and video. The value "Standard" translates to 0 or best effort. In other words, the traffic is not getting any special treatment.
+
+ - Column: DSCP
+ - Label: Dscp
+
+})
+_
Figure 8: DSCP
_
+
+2. Availability Zones
+A region defines a geographical area and consists of one or more availability zones. For example, if a region is named us-west-1, then the zones might be us-west-1a, us-west-1b, and us-west-1c, where each zone might have one or more physical data centers.
+
+ - Columns: Source Zone, Destination Zone
+ - Labels: SrcK8S_Zone, DstK8S_Zone
+
+})
+_
Figure 9: Availability Zone
_
+
+3. Cluster ID
+The cluster ID is the same value shown in the **Home > Overview**, Details section.
+
+ - Column: Cluster
+ - Label: K8S_ClusterName
+
+})
+_
Figure 10: Cluster ID
_
+
+#### Manage columns selection
+
+Like the **Manage panels** dialog, the **Manage columns** dialog, found under "Show advanced options", alos provides a simple filter (Figure 11). Click one or more buttons to filter on the selection.
+
+})
+_
Figure 11: Manage columns
_
+
+### Topology tab
+
+Topology also supports the same data in the **Overview** graphs for its edge labels, such as P90 (90th percentile) and P99 (99th percentile)
+
+})
+_
Figure 12: Topology changes
_
+
+### Filter
+
+At the top of the screen is the filter used by all three tabs. A dropdown button was added to show recently-used entries and to do auto-completion (Figure 13).
+
+})
+_
Figure 13: Filter
_
+
+## FlowMetrics API
+
+The FlowMetrics API allows you take any combination of [flow data labels](https://docs.openshift.com/container-platform/4.14/network_observability/json-flows-format-reference.html) and turn it into a Prometheus metric. In other words, you can create your own custom metric and then even create alerts and external notifications based on them. This is a development preview feature. Please be aware that generating too many metrics or not understanding how performance is impacted by querying these metrics can result in over utilization of resources and storage and cause instability.
+
+To create a metric, go to **Operators > Installed Operator** and for the *Network Observability* row, click "Flow Metric" in the **Provided APIs** column (Figure 1). Click the **Create FlowMetric** button to begin.
+
+Minimally, you need to provide a metric name and specify the type, although you will likely need to use filters and possibly labels. Prometheus provides some [best practices on naming](https://prometheus.io/docs/practices/naming/). Just remember that the actual Prometheus metric name is prefixed with "netobserv_". There is also information on the various [metric types](https://prometheus.io/docs/concepts/metric_types/). FlowMetrics only supports Counter and Histogram and not Gauge or Summary.
+
+As an example, let's create a metric that reports the number of bytes coming externally to a namespace of our choosing. To achieve this, use a label for the destination namespace which is called *DstK8S_Namespace*. The traffic will be considered external if the source name doesn't exist. Enter the following values in the Form view for FlowMetric. Also, make sure you remove the pre-existing filters. Note: This is what you enter in the UI; it is not YAML.
+
+```
+metricName: ingress_external_bytes_total
+type: Counter
+direction: Ingress
+filters:
+ field: SrcK8S_Name
+ matchType: Absence
+ value:
+labels:
+ - DstK8S_Namespace
+```
+
+When you create this instance or make any changes to FlowMetric, the flowlogs-pipeline pods will restart automatically. Now go to **Observe > Metrics** and enter `netobserv_ingress_external_bytes_total` (don't forget the prefix "netobserv_"). Because of the label, it separates out each destination namespace in its own graph line. Try out the other PromQL queries below.
+
+1. Graph the number of bytes incoming on namespace "openshift-ingress". You can replace with any namespace.
+`netobserv_ingress_external_bytes_total{ DstK8S_Namespace="openshift-ingress"}`
+
+2. In some cases like "openshift-dns", you might get more than one graph line because it's running on multiple pods. Use `sum` to combine them into one graph line.
+`sum(netobserv_ingress_external_bytes_total{ DstK8S_Namespace="openshift-dns"})`
+
+3. Graph the average rate over a 5-minute interval.
+`sum(rate(netobserv_ingress_external_bytes_total{ DstK8S_Namespace="openshift-ingress"}[5m]))`
+
+## Conclusion
+
+Hopefully, you are excited as I am on all the changes in this release. I hope you get the chance to try it out, and let us know what you think! You can always reach the NetObserv team on this [discussion board](https://github.com/netobserv/network-observability-operator/discussions).
diff --git a/content/posts/2024-04-05-agent_metrics_perf.md b/content/posts/2024-04-05-agent_metrics_perf.md
new file mode 100644
index 0000000..ffff179
--- /dev/null
+++ b/content/posts/2024-04-05-agent_metrics_perf.md
@@ -0,0 +1,224 @@
+---
+layout: :theme/post
+title: "Performance fine-tuning - a deep dive in eBPF agent metrics"
+description: "You can improve NetObserv performance with a bit of fine-tuning"
+tags: eBPF,Performance,Configuration,Metrics
+authors: [jotak]
+---
+
+When you install Network Observability (NetObserv) on your OpenShift or Kubernetes cluster, it comes with a default configuration that is designed to fit the most common use cases of cluster size and load. It should "just work". However it might not be optimal, because the effects of configuring some components, such as the eBPF agent cache, would highly vary depending on its environment: it can be affected by the number of nodes in the cluster, the number of pods, the traffic bandwidth, the cardinality of connections, etc. This is why it is recommended to spend some time on fine-tuning.
+
+We have recently introduced new metrics to instrument the eBPF agent, which are incredibly useful for performance fine-tuning.
+This blog focuses on some of the agent internal mechanisms of flows eviction, and more specifically how tuning the `cacheMaxFlows` parameter can help you improve the memory consumption while keeping the best possible performances.
+
+## Testbed
+
+We will be running a test scenario consisting in:
+
+- An OpenShift 4.15 cluster deployed on AWS, with 3 worker nodes and 3 control-plane nodes, all amd64, `m6i.xlarge`.
+- Stable traffic generated by [hey-ho](https://github.com/jotak/hey-ho): `./hey-ho.sh -r 3 -d 3 -z 60m -n 2 -q 2 -p -b`. This creates 900 small load generators distributed in 2 namespaces, 6 deployments and 18 pods. Here I am more interested in the number of distinct 5-tuples that it generates (source/destination IP and ports, protocol) than in the bytes throughput itself, as this is what primarily impacts the number of created flows. Higher throughput does not necessarily mean more flows, as flows are an aggregation of packets meta-data per 5-tuple.
+- NetObserv 1.6
+- An almost-default `FlowCollector` resource installed, with just:
+ - `spec.agent.ebpf.sampling` set to `1`, meaning: collect everything
+ - `spec.loki.enable` set to `false` as we don't need it here
+
+## A revisited Health dashboard
+
+The dashboard called "NetObserv / Health" is created when you install a `FlowCollector` resource. You can find it in the OpenShift Console under the "Observe" > "Dashboards" menu. It has got a fresh restyling while we added there the new agent metrics.
+
+It shows a bunch of statistics such as the flows per second that NetObserv captures, the configured sampling ratio (0 or 1 mean sample everything), the errors reported by managed components and the number of flows dropped, either upstream from the eBPF agent, or downstream not stored in Loki. Below, the dashboard is broken down into a different section per component, and lastly the resource usage.
+
+})
+
+For this blog we are more interested in the eBPF agent statistics and the resource usage.
+
+## Generating traffic
+
+Like mentioned above, let's generate some traffic with `hey-ho`:
+
+```bash
+./hey-ho.sh -r 3 -d 3 -z 60m -n 2 -q 2 -p -b
+```
+
+})
+
+This is spawning 18 pods in 2 namespaces, talking to each other. Let's have a look at the metrics then.
+
+The dashboard shows a stable number of flows captured per second, most of the time between 3K and 3.5K. No drops, no errors:
+
+})
+
+We may also check the `hey-ho` traffic captured by NetObserv, in bytes per second, with this `promql` query: `sum(rate(netobserv_workload_ingress_bytes_total{ DstK8S_Namespace=~"gallery.*",DstK8S_OwnerType="Deployment"}[2m]))`. It is very stable at 4MBps:
+
+})
+
+Now looking at the resource usage:
+
+})
+
+That's also relatively stable, with the eBPF pods using in total around 0.08 CPU and around 340 MB.
+
+## Agent stats
+
+Now let's look at the agent stats:
+
+})
+
+What does all this mean? OK, take a breath. We need to talk about the [agent architecture](https://github.com/netobserv/netobserv-ebpf-agent/blob/main/docs/architecture.md) first.
+
+### Agent architecture
+
+})
+
+The agent runs on every node and injects an [eBPF](https://ebpf.io/) program in the Linux kernel in order to listen received and sent packets on network interfaces. The Linux architecture segregates the kernel space and the user space, restricting how data can flow between them. Some specific data structures are available to eBPF programs in order to transfer data between those spaces. By default, our agent uses two of these structures: a ring buffer, and per-CPU hashmaps (other structures can be used depending on the enabled features of the agent).
+
+The diagram above shows the data path coming from the kernel space (the `FlowFetcher` box at the top), and being either retrieved from the ring buffer or from the maps, before being eventually merged into a single stream that goes down to the exporters.
+
+Why two structures? When does a flow come from ring buffer, and when does it come from maps?
+Well, maps are the "normal" way to go. [We've found that they perform better than the ring buffer](https://opensource.com/article/22/8/ebpf-network-observability-cloud) for this use case. So normally, all flows should go through the maps.
+
+But because the maps are polled from the user space, it might happen sometimes, when a new flow comes up, it cannot be added to the map, generally because it is busy or full. Those flows would be dropped unless we find another way to send them to the user space; and here comes the ring buffer. This is it: just a fallback mechanism to avoid loosing flows.
+
+The fundamental difference for us, between maps and the ring buffer, is that maps allow to cache data in kernel and perform aggregations of the packets meta-data into the cached flows, whereas the ring buffer transfers data to the user space every time a new flow packet is received. Thus, it involves many more exchanges between kernel and user spaces, which comes with a computational cost. When the ring buffer is involved, this is like a degraded situation; but with the intent that it's just temporary and exceptional. When a packet is received in user space from the ring buffer, if the reason was that the map was full, it triggers a map flush event to get things back to normal as soon as possible.
+
+Previously, it was difficult to track what's going on under the cover, especially about the agent data path. We mostly had to turn on profiling and deep dive using `pprof`. Now metrics give both developers and users a better insight that allows taking more informed decisions about fine-tuning. So let's go back to the metrics.
+
+### Back to the dashboard
+
+Parenthesis closed, we were looking at the different charts under the eBPF agent stats section:
+
+- **Eviction rate**: this is the rate of eviction events, broken down per internal component
+
+})
+
+In theory, you should see the same rate between the exporter (`grpc` here) and the `deduper`, and it should also equal the sum of `hashmap` and `accounter` (which is in the ring buffer data path).
+
+We seen on this picture that the hashmap is much more used than the ring buffer (accounter), which is expected when everything works well.
+
+You may also notice that the hashmap eviction rate is a flat constant 1.2. That's because the `cacheTimeout` setting used is the default `5s`, and I have 6 pods. (1 / 5s) x 6 = 1.2. In other words, all the evictions from the hashmap currently obey to the timeout rule.
+
+- **Ringbuffer / HashMap ratio**: ratio between ring-buffer evictions and hashmap evictions.
+
+})
+
+Keep it as low as possible. The picture here is fine: even the spike is actually a low one, at 4e-4.
+
+- **Evicted flows rate**: similar to the rate of evictions except it counts the number of flows rather than the individual eviction events. Also broken down per internal component.
+
+})
+
+- **Buffer sizes**: some internal buffer sizes. This will be our starting point for fine-tuning.
+
+})
+
+Even if there are five metrics, it shows mostly three things: the deduper cache size, the hashmap size and the accounter cache size. `deduper-map` and `deduper-list` should normally be identical, as well as `hashmap-total` and `hashmap-unique`. They were mostly duplicated for debugging. If you find that they aren't identical, that might be an indication that something isn't going as expected. In that case, feel free to [open a github issue](https://github.com/netobserv/netobserv-ebpf-agent/issues) to discuss.
+
+## What can we learn already?
+
+The buffer size metrics tell us that the hashmaps are containing between 15K and 25K elements, which is a sum for every eBPF agent pods. We are interested to know if the hashmap configuration isn't over-sized. We can click the Inspect link and edit a little bit the promQL to see per-pod utilization:
+
+`netobserv_agent_buffer_size{ name="hashmap-unique"}` shows per-pod maps size, or `max(netobserv_agent_buffer_size{ name="hashmap-unique"})` shows the maximum map utilization across pods.
+
+})
+
+Sounds like it never goes above 4K.
+
+## Fine-tuning
+
+Remember the `FlowCollector` settings? We didn't change the `spec.agent.ebpf.cacheMaxFlows` value. This is the setting used to set the map sizes, and it defaults to 100K. So yes, for this usage, perhaps it is over-sized as the maps are generally under 4K.
+
+Let's halve it and see what happens.
+
+### cacheMaxFlows=50000
+
+})
+
+The eviction rate, and the flows per second haven't changed a lot, this is reassuring. The ring buffer ratio is still low. We can also take a look at the captured traffic, to double-check we're not missing anything:
+
+})
+
+Still a pretty flat 4 MBps. So far so good. So what, does it have any impact at all? What about the resource usage?
+
+})
+
+Oh, waw! Although no much impact on CPU, the memory has been greatly reduced! From more than 400 MB to 250 MB. That was a good move.
+
+Let's go further and set `cacheMaxFlows` to 10K.
+
+### cacheMaxFlows=10000
+
+We're getting closer to the 4K utilization that we were seeing before. If this threshold is reached, we can expect more use of the ring buffer. Let's see if that happens.
+
+})
+
+While the ring buffer doesn't seem to be more used most of the time, there is a spike at 11:25. Maps are still well used but it had an impact on the deduper buffer size and the flows evicted.
+
+Taking a close look at the eviction rate graph, there's a small increase of the hashmap line (purple) at the same time, whereas it used to be a flat 1.2 otherwise. What does it say? It says that for the first time here, the map eviction was not due to the `cacheTimeout` setting (evicting every 5s), but it was due to the map being full.
+
+Note that there is an artifact visible here, a global increase of the flows being generated (~3.5K to ~4K), which could be related to a test workloads restart. 10 minutes later it retrieved its previous level, closer to 3K:
+
+})
+
+What about the resource usage?
+
+})
+
+Memory decreased again, though not as much as before. There is a slight CPU increase which can be attributed to the increased number of flows (which decreases as well after 10 minutes). So it sounds like despite approaching the utilization threshold, we're still on a positive trend, but it weakens.
+
+Next step: dare the devil below the utilization threshold, with 2K.
+
+### cacheMaxFlows=2000
+
+We shouldn't expect anything good here, but let's see.
+
+})
+
+Resource usage:
+
+})
+
+Well, the situation has worsened, but not as much as we could fear. The CPU has increased by +40% but the number of flows, while also growing, is not exploding. Memory consumption looks unchanged, although it has probably been re-balanced internally between the hashmap and other parts (we could run a profiler if we really want to know). The ring buffer is now consistently used, indicating a somewhat degraded situation, but usage is still in a decent proportion. Things can really get out of hand when the ratio exceeds ~0.05, and here it is still an order of magnitude below.
+
+Also, something interesting to note is that the hashmap evictions (purple line in Evictions rate graph) are now consistently above 1.2, meaning that they are not due to the timeout, but to the maps being full. Let's see what happens if we set a more aggressive timeout.
+
+### cacheTimeout=1s
+
+The goal for setting a more aggressive timeout is to flush the hashmaps more often, hence removing as much as possible the need of the ring buffer as a fallback due to having full maps. But flushing maps more often comes at the cost of generating more flows.
+
+})
+
+We reached our goal: the ring buffer ratio has dropped. But we see more flows are generated, around 8K instead of 5-6K previously. Also, buffers are smaller since we flush them more often.
+
+})
+
+More flows mean more CPU. The impact goes beyond the agent alone, as the components that are downstream the pipeline (flowlogs-pipeline and, if you use them, Kafka and Loki), will also need to process more flows. But while the situation seems less glorious here, this is on purpose: to keep us out of a flows runaway due to over-use of the ring buffer, which we will see next.
+
+### When it all goes wrong
+
+Just for the sake of the demonstration, here's how it looks like with an undersized hashmap leading to over-use of the ring buffer. This is between 12:20 and 12:30 in the charts:
+
+})
+
+The ring buffer ratio went above 0.05 with even a huge spike to 0.5. This resulted in a burst of evicted flows from ~5K to ~20K.
+
+})
+
+This had a big impact on CPU usage:
+- +457% CPU when compared to `cacheMaxFlows=10000`
+- +143% CPU when compared to `cacheMaxFlows=2000, cacheTimeout=1s`
+
+To avoid this, it's best to keep `cacheMaxFlows` big enough to minimize the ring buffer ratio usage, in spite of the increased memory usage. Other mitigation options could be limiting the number of generated flows by other means, such as [configuring the agent](https://github.com/netobserv/network-observability-operator/blob/19bcb45d6899f12feb13f94a925a10a4f4c92106/docs/FlowCollector.md#flowcollectorspecagentebpf-1) to add filters on monitored interfaces or to increase the sampling value, if the resulting loss in observability is an acceptable trade-off for you.
+
+## Conclusion
+
+The key takeaways are:
+
+1. Ensure to not use under-sized eBPF hashmaps, which is controlled in `FlowCollector` with `spec.agent.ebpf.cacheMaxFlows`. The suggested way to do this is by monitoring the Ringbuffer / HashMap ratio. It might be a good idea to create a Prometheus alert when the ratio reaches some threshold such as 0.05.
+
+2. While keeping point 1 in mind, there are potentially nice improvements to be made on the memory footprint, by downsizing the hashmaps where possible. It is however highly recommended to keep a safety margin, because of course, real world traffic isn't flat and the maps must be able to absorb traffic increases.
+
+To conclude with a last picture, this is how the captured traffic looked during all these tests (in orange) versus the same from cAdvisor metrics taken as a reference (in blue):
+
+})
+
+You can see that they almost perfectly match. It means that all the tweaks we did haven't affected the correctness of the data, even during the "flows runaway" at 12:25 where we could have feared some drops.
diff --git a/content/posts/2024-07-25-cli.md b/content/posts/2024-07-25-cli.md
new file mode 100644
index 0000000..f346a0b
--- /dev/null
+++ b/content/posts/2024-07-25-cli.md
@@ -0,0 +1,505 @@
+---
+layout: :theme/post
+title: "Network Observability On Demand"
+description: "Check out the new use cases covered by the brand new CLI, such as packet capture (pcap)"
+tags: CLI,Troubleshooting,Packet Capture
+authors: [jpinsonneau]
+---
+
+
+
+})
+
+_Thanks to: Joël Takvorian and Sara Thomas for reviewing_
+
+Installing an entire observability stack may be hard to handle and not worth the effort in some cases. That's why we are introducing Network Observability CLI as a technical preview !
+This first version of the tool allows users to capture `flows` or `packets` running a simple command. It reuses the netobserv components without the need to install and configure operator(s).
+
+## Architecture
+
+})
+
+The CLI deploys eBPF agents as a DaemonSet embedding flowlogs pipeline in the same pods. These collect either flows or packets and send these data to a collector pod. The collector pod displays the collected content during the capture. Flows are stored as JSON and SQLite database files and packets are stored as pcap file(s).
+
+Behind the scene, your local terminal calls `oc run` to deploy the collector and then `oc exec` for a distant terminal access. Finally, when you exit a capture using `CTRL + C`, the CLI runs the `oc cp` command to copy the output files to your local machine.
+
+
+## A different approach for each scenario
+
+Let's first compare which deployment methods of the Network Observability stack best fit with these example scenarios:
+
+
+
+
+
Deployment method
+
Configuration
+
Short debug session
+
Overall observability on short period of time
+
Long term observability
+
Per flows details
+
Packet capture (pcap)
+
+
+
+
+
CLI
+
Flows
+
🗸 best for enriched content
+
✗
+
✗
+
🗸
+
✗
+
+
+
+
Packets
+
🗸 best for data analysis
+
✗
+
✗
+
✗ no enrichment
+
🗸
+
+
+
Operator
+
Loki
+
✗
+
🗸
+
✗ unsatisfactory metrics performances
+
🗸
+
✗
+
+
+
+
Prometheus
+
✗
+
🗸
+
🗸
+
✗
+
✗
+
+
+
+
Using both
+
✗
+
🗸
+
🗸
+
🗸
+
✗
+
+
+
+
+It's not worth installing the operator and dependent storage(s) for a short debug session or to get a preview of what eBPF agents can capture whereas it makes sense for a long run scenario where you aim to keep history of logs or metrics for several days.
+
+To see flows in details, both CLI and Operators allows you to deep dive into the K8S enriched fields (Node / Owner / Pod / Service names + Zones) and featured fields such as Bytes / Packets drops, DNS Ids and Latencies and Round Trip Time.
+
+## How to install ?
+
+`kubectl` and `oc` CLIs allows installation of plugins that extends their capabilities with additionnal commands.
+A plugin is mainly a script placed in your `PATH` and prefixed with the corresponding name such as `oc-netobserv`.
+Read more about [kubectl-plugins](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/) and [oc-plugins](https://docs.openshift.com/container-platform/4.15/cli_reference/openshift_cli/extending-cli-plugins.html#cli-installing-plugins_cli-extend-plugins).
+
+For the purpose of this article, the following commands assume you are using `oc`.
+
+### The krew way
+
+> Krew itself is a kubectl plugin that is installed and updated via Krew (yes, Krew self-hosts).
+
+Follow the instructions on [krew.sigs.k8s.io](https://krew.sigs.k8s.io/docs/user-guide/setup/install/) official website.
+Once installed, run the following command to install netobserv:
+```
+oc krew install netobserv
+```
+
+### From tar archive
+
+Download the latest version either from [github releases](https://github.com/netobserv/network-observability-cli/releases) or [developers.redhat.com](https://developers.redhat.com/content-gateway/rest/mirror2/pub/openshift-v4/clients/netobserv/latest).
+
+Then follow the instructions on [Installing and using CLI plugins](https://docs.openshift.com/container-platform/4.15/cli_reference/openshift_cli/extending-cli-plugins.html#cli-installing-plugins_cli-extend-plugins) from Openshift documentation.
+
+These should resume as following commands using `/usr/local/bin` as PATH folder:
+```
+tar -xvzf ./netobserv-linux-amd64.tar.gz
+chmod +x ./netobserv-linux-amd64/build/oc-netobserv
+sudo mv ./netobserv-linux-amd64/build/oc-netobserv /usr/local/bin/.
+```
+
+## Verify the installation
+
+To ensure the installation completed correctly, simply run the following command:
+```
+oc netobserv version
+```
+
+It should print `Netobserv CLI version XXX` with the version you picked earlier.
+
+## Usage
+
+Use the following command to display the help:
+```
+oc netobserv help
+```
+
+```
+Netobserv allows you to capture flow and packets from your cluster.
+Find more information at: https://github.com/netobserv/network-observability-cli/
+
+Syntax: netobserv [flows|packets|cleanup] [filters]
+
+options:
+ flows Capture flows information. Use options below for features / filtering.
+ Options:
+ --interfaces: interfaces to monitor
+ --enable_pktdrop: enable packet drop (default: false)
+ --enable_dns: enable DNS tracking (default: false)
+ --enable_rtt: enable RTT tracking (default: false)
+ --enable_filter: enable flow filter (default: false)
+ --direction: flow filter direction
+ --cidr: flow filter CIDR (default: 0.0.0.0/0)
+ --protocol: flow filter protocol
+ --sport: flow filter source port
+ --dport: flow filter destination port
+ --port: flow filter port
+ --sport_range: flow filter source port range
+ --dport_range: flow filter destination port range
+ --port_range: flow filter port range
+ --icmp_type: ICMP type
+ --icmp_code: ICMP code
+ --peer_ip: peer IP
+ --action: flow filter action (default: Accept)
+ packets Capture packets from a specific protocol/port pair such as 'netobserv packets tcp,80'.
+ cleanup Remove netobserv components.
+ version Print software version.
+ ```
+
+As you can see, the CLI offers two captures options for now:
+- `flows` to get network flows containing [enriched informations](https://github.com/netobserv/network-observability-operator/blob/main/docs/flows-format.adoc#network-flows-format-reference)
+
+On top of this command, you can add extra features and filters. Example to capture `Round Trip Time` of `TCP` flows using port `80`:
+```
+oc netobserv flows --enable_filter=true --protocol=tcp --port=80 --enable_rtt=true
+```
+
+})
+
+It will display a table view with latest flows collected and write data under output/flow directory.
+To stop capturing press `CTRL + C`.
+
+This will write data into two separate files:
+- `./output/flow/.json` containing json array of received data such as:
+```json
+{
+ "AgentIP": "10.0.1.76",
+ "Bytes": 561,
+ "DnsErrno": 0,
+ "Dscp": 20,
+ "DstAddr": "f904:ece9:ba63:6ac7:8018:1e5:7130:0",
+ "DstMac": "0A:58:0A:80:00:37",
+ "DstPort": 9999,
+ "Duplicate": false,
+ "Etype": 2048,
+ "Flags": 16,
+ "FlowDirection": 0,
+ "IfDirection": 0,
+ "Interface": "ens5",
+ "K8S_FlowLayer": "infra",
+ "Packets": 1,
+ "Proto": 6,
+ "SrcAddr": "3e06:6c10:6440:2:a80:37:b756:270f",
+ "SrcMac": "0A:58:0A:80:00:01",
+ "SrcPort": 46934,
+ "TimeFlowEndMs": 1709741962111,
+ "TimeFlowRttNs": 121000,
+ "TimeFlowStartMs": 1709741962111,
+ "TimeReceived": 1709741964
+}
+```
+- `./output/flow/.db` database that can be inspected using `sqlite3` for example:
+```bash
+bash-5.1$ sqlite3 ./output/flow/.db
+SQLite version 3.34.1 2021-01-20 14:10:07
+Enter ".help" for usage hints.
+sqlite> SELECT DnsLatencyMs, DnsFlagsResponseCode, DnsId, DstAddr, DstPort, Interface, Proto, SrcAddr, SrcPort, Bytes, Packets FROM flow WHERE DnsLatencyMs >10 LIMIT 10;
+12|NoError|58747|10.128.0.63|57856||17|172.30.0.10|53|284|1
+11|NoError|20486|10.128.0.52|56575||17|169.254.169.254|53|225|1
+11|NoError|59544|10.128.0.103|51089||17|172.30.0.10|53|307|1
+13|NoError|32519|10.128.0.52|55241||17|169.254.169.254|53|254|1
+12|NoError|32519|10.0.0.3|55241||17|169.254.169.254|53|254|1
+15|NoError|57673|10.128.0.19|59051||17|172.30.0.10|53|313|1
+13|NoError|35652|10.0.0.3|46532||17|169.254.169.254|53|183|1
+32|NoError|37326|10.0.0.3|52718||17|169.254.169.254|53|169|1
+14|NoError|14530|10.0.0.3|58203||17|169.254.169.254|53|246|1
+15|NoError|40548|10.0.0.3|45933||17|169.254.169.254|53|174|1
+```
+or `dbeaver`:
+})
+
+- `packets` to get pcap file containing [full packet data](https://github.com/netobserv/netobserv-ebpf-agent/blob/main/examples/packetcapture-dump/README.md).
+
+})
+
+It will display a table view with latest packets collected and write data under output/pcap directory.
+To stop capturing press `CTRL + C`.
+
+This will write pcap into a single file located in `./output/pcap/.pcap` that can be opened with Wireshark for example:
+
+})
+
+This command must have both protocol and port specified to work. We will improve the packet capture filtering options in the future.
+Packet drop, DNS latencies and RTT features are not available in this command.
+
+A third option called `cleanup` allows you to remove any remaining netobserv component. That should not happen since this command is automatically run when exiting the capture but it may be necessary to manually execute it in case of connectivity issue or crash.
+
+### Use cases
+
+Let's move on some concrete scenarios. For each of the following use cases, you must have `netobserv CLI` installed and you need to be connected to your cluster using:
+```
+oc login --username --password
+```
+
+To observ what's our CLI deploys on your cluster, you can run `oc events -n netobserv-cli -w` command to watch all the events happening in the `netobserv-cli` namespace.
+
+The result will look like:
+```
+LAST SEEN TYPE REASON OBJECT MESSAGE
+0s Normal SuccessfulCreate DaemonSet/netobserv-cli Created pod: netobserv-cli-t2vlr
+0s Normal Scheduled Pod/netobserv-cli-t2vlr Successfully assigned netobserv-cli/netobserv-cli-t2vlr to ip-10-0-1-202.ec2.internal
+0s Normal SuccessfulCreate DaemonSet/netobserv-cli Created pod: netobserv-cli-hlmxx
+0s Normal Scheduled Pod/netobserv-cli-hlmxx Successfully assigned netobserv-cli/netobserv-cli-hlmxx to ip-10-0-1-220.ec2.internal
+0s Normal Pulling Pod/netobserv-cli-t2vlr Pulling image "quay.io/netobserv/netobserv-ebpf-agent:main"
+0s Normal Pulling Pod/netobserv-cli-hlmxx Pulling image "quay.io/netobserv/netobserv-ebpf-agent:main"
+0s Normal Pulled Pod/netobserv-cli-hlmxx Successfully pulled image "quay.io/netobserv/netobserv-ebpf-agent:main" in 2.049s (2.049s including waiting)
+0s Normal Created Pod/netobserv-cli-hlmxx Created container netobserv-cli
+0s Normal Started Pod/netobserv-cli-hlmxx Started container netobserv-cli
+0s Normal Pulled Pod/netobserv-cli-t2vlr Successfully pulled image "quay.io/netobserv/netobserv-ebpf-agent:main" in 5.376s (5.376s including waiting)
+0s Normal Created Pod/netobserv-cli-t2vlr Created container netobserv-cli
+0s Normal Started Pod/netobserv-cli-t2vlr Started container netobserv-cli
+0s Normal Scheduled Pod/collector Successfully assigned netobserv-cli/collector to ip-10-0-1-220.ec2.internal
+0s Normal AddedInterface Pod/collector Add eth0 [10.129.0.35/23] from ovn-kubernetes
+0s Normal Pulling Pod/collector Pulling image "quay.io/netobserv/network-observability-cli:main"
+0s Normal Pulled Pod/collector Successfully pulled image "quay.io/netobserv/network-observability-cli:main" in 1.724s (1.724s including waiting)
+0s Normal Created Pod/collector Created container collector
+0s Normal Started Pod/collector Started container collector
+```
+
+#### Connectivity check(s) between two endpoints
+
+Let's start with a simple case where you have a pod not able to reach an endpoint. We are using a simple nodejs sample app deployed in `connectivity-scenario` namespace for the demo.
+
+})
+
+This could be related to many issues such as:
+- DNS issue
+- Policy or kernel drops
+- Timeouts
+
+Since we don't know what we are looking for yet, we should enable all the features using the options:
+```
+--enable_pktdrop=true --enable_dns=true --enable_rtt=true
+```
+
+By clicking on the pod name, we can see that our current pod IP is `10.129.0.48`. To capture all the traffic going in and out of this pod, we will use the filter:
+```
+--enable_filter=true --peer_ip=10.129.0.48
+```
+
+Alternatively, you could also use the service port
+```
+--enable_filter=true --port=3001
+```
+
+WARNING: Running the capture without filtering is also an option but not recommended as we are going to collect all the flows of the cluster. Depending of the size of your cluster, this could be a lot and make the collector pod crash.
+
+All together, the command to run flow capture with all the features on our pod IP will be:
+```
+oc netobserv flows --enable_pktdrop=true --enable_dns=true --enable_rtt=true --enable_filter=true --peer_ip=10.129.0.48
+```
+
+The script will connect to your cluster and start deploying eBPF agents and collector pod:
+```
+Setting up...
+cluster-admin
+creating netobserv-cli namespace
+namespace/netobserv-cli created
+creating service account
+serviceaccount/netobserv-cli created
+clusterrole.rbac.authorization.k8s.io/netobserv-cli configured
+clusterrolebinding.rbac.authorization.k8s.io/netobserv-cli unchanged
+creating collector service
+service/collector created
+creating flow-capture agents:
+env: pktdrop_enable, env_value: true
+env: dns_enable, env_value: true
+env: rtt_enable, env_value: true
+env: filter_enable, env_value: true
+env: filter_peer_ip, env_value: 10.129.0.48
+daemonset.apps/netobserv-cli created
+Waiting for daemon set "netobserv-cli" rollout to finish: 0 of 2 updated pods are available...
+Waiting for daemon set "netobserv-cli" rollout to finish: 1 of 2 updated pods are available...
+daemon set "netobserv-cli" successfully rolled out
+Running network-observability-cli get-flows...
+pod/collector created
+pod/collector condition met
+```
+
+Once that done, it will connect to the collector and display its output:
+```
+Starting network-observability-cli:
+=====
+Build Version:
+Build Date:
+
+INFO[0000] Running network-observability-cli
+Log level: info
+Filter(s): --enable_pktdrop=true --enable_dns=true --enable_rtt=true --enable_filter=true --peer_ip=10.129.0.48
+INFO[0000] Starting Flow Capture...
+INFO[0000] Creating database...
+INFO[0000] flows.db created
+INFO[0000] Create flows table...
+INFO[0000] flows table created
+```
+
+At this stage, the collector wait for incoming data. If nothing shows yet, it means that no traffic is captured. Try to open the route of your application or update the filters of the capture.
+
+Once some traffic is captured, the output will look like:
+})
+
+You can cycle to different views using left / right arrow keys and change the displayed enrichment colomns using page up / down ones.
+Also, to adapt to your screen height, you can increase / decrease the number of displayed flows using up / down arrow keys.
+
+In this capture, we see that the traffic is blocked by OVS since it reports the `OVS_DROP_LAST_ACTION` drop cause. This probably means that a Network Policy is involved.
+Edit your network policies and give another try.
+
+Behind the scenes in our scenario, we used to have a deny all on the pod label:
+```
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: deny-nodejs
+ namespace: connectivity-scenario
+spec:
+ podSelector:
+ matchLabels:
+ app: nodejs-basic
+ policyTypes:
+ - Ingress
+ - Egress
+```
+
+Once you updated your policies, you can give another try to your route until you fix the issue:
+})
+
+The drop cause will dissapear and your route should open correctly now. On top of that, you can ensure that the Round Trip Time is correct.
+If you are still experienting issues with the route, you may update / get rid of the filter(s) and play with live filtering.
+
+- While running a capture, you can place additionnal live filters to the view by simply typing keywords on your keyboard such as `nodejs`:
+})
+
+- And add as many keywords as you want by pressing enter:
+})
+
+- If your deployment involve some DNS resolution, you can switch to the DNS display and show latencies and errors:
+Once you updated your policies, you can give another try to your route until you fix the issue:
+})
+
+ Those `NxDomain` errors could be from a misconfiguration in your app deployment trying to reach the wrong domain.
+
+Once you are done, simply press `CTRL + C` to exit. Your capture will be copied to your local machine for post mortem analysis.
+
+That's the end of the first scenario about connectivity checks !
+
+#### Identify unknown traffic content
+
+In this next scenario, we are going to dig into unknown packets using unencrypted traffic on `TCP` protocol on port `80`. We usually avoid such usage on production cluster and would like to understand who's involved in these.
+
+For the demo purepose, we are using again a nodejs basic deployment, exposing unencrypted traffic on port 80 in `packet-capture-scenario` namespace.
+
+Let's start a packet capture using the following command:
+```
+oc netobserv packets tcp,80
+```
+
+Similarly to the previous scenario, the script will connect to your cluster and start deploying eBPF agents and collector pod but capturing full packet content this time.
+
+Once first packet is captured, you will see a table with the amount of packets and bytes:
+
+})
+
+Let the capture run enough time to get some packets and press `CTRL + C` to exit.
+Open the generated pcap file using Wireshark and look for your IP as source for example:
+
+})
+
+This time, we can see the HTTP content and see the request URL and response. Since we have the entire payload, we cand check for any authentification header, cookie, encoding and so on that may be wrong.
+This is useful to identify traffic content but also to debug a deployment that may be misconfigured or requesting unexpected content on unencrypted connections.
+
+#### Encrypted traffic
+
+What about encrypted traffic ?
+
+Most of the time, your traffic will be secured and you will not have access to the data it holds. However, Wireshark has the ability to decrypt the content if you [provide the proper secrets](https://wiki.wireshark.org/TLS#tls-decryption). However, getting these secrets may be tricky depending on where the encryption happens and needs some juggling.
+If you are looking for the traffic between your browser and the cluster, you can simply run the following command to capture [pre-master-secret keylog file](https://wiki.wireshark.org/TLS#using-the-pre-master-secret):
+```
+SSLKEYLOGFILE="keylog.txt" chromium-browser &
+```
+
+This generated file contains each client and server traffic secrets to decode your packets.
+
+Then in Wireshark, specify the file path in `Edit→Preferences→Protocols→TLS→(Pre)-Master-Secret log filename`. A single file can hold keys for multiple TLS connections.
+
+})
+
+You should now have access to decrypted packets !
+
+What about a secure connection between two pods ?
+For these cases, you need to have a good understanding of what's involved behind the scene. If your application rely on OpenSSL, GnuTLS or NSS TLS library, you should be able to set the `SSLKEYLOGFILE` enviroment variable and extract the result.
+
+For our nodejs example, you need to either use the cli option [--tls-keylog](https://nodejs.org/api/cli.html#cli_tls_keylog_file) or modify the code and subscribe on [keylog event](https://nodejs.org/api/tls.html#event-keylog). When multiple teams are involved, that may take a while !
+
+Another alternative is to get a man in the middle approach using a proxy. This can be done using [kubetap](https://soluble-ai.github.io/kubetap/).
+
+You can install it using krew by running:
+```
+oc krew install tap
+```
+
+Then you can run the following command to port forward the traffic of your service to the proxy:
+```
+oc tap on -n packet-capture-scenario -p 3001 --https nodejs-basic --port-forward
+```
+
+The output should look like this:
+```
+Establishing port-forward tunnels to Service...
+
+
+Port-Forwards:
+
+ mitmproxy - http://127.0.0.1:2244
+ nodejs-basic - http://127.0.0.1:4000
+```
+
+Open the mitm proxy url and generate a query to your route. You can see queries listed in the proxy web UI with the content displayed:
+
+})
+
+## Future improvements
+
+For now, the Network Observability CLI is only providing `capture commands` such as [many other observability projects](https://github.com/collabnix/kubetools?tab=readme-ov-file#observability). There are planned improvements to embed tools to facilitate your life as much as possible.
+
+We have in mind to improve the capture process by automatically finding IP addresses and ports that match to the pods you are looking for and automatically filtering on these.
+
+The packet capture needs to be improved to align with flows filter capabilities and facilitate decryption of traffic. We are also investigating ways to embed enriched information inside the pcap file format.
+
+Also, the CLI could hold additional functionalities, such as installing and configuring the Network Observability Operator in a step-by-step setup, including Loki and Prometheus configurations.
+
+It could become 'yet another' toolset of observing and debugging tools such as [inspektor-gadget](https://github.com/inspektor-gadget/inspektor-gadget) but fully tested and supported by Red Hat as part of the [Openshift Network Observability](https://docs.openshift.com/container-platform/4.16/observability/network_observability/network-observability-overview.html) .
+
+## Feedback
+
+We hope you liked this article !
+
+Netobserv is an OpenSource project [available on github](https://github.com/netobserv).
+Feel free to share your [ideas](https://github.com/netobserv/network-observability-operator/discussions/categories/ideas), [use cases](https://github.com/netobserv/network-observability-operator/discussions/categories/show-and-tell) or [ask the community for help](https://github.com/netobserv/network-observability-operator/discussions/categories/q-a).
diff --git a/content/posts/2024-09-19-lokiless_netobserv.md b/content/posts/2024-09-19-lokiless_netobserv.md
new file mode 100644
index 0000000..c52ea64
--- /dev/null
+++ b/content/posts/2024-09-19-lokiless_netobserv.md
@@ -0,0 +1,166 @@
+---
+layout: :theme/post
+title: "Light-weight Network Observability operator without Loki"
+description: "Get the pros and cons to install NetObserv without Loki"
+tags: Performance,Metrics,Loki
+authors: [memodi,stleerh]
+---
+
+
+
+Recently, the Network Observability Operator released version 1.6, which added a major enhancement to provide network insights for your OpenShift cluster without Loki. This enhancement was also featured in [What's new in Network Observability 1.6](https://developers.redhat.com/articles/2024/08/12/whats-new-network-observability-16) blog, providing a quick overview of the feature. Until this release, Loki was required to be deployed alongside Network Observability to store the network flows data. In this blog, lets look at some of the advantages and trade-offs users would have when deploying the Network Observability Operator with Loki disabled. As more metrics are enabled by default with this feature, we'll also demonstrate a use-case on how those metrics can benefit users for real world scenarios.
+
+# Configure Network Observability without Loki
+Loki as datasource is currently enabled by default. To configure the Network Observability Operator without Loki, set the `FlowCollector` resource specification, `.spec.loki.enable`, to `false`
+
+```yaml
+loki:
+ enable: false
+```
+When Loki is disabled, metrics continue to get scraped by the OpenShift cluster Prometheus without any additional configuration. The Network Traffic console uses Prometheus as a source for fetching the data.
+
+## Performance and Resource utilization gains
+In this section, lets dive into the query performance and resource utilization differences when Network Observability is configured with Loki and without it.
+
+### Query performance:
+Prometheus queries are blazing fast compared to Loki queries, but don't take my word for it, let's look at the data from the query performance tests:
+
+**Test bench environment**:
+
+* **Test**: We conducted 50 identical queries without any filters for 3 separate time ranges to render a topology view for both Loki and Prometheus. Such a query requests all K8s Owners for the workload running in an OpenShift Cluster that had network flows associated to them.
+
+* **Test bed**: 9 worker and 3 master nodes, AWS m5.2xlarge machines
+* **LokiStack size**: 1x.small
+
+Results:
+
+ The following table shows the 90th percentile query times for each table:
+
+
+
+
+
Time Range
+
Loki
+
Prometheus
+
+
+
+
+
Last 5m
+
984 ms
+
99 ms
+
+
+
Last 1h
+
2410 ms
+
236 ms
+
+
+
Last 6h
+
> 10 s
+
474 ms
+
+
+
+
+As the time range to fetch network flows gets wider, Loki queries tend to get slower or time out, while Prometheus queries are able to render the data within a fraction of a second.
+
+### Resource utilization:
+In our tests conducted on 3 different test beds with varied workloads and network throughput, when Network Observability is configured without Loki, total savings of memory usage are in the 45-65% range and CPU utilization is lower by 10-20%*. Not to mention you do not need to provision and plan for additional object storage in public clouds for Loki, overall reducing the cost and improving operational efficiency significantly.
+
+In our perf tests, [kube-burner](https://github.com/kube-burner/kube-burner) workloads were used to generate several objects and create heavy network traffic. We used a sampling rate of 1 for all of the following tests:
+
+1. **Test bed 1**: 25 nodes cluster - this test takes into account the total number of namespace, pods and services in an OpenShift Container Platform cluster, places load on the eBPF agent, and represents use cases with a high number of workloads for a given cluster size. For example, Test 1 consists of 76 Namespaces, 5153 Pods, and 2305 Services.
+2. **Test bed 2**: 65 nodes cluster - this test takes into account a high ingress traffic volume.
+3. **Test bed 3**: 120 nodes cluster - this test takes into account the total number of namespace, pods and services in an OpenShift Container Platform cluster, places load on the eBPF agent on a larger scale than Test bed 1, and represents use cases with a high number of workloads for a given cluster size. For example, Test bed 3 consists of 553 Namespaces, 6998 Pods, and 2508 Services
+
+The following graphs show total vCPU, memory and storage usage for a recommended Network Observability stack - flowlogs-pipeline, eBPF-agent, Kafka, Prometheus and optionally Loki for production clusters.
+
+})
+})
+
+Let's look at the amount of estimated storage you need for all the network flows and Prometheus metrics that Network Observability has to store. For context, even when Loki is installed, Network Observability publishes a default set of Prometheus metrics for monitoring dashboards, and it adds additional metrics when Loki is disabled to visualize network flows. The graphs below show the estimated amount of storage required to store 15 days of network flows data (when configured with Loki), with Prometheus metrics and Kafka as an intermediary data streaming layer between the eBPF-agent and the flowlogs-pipeline.
+
+The network flows rate for each test bed was 10K, 13K, 30K flows/second respectively. The storage for Loki includes AWS S3 bucket utilization and its PVC usage. For Kafka PVC storage value, it assumes 1 day of retention or 100 GB whichever is attained first.
+
+})
+
+As seen across the test beds, we find a storage savings of 90% when Network Observability is configured without Loki.
+
+* actual resource utilization may depend on various factors such as network traffic, FlowCollector sampling size, and the number of workloads and nodes in an OpenShift Container Platform cluster
+
+## Trade-offs:
+We saw having Prometheus as datasource provides impressive performance gains and sub-second query times, however it introduces the following constraints:
+
+1. Without storage of network flows data, the Network Observability OpenShift web console no longer provides the Traffic flows table.
+
+})
+
+2. Per-pod level of resource granularity is not available since it causes Prometheus metrics to have high cardinality.
+
+})
+
+ Should you need per-flow or per-pod level of granularity for diagnostic and troubleshooting, other than enabling Loki you have multiple other options available:
+
+ a. Collect flowlogs into your preferred data analytics tool using the`.spec.exporters` configuration in the FlowCollector. Currently Kafka and IPFIX are supported exporters.
+
+ b. In this release, Network Observability also introduced the `FlowMetrics` API, which lets you create custom metrics that are not available out of the box. The `FlowMetrics` API creates on-demand Prometheus metrics based on enriched flowlogs fields, which can be used as labels for custom Prometheus metrics. _Note: Use this option with caution, as introducing metrics that may have labels with high cardinality increases the cluster's Prometheus resource usage and might impact overall cluster monitoring_.
+
+3. Restricted multi-tenancy - Prometheus in OpenShift cluster currently doesn't support multi-tenancy in a way that Loki does. Non-admin users can be added to `cluster-monitoring-view` where the user can have access to view all available Prometheus metrics.
+
+ For example, the following command can be used to enable Prometheus metrics, visualizing for the `testuser-0` user.
+
+ `oc adm policy add-cluster-role-to-user cluster-monitoring-view testuser-0`
+
+## Network Observability metrics use case:
+Let's look at a scenario about how users can benefit from metrics published by the Network Observability Operator. For instance, if you suspect anomaly with DNS lookups in your cluster and want to investigate workloads that may be facing DNS latencies. With Network Observability's `DNSTracking` feature and enriched Prometheus metrics you can quickly set up an alert to trigger on high DNS latencies.
+
+For example, the following alert is triggered for any workloads that experience a DNS latency > 100ms:
+```yaml
+apiVersion: monitoring.coreos.com/v1
+kind: PrometheusRule
+metadata:
+ name: dns-latency-alert
+ namespace: netobserv
+spec:
+ groups:
+ - name: DNSLatencyAlert
+ rules:
+ - alert: DNSLatencyAlert
+ annotations:
+ message: |-
+ {{ $labels.DstK8S_OwnerName }} in {{ $labels.DstK8S_Namespace }} is experiencing high DNS Latencies.
+ summary: "Trigger for any workloads experiencing > than 100ms DNS Latency."
+ expr: histogram_quantile(0.9, sum(rate(netobserv_workload_dns_latency_seconds_bucket{ DstK8S_Namespace!=""}[2m])) by (le,DstK8S_Namespace,DstK8S_OwnerName))*1000 > 100
+ for: 10s
+ labels:
+ severity: warning
+```
+
+To demonstrate this use-case, I configured the CoreDNS [erratic plugin](https://coredns.io/plugins/erratic/) in `openshift-dns` namespace to add latencies for `example.org` domain using the following configuration:
+
+```
+example.org {
+ erratic {
+ delay 2 100ms
+ }
+}
+```
+
+Configuring for DNS latencies adds 100ms delay to every 2nd DNS request coming in for `example.org`. A test pod performing DNS lookups for `example.org` every 1 second was created, eventually triggering earlier configured `DNSLatencyAlert` in my OCP cluster.
+
+})
+
+Similarly, additional alerts on different DNS response codes could be set up, for example an alert for DNS lookup failures such as DNS queries receiving NXDOMAIN or SERVFAIL responses can also be set up as flowlogs and metrics are already enriched with DNS response codes.
+
+In addition to metrics for the `DNSTracking` feature, Network Observability provides metrics for other features, such as Round-Trip-Time and Packet Drops.
+
+## Conclusion and next steps:
+
+The Network Observability Operator provides the visibility you need to proactively detect issues within OpenShift cluster networking. Now with an option to disable Loki, and instead leverage Prometheus metrics, the Network Observability Operator provides a light-weight solution to visualize, diagnose and troubleshoot networking issues faster and at a lower cost.
+
+Whether you have already deployed or considering to deploy Network Observability, we would love to engage with you and hear your thoughts [here](https://github.com/netobserv/network-observability-operator/discussions).
+
+_Special thanks to Joel Takvorian, Julien Pinsonneau, and Sara Thomas for providing information for this article._
diff --git a/content/posts/2024-10-18-network_events.md b/content/posts/2024-10-18-network_events.md
new file mode 100644
index 0000000..0fa3ba1
--- /dev/null
+++ b/content/posts/2024-10-18-network_events.md
@@ -0,0 +1,290 @@
+---
+layout: :theme/post
+title: "Monitoring OVN Networking Events using Network Observability"
+description: OVN network events provide enriched information such as network policy drops / accepts
+tags: Monitoring,Network,NetworkPolicy,OVN
+authors: [msherif1234]
+---
+
+
+
+Network security and performance maintenance crucially depend on monitoring network events triggered
+by OVN (Open Virtual Network), including network policies, admin network policies, and egress firewalls.
+You can achieve this using network observability eBPF agent, which runs in the Linux kernel and can trace
+various network activities with minimal performance overhead, allowing you to observe and capture detailed
+information about network traffic and events in real-time.
+
+## Key Components for Network Observability with eBPF
+
+1- eBPF network events monitoring `Kprobe` eBPF hook
+
+Network events monitoring using eBPF kernel probes (kprobes) provides deep, kernel-level insights into
+network stack behavior. The NetObserv eBPF agent leverages the [psample_sample_packet](https://github.com/torvalds/linux/blob/e32cde8d2bd7d251a8f9b434143977ddf13dcec6/net/psample/psample.c#L363) entry point to efficiently
+capture packet metadata and identify policy violations with minimal overhead.
+
+The hook implemented in the NetObserv eBPF agent can capture multiple events within the same network flow
+and generate a list of network events that applied to that flow, with a limit of up to four events per flow.
+
+2- [ovn-kubernetes observability library](https://github.com/ovn-org/ovn-kubernetes/tree/master/go-controller/observability-lib)
+
+The eBPF agent captures network events as an array of bytes, which is not very user-friendly.
+This library provides functionality to convert these events into human-readable strings, making
+them easily understandable for customers.
+
+## Use Cases for Network Observability with eBPF
+
+1. Monitor [network policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/)
+
+When you apply OVN network policies (like Kubernetes NetworkPolicy), eBPF agent can monitor allowed
+and/or blocked traffic, detecting whether packets are allowed or blocked based on network policies.
+An example of these network policies follows:
+
+```yaml
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: iperf3-server-access-ingress
+ namespace: iperf
+spec:
+ podSelector:
+ matchLabels:
+ app: iperf3-server
+ ingress:
+ - ports:
+ - port: 5501
+ from:
+ - podSelector:
+ matchLabels:
+ app: iperf3-client
+---
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: iperf3-server-access-egress
+ namespace: iperf
+spec:
+ podSelector:
+ matchLabels:
+ app: iperf3-client
+ egress:
+ - ports:
+ - port: 5201
+ protocol: TCP
+ podSelector: {}
+ policyTypes:
+ - Egress
+```
+
+
+
+_Screen capture of the traffic flows in the NetObserv console plugin,
+with a network events column showing traffic allowed or denied by network policy rules_
+
+2. Monitor [admin network Policies](https://network-policy-api.sigs.k8s.io/api-overview/#the-adminnetworkpolicy-resource)
+
+An Admin network Policy is a high-level security policy designed to provide cluster administrators with
+more control over network traffic in Kubernetes environments.
+eBPF agent can monitor allowed/blocked Traffic: Detect whether packets are allowed or blocked based on
+admin network policies.
+
+An Example of admin network policy and egress network policy to show multiple events use case :
+
+```yaml
+apiVersion: policy.networking.k8s.io/v1alpha1
+kind: AdminNetworkPolicy
+metadata:
+ name: allow-egress-iperf
+spec:
+ egress:
+ - action: Pass
+ to:
+ - namespaces: {}
+ priority: 10
+ subject:
+ namespaces:
+ matchLabels:
+ kubernetes.io/metadata.name: iperf
+
+---
+
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: iperf3-server-access-egress
+ namespace: iperf
+spec:
+ podSelector:
+ matchLabels:
+ app: iperf3-client
+ egress:
+ - ports:
+ - port: 5201
+ protocol: TCP
+ podSelector: {}
+ policyTypes:
+ - Egress
+
+```
+
+
+
+_Screen capture of the traffic flows in the NetObserv console plugin, with a network events column
+showing the delegation by the admin policy resulting in traffic allowed or denied_
+
+3. Monitor [egress firewall traffic](https://docs.openshift.com/container-platform/4.17/networking/network_security/egress_firewall/configuring-egress-firewall-ovn.html)
+
+For egress firewall monitoring, the eBPF agent can do the following:
+
+Trace egress traffic: Track outbound traffic and see whether it adheres to egress firewall rules.
+Detect unauthorized outbound connections: You can flag outbound traffic that violates egress rules.
+
+In the following example, there are three events, one for network policy, another for admin network policy and the third for egress firewall
+
+```yaml
+apiVersion: k8s.ovn.org/v1
+kind: EgressFirewall
+metadata:
+ name: default
+ namespace: iperf
+spec:
+ egress:
+ - to:
+ cidrSelector: 8.8.8.8/24
+ type: Allow
+ - to:
+ cidrSelector: 0.0.0.0/0
+ type: Deny
+
+---
+apiVersion: policy.networking.k8s.io/v1alpha1
+kind: AdminNetworkPolicy
+metadata:
+ name: allow-egress-iperf
+spec:
+ egress:
+ - action: Pass
+ to:
+ - namespaces: {}
+ priority: 10
+ subject:
+ namespaces:
+ matchLabels:
+ kubernetes.io/metadata.name: iperf
+
+---
+kind: NetworkPolicy
+apiVersion: networking.k8s.io/v1
+metadata:
+ name: iperf3-server-access-egress
+ namespace: iperf
+spec:
+ podSelector:
+ matchLabels:
+ app: iperf3-client
+ egress:
+ - ports:
+ - port: 5201
+ protocol: TCP
+ podSelector: {}
+ policyTypes:
+ - Egress
+
+```
+
+
+
+_Screen capture of the traffic flows in the NetObserv console plugin,
+with a network events column showing traffic allowed or denied by egress firewall rules_
+
+## Integration with the Network Observability stack
+
+- `eBPF Agent`:
+
+The agent manages a new `kprobe` hook through a configuration option.
+It also registers with the OVN observability library, allowing eBPF-generated events to be enriched
+into meaningful strings.
+
+- `Agent User Space`:
+
+The Agent user space handles the aggregation of events for processing.
+
+- `Flowlogs Pipeline`:
+
+Generated flows are transmitted over gRPC to the flowlogs-pipeline,
+where the flow content is enriched with Kubernetes metadata.
+
+- `Loki storage and Console-plugin`:
+
+The enriched flows are then sent to Loki storage, making them available for
+consumption by the NetObserv console plugin. The new events are displayed in the console.
+
+- `New Filtering Capability`:
+
+A filter is introduced to filter flows based on network event enrichment.
+
+})
+
+## Configuration
+
+- Enable the `OVNObservability` feature in the `FeatureGate` custom resource.
+
+```shell
+$ oc edit featuregates.config.openshift.io cluster
+```
+
+```yaml
+spec:
+ featureSet: TechPreviewNoUpgrade
+enabled:
+- name: OVNObservability
+```
+
+Note:
+ The above FeatureGate might be on by default at the time this feature becomes GA.
+
+- Enable Network events in the Network Observability `FlowCollector` custom resource.
+
+```yaml
+apiVersion: flows.netobserv.io/v1beta2
+kind: FlowCollector
+metadata:
+ name: cluster
+spec:
+ agent:
+ type: eBPF
+ ebpf:
+ sampling: 1
+ privileged: true
+ features:
+ - "NetworkEvents"
+```
+
+Note:
+
+- in the above example we set `sampling` to 1 to be able to capture all network events without missing any.
+
+- `privileged` is set to `true` because the `OVN observability` library needs to access local OVS socket and OVN databases.
+
+## Availability
+
+The networking events monitoring feature is available as Developer Preview for OCP 4.17 z-stream and NetObserv release 1.7,
+and is planned for GA in OCP 4.18 and NetObserv release 1.8.
+
+## Conclusion
+
+Relying on eBPF technology for network observability, particularly in environments governed by OVN network policies and egress firewalls,
+offers deep, real-time insights into network traffic.
+Users can monitor policy compliance, detect violations, and track detailed network flows.
+This helps you maintain a secure, high-performing network environment.
+
+## Feedback
+
+We hope you liked this article !
+Netobserv is an OpenSource project [available on github](https://github.com/netobserv).
+Feel free to share your [ideas](https://github.com/netobserv/network-observability-operator/discussions/categories/ideas), [use cases](https://github.com/netobserv/network-observability-operator/discussions/categories/show-and-tell) or [ask the community for help](https://github.com/netobserv/network-observability-operator/discussions/categories/q-a).
diff --git a/content/posts/2024-10-23-whats_new_1_6.md b/content/posts/2024-10-23-whats_new_1_6.md
new file mode 100644
index 0000000..6fc051d
--- /dev/null
+++ b/content/posts/2024-10-23-whats_new_1_6.md
@@ -0,0 +1,226 @@
+---
+layout: :theme/post
+title: "What's new in Network Observability 1.6"
+description: "Check out the new features: deploying without Loki, a new CLI, new eBPF filters and more..."
+tags: What's New,Prometheus,Loki,Performance,Configuration,Metrics,CLI
+authors: [stleerh]
+---
+
+
+
+Network Observability 1.6 was released on June 2024. Even though this is considered a minor version upgrade from 1.5, it is a significant release that could lower the barrier to adoption into production.
+
+But before we go further, for those of you new to Network Observability, NetObserv, for short, is an optional operator that provides a slew of capabilities to track and provide insight into your network traffic flows. While it works on any Kubernetes cluster, it works even better in an OpenShift environment, which is what I will focus on in this article. I will only discuss the new features in this release so if you want the full feature list, read the documentation on [About Network Observability](https://docs.openshift.com/container-platform/4.16/observability/network_observability/network-observability-overview.html).
+
+
+## Graphs and Logs Without Loki and Storage
+
+Prior to 1.4, NetObserv required an external component called Loki as well as storage, such as an S3 bucket, to store logs. These flow logs allowed NetObserv to provide a rich UI to display graphs, tables, and a topology. The CPU and memory resources required by Loki can be significant, particularly if you have lots of traffic and are sampling all data, not to mention the storage required. In 1.4 and 1.5, if you have your own observability platform and only need the flow logs data, you can simply export this data and not install Loki or provide storage. When you do this, you essentially get no UI besides some minimal flow metrics in **Observe > Dashboards**, because the expectation is that your platform will provide the features and the visuals.
+
+This release changes that premise. It brings back the graphs in the **Overview** panel and the topology in the **Topology** panel. This is huge because the core of Network Observability is now fully functional at a fraction of the resources required when Loki is used! It achieves this by creating Prometheus metrics from the flows and storing them at 15-second intervals.
+
+So what's the catch? Without storing the flow logs as JSON data, there is some impact. The most notable is that there won't be a traffic flows table, because flows are no longer stored (Figure 1).
+
+})
+_
Figure 1: Traffic flows grayed out
_
+
+The other item is that metrics don't have information at the pod level so for example, in the topology, the **Zone** and **Cluster** scopes do not exist (Figure 2).
+
+})
+_
Figure 2: Topology - No "Resources"
_
+
+A couple of other features, namely packet drop reason and multi-tenancy, are not supported but are planned for a following release. If you need any of these capabilities, then go ahead and install Loki and provide storage as usual.
+
+Let's walk through how to configure a Loki-less setup. Install the Network Observability Operator. In **Operators > Installed Operators**, click the **Flow Collector** link, and then **Create FlowCollector**. Click **Loki client settings** to open this up (Figure 3).
+
+})
+_
Figure 3: Loki client settings
_
+
+Set **Enable** to false, since Loki is enabled by default. That's it!
+
+There is one other note worth mentioning. Even if you do install Loki, in the Web console, **Observe > Network Traffic**, it favors using metrics instead of Loki for querying whenever possible. By doing this, not only is the user experience faster, but it is also possible to query data over a period of weeks or months. This behavior is configurable in the **Prometheus**, **Querier** in the **Enable** setting (Figure 4).
+
+})
+_
Figure 4: Prometheus settings
_
+
+
+## eBPF Agent Enhancements
+
+The eBPF Agent probes the network interfaces and generates flows when it sees network traffic. There were a number of eBPF Agent enhancements made. Let's go through them one-by-one.
+
+### Deploy on specific nodes
+
+By default, the eBPF Agent is deployed on each node using a DaemonSet. If you know for sure that you do not need to run it on all nodes, you can control which nodes to deploy it on. This is actually a [Kubernetes feature](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/) in the scheduler that is now implemented in the eBPF Agent. There are many ways to do this, and the following method uses node affinity to deploy the eBPF Agent only on pods with a specific label.
+
+```
+ agent:
+ ebpf:
+ advanced:
+ scheduling:
+ affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: ebpf-agent
+ operator: In
+ values:
+ - "true" # make sure this has quotes
+```
+
+If you have **oc** installed on your computer, enter `oc edit flowcollector`. Look for the `ebpf` section and add the lines above starting at `advanced`. You can also do this in Web console. Go to **Operators > Installed Operators**. Look for the **Network Observability** row, click the **Flow Collector** link and then the **cluster** link. Because this is an advanced feature, it is not in Form view, so click the **YAML** tab to edit the manifest.
+
+Now this only deploys on nodes with the `ebpf-agent=true` label. Set this label by replacing *node-name* with your node name below.
+
+```
+oc label nodes node-name ebpf-agent=true
+```
+
+### Flow filter at eBPF level
+
+Network Observability always had great filtering capability in the **Network Traffic** panel. However, that is done at the UI level, meaning the flows are still generated and stored, and hence resources are being consumed. If resources are a major concern, consider this feature ***if*** the filtering fits your requirements.
+
+To generate flows (or not generate flows) for very specific data, you can specify a single filter to do this. Here's an example to only generate flows for network traffic on TCP port 6443.
+
+```
+ agent:
+ ebpf:
+ flowFilter:
+ enable: true
+ action: Accept
+ cidr: 0.0.0.0/0 # refers to any traffic
+ ports: 6443
+ protocol: TCP
+```
+
+Enter `oc edit flowcollector`. Again, look for the `ebpf` section and add the rest of the lines starting at `flowFilter`. The `cidr` specifies a network address and prefix. The example refers to any traffic, but for a specific network, use a value like `10.0.62.0/24`. The feature is limited to one filter and many of the attributes can only have one value. For more details, see the [flowFilter reference](https://github.com/netobserv/network-observability-operator/blob/main/docs/flowcollector-flows-netobserv-io-v1beta2.adoc#specagentebpfflowfilter).
+
+### eBPF Agent metrics
+
+You can view statistics for eBPF Agent. This is in Web console under **Observe > Dashboards**. Select **NetObserv / Health** in the Dashboard dropdown (Figure 5). There are graphs for eviction rates, dropped flow rates, and more.
+
+})
+_
Figure 5: eBPF Agent statistics
_
+
+### Other eBPF changes
+
+Here are a few other minor eBPF changes.
+
+1. Option to alert if it's dropping flows
+There is a new option in the FlowCollector to control whether an alert is shown if it's dropping flows (Figure 6). By default, this is enabled.
+
+})
+_
_
+
+2. Use enhanced TCx hook
+Internally, the eBPF Agent uses the Traffic Control (TC) hook to probe the ingress and egress traffic on the interfaces. In OCP 4.16, which upgrades RHEL to 9.4, it leverages the enhanced TCx hook for performance gains.
+
+3. Mapping performance improvement
+With RHEL 9.x, it leverages a new map (hash table) method for flows and packets to achieve significant performance improvement.
+
+4. DNS Tracking improvement
+Previously with the *DNSTracking* feature, it was unlikely to generate DNS statistics if sampling was configured to be greater than 1, because the probe expected to catch both the request and the response. However, the request and response is only necessary to calculate DNS latency. Therefore, this has been improved so that it still saves the DNS id and flags even if it only receives the response. Note that there is no information saved on the request.
+
+
+## Flow Collector Enhancements
+
+A few enhancements were made in Flow Collector. They are:
+
+1. Filter on not 'ip'
+In **Observe > Network Traffic**, for the IP-related filter fields, such as SourceIP, Destination IP, Source Node IP, and Destination Node IP, you can filter by *not* matching or excluding that IP or range (Figure 7).
+
+})
+_
Figure 7: Not 'ip' filter
_
+
+2. De-duplication of flows
+ When a flow is a duplicate on another interface, instead of saving multiple copies of that flow data, only one is stored now. It keeps track of the list of interfaces that refer to the flow data. This greatly reduces the amount of storage.
+
+ The raw JSON fields have been renamed and pluralized to `Interfaces` and `IfDirections`, since the type changed to a list from a single value. Note the use of square brackets for the lists below.
+
+ ```
+ "IfDirections": [
+ 0
+ ],
+ "Interfaces": [
+ "br-ex"
+ ],
+ ```
+
+3. Subnet labels
+ You can define a list of names for CIDRs (IP ranges and/or hosts). When the CIDR matches, the name appears in the flow data as the `SrcSubnetLabel` or `DestSubnetLabel` field. Here is an example.
+
+ ```
+ processor:
+ subnetLabels:
+ customLabels:
+ - cidrs:
+ - 200.1.1.1/32 # provide a name for this host
+ name: Ext_server
+ openShiftAutoDetect: true # this is the default
+ ```
+
+ Enter `oc edit flowcollector`. Look for the `processor` section and add the rest of the lines starting at `subnetLabels`. The Form view in Web console looks like Figure 8.
+
+})
+ _
Figure 8: Subnet labels configuration
_
+
+ By default, the OpenShift auto-detect mode is enabled to identify internal CIDRs as `Pods`, `Services`, `Machines` or `n/a` for not applicable. While CIDRs can be internal or external, they are typically external to allow you to provide a custom name for them. If you use a naming convention such as prefixing "Ext_" for all cluster-external traffic, then you can create a custom metric for this. Here's a PromQL that displays a graph of external traffic in bytes over a 1-minute period.
+
+ ```
+ sum(rate(netobserv_workload_egress_bytes_total{ DstSubnetLabel=~"|Ext_.*"}[1m]))
+ ```
+
+ This assumes the `workload_egress_bytes_total` metric has been included in `processor.metrics.includeList`. See my [Network Observability 1.5 blog](https://developers.redhat.com/articles/2024/03/20/whats-new-network-observability-15) on how to do this.
+
+ In the Traffic flow table, this is what you see if you add the Subnet Label columns (Figure 9).
+
+})
+ _
Figure 9: Subnet Label columns
_
+
+
+## Custom Metrics
+
+In my [Network Observability 1.5 blog](https://developers.redhat.com/articles/2024/03/20/whats-new-network-observability-15), I covered the development preview of the FlowMetrics API. While it's possible to take any [flow data labels](https://docs.openshift.com/container-platform/4.16/observability/network_observability/json-flows-format-reference.html) and turn it into a Prometheus metric, that web page was updated to indicate which fields can be safely used as labels to avoid high cardinality.
+
+This feature is now GA, and includes more filtering options (see [reference](https://github.com/netobserv/network-observability-operator/blob/main/docs/FlowMetric.md)) and support for [dashboards in OpenShift](https://github.com/netobserv/network-observability-operator/blob/main/docs/Metrics.md#charts-openshift-only). That link also has many more examples of using custom metrics.
+
+
+## Network Observability CLI
+
+This release has yet another significant technical preview feature called Network Observability CLI (NetObserv CLI). It is a kubectl plug-in that effectively installs Network Observability from the command line but is text-based only. When you exit the program, it cleans up and removes itself. In other words, you can now run Network Observability on-demand!
+
+While it reuses much of the NetObserv code, it is separate from the Network Observability Operator. This means even if you have NetObserv running, you can still run the NetObserv CLI independently. For this preview, it only supports nodes running `x86_64` architecture.
+
+It is also not just a subset of features of the Network Observability Operator. There is an option to capture packets and save them in a pcap file to be used by a network analysis tool like Wireshark! Here is a sample screenshot of NetObserv CLI that is filtering and displaying traffic on port 443 (Figure 10).
+
+})
+_
Figure 10: Network Observability CLI
_
+
+Follow the steps to [install the Network Observability CLI](https://docs.openshift.com/container-platform/4.16/observability/network_observability/netobserv_cli/netobserv-cli-install.html#network-observability-cli-install_netobserv-cli-install).
+
+To get help, enter:
+
+```
+oc netobserv help
+```
+
+Figure 10 was run using:
+
+```
+oc netobserv flows --enable_filter=true --protocol=tcp --port=443
+```
+
+To stop the program, press ctrl-C. More information about NetObserv CLI will be provided in a future blog. In the meantime, enjoy!
+
+
+## Closing
+
+If you are hesitant about deploying Network Observability, fear not. With Network Observability CLI, you can experiment and have it completely removed when you are done using it. The second option lets you install Network Observability without Loki, while still providing the majority of the features of this operator.
+
+What are you waiting for? Give it a try, and let us know what you think on the [discussion board](https://github.com/netobserv/network-observability-operator/discussions).
+
+---
+
+Special thanks to Joel Takvorian, Julien Pinsonneau, and Sara Thomas for providing information for this article.
diff --git a/content/posts/2024-11-07-whats_new_1_7.md b/content/posts/2024-11-07-whats_new_1_7.md
new file mode 100644
index 0000000..9543a25
--- /dev/null
+++ b/content/posts/2024-11-07-whats_new_1_7.md
@@ -0,0 +1,173 @@
+---
+layout: :theme/post
+title: "What's new in Network Observability 1.7"
+description: "Check out the new features: OpenTelemetry, secondary interfaces, multi-tenancy for developer teams and more..."
+tags: What's New,Developer,OpenTelemetry,eBPF,CLI
+authors: [stleerh]
+---
+
+Network Observability 1.7 aligns with OpenShift Container Platform (OCP) 4.17, although it is compatible all the way back to 4.12. Network Observability is an optional operator that provides insights into your network traffic and can help you troubleshoot networking issues. There is an upstream version that runs on bare Kubernetes, but this blog focuses on the downstream version on OCP where you get the most benefit.
+
+It was only a few months ago when 1.6 was released, and you can read all about it in my [last post](https://developers.redhat.com/articles/2024/08/12/whats-new-network-observability-16). There are a number of features added in this release. The most notable ones are:
+
+- Export data using OpenTelemetry Protocol (OTLP)
+- Enhance secondary interface support
+- eBPF Agent enhancements
+- Network Observability in Developer perspective
+- Security features
+- Network Observability CLI General Availability (GA)
+
+## Export data using OpenTelemetry Protocol (OTLP)
+
+OpenTelemetry is a popular open source framework for managing telemetry data. Network Observability can now export flow logs and flow metrics using the OpenTelemetry Protocol (OTLP).
+
+To do this, after you install the Network Observability operator, go to **Operators > Installed Operators**. On the Network Observability row, click the **Flow Collector** link under the **Provided APIs** column. Click **Create FlowCollector**. Make sure you are in **Form view**. At the bottom, click **Advanced configuration** to reveal the **Exporters** section (Figure 1).
+
+})
+
Figure 1: Exporters - OpenTelemetry
+
+By default, the field names follow the [OpenTelemetry Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/). The [Network flows format reference](https://docs.openshift.com/container-platform/4.17/observability/network_observability/json-flows-format-reference.html) shows the field mapping in the new **OpenTelemetry** column. In case you prefer a different name, any of the fields can be renamed to your liking under the **fieldMapping** section (Figure 2).
+
+})
+
Figure 2: OpenTelemetry configuration
+
+
+## Enhanced secondary interface support
+
+There are several use cases for wanting a secondary interface on a pod.
+
+1. Partition a NIC in SR-IOV and use the Multus and SR-IOV CNI plugins to attach an SR-IOV virtual function to your pod. Network Observability supported this in 1.4.
+
+2. Create a [User Defined Network (UDN)](https://docs.openshift.com/container-platform/4.17/networking/multiple_networks/understanding-user-defined-network.html). UDN provides isolation and segmentation to your traffic, and is a Technology Preview in OCP 4.17. The pods have a secondary interface to connect to UDN.
+
+3. Create a secondary overlay network in [OpenShift Virtualization](https://docs.openshift.com/container-platform/4.17/virt/about_virt/about-virt.html) to allow east-west traffic between virtual machines (VMs). The VMs have a secondary interface to connect to the overlay network.
+
+Network Observability 1.7 supports all three scenarios when **privileged** mode is set to `true` in the FlowCollector resource. Click **>** to the right of the text to open up **Agent configuration** and **eBPF Agent configuration** (Figure 3).
+
+})
+
+
+
+Network Observability handles the rest by tracking the secondary interfaces that come and go, and identifying which namespace and pod they belong to. In **Observe > Network Traffic**, Traffic flows table, click **Show advanced options** on the right side, then **Manage columns**, and add the column **Interfaces and Directions** (Figure 4). If the flows for these interfaces show `n/a` for the **Name** and **Namespace**, follow [these steps](https://docs.openshift.com/container-platform/4.17/observability/network_observability/network-observability-secondary-networks.html#network-observability-virtualization-config_network-observability-secondary-networks) to provide FlowCollector with more information to be able to provide this data.
+
+})
+
Figure 4: Traffic flows - Interfaces
+
+
+## eBPF Agent enhancements
+
+These are the other smaller but useful enhancements made to the eBPF Agent, which is the component that collects and aggregates flows in Network Observability.
+
+- The eBPF flow filter allows simple filtering at the core level where it decides what flows to collect. Here are the changes:
+ - `ports`, `sourcePorts` or `destPorts`: Supports up to two TCP, UDP or SCTP ports. Previously, it allowed only one port.
+ - If `ports` is specified but not `protocol`, it filters on TCP and UDP flows.
+ - `tcpFlags`: Filter the flows with this TCP flag. It must be one of "SYN", "SYN-ACK", "ACK", "FIN", "RST", "URG", "ECE", "CWR", "FIN-ACK", or "RST-ACK".
+
+- The Kubernetes service for DNS does a reverse proxy and maps to an internal port at the pod running DNS. For the DNS Tracking feature to work end-to-end, specify the internal port value using the environment variable `DNS_TRACKING_PORT`.
+
+Listing 1 shows an example use-case scenario that only collects DNS traffic on ports `53` and `5353`. OVN, which is the default CNI for OpenShift Container Platform, maps the internal `DNS_TRACKING_PORT` to `5353`. If the DNS Tracking feature is enabled, it displays data for DNS latency, response code, and error on a per-flow basis in the **Traffic flows** table.
+```
+ agent:
+ ebpf:
+ flowFilter:
+ enable: true
+ ports: 53,5353 # only have flows for these two ports
+ advanced:
+ env:
+ DNS_TRACKING_PORT: "5353" # must be a string
+ sampling: 1
+ features:
+ - DNSTracking
+```
+
Listing 1: eBPF flow filter for DNS traffic
+
+Assuming you have the OpenShift CLI (`oc`) installed on your computer, enter `oc edit flowcollector`. Look for the `ebpf` section and add the lines in Listing 1.
+
+Listing 2 shows an example where the eBPF Agent collects only TCP flows that have the `SYN` flag, which are flows that initiate a TCP connection. By not specifying `protocol`, it will also collect UDP.
+
+```
+ agent:
+ ebpf:
+ flowFilter:
+ enable: true
+ tcpFlags: SYN
+ sampling: 1
+```
+
Listing 2: eBPF flow filter for TCP SYN and UDP traffic
+
+In the **Traffic flows** table, you can add the **TCP flags** column. You can also filter on this column (Figure 5).
+
+})
+
Figure 5: Traffic flows - TCP flags
+
+
+## Network Observability in Developer perspective
+
+For the first time, Network Observability is providing observability in the Developer perspective! If you are in Administrator perspective, click **Administrator** in the upper left corner and select **Developer**. Click **Project** and select a project in the drop down near the top of the page. In the **Inventory** section, click **Pods** or **Service**. Click a particular item on a row. There is a **Network Traffic** tab. Click this link to bring up the familiar page with **Overview**, **Traffic flows**, and **Topology** tabs filtered to this pod or service (Figure 6). To provide access to a specific user, group, or non-cluster admin, follow [these steps](https://docs.openshift.com/container-platform/4.17/observability/network_observability/installing-operators.html#network-observability-multi-tenancy_network_observability) to add authorization to various roles.
+
+})
+
Figure 6: Network Observability in Developer perspective
+
+
+## Security features
+
+There are two security-related features in this release.
+
+### FIPS compliance
+
+Network Observability 1.7 is compliant with FIPS 140-3, ensuring that it meets security requirements for cryptographic modules. This means it can be used when OpenShift is in [FIPS mode](https://docs.openshift.com/container-platform/4.17/installing/overview/installing-fips.html).
+
+### Lock down access to Network Observability
+
+For added security, it is simple to lock down access to Network Observability so only known components can access it. In the `FlowCollector` resource, enable this feature (Figure 7). This creates a Kubernetes network policy in the *netobserv* and *netobserv_privileged* namespaces to restrict its access. Although this is disabled by default, it is recommended to enable this or create your own network policies.
+
+})
+
Figure 7: Network policy
+
+
+## Network Observability CLI General Availability (GA)
+
+The Network Observability CLI (`oc netobserv`) is a kubectl plug-in that installs a separate, lightweight Network Observability from the command line and displays a text-based flows table. The CLI can also capture packets to a pcap file. It uses no storage on the cluster! When you exit the program, it cleans up and removes itself.
+
+You don't need to install the Network Observability Operator because Network Observability CLI handles the necessary components for you. Just [follow the instructions here](https://docs.openshift.com/container-platform/4.17/observability/network_observability/netobserv_cli/netobserv-cli-install.html) to install Network Observability CLI. The prerequisite is to have the `oc` CLI installed on your computer and to be logged in with the cluster-admin role.
+
+Make sure you have the 1.7 version, which is the General Availability (GA) version by entering `oc netobserv version`. Here is the command and output from the command line.
+```
+$ oc netobserv version
+Netobserv CLI version 1.7.0
+```
+
+There were a number of significant changes in Network Observability CLI from the last Network Observability release. To start, the command line options changed so that when doing packet capture, you now have many of the same options as flow capture, particularly for the eBPF flow filters. To see these options, enter `oc netobserv help`. You might need to widen the terminal to view this legibly.
+
+Regardless whether you do flow capture or packet capture, it displays the flows table. The screen is pretty self-explanatory on what you can do such as filtering data, showing more columns of data, and increasing or decreasing the number of rows. To exit, press ctrl-c. There is a prompt to save the capture output. If you respond with y, it saves the data with a timestamp filename in the directory `./output/flow/` for flows and `./output/pcap/` for packets. Figure 8 shows a screenshot of Network Observability CLI after running:
+```
+oc netobserv flows
+```
+
+})
+
Figure 8: Network Observability CLI
+
+For packet capture, it's advisable to set a filter as the amount of data will grow very quickly. By default, there is a maximum byte size of 50 MB and a maximum time limit of 5 minutes before it exits, whichever comes first, although they can be changed with the `--max-bytes` and `--max-time` options respectively.
+
+What's unique about the packet capture is that it stores enriched Kubernetes data in the pcap file! Here are the commands and output from the command line and a screenshot of [Wireshark](https://www.wireshark.org/) loaded from a pcapng file created by Network Observability CLI (Figure 9). You need to have Wireshark installed.
+```
+$ oc netobserv packets --protocol=TCP --port=8443
+<Press ctrl-c to exit>
+
+# Update command with your filename.
+$ wireshark output/pcap/2024-10-23T045400Z.pcapng
+```
+
+})
+
Figure 9: Wireshark displaying pcapng file
+
+The Frame 6 row is selected and highlighted in blue. In the Packet Details section below, click **>** on the first line to open up the "Frame 6" content. Then click **>** on "Interface id" to open up the interface details. You can then see that source IP address 10.129.0.23 in the selected row corresponds to a pod named `prometheus-k8s-0` in the namespace `openshift-monitoring`.
+
+
+## Closing
+
+There are a lot of features packed into this release. Spend the time to experiment with the features, and let us know how it helps you perform your tasks. If you have any comments or suggestions, you can contact us on the [discussion board](https://github.com/netobserv/network-observability-operator/discussions).
+
+---
+
+Special thanks to Julien Pinsonneau, Mohamed Mahmoud, and Sara Thomas for reviewing this article.
diff --git a/content/rss.xml b/content/rss.xml
new file mode 100644
index 0000000..3d8a2b8
--- /dev/null
+++ b/content/rss.xml
@@ -0,0 +1 @@
+{#include fm/rss.html}
\ No newline at end of file
diff --git a/data/authors.yml b/data/authors.yml
new file mode 100644
index 0000000..a8f35c3
--- /dev/null
+++ b/data/authors.yml
@@ -0,0 +1,42 @@
+Amoghrd:
+ name: "Amogh RD"
+ avatar: "https://github.com/Amoghrd.png"
+ profile: "https://github.com/Amoghrd"
+ nickname: "Amoghrd"
+ bio: "Bio coming soon..."
+dushyantbehl:
+ name: "Dushyant Behl"
+ avatar: "https://github.com/dushyantbehl.png"
+ profile: "https://github.com/dushyantbehl"
+ nickname: "dushyantbehl"
+ bio: "Bio coming soon..."
+jotak:
+ name: "Joël Takvorian"
+ avatar: "https://github.com/jotak.png"
+ profile: "https://framapiaf.org/@jotak"
+ nickname: "jotak"
+ bio: "Bio coming soon..."
+jpinsonneau:
+ name: "Julien Pinsonneau"
+ avatar: "https://github.com/jpinsonneau.png"
+ profile: "https://github.com/jpinsonneau"
+ nickname: "jpinsonneau"
+ bio: "Bio coming soon..."
+memodi:
+ name: "Mehul Modi"
+ avatar: "https://github.com/memodi.png"
+ profile: "https://github.com/memodi"
+ nickname: "memodi"
+ bio: "Bio coming soon..."
+msherif1234:
+ name: "Mohamed S. Mahmoud"
+ avatar: "https://github.com/msherif1234.png"
+ profile: "https://github.com/msherif1234"
+ nickname: "msherif1234"
+ bio: "Bio coming soon..."
+stleerh:
+ name: "Steven Lee"
+ avatar: "https://github.com/stleerh.png"
+ profile: "https://github.com/stleerh"
+ nickname: "stleerh"
+ bio: "Bio coming soon..."
diff --git a/data/events.yml b/data/events.yml
new file mode 100644
index 0000000..8e076cf
--- /dev/null
+++ b/data/events.yml
@@ -0,0 +1,12 @@
+- title: "Finally, a blog"
+ description: "This blog comes to life, powered by Roq and Quarkus. Want an easy way to generate static HTML for your own blog? Check it out!"
+ date: "2024-11-15"
+ link: https://pages.quarkiverse.io/quarkus-roq/
+- title: "General Availability"
+ description: "NetObserv 1.0 is out, officially a new Red Hat product for OpenShift!"
+ date: "2023-01-17"
+ link: https://www.redhat.com/en/blog/check-out-the-new-network-observability-support-in-openshift-4.12
+- title: "NetObserv birth"
+ description: "This was the first release of the NetObserv operator on OperatorHub!"
+ date: "2022-02-14"
+ link: https://github.com/netobserv/network-observability-operator/discussions/56
diff --git a/data/menu.yml b/data/menu.yml
new file mode 100644
index 0000000..febdec5
--- /dev/null
+++ b/data/menu.yml
@@ -0,0 +1,17 @@
+items:
+ - title: "Blog"
+ path: "/"
+ icon: "fa-regular fa-newspaper"
+ - title: "Timeline"
+ path: "/events"
+ icon: "fa fa-timeline"
+ - title: "Documentation"
+ path: "https://github.com/netobserv/network-observability-operator/blob/main/README.md"
+ icon: "fa-solid fa-book"
+ target: "_blank"
+ - title: "About NetObserv"
+ path: "/about"
+ icon: "fa fa-info"
+ - title: "Authors"
+ path: "/authors"
+ icon: "fa fa-user"
diff --git a/documents b/documents
deleted file mode 160000
index ab9f98f..0000000
--- a/documents
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit ab9f98fb881578566e8402fcd33850c87fa93d59
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..f0343c5
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,144 @@
+
+
+ 4.0.0
+ io.netobserv
+ netobserv-blog
+ 1.0.0-SNAPSHOT
+ NetObserv Blog
+
+
+ 3.13.0
+ 17
+ UTF-8
+ UTF-8
+ quarkus-bom
+ io.quarkus.platform
+ 3.16.1
+ 1.0.4
+ true
+ 3.5.2
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ ${quarkus.platform.artifact-id}
+ ${quarkus.platform.version}
+ pom
+ import
+
+
+
+
+
+
+ io.quarkiverse.roq
+ quarkus-roq
+ ${quarkus-roq.version}
+
+
+ io.quarkiverse.roq
+ quarkus-roq-theme-default
+ ${quarkus-roq.version}
+
+
+ io.quarkiverse.roq
+ quarkus-roq-plugin-tagging
+ ${quarkus-roq.version}
+
+
+ io.quarkiverse.roq
+ quarkus-roq-plugin-aliases
+ ${quarkus-roq.version}
+
+
+ io.quarkiverse.roq
+ quarkus-roq-plugin-asciidoc
+ ${quarkus-roq.version}
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
+
+ io.quarkiverse.web-bundler
+ quarkus-web-bundler
+ 1.7.3
+
+
+ io.quarkiverse.qute.web
+ quarkus-qute-web-markdown-autolink
+ 3.2.2
+
+
+ org.mvnpm
+ highlight.js
+ 11.10.0
+ provided
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ quarkus-maven-plugin
+ ${quarkus.platform.version}
+ true
+
+
+
+ build
+ generate-code
+ generate-code-tests
+ native-image-agent
+
+
+
+
+
+ maven-compiler-plugin
+ ${compiler-plugin.version}
+
+ true
+
+
+
+
+
+
+
+ native
+
+
+ native
+
+
+
+ false
+ true
+
+
+
+ standalone
+
+
+ standalone
+
+
+
+ ${quarkus-roq.version}
+
+
+
+
diff --git a/src/main/java/Events.java b/src/main/java/Events.java
new file mode 100644
index 0000000..0a55dd6
--- /dev/null
+++ b/src/main/java/Events.java
@@ -0,0 +1,14 @@
+import io.quarkiverse.roq.data.runtime.annotations.DataMapping;
+import java.time.LocalDate;
+import java.util.List;
+
+@DataMapping(value = "events", parentArray = true)
+public record Events(List list) {
+
+ public record Event(String title, String description, String date, String link) {
+
+ public LocalDate parsedDate() {
+ return LocalDate.parse(date);
+ }
+ }
+}
diff --git a/src/main/java/ListExtensions.java b/src/main/java/ListExtensions.java
new file mode 100644
index 0000000..1b58e8d
--- /dev/null
+++ b/src/main/java/ListExtensions.java
@@ -0,0 +1,12 @@
+import java.util.*;
+
+import io.quarkus.qute.TemplateExtension;
+
+@TemplateExtension(namespace = "lists")
+public class ListExtensions {
+ static List shuffle(Collection c) {
+ List l = new ArrayList(c);
+ Collections.shuffle(l);
+ return l;
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..cce78d1
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+quarkus.web-bundler.dependencies.auto-import=all
+quarkus.log.category."io.quarkiverse.roq.frontmatter.deployment.scan".level=DEBUG
diff --git a/src/main/resources/web/app/app.scss b/src/main/resources/web/app/app.scss
new file mode 100644
index 0000000..8db274d
--- /dev/null
+++ b/src/main/resources/web/app/app.scss
@@ -0,0 +1,77 @@
+.giscus {
+ padding: 10px;
+}
+
+.event {
+ background-color: #f9f9f9;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+ margin-bottom: 20px;
+ padding: 20px;
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+
+ &:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
+ }
+
+ .event-content {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+
+ .post-date {
+ color: #333;
+ font-size: 1.3rem;
+ font-weight: 500;
+
+ i {
+ margin-right: 20px;
+ }
+ }
+
+ .event-title {
+ font-size: 1.5rem;
+ font-weight: 700;
+ color: #000;
+ margin: 0;
+ transition: color 0.2s ease;
+
+ }
+
+ p {
+ color: #555;
+ line-height: 1.6;
+ margin: 0;
+ font-size: 1rem;
+ }
+
+ a {
+ font-weight: 600;
+ text-decoration: none;
+ margin-top: 10px;
+ transition: color 0.2s ease;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+}
+
+// Responsive design
+@media (max-width: 768px) {
+ .event {
+ padding: 15px;
+ }
+
+ .event-content {
+ .event-title {
+ font-size: 1.3rem;
+ }
+
+ p {
+ font-size: 0.95rem;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/web/app/main.js b/src/main/resources/web/app/main.js
new file mode 100644
index 0000000..824ae02
--- /dev/null
+++ b/src/main/resources/web/app/main.js
@@ -0,0 +1,4 @@
+import hljs from 'highlight.js';
+import 'highlight.js/scss/github.scss';
+
+hljs.highlightAll();
diff --git a/static/assets/images/3d-topology/3d-building.png b/static/assets/images/3d-topology/3d-building.png
new file mode 100644
index 0000000..4cafe33
Binary files /dev/null and b/static/assets/images/3d-topology/3d-building.png differ
diff --git a/static/assets/images/3d-topology/3d-connection.png b/static/assets/images/3d-topology/3d-connection.png
new file mode 100644
index 0000000..5d36fb9
Binary files /dev/null and b/static/assets/images/3d-topology/3d-connection.png differ
diff --git a/static/assets/images/3d-topology/3d-ownership.png b/static/assets/images/3d-topology/3d-ownership.png
new file mode 100644
index 0000000..4ec6d56
Binary files /dev/null and b/static/assets/images/3d-topology/3d-ownership.png differ
diff --git a/static/assets/images/3d-topology/gallery-1.png b/static/assets/images/3d-topology/gallery-1.png
new file mode 100644
index 0000000..d207794
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-1.png differ
diff --git a/static/assets/images/3d-topology/gallery-2.png b/static/assets/images/3d-topology/gallery-2.png
new file mode 100644
index 0000000..031556c
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-2.png differ
diff --git a/static/assets/images/3d-topology/gallery-3.png b/static/assets/images/3d-topology/gallery-3.png
new file mode 100644
index 0000000..76bc435
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-3.png differ
diff --git a/static/assets/images/3d-topology/gallery-4.png b/static/assets/images/3d-topology/gallery-4.png
new file mode 100644
index 0000000..c07caa6
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-4.png differ
diff --git a/static/assets/images/3d-topology/gallery-5.png b/static/assets/images/3d-topology/gallery-5.png
new file mode 100644
index 0000000..b50ebb2
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-5.png differ
diff --git a/static/assets/images/3d-topology/gallery-6.png b/static/assets/images/3d-topology/gallery-6.png
new file mode 100644
index 0000000..be0740d
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-6.png differ
diff --git a/static/assets/images/3d-topology/gallery-7.png b/static/assets/images/3d-topology/gallery-7.png
new file mode 100644
index 0000000..b599b6a
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-7.png differ
diff --git a/static/assets/images/3d-topology/gallery-8.png b/static/assets/images/3d-topology/gallery-8.png
new file mode 100644
index 0000000..6c0c9a1
Binary files /dev/null and b/static/assets/images/3d-topology/gallery-8.png differ
diff --git a/static/assets/images/3d-topology/graph.png b/static/assets/images/3d-topology/graph.png
new file mode 100644
index 0000000..f29bcf0
Binary files /dev/null and b/static/assets/images/3d-topology/graph.png differ
diff --git a/static/assets/images/3d-topology/huge-topology.png b/static/assets/images/3d-topology/huge-topology.png
new file mode 100644
index 0000000..264d7cc
Binary files /dev/null and b/static/assets/images/3d-topology/huge-topology.png differ
diff --git a/static/assets/images/3d-topology/sample-app-deployed.png b/static/assets/images/3d-topology/sample-app-deployed.png
new file mode 100644
index 0000000..cb6420a
Binary files /dev/null and b/static/assets/images/3d-topology/sample-app-deployed.png differ
diff --git a/static/assets/images/3d-topology/sample-app-deployment.png b/static/assets/images/3d-topology/sample-app-deployment.png
new file mode 100644
index 0000000..4f90209
Binary files /dev/null and b/static/assets/images/3d-topology/sample-app-deployment.png differ
diff --git a/static/assets/images/3d-topology/table.png b/static/assets/images/3d-topology/table.png
new file mode 100644
index 0000000..84f4b2f
Binary files /dev/null and b/static/assets/images/3d-topology/table.png differ
diff --git a/static/assets/images/3d-topology/topology.png b/static/assets/images/3d-topology/topology.png
new file mode 100644
index 0000000..5426b8d
Binary files /dev/null and b/static/assets/images/3d-topology/topology.png differ
diff --git a/static/assets/images/acm/console-acm-all-clusters.png b/static/assets/images/acm/console-acm-all-clusters.png
new file mode 100644
index 0000000..2d704ad
Binary files /dev/null and b/static/assets/images/acm/console-acm-all-clusters.png differ
diff --git a/static/assets/images/acm/console-acm-grafana.png b/static/assets/images/acm/console-acm-grafana.png
new file mode 100644
index 0000000..c50312c
Binary files /dev/null and b/static/assets/images/acm/console-acm-grafana.png differ
diff --git a/static/assets/images/acm/overview-1.png b/static/assets/images/acm/overview-1.png
new file mode 100644
index 0000000..306c65b
Binary files /dev/null and b/static/assets/images/acm/overview-1.png differ
diff --git a/static/assets/images/acm/overview-2.png b/static/assets/images/acm/overview-2.png
new file mode 100644
index 0000000..9b9a2f7
Binary files /dev/null and b/static/assets/images/acm/overview-2.png differ
diff --git a/static/assets/images/acm/per-cluster-1.png b/static/assets/images/acm/per-cluster-1.png
new file mode 100644
index 0000000..7847ad2
Binary files /dev/null and b/static/assets/images/acm/per-cluster-1.png differ
diff --git a/static/assets/images/acm/per-cluster-2.png b/static/assets/images/acm/per-cluster-2.png
new file mode 100644
index 0000000..2a06c09
Binary files /dev/null and b/static/assets/images/acm/per-cluster-2.png differ
diff --git a/static/assets/images/acm/search-dashboard.png b/static/assets/images/acm/search-dashboard.png
new file mode 100644
index 0000000..c8f99d1
Binary files /dev/null and b/static/assets/images/acm/search-dashboard.png differ
diff --git a/static/assets/images/agent-metrics-perf/agent-architecture.png b/static/assets/images/agent-metrics-perf/agent-architecture.png
new file mode 100644
index 0000000..6f3dd19
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/agent-architecture.png differ
diff --git a/static/assets/images/agent-metrics-perf/agent-stats-10000.png b/static/assets/images/agent-metrics-perf/agent-stats-10000.png
new file mode 100644
index 0000000..692a8c4
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/agent-stats-10000.png differ
diff --git a/static/assets/images/agent-metrics-perf/agent-stats-1s.png b/static/assets/images/agent-metrics-perf/agent-stats-1s.png
new file mode 100644
index 0000000..dab50aa
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/agent-stats-1s.png differ
diff --git a/static/assets/images/agent-metrics-perf/agent-stats-2000.png b/static/assets/images/agent-metrics-perf/agent-stats-2000.png
new file mode 100644
index 0000000..1301d37
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/agent-stats-2000.png differ
diff --git a/static/assets/images/agent-metrics-perf/agent-stats-50000.png b/static/assets/images/agent-metrics-perf/agent-stats-50000.png
new file mode 100644
index 0000000..1b656ec
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/agent-stats-50000.png differ
diff --git a/static/assets/images/agent-metrics-perf/agent-stats-overview.png b/static/assets/images/agent-metrics-perf/agent-stats-overview.png
new file mode 100644
index 0000000..a999438
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/agent-stats-overview.png differ
diff --git a/static/assets/images/agent-metrics-perf/agent-stats-runaway.png b/static/assets/images/agent-metrics-perf/agent-stats-runaway.png
new file mode 100644
index 0000000..726cc5f
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/agent-stats-runaway.png differ
diff --git a/static/assets/images/agent-metrics-perf/buffer-sizes.png b/static/assets/images/agent-metrics-perf/buffer-sizes.png
new file mode 100644
index 0000000..bceeb71
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/buffer-sizes.png differ
diff --git a/static/assets/images/agent-metrics-perf/evicted-flows-rate.png b/static/assets/images/agent-metrics-perf/evicted-flows-rate.png
new file mode 100644
index 0000000..7bbeca6
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/evicted-flows-rate.png differ
diff --git a/static/assets/images/agent-metrics-perf/eviction-rate.png b/static/assets/images/agent-metrics-perf/eviction-rate.png
new file mode 100644
index 0000000..47e920f
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/eviction-rate.png differ
diff --git a/static/assets/images/agent-metrics-perf/fps-1.png b/static/assets/images/agent-metrics-perf/fps-1.png
new file mode 100644
index 0000000..8a08e0a
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/fps-1.png differ
diff --git a/static/assets/images/agent-metrics-perf/fps-back-normal.png b/static/assets/images/agent-metrics-perf/fps-back-normal.png
new file mode 100644
index 0000000..6975f00
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/fps-back-normal.png differ
diff --git a/static/assets/images/agent-metrics-perf/health-overview.png b/static/assets/images/agent-metrics-perf/health-overview.png
new file mode 100644
index 0000000..4dd5668
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/health-overview.png differ
diff --git a/static/assets/images/agent-metrics-perf/hey-ho.png b/static/assets/images/agent-metrics-perf/hey-ho.png
new file mode 100644
index 0000000..6ed924f
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/hey-ho.png differ
diff --git a/static/assets/images/agent-metrics-perf/heyho-mbps-1.png b/static/assets/images/agent-metrics-perf/heyho-mbps-1.png
new file mode 100644
index 0000000..bfa36ca
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/heyho-mbps-1.png differ
diff --git a/static/assets/images/agent-metrics-perf/heyho-mbps-2.png b/static/assets/images/agent-metrics-perf/heyho-mbps-2.png
new file mode 100644
index 0000000..fadf6bb
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/heyho-mbps-2.png differ
diff --git a/static/assets/images/agent-metrics-perf/heyho-mbps-3.png b/static/assets/images/agent-metrics-perf/heyho-mbps-3.png
new file mode 100644
index 0000000..05a2d04
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/heyho-mbps-3.png differ
diff --git a/static/assets/images/agent-metrics-perf/hm-rb-ratio.png b/static/assets/images/agent-metrics-perf/hm-rb-ratio.png
new file mode 100644
index 0000000..4f99278
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/hm-rb-ratio.png differ
diff --git a/static/assets/images/agent-metrics-perf/per-pod-hashmap-size.png b/static/assets/images/agent-metrics-perf/per-pod-hashmap-size.png
new file mode 100644
index 0000000..1760c0b
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/per-pod-hashmap-size.png differ
diff --git a/static/assets/images/agent-metrics-perf/res-usage-10000.png b/static/assets/images/agent-metrics-perf/res-usage-10000.png
new file mode 100644
index 0000000..338f15d
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/res-usage-10000.png differ
diff --git a/static/assets/images/agent-metrics-perf/res-usage-100000.png b/static/assets/images/agent-metrics-perf/res-usage-100000.png
new file mode 100644
index 0000000..d83d84d
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/res-usage-100000.png differ
diff --git a/static/assets/images/agent-metrics-perf/res-usage-1s.png b/static/assets/images/agent-metrics-perf/res-usage-1s.png
new file mode 100644
index 0000000..b22931b
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/res-usage-1s.png differ
diff --git a/static/assets/images/agent-metrics-perf/res-usage-2000.png b/static/assets/images/agent-metrics-perf/res-usage-2000.png
new file mode 100644
index 0000000..dbccbb5
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/res-usage-2000.png differ
diff --git a/static/assets/images/agent-metrics-perf/res-usage-50000.png b/static/assets/images/agent-metrics-perf/res-usage-50000.png
new file mode 100644
index 0000000..bae0f27
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/res-usage-50000.png differ
diff --git a/static/assets/images/agent-metrics-perf/res-usage-runaway.png b/static/assets/images/agent-metrics-perf/res-usage-runaway.png
new file mode 100644
index 0000000..bf517ba
Binary files /dev/null and b/static/assets/images/agent-metrics-perf/res-usage-runaway.png differ
diff --git a/static/assets/images/cli/cli-architecture.png b/static/assets/images/cli/cli-architecture.png
new file mode 100644
index 0000000..68478ef
Binary files /dev/null and b/static/assets/images/cli/cli-architecture.png differ
diff --git a/static/assets/images/cli/cli-logo.png b/static/assets/images/cli/cli-logo.png
new file mode 100644
index 0000000..ded97a9
Binary files /dev/null and b/static/assets/images/cli/cli-logo.png differ
diff --git a/static/assets/images/cli/connectivity-scenario-cli-dns.png b/static/assets/images/cli/connectivity-scenario-cli-dns.png
new file mode 100644
index 0000000..f45cf08
Binary files /dev/null and b/static/assets/images/cli/connectivity-scenario-cli-dns.png differ
diff --git a/static/assets/images/cli/connectivity-scenario-cli-dropped.png b/static/assets/images/cli/connectivity-scenario-cli-dropped.png
new file mode 100644
index 0000000..c6c4291
Binary files /dev/null and b/static/assets/images/cli/connectivity-scenario-cli-dropped.png differ
diff --git a/static/assets/images/cli/connectivity-scenario-cli-live-filter.png b/static/assets/images/cli/connectivity-scenario-cli-live-filter.png
new file mode 100644
index 0000000..528e858
Binary files /dev/null and b/static/assets/images/cli/connectivity-scenario-cli-live-filter.png differ
diff --git a/static/assets/images/cli/connectivity-scenario-cli-live-filters.png b/static/assets/images/cli/connectivity-scenario-cli-live-filters.png
new file mode 100644
index 0000000..1413c72
Binary files /dev/null and b/static/assets/images/cli/connectivity-scenario-cli-live-filters.png differ
diff --git a/static/assets/images/cli/connectivity-scenario-cli-ok.png b/static/assets/images/cli/connectivity-scenario-cli-ok.png
new file mode 100644
index 0000000..e68a64e
Binary files /dev/null and b/static/assets/images/cli/connectivity-scenario-cli-ok.png differ
diff --git a/static/assets/images/cli/connectivity-scenario-pod.png b/static/assets/images/cli/connectivity-scenario-pod.png
new file mode 100644
index 0000000..566bf25
Binary files /dev/null and b/static/assets/images/cli/connectivity-scenario-pod.png differ
diff --git a/static/assets/images/cli/dbeaver.png b/static/assets/images/cli/dbeaver.png
new file mode 100644
index 0000000..44c8914
Binary files /dev/null and b/static/assets/images/cli/dbeaver.png differ
diff --git a/static/assets/images/cli/flow-table.png b/static/assets/images/cli/flow-table.png
new file mode 100644
index 0000000..c6a79d7
Binary files /dev/null and b/static/assets/images/cli/flow-table.png differ
diff --git a/static/assets/images/cli/mitm-proxy.png b/static/assets/images/cli/mitm-proxy.png
new file mode 100644
index 0000000..5ff23a0
Binary files /dev/null and b/static/assets/images/cli/mitm-proxy.png differ
diff --git a/static/assets/images/cli/packet-capture-scenario-cli.png b/static/assets/images/cli/packet-capture-scenario-cli.png
new file mode 100644
index 0000000..302b61f
Binary files /dev/null and b/static/assets/images/cli/packet-capture-scenario-cli.png differ
diff --git a/static/assets/images/cli/packet-table.png b/static/assets/images/cli/packet-table.png
new file mode 100644
index 0000000..48d54d4
Binary files /dev/null and b/static/assets/images/cli/packet-table.png differ
diff --git a/static/assets/images/cli/wireshark-tls-keylog.png b/static/assets/images/cli/wireshark-tls-keylog.png
new file mode 100644
index 0000000..c156734
Binary files /dev/null and b/static/assets/images/cli/wireshark-tls-keylog.png differ
diff --git a/static/assets/images/cli/wireshark-unencrypted-pcap.png b/static/assets/images/cli/wireshark-unencrypted-pcap.png
new file mode 100644
index 0000000..eb228f8
Binary files /dev/null and b/static/assets/images/cli/wireshark-unencrypted-pcap.png differ
diff --git a/static/assets/images/cli/wireshark.png b/static/assets/images/cli/wireshark.png
new file mode 100644
index 0000000..e964adb
Binary files /dev/null and b/static/assets/images/cli/wireshark.png differ
diff --git a/static/assets/images/dns-tracking/advanced-options1.png b/static/assets/images/dns-tracking/advanced-options1.png
new file mode 100644
index 0000000..c256f9f
Binary files /dev/null and b/static/assets/images/dns-tracking/advanced-options1.png differ
diff --git a/static/assets/images/dns-tracking/advanced-options2.png b/static/assets/images/dns-tracking/advanced-options2.png
new file mode 100644
index 0000000..f0abda5
Binary files /dev/null and b/static/assets/images/dns-tracking/advanced-options2.png differ
diff --git a/static/assets/images/dns-tracking/dns-filters.png b/static/assets/images/dns-tracking/dns-filters.png
new file mode 100644
index 0000000..fc6dc19
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-filters.png differ
diff --git a/static/assets/images/dns-tracking/dns-graphs1.png b/static/assets/images/dns-tracking/dns-graphs1.png
new file mode 100644
index 0000000..e5640dc
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-graphs1.png differ
diff --git a/static/assets/images/dns-tracking/dns-graphs2.png b/static/assets/images/dns-tracking/dns-graphs2.png
new file mode 100644
index 0000000..30817b3
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-graphs2.png differ
diff --git a/static/assets/images/dns-tracking/dns-id.png b/static/assets/images/dns-tracking/dns-id.png
new file mode 100644
index 0000000..73fde11
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-id.png differ
diff --git a/static/assets/images/dns-tracking/dns-latency-more-than.png b/static/assets/images/dns-tracking/dns-latency-more-than.png
new file mode 100644
index 0000000..74e05e0
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-latency-more-than.png differ
diff --git a/static/assets/images/dns-tracking/dns-response-code.png b/static/assets/images/dns-tracking/dns-response-code.png
new file mode 100644
index 0000000..f73e9b8
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-response-code.png differ
diff --git a/static/assets/images/dns-tracking/dns-table.png b/static/assets/images/dns-tracking/dns-table.png
new file mode 100644
index 0000000..ce7fc29
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-table.png differ
diff --git a/static/assets/images/dns-tracking/dns-tracking-logo.png b/static/assets/images/dns-tracking/dns-tracking-logo.png
new file mode 100644
index 0000000..1f56fe8
Binary files /dev/null and b/static/assets/images/dns-tracking/dns-tracking-logo.png differ
diff --git a/static/assets/images/generator-runtime-discussion.png b/static/assets/images/generator-runtime-discussion.png
new file mode 100644
index 0000000..c18894b
Binary files /dev/null and b/static/assets/images/generator-runtime-discussion.png differ
diff --git a/static/assets/images/iamroq.png b/static/assets/images/iamroq.png
new file mode 100644
index 0000000..d76663c
Binary files /dev/null and b/static/assets/images/iamroq.png differ
diff --git a/static/assets/images/lokiless-netobserv/15-days-storage-consumption.png b/static/assets/images/lokiless-netobserv/15-days-storage-consumption.png
new file mode 100644
index 0000000..7d565fd
Binary files /dev/null and b/static/assets/images/lokiless-netobserv/15-days-storage-consumption.png differ
diff --git a/static/assets/images/lokiless-netobserv/disabled-table-view.png b/static/assets/images/lokiless-netobserv/disabled-table-view.png
new file mode 100644
index 0000000..2d3ed66
Binary files /dev/null and b/static/assets/images/lokiless-netobserv/disabled-table-view.png differ
diff --git a/static/assets/images/lokiless-netobserv/dns-latency-alert-firing.png b/static/assets/images/lokiless-netobserv/dns-latency-alert-firing.png
new file mode 100644
index 0000000..8961b5f
Binary files /dev/null and b/static/assets/images/lokiless-netobserv/dns-latency-alert-firing.png differ
diff --git a/static/assets/images/lokiless-netobserv/memory-consumed-by-netobserv-stack.png b/static/assets/images/lokiless-netobserv/memory-consumed-by-netobserv-stack.png
new file mode 100644
index 0000000..386c41d
Binary files /dev/null and b/static/assets/images/lokiless-netobserv/memory-consumed-by-netobserv-stack.png differ
diff --git a/static/assets/images/lokiless-netobserv/owner-screenshot.png b/static/assets/images/lokiless-netobserv/owner-screenshot.png
new file mode 100644
index 0000000..7390236
Binary files /dev/null and b/static/assets/images/lokiless-netobserv/owner-screenshot.png differ
diff --git a/static/assets/images/lokiless-netobserv/topology-scope.png b/static/assets/images/lokiless-netobserv/topology-scope.png
new file mode 100644
index 0000000..d54bf57
Binary files /dev/null and b/static/assets/images/lokiless-netobserv/topology-scope.png differ
diff --git a/static/assets/images/lokiless-netobserv/vcpus-consumed-by-netobserv-stack.png b/static/assets/images/lokiless-netobserv/vcpus-consumed-by-netobserv-stack.png
new file mode 100644
index 0000000..3bc9f6b
Binary files /dev/null and b/static/assets/images/lokiless-netobserv/vcpus-consumed-by-netobserv-stack.png differ
diff --git a/static/assets/images/lokiless/arch-before-after.gif b/static/assets/images/lokiless/arch-before-after.gif
new file mode 100644
index 0000000..b86dc0d
Binary files /dev/null and b/static/assets/images/lokiless/arch-before-after.gif differ
diff --git a/static/assets/images/lokiless/arch-before-after.xcf b/static/assets/images/lokiless/arch-before-after.xcf
new file mode 100644
index 0000000..7607b3c
Binary files /dev/null and b/static/assets/images/lokiless/arch-before-after.xcf differ
diff --git a/static/assets/images/netobserv.svg b/static/assets/images/netobserv.svg
new file mode 100755
index 0000000..b405ab1
--- /dev/null
+++ b/static/assets/images/netobserv.svg
@@ -0,0 +1,51 @@
+
+
+
diff --git a/static/assets/images/network-events/admin-policy-network-events.png b/static/assets/images/network-events/admin-policy-network-events.png
new file mode 100644
index 0000000..b52ca0e
Binary files /dev/null and b/static/assets/images/network-events/admin-policy-network-events.png differ
diff --git a/static/assets/images/network-events/egress-fw-network-events.png b/static/assets/images/network-events/egress-fw-network-events.png
new file mode 100644
index 0000000..ae9eac4
Binary files /dev/null and b/static/assets/images/network-events/egress-fw-network-events.png differ
diff --git a/static/assets/images/network-events/ingr-egr-network-events.png b/static/assets/images/network-events/ingr-egr-network-events.png
new file mode 100644
index 0000000..a1e1d3f
Binary files /dev/null and b/static/assets/images/network-events/ingr-egr-network-events.png differ
diff --git a/static/assets/images/network-events/network-events-design.drawio.png b/static/assets/images/network-events/network-events-design.drawio.png
new file mode 100644
index 0000000..c8d0df2
Binary files /dev/null and b/static/assets/images/network-events/network-events-design.drawio.png differ
diff --git a/static/assets/images/network-events/network-events-logo.drawio.png b/static/assets/images/network-events/network-events-logo.drawio.png
new file mode 100644
index 0000000..f23ebdb
Binary files /dev/null and b/static/assets/images/network-events/network-events-logo.drawio.png differ
diff --git a/static/assets/images/packet-drops/NO-SOCKET-overview.png b/static/assets/images/packet-drops/NO-SOCKET-overview.png
new file mode 100644
index 0000000..5b094e3
Binary files /dev/null and b/static/assets/images/packet-drops/NO-SOCKET-overview.png differ
diff --git a/static/assets/images/packet-drops/NO-SOCKET-table.png b/static/assets/images/packet-drops/NO-SOCKET-table.png
new file mode 100644
index 0000000..ba86651
Binary files /dev/null and b/static/assets/images/packet-drops/NO-SOCKET-table.png differ
diff --git a/static/assets/images/packet-drops/OVS-overview.png b/static/assets/images/packet-drops/OVS-overview.png
new file mode 100644
index 0000000..f827697
Binary files /dev/null and b/static/assets/images/packet-drops/OVS-overview.png differ
diff --git a/static/assets/images/packet-drops/OVS-table.png b/static/assets/images/packet-drops/OVS-table.png
new file mode 100644
index 0000000..8a23795
Binary files /dev/null and b/static/assets/images/packet-drops/OVS-table.png differ
diff --git a/static/assets/images/packet-drops/OVS-topology.png b/static/assets/images/packet-drops/OVS-topology.png
new file mode 100644
index 0000000..837381e
Binary files /dev/null and b/static/assets/images/packet-drops/OVS-topology.png differ
diff --git a/static/assets/images/packet-drops/advanced-options.png b/static/assets/images/packet-drops/advanced-options.png
new file mode 100644
index 0000000..c256f9f
Binary files /dev/null and b/static/assets/images/packet-drops/advanced-options.png differ
diff --git a/static/assets/images/packet-drops/cause-filter.png b/static/assets/images/packet-drops/cause-filter.png
new file mode 100644
index 0000000..2e24d69
Binary files /dev/null and b/static/assets/images/packet-drops/cause-filter.png differ
diff --git a/static/assets/images/packet-drops/drop-filter-query-option.png b/static/assets/images/packet-drops/drop-filter-query-option.png
new file mode 100644
index 0000000..07e638d
Binary files /dev/null and b/static/assets/images/packet-drops/drop-filter-query-option.png differ
diff --git a/static/assets/images/packet-drops/drop-graph-options.png b/static/assets/images/packet-drops/drop-graph-options.png
new file mode 100644
index 0000000..902802c
Binary files /dev/null and b/static/assets/images/packet-drops/drop-graph-options.png differ
diff --git a/static/assets/images/packet-drops/drop-graphs1.png b/static/assets/images/packet-drops/drop-graphs1.png
new file mode 100644
index 0000000..8ce6121
Binary files /dev/null and b/static/assets/images/packet-drops/drop-graphs1.png differ
diff --git a/static/assets/images/packet-drops/drop-graphs2.png b/static/assets/images/packet-drops/drop-graphs2.png
new file mode 100644
index 0000000..97cf610
Binary files /dev/null and b/static/assets/images/packet-drops/drop-graphs2.png differ
diff --git a/static/assets/images/packet-drops/drop-graphs3.png b/static/assets/images/packet-drops/drop-graphs3.png
new file mode 100644
index 0000000..3c07b93
Binary files /dev/null and b/static/assets/images/packet-drops/drop-graphs3.png differ
diff --git a/static/assets/images/packet-drops/drop-state-cause-filters.png b/static/assets/images/packet-drops/drop-state-cause-filters.png
new file mode 100644
index 0000000..7a4aa2e
Binary files /dev/null and b/static/assets/images/packet-drops/drop-state-cause-filters.png differ
diff --git a/static/assets/images/packet-drops/drop-table.png b/static/assets/images/packet-drops/drop-table.png
new file mode 100644
index 0000000..0627e1a
Binary files /dev/null and b/static/assets/images/packet-drops/drop-table.png differ
diff --git a/static/assets/images/packet-drops/drop-topology.png b/static/assets/images/packet-drops/drop-topology.png
new file mode 100644
index 0000000..773e3ba
Binary files /dev/null and b/static/assets/images/packet-drops/drop-topology.png differ
diff --git a/static/assets/images/packet-drops/packets-drop-logo.png b/static/assets/images/packet-drops/packets-drop-logo.png
new file mode 100644
index 0000000..d94654c
Binary files /dev/null and b/static/assets/images/packet-drops/packets-drop-logo.png differ
diff --git a/static/assets/images/packet-drops/state-filter.png b/static/assets/images/packet-drops/state-filter.png
new file mode 100644
index 0000000..490f53f
Binary files /dev/null and b/static/assets/images/packet-drops/state-filter.png differ
diff --git a/static/assets/images/rtt/advanced-options.png b/static/assets/images/rtt/advanced-options.png
new file mode 100644
index 0000000..c256f9f
Binary files /dev/null and b/static/assets/images/rtt/advanced-options.png differ
diff --git a/static/assets/images/rtt/flow-rtt-filter.png b/static/assets/images/rtt/flow-rtt-filter.png
new file mode 100644
index 0000000..ccc40df
Binary files /dev/null and b/static/assets/images/rtt/flow-rtt-filter.png differ
diff --git a/static/assets/images/rtt/rtt-graphs.png b/static/assets/images/rtt/rtt-graphs.png
new file mode 100644
index 0000000..83f05cf
Binary files /dev/null and b/static/assets/images/rtt/rtt-graphs.png differ
diff --git a/static/assets/images/rtt/rtt-table.png b/static/assets/images/rtt/rtt-table.png
new file mode 100644
index 0000000..a9a184e
Binary files /dev/null and b/static/assets/images/rtt/rtt-table.png differ
diff --git a/static/assets/images/rtt/rtt-topology.png b/static/assets/images/rtt/rtt-topology.png
new file mode 100644
index 0000000..1c7c439
Binary files /dev/null and b/static/assets/images/rtt/rtt-topology.png differ
diff --git a/static/assets/images/rtt/tcp-rtt-calculations.png b/static/assets/images/rtt/tcp-rtt-calculations.png
new file mode 100644
index 0000000..c07224c
Binary files /dev/null and b/static/assets/images/rtt/tcp-rtt-calculations.png differ
diff --git a/static/assets/images/secondary-interface/sriov-flow.png b/static/assets/images/secondary-interface/sriov-flow.png
new file mode 100644
index 0000000..87bd816
Binary files /dev/null and b/static/assets/images/secondary-interface/sriov-flow.png differ
diff --git a/static/assets/images/secondary-interface/sriov.png b/static/assets/images/secondary-interface/sriov.png
new file mode 100644
index 0000000..f4098b0
Binary files /dev/null and b/static/assets/images/secondary-interface/sriov.png differ
diff --git a/static/assets/images/site-icon.svg b/static/assets/images/site-icon.svg
new file mode 100644
index 0000000..b405ab1
--- /dev/null
+++ b/static/assets/images/site-icon.svg
@@ -0,0 +1,51 @@
+
+
+
diff --git a/static/assets/images/whats-new-1-4/dashboards-netobserv-health.png b/static/assets/images/whats-new-1-4/dashboards-netobserv-health.png
new file mode 100644
index 0000000..0f8be0f
Binary files /dev/null and b/static/assets/images/whats-new-1-4/dashboards-netobserv-health.png differ
diff --git a/static/assets/images/whats-new-1-4/dashboards-netobserv.png b/static/assets/images/whats-new-1-4/dashboards-netobserv.png
new file mode 100644
index 0000000..8f7295b
Binary files /dev/null and b/static/assets/images/whats-new-1-4/dashboards-netobserv.png differ
diff --git a/static/assets/images/whats-new-1-4/ebpf-agent-priv-features.png b/static/assets/images/whats-new-1-4/ebpf-agent-priv-features.png
new file mode 100644
index 0000000..fa66dd4
Binary files /dev/null and b/static/assets/images/whats-new-1-4/ebpf-agent-priv-features.png differ
diff --git a/static/assets/images/whats-new-1-4/ebpf-agent-priv.png b/static/assets/images/whats-new-1-4/ebpf-agent-priv.png
new file mode 100644
index 0000000..848f794
Binary files /dev/null and b/static/assets/images/whats-new-1-4/ebpf-agent-priv.png differ
diff --git a/static/assets/images/whats-new-1-4/ibm-z15-mainframe.png b/static/assets/images/whats-new-1-4/ibm-z15-mainframe.png
new file mode 100644
index 0000000..4feeba4
Binary files /dev/null and b/static/assets/images/whats-new-1-4/ibm-z15-mainframe.png differ
diff --git a/static/assets/images/whats-new-1-4/managed-panels.png b/static/assets/images/whats-new-1-4/managed-panels.png
new file mode 100644
index 0000000..5e25692
Binary files /dev/null and b/static/assets/images/whats-new-1-4/managed-panels.png differ
diff --git a/static/assets/images/whats-new-1-4/netobserv-installed-operator.png b/static/assets/images/whats-new-1-4/netobserv-installed-operator.png
new file mode 100644
index 0000000..f199a3b
Binary files /dev/null and b/static/assets/images/whats-new-1-4/netobserv-installed-operator.png differ
diff --git a/static/assets/images/whats-new-1-4/netobserv-operator.png b/static/assets/images/whats-new-1-4/netobserv-operator.png
new file mode 100644
index 0000000..a63d1e2
Binary files /dev/null and b/static/assets/images/whats-new-1-4/netobserv-operator.png differ
diff --git a/static/assets/images/whats-new-1-4/overview-dns.png b/static/assets/images/whats-new-1-4/overview-dns.png
new file mode 100644
index 0000000..730c79f
Binary files /dev/null and b/static/assets/images/whats-new-1-4/overview-dns.png differ
diff --git a/static/assets/images/whats-new-1-4/overview-drops.png b/static/assets/images/whats-new-1-4/overview-drops.png
new file mode 100644
index 0000000..44f75e8
Binary files /dev/null and b/static/assets/images/whats-new-1-4/overview-drops.png differ
diff --git a/static/assets/images/whats-new-1-4/overview-rtt.png b/static/assets/images/whats-new-1-4/overview-rtt.png
new file mode 100644
index 0000000..0a48820
Binary files /dev/null and b/static/assets/images/whats-new-1-4/overview-rtt.png differ
diff --git a/static/assets/images/whats-new-1-4/query-filter.png b/static/assets/images/whats-new-1-4/query-filter.png
new file mode 100644
index 0000000..e0147b0
Binary files /dev/null and b/static/assets/images/whats-new-1-4/query-filter.png differ
diff --git a/static/assets/images/whats-new-1-4/scope-slider.png b/static/assets/images/whats-new-1-4/scope-slider.png
new file mode 100644
index 0000000..a5849f1
Binary files /dev/null and b/static/assets/images/whats-new-1-4/scope-slider.png differ
diff --git a/static/assets/images/whats-new-1-4/swap-and-back-and-forth.png b/static/assets/images/whats-new-1-4/swap-and-back-and-forth.png
new file mode 100644
index 0000000..17ea6d5
Binary files /dev/null and b/static/assets/images/whats-new-1-4/swap-and-back-and-forth.png differ
diff --git a/static/assets/images/whats-new-1-4/table-drops.png b/static/assets/images/whats-new-1-4/table-drops.png
new file mode 100644
index 0000000..0742c78
Binary files /dev/null and b/static/assets/images/whats-new-1-4/table-drops.png differ
diff --git a/static/assets/images/whats-new-1-4/table-rtt.png b/static/assets/images/whats-new-1-4/table-rtt.png
new file mode 100644
index 0000000..f178094
Binary files /dev/null and b/static/assets/images/whats-new-1-4/table-rtt.png differ
diff --git a/static/assets/images/whats-new-1-4/topology-drops.png b/static/assets/images/whats-new-1-4/topology-drops.png
new file mode 100644
index 0000000..c4dbc63
Binary files /dev/null and b/static/assets/images/whats-new-1-4/topology-drops.png differ
diff --git a/static/assets/images/whats-new-1-5/console-plugin-configuration.png b/static/assets/images/whats-new-1-5/console-plugin-configuration.png
new file mode 100644
index 0000000..e28b73b
Binary files /dev/null and b/static/assets/images/whats-new-1-5/console-plugin-configuration.png differ
diff --git a/static/assets/images/whats-new-1-5/filter.png b/static/assets/images/whats-new-1-5/filter.png
new file mode 100644
index 0000000..4a65bc7
Binary files /dev/null and b/static/assets/images/whats-new-1-5/filter.png differ
diff --git a/static/assets/images/whats-new-1-5/flow-table-cluster-id.png b/static/assets/images/whats-new-1-5/flow-table-cluster-id.png
new file mode 100644
index 0000000..f63f427
Binary files /dev/null and b/static/assets/images/whats-new-1-5/flow-table-cluster-id.png differ
diff --git a/static/assets/images/whats-new-1-5/flow-table-dscp.png b/static/assets/images/whats-new-1-5/flow-table-dscp.png
new file mode 100644
index 0000000..42343d0
Binary files /dev/null and b/static/assets/images/whats-new-1-5/flow-table-dscp.png differ
diff --git a/static/assets/images/whats-new-1-5/flow-table-zone.png b/static/assets/images/whats-new-1-5/flow-table-zone.png
new file mode 100644
index 0000000..86c96f3
Binary files /dev/null and b/static/assets/images/whats-new-1-5/flow-table-zone.png differ
diff --git a/static/assets/images/whats-new-1-5/graph-type-donut.png b/static/assets/images/whats-new-1-5/graph-type-donut.png
new file mode 100644
index 0000000..59468bc
Binary files /dev/null and b/static/assets/images/whats-new-1-5/graph-type-donut.png differ
diff --git a/static/assets/images/whats-new-1-5/graph-type-lines.png b/static/assets/images/whats-new-1-5/graph-type-lines.png
new file mode 100644
index 0000000..ce10826
Binary files /dev/null and b/static/assets/images/whats-new-1-5/graph-type-lines.png differ
diff --git a/static/assets/images/whats-new-1-5/loki-client-settings.png b/static/assets/images/whats-new-1-5/loki-client-settings.png
new file mode 100644
index 0000000..1a3f44e
Binary files /dev/null and b/static/assets/images/whats-new-1-5/loki-client-settings.png differ
diff --git a/static/assets/images/whats-new-1-5/manage-columns.png b/static/assets/images/whats-new-1-5/manage-columns.png
new file mode 100644
index 0000000..1f83af3
Binary files /dev/null and b/static/assets/images/whats-new-1-5/manage-columns.png differ
diff --git a/static/assets/images/whats-new-1-5/manage-panels.png b/static/assets/images/whats-new-1-5/manage-panels.png
new file mode 100644
index 0000000..005018a
Binary files /dev/null and b/static/assets/images/whats-new-1-5/manage-panels.png differ
diff --git a/static/assets/images/whats-new-1-5/noo-apis.png b/static/assets/images/whats-new-1-5/noo-apis.png
new file mode 100644
index 0000000..0d94044
Binary files /dev/null and b/static/assets/images/whats-new-1-5/noo-apis.png differ
diff --git a/static/assets/images/whats-new-1-5/processor-configuration.png b/static/assets/images/whats-new-1-5/processor-configuration.png
new file mode 100644
index 0000000..dbf5297
Binary files /dev/null and b/static/assets/images/whats-new-1-5/processor-configuration.png differ
diff --git a/static/assets/images/whats-new-1-5/single-graph-focus.png b/static/assets/images/whats-new-1-5/single-graph-focus.png
new file mode 100644
index 0000000..6f22956
Binary files /dev/null and b/static/assets/images/whats-new-1-5/single-graph-focus.png differ
diff --git a/static/assets/images/whats-new-1-5/topology-display-options.png b/static/assets/images/whats-new-1-5/topology-display-options.png
new file mode 100644
index 0000000..8e869aa
Binary files /dev/null and b/static/assets/images/whats-new-1-5/topology-display-options.png differ
diff --git a/static/assets/images/whats-new-1-6/ebpf-agent-statistics.png b/static/assets/images/whats-new-1-6/ebpf-agent-statistics.png
new file mode 100644
index 0000000..b9a11f0
Binary files /dev/null and b/static/assets/images/whats-new-1-6/ebpf-agent-statistics.png differ
diff --git a/static/assets/images/whats-new-1-6/ebpf-metrics-configuration.png b/static/assets/images/whats-new-1-6/ebpf-metrics-configuration.png
new file mode 100644
index 0000000..9f239bb
Binary files /dev/null and b/static/assets/images/whats-new-1-6/ebpf-metrics-configuration.png differ
diff --git a/static/assets/images/whats-new-1-6/flp-loki-client-settings.png b/static/assets/images/whats-new-1-6/flp-loki-client-settings.png
new file mode 100644
index 0000000..1dac474
Binary files /dev/null and b/static/assets/images/whats-new-1-6/flp-loki-client-settings.png differ
diff --git a/static/assets/images/whats-new-1-6/flp-prometheus.png b/static/assets/images/whats-new-1-6/flp-prometheus.png
new file mode 100644
index 0000000..72cb48b
Binary files /dev/null and b/static/assets/images/whats-new-1-6/flp-prometheus.png differ
diff --git a/static/assets/images/whats-new-1-6/netobserv-cli.png b/static/assets/images/whats-new-1-6/netobserv-cli.png
new file mode 100644
index 0000000..51c6256
Binary files /dev/null and b/static/assets/images/whats-new-1-6/netobserv-cli.png differ
diff --git a/static/assets/images/whats-new-1-6/not-ip-filter.png b/static/assets/images/whats-new-1-6/not-ip-filter.png
new file mode 100644
index 0000000..6c08ec9
Binary files /dev/null and b/static/assets/images/whats-new-1-6/not-ip-filter.png differ
diff --git a/static/assets/images/whats-new-1-6/subnet-labels-columns.png b/static/assets/images/whats-new-1-6/subnet-labels-columns.png
new file mode 100644
index 0000000..4f9df93
Binary files /dev/null and b/static/assets/images/whats-new-1-6/subnet-labels-columns.png differ
diff --git a/static/assets/images/whats-new-1-6/subnet-labels-configuration.png b/static/assets/images/whats-new-1-6/subnet-labels-configuration.png
new file mode 100644
index 0000000..15a2aca
Binary files /dev/null and b/static/assets/images/whats-new-1-6/subnet-labels-configuration.png differ
diff --git a/static/assets/images/whats-new-1-6/topology-no-resources.png b/static/assets/images/whats-new-1-6/topology-no-resources.png
new file mode 100644
index 0000000..379e684
Binary files /dev/null and b/static/assets/images/whats-new-1-6/topology-no-resources.png differ
diff --git a/static/assets/images/whats-new-1-6/traffic-flows-grayed-out.png b/static/assets/images/whats-new-1-6/traffic-flows-grayed-out.png
new file mode 100644
index 0000000..bae09a0
Binary files /dev/null and b/static/assets/images/whats-new-1-6/traffic-flows-grayed-out.png differ
diff --git a/static/assets/images/whats-new-1-7/developer-perspective-network-traffic.png b/static/assets/images/whats-new-1-7/developer-perspective-network-traffic.png
new file mode 100644
index 0000000..b48f990
Binary files /dev/null and b/static/assets/images/whats-new-1-7/developer-perspective-network-traffic.png differ
diff --git a/static/assets/images/whats-new-1-7/flowcollector-ebpf-agent-privileged.png b/static/assets/images/whats-new-1-7/flowcollector-ebpf-agent-privileged.png
new file mode 100644
index 0000000..d81878f
Binary files /dev/null and b/static/assets/images/whats-new-1-7/flowcollector-ebpf-agent-privileged.png differ
diff --git a/static/assets/images/whats-new-1-7/flowcollector-exporters-opentelemetry.png b/static/assets/images/whats-new-1-7/flowcollector-exporters-opentelemetry.png
new file mode 100644
index 0000000..7ea6629
Binary files /dev/null and b/static/assets/images/whats-new-1-7/flowcollector-exporters-opentelemetry.png differ
diff --git a/static/assets/images/whats-new-1-7/flowcollector-network-policy.png b/static/assets/images/whats-new-1-7/flowcollector-network-policy.png
new file mode 100644
index 0000000..1ff2411
Binary files /dev/null and b/static/assets/images/whats-new-1-7/flowcollector-network-policy.png differ
diff --git a/static/assets/images/whats-new-1-7/flowcollector-opentelemetry.png b/static/assets/images/whats-new-1-7/flowcollector-opentelemetry.png
new file mode 100644
index 0000000..c0d4c8c
Binary files /dev/null and b/static/assets/images/whats-new-1-7/flowcollector-opentelemetry.png differ
diff --git a/static/assets/images/whats-new-1-7/netobserv-cli.png b/static/assets/images/whats-new-1-7/netobserv-cli.png
new file mode 100644
index 0000000..2c54ef4
Binary files /dev/null and b/static/assets/images/whats-new-1-7/netobserv-cli.png differ
diff --git a/static/assets/images/whats-new-1-7/traffic-flows-interfaces.png b/static/assets/images/whats-new-1-7/traffic-flows-interfaces.png
new file mode 100644
index 0000000..dcf841b
Binary files /dev/null and b/static/assets/images/whats-new-1-7/traffic-flows-interfaces.png differ
diff --git a/static/assets/images/whats-new-1-7/traffic-flows-tcp-flags.png b/static/assets/images/whats-new-1-7/traffic-flows-tcp-flags.png
new file mode 100644
index 0000000..ffd56ef
Binary files /dev/null and b/static/assets/images/whats-new-1-7/traffic-flows-tcp-flags.png differ
diff --git a/static/assets/images/whats-new-1-7/wireshark-pcapng.png b/static/assets/images/whats-new-1-7/wireshark-pcapng.png
new file mode 100644
index 0000000..b06e18c
Binary files /dev/null and b/static/assets/images/whats-new-1-7/wireshark-pcapng.png differ
diff --git a/templates/layouts/roq-default/default.html b/templates/layouts/roq-default/default.html
new file mode 100644
index 0000000..44bea87
--- /dev/null
+++ b/templates/layouts/roq-default/default.html
@@ -0,0 +1,10 @@
+---
+layout: theme-layouts/roq-default/default
+---
+
+{#insert /}
+
+{#head}
+
+
+{/}
\ No newline at end of file
diff --git a/templates/layouts/roq-default/main.html b/templates/layouts/roq-default/main.html
new file mode 100644
index 0000000..334b890
--- /dev/null
+++ b/templates/layouts/roq-default/main.html
@@ -0,0 +1,33 @@
+---
+layout: theme-layouts/roq-default/main
+---
+
+
+
+{#insert /}
+
+{#description}
+