Skip to content

fix: IP-to-FQDN resolution, OpenSSL 3.x TLS capture, and log cleanup#200

Merged
blue4209211 merged 11 commits into
mainfrom
fix-ip-to-fqdn
Feb 16, 2026
Merged

fix: IP-to-FQDN resolution, OpenSSL 3.x TLS capture, and log cleanup#200
blue4209211 merged 11 commits into
mainfrom
fix-ip-to-fqdn

Conversation

@mayankpande88

Copy link
Copy Markdown
Contributor

Summary

  • IP-to-FQDN resolution in metrics: External destinations in TCP/HTTP metrics now show FQDNs instead of raw IPs. Connection DestinationKey is migrated when DNS becomes available, and connection stats are aggregated by enriched key to prevent duplicate metrics.
  • ip_resolver rewrite: Replaced heavy v1.Pod structs with minimal MinimalPod, switched from linear scan to O(1) map lookup by IP, added stale IP cleanup.
  • OpenSSL 3.x TLS capture: Fixed ssl_st struct offsets — in OpenSSL 3.x, rbio/wbio moved to ssl_connection_st at offsets 80/88 (not 16/24 as in 1.x). Added GET_FD_V3 macro and v3_0 uprobe variants.
  • System libssl preference: Agent now prefers system libssl.so over psycopg2's bundled copy, fixing TLS capture for Python processes using both ssl module and psycopg2.
  • HTTP parsing dedup: Eliminated duplicate HTTP response parsing across container.go and l7/http.go, removed dead code.
  • Race condition fixes: Missing informer wait, eBPF map bounds checks, proper locking in connection tracking.
  • Log noise reduction: Hot-path per-event logs (L7_EVENT_REGISTRY, CONTAINER_FOUND, TIMESTAMP_MISMATCH — ~15K lines/min at KLOG_V=2) moved to V(5). Occasional logs to V(3). Per-process one-shot logs to V(2).

Test plan

  • Deployed and verified OpenSSL 3.x TLS fix captures HTTPS traffic from Python test pod
  • Verified system libssl selected over psycopg2 bundled lib for notification server
  • Confirmed container_http_requests_total shows method/path/status for TLS traffic
  • Verified zero CONN_NOT_FOUND errors after fix
  • Log volume reduced from ~15K lines/min to normal levels at KLOG_V=2

DestinationKey is set at TCP connection time, but DNS may not be cached
yet due to per-CPU perf buffer race conditions. This causes all metric
labels (destination, destination_workload_name) to show raw IPs instead
of FQDNs for external services.

Add enrichDestinationKey() that checks the DNS cache at metric emission
time and substitutes the FQDN when available. Applied to all TCP metrics
(bytes, connections, retransmits) and all L7 protocol metrics (HTTP,
Postgres, Redis, etc).
…metrics

Multiple IPs resolving to the same FQDN (e.g., Google's shared IPs for
monitoring.googleapis.com) caused duplicate metric errors when enriched
to the same label set. Aggregate stats by enriched DestinationKey before
emitting TCP metrics.
Root cause fix for duplicate metric errors. When a TCP connection opens
before DNS is cached (per-CPU perf buffer race), the DestinationKey
stores the raw IP. Later connections get an FQDN-based key. Both enrich
to the same FQDN at emit time, causing "collected before with same label
values" errors.

migrateConnectionKeyIfNeeded updates conn.DestinationKey in-place and
migrates connectionStats from the old IP-based key to the FQDN-based
key. Called from updateConnectionTrafficStats and onL7RequestWithResult.
Collect() aggregation kept as safety net for stale entries.
Replace full K8s API objects with minimal structs (MinimalOwnerInfo,
MinimalService, MinimalNode) to reduce memory ~10x per resource.
Add PodNameIndex for O(1) ResolvePodOwner instead of O(pods) scan.
Deduplicate service resolution into resolveServiceWorkload().
Simplify getControllerOfOwner from 7 switch cases to unified lookup.
Remove 3 unused functions (ParseHTTPResponse, ParseHttpResponse,
ParseHostFromHttpRequest). Fix parseRequest() to call ParseHTTPRequest
once instead of both ParseHttp + ParseHTTPRequest. Pass pre-parsed
method/path to observe() instead of re-parsing payload a third time.
Fix pre-existing RawPath bug in ParseHTTPRequest URL construction.
…unds checks

- Fix concurrent map access in getMounts/getListens/ping (copy c.processes under lock)
- Fix conn.Closed written outside lock in onConnectionClose
- Add missing CronJob informer handler for owner chain resolution
- Fix InstanceMeta missing Instance field in initial snapshot
- Fix storeWorkloadsIP check-then-act race with mutex
- Clean stale ClusterIPs on Service update and old pod IPs on Pod update
- Add bounds checks in memcached/redis eBPF parsers to prevent OOB reads
- Remove misleading defer req.Body.Close() in ParseHTTPRequest
In OpenSSL 3.x, the SSL struct was split into ssl_st (base) and
ssl_connection_st (connection data). rbio/wbio moved from offset
16/24 to 80/88. The eBPF code was reading garbage pointers for the
BIO, causing FD extraction to fail (CONN_NOT_FOUND with invalid FDs
like 2868022864). HTTP payload was captured correctly since it comes
from function parameters, but the connection couldn't be matched.

Adds GET_FD_V3 macro that reads rbio/wbio at the correct offsets
for OpenSSL 3.x (verified against OpenSSL 3.5.4 with a test program).
Processes like the notification server load both psycopg2's bundled
libssl-*.so and the system /usr/lib/libssl.so.3. The agent was picking
the first match from /proc/pid/maps (psycopg2's), but Python's ssl
module uses the system lib for HTTPS. This caused SSL uprobes to fire
on the wrong library, missing Slack/Teams API calls.
Per-event hot-path logs (L7_EVENT_REGISTRY, CONTAINER_FOUND,
TIMESTAMP_MISMATCH) were at V(2), producing ~15K lines/min with
KLOG_V=2. Raised to V(5). Per-request logs (HTTP2_COMPLETED, LLM_TRACK)
raised to V(4). Occasional logs raised to V(3). TLS per-process debug
logs moved from unconditional Infof to V(2)/V(3).
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @mayankpande88, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the agent's network observability capabilities by implementing robust IP-to-FQDN resolution for external destinations in metrics and enabling TLS traffic capture for OpenSSL 3.x. It also includes a substantial rewrite of the Kubernetes IP resolver for improved efficiency and accuracy. Furthermore, the PR addresses several stability and performance concerns through race condition fixes, HTTP parsing deduplication, and a comprehensive reduction in log verbosity for hot-path events.

Highlights

  • IP-to-FQDN Resolution in Metrics: External destinations in TCP/HTTP metrics now display FQDNs instead of raw IPs. Connection DestinationKey is migrated when DNS becomes available, and connection statistics are aggregated by the enriched key to prevent duplicate metrics.
  • IP Resolver Rewrite: The Kubernetes IP resolver was refactored to use lightweight MinimalPod structs, switch from linear scans to O(1) map lookups by IP, and include stale IP cleanup mechanisms.
  • OpenSSL 3.x TLS Capture: Fixed ssl_st struct offsets for OpenSSL 3.x, where rbio/wbio moved to ssl_connection_st, and added GET_FD_V3 macro and v3_0 uprobe variants to ensure proper TLS traffic capture.
  • System Libssl Preference: The agent now prioritizes the system's libssl.so over bundled copies (e.g., from psycopg2), resolving TLS capture issues for Python processes using both the ssl module and psycopg2.
  • HTTP Parsing Deduplication: Eliminated redundant HTTP response parsing logic across container.go and l7/http.go, removing dead code and streamlining the parsing process.
  • Race Condition Fixes: Addressed several race conditions, including missing informer waits, eBPF map bounds checks, and improved locking mechanisms in connection tracking.
  • Log Noise Reduction: High-volume, per-event logs (e.g., L7_EVENT_REGISTRY, CONTAINER_FOUND, TIMESTAMP_MISMATCH) were moved to higher verbosity levels (V(5) or V(3)), significantly reducing log output at normal verbosity levels.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • common/ip_resolver.go
    • Removed v1beta1 import.
    • Introduced MinimalOwnerInfo, MinimalService, and MinimalNode structs to reduce memory footprint.
    • Updated clusterSnapshot to use new minimal structs and added PodNameIndex for O(1) lookups.
    • Added ipsMapMu mutex for protecting ipsMap.
    • Added cronJobInformer and addCronJobHandlers for CronJob resource tracking.
    • Refactored resource handlers (ReplicaSet, DaemonSet, StatefulSet, Job, Deployment) to store MinimalOwnerInfo.
    • Updated addServiceHandlers to store MinimalService and handle IP updates/deletions more explicitly.
    • Modified addPodHandlers to clean up old IPs on update and delete PodNameIndex entries.
    • Populated PodNameIndex in handlePodAdd and getFullClusterSnapshot.
    • Updated handleNodeEvent and getFullClusterSnapshot to store MinimalNode.
    • Modified updateIpMapping to use MinimalService and resolveServiceWorkload.
    • Added locking to storeWorkloadsIP.
    • Introduced resolveServiceWorkload, labelsMatch, and getControllerOwnerRef helper functions.
    • Refactored getControllerOfOwner to use MinimalOwnerInfo and a more generic map lookup.
    • Optimized ResolvePodOwner to use PodNameIndex for efficient lookup.
  • common/net.go
    • Removed debug logging from NewDestinationKey.
    • Added WithResolvedDomain method to DestinationKey for FQDN enrichment.
  • containers/container.go
    • Removed LLMStats struct and llmStats field from Container.
    • Implemented aggregation logic for connectionStats by enriched key to prevent duplicate metrics.
    • Modified Collect method to use aggregated connection stats.
    • Adjusted onConnectionClose to acquire lock once and handle nil connection.
    • Added migrateConnectionKeyIfNeeded call in updateConnectionTrafficStats.
    • Reduced logging verbosity for LLM tracking functions (trackLLMRequest, onLLMStreamComplete).
    • Introduced enrichDestinationKey function to resolve IP-based workload names to FQDNs.
    • Added migrateConnectionKeyIfNeeded function to update connection keys from IP to FQDN and migrate stats.
    • Reduced logging verbosity for connection creation from socket info, L7_EVENT_CONN_NOT_FOUND, and L7_EVENT_TIMESTAMP_MISMATCH.
    • Added migrateConnectionKeyIfNeeded call in onL7RequestWithResult.
    • Updated l7Stats.observe calls to pass method and path arguments for HTTP.
    • Removed HTTP/2 LLM tracking logic from onL7RequestWithResult as it's now handled by the stream tracker.
    • Added locking around c.processes and c.listens access in getMounts, getListens, and ping to prevent race conditions.
    • Reduced logging verbosity for HTTP2_CONNECTIONLESS LLM detection.
  • containers/http_processor.go
    • Refactored parseRequest to use l7.ParseHTTPRequest for more robust parsing of method, path, and headers, with a fallback for malformed URIs.
  • containers/l7.go
    • Added mu (RWMutex) to L7Stats for thread safety.
    • Changed observe, ensureInitialized, and collect methods to use pointer receiver (*L7Stats) and added locking.
    • Modified observe method signature to include path for HTTP metrics.
    • Updated HTTP metric label values to use the new method and path parameters.
    • Updated delete method to use pointer receiver.
  • containers/llm_stream.go
    • Reduced logging verbosity for LLM_STREAM_START and LLM_STREAM_FIRST_TOKEN.
  • containers/metrics.go
    • Removed LLMRequests, LLMTokensUsed, and LLMLatency Prometheus metrics.
  • containers/registry.go
    • Reduced logging verbosity for L7_EVENT_REGISTRY, L7_EVENT_CONTAINER_FOUND, L7_EVENT_QUEUE_FULL, L7_EVENT_QUEUED, L7_EVENT_EXPIRED, L7_EVENT_MAX_RETRIES, and L7_EVENT_RETRY_SUCCESS.
  • ebpftracer/ebpf/l7/memcached.c
    • Added a bounds check (buf_size < 5) in is_memcached_response to prevent out-of-bounds access.
  • ebpftracer/ebpf/l7/openssl.c
    • Added comments explaining OpenSSL 1.x vs 3.x ssl_st layout differences.
    • Defined SSL_V3_RBIO_OFFSET and SSL_V3_WBIO_OFFSET for OpenSSL 3.x.
    • Introduced GET_FD_V3 macro for extracting file descriptors in OpenSSL 3.x.
    • Updated openssl_SSL_write_enter_v3_0, openssl_SSL_read_enter_v3_0, and openssl_SSL_read_ex_enter_v3_0 to use GET_FD_V3 and explicitly track connections.
  • ebpftracer/ebpf/l7/redis.c
    • Added a bounds check (buf_size < 3) in is_redis_response to prevent out-of-bounds access.
  • ebpftracer/l7/http.go
    • Added RawPath to the url.URL struct in ParseHTTPRequest.
    • Removed ParseHostFromHttpRequest, ParseHTTPResponse, parseStatusCode, and ParseHttpResponse functions, indicating deduplication of HTTP parsing logic.
  • ebpftracer/tls.go
    • Reduced logging verbosity for Go TLS attachment attempts and filtered errors.
    • Modified getSslLibPathAndVersion to prioritize system libssl.so and libcrypto.so over bundled versions (e.g., from psycopg2), falling back to bundled if system libs are not found.
Activity
  • Verified OpenSSL 3.x TLS fix captures HTTPS traffic from a Python test pod.
  • Confirmed system libssl is selected over the psycopg2 bundled lib for the notification server.
  • Validated that container_http_requests_total Prometheus metric now shows method/path/status for TLS traffic.
  • Ensured zero CONN_NOT_FOUND errors after the fix was applied.
  • Observed a significant reduction in log volume from approximately 15K lines/min to normal levels at KLOG_V=2.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant refactoring and improvements to the Kubernetes IP resolver and L7 traffic monitoring components. Key changes include optimizing memory usage in the IP resolver by introducing minimal structs for Kubernetes resources (like MinimalOwnerInfo, MinimalService, MinimalNode) and updating the clusterSnapshot to use these. It also enhances the IP resolver's functionality by adding a PodNameIndex for faster lookups, incorporating CronJob watching, and improving service IP handling with a new mutex for thread safety. In L7 traffic monitoring, the changes address duplicate metrics by aggregating connection statistics based on an 'enriched' destination key that resolves IP addresses to FQDNs using a DNS cache, and by migrating connection keys from IP to FQDN when DNS information becomes available. The LLM (Large Language Model) tracking mechanism has been streamlined by removing internal aggregation maps and directly emitting metrics, along with adjustments to logging verbosity across several components. Additionally, the HTTP request parsing logic was made more robust, and thread safety was improved in various Container and L7Stats methods by adding mutexes and read locks to prevent concurrent map access issues. The eBPF openssl probes were updated to support OpenSSL 3.x by correctly identifying rbio/wbio offsets, and minor fixes were applied to memcached and redis eBPF response parsing for improved robustness. Finally, the logic for detecting SSL libraries in processes was refined to prefer system libraries over bundled ones.

- Rename L7 labels to match TCP: destination_region → destination_workload_region,
  destination_az → destination_workload_az, destination_instance → actual_destination_instance
- Add missing actual_destination_region and actual_destination_az labels to L7 metrics
- Fix L7 destination_workload_region/az to use destinationWorkload (was using actualDestWorkload)
- Remove dead fields from ConnectionKey (srcWorkload, dstWorkload, actualDestWorkload — never set)
- Remove dead fields from ActiveConnection (dstWorkload, actualDestWorkload — set but never read)
- Remove redundant DNS re-enrichment in trace creation (migrateConnectionKeyIfNeeded already handles it)
@blue4209211 blue4209211 merged commit 2283552 into main Feb 16, 2026
1 check passed
@blue4209211 blue4209211 deleted the fix-ip-to-fqdn branch February 16, 2026 03:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants