Skip to content

Configuration

Edge settings, rules from the ConfigMap, annotations and the fleet, and shadow mode

General Configuration

Auditty Edge can be configured through Helm values and the ConfigMap. Most fields, including rules, enable_rule_annotations, and suppression policy settings, are cluster-wide and take effect within about a minute of a helm upgrade, with no pod restart. A few startup-only values (e.g. edge_api.service_url) do require a restart to take effect.

Key Configuration Fields:

  • hivemind_api_key (required): API key for connecting to Auditty control plane
  • secretRef: Store API key in a Kubernetes Secret instead of ConfigMap
  • edgeApi.enabled (default: true): Deploy Edge API for K8s API calls and metrics
  • cluster_name (required): Identifier for this cluster in Auditty; Edge will not start without this
  • env_name (optional): Environment identifier (dev, staging, prod). When set, Auditty surfaces an Environment filter across all dashboard, metrics, insights, and reports pages, letting you slice data by environment independently from cluster
  • log_level (default: info since Edge 1.7.5): what the Edge pods log. At info every line is about your logs: one per container when interception starts, stops or is skipped by a rule, one per incident, in plain words and without a line of your logs. warn keeps only incidents; debug is for working with support
  • shadow_mode (default: false): read every selected container in shadow mode. Every rule runs and what it would suppress is counted; nothing is suppressed. The same thing as a rule with action: measure and no scope; the fleet-wide switch lives on the Fleet Rules page and needs no config change
  • remote_rules.enabled (default: true): take fleet rules from Auditty; set to false for a node that must only follow its own ConfigMap
  • enable_rule_annotations (default: false): enable per-workload annotation rules; needs Edge API. annotation_cache_ttl (default 60s) is how long an annotation reading is trusted before it is read again, so a changed annotation takes effect within about a minute
  • interceptor.multiline.mode (default: auto): how lines are joined into one entry. auto keeps a stack trace (Java, Python, Go, .NET and the usual indented continuations) together with the line that raised it and judges the whole entry by that line’s level, so an ERROR trace is protected as the error it is; lines makes every line its own entry; custom uses only your own interceptor.multiline.patterns (name, regex, continuation, priority; the built-in patterns run at 30 to 100, so 101 and above beats them all)

Settings that no longer do anything

org_name and org_unit (and a few older tuning knobs such as pipeline_batch_size and interceptor.fd_polling_interval) are retired. A ConfigMap that still names one loads fine; Edge logs once at startup that the setting has no effect and ignores it. A misspelt key, on the other hand, is refused at load, so a typo is caught before it can disable a rule.

Looking for suppression policy settings?

Everything under policy.suppression (summary format and thresholds, per-namespace/workload overrides, promote_numeric_fields, and the Total-Recall search_index (search on any value directly in your platform)) is documented, together with outlier passthrough (processor.fingerprint.outlier), with full config examples in the Suppression guide. All of it is hot-reloadable through the same ConfigMap.

Example: Exclude monitoring namespace while intercepting all others:

configMap:
  rules:
    - name: "skip-monitoring"
      action: skip
      scope:
        namespace: "monitoring"
    - name: "intercept-all-others"
      action: intercept
      scope:
        namespace: "all"

Auto-Rollout on Config Change (optional)

Edge hot-reloads most configuration at runtime, but a few values (e.g. edge_api.service_url) are read once at startup. Set configMap.rollOnConfigChange: true and any ConfigMap change rolls the Edge DaemonSet and the Edge API Deployment on the next helm upgrade, no manual restart. Defaults to false.

Edge API Configuration

Auditty Edge deploys two components: the DaemonSet (log interception; runs as root with scoped capabilities, not privileged mode) and Edge API (non-privileged, cluster-level service). Edge API has RBAC permissions to query the K8s API for workload resolution. And it sends metrics to the Auditty backend.

Edge API Benefits:

  • Accurate workload names: a pod is reported under the Deployment, StatefulSet or other workload that owns it
  • One connection to Auditty per cluster: Edge API speaks for every node, and your Vault is read only from inside your cluster
  • Light on the Kubernetes API: watches workloads once per cluster rather than once per node
# Edge API configuration (values.yaml)
edgeApi:
  enabled: true           # Set to false to disable Edge API
  replicas: 1             # Single replica sufficient for most clusters (holds per-cluster state, do not scale beyond 1)
  resources:
    requests:
      memory: "256Mi"
      cpu: "250m"
    limits:
      memory: "768Mi"
      cpu: "1000m"

Air-Gapped Mode:

Setting edgeApi.enabled: false disables the Edge API component: no K8s API calls, no centralized workload-name resolution. Suppression works perfectly well without it. Metrics still flow directly to Auditty unless you also set hivemind_api_url to "disabled"; that is the setting for true air-gapped/no-egress operation.

API Key Configuration

The Auditty API key identifies your cluster to Auditty. Treat it as a credential: keep it in a Kubernetes Secret and point the chart at it with secretRef (secretRef.enabled: true, secretName, apiKeyName); setting it inline in values.yaml also works but puts it in the ConfigMap.

Option 1: ConfigMap (simple)

configMap:
  hivemind_api_key: "your-api-key-here"

Option 2: Secret Reference

Store the API key in a Kubernetes Secret for better security practices.

# First, create the secret:
kubectl create secret generic auditty-secret \
  --namespace auditty \
  --from-literal=hivemind_api_key=your-api-key-here

# Then reference it in values.yaml:
secretRef:
  enabled: true
  secretName: "auditty-secret"
  apiKeyName: "hivemind_api_key"

Rules Overview

Auditty Edge uses rules to control which logs are intercepted and how they're processed. Rules come from three sources, merged at runtime:

  • ConfigMap rules (cluster-wide): Managed by platform/DevOps teams in the Helm values
  • Annotation rules (per-workload): Managed by application teams directly on their Deployments
  • Fleet rules (Auditty-authored): Created on the Fleet Rules page and delivered to every Edge node automatically, no ConfigMap edit or pod restart

A rule has a name, an action (intercept, skip, measure, preserve or suppress), an optional scope (which namespaces, workloads or containers it selects), an optional match (which lines it applies to) and an optional description. The same shape is used in the ConfigMap, in a pod annotation and on the Fleet Rules page. This guide shows common patterns for configuring log interception across your cluster.

Enabling Annotation Rules

To enable annotation rules, set the feature flag in your ConfigMap:

configMap:
  enable_rule_annotations: true

Fleet Rules

Fleet rules close the loop between Auditty and Edge: rules authored on the Fleet Rules page (or generated by "Sync Monitors" with "Apply to Fleet") reach every Edge node within about a second of being saved, and a fleet whose rules have not changed costs nothing. Authoring a fleet rule requires the editor role; switching the whole fleet into or out of shadow mode (below) requires admin.

Delivery is on by default since Edge 1.7.5 whenever the node can reach Auditty; there is nothing to enable. An install that must not take rules from Auditty turns it off in the Edge config, and that node keeps only its ConfigMap and annotation rules:

configMap:
  remote_rules:
    enabled: false   # default: true
  • First rule set before the first line: an Edge pod that starts waits briefly (up to 3 seconds) for the fleet rules before it intercepts anything, so a container is read live or in shadow mode from its first line
  • Last good set stays in force: until a new rule set arrives and validates, a node keeps the one it has; local ConfigMap and annotation rules are untouched by fleet delivery
  • Local overrides remote: a fleet rule whose name matches a local ConfigMap or annotation rule is ignored on that node; the local definition always wins. Define a local rule with the same name to pin or veto any fleet rule
  • Overrides are visible: the Fleet Rules page shows "Local rule wins on N nodes" under the rule (hover for the node, environment, the winning local action, and whether it came from ConfigMap or annotation), so you always know where a fleet rule is in force
  • Connected Fleet: each node reports whether it is consuming fleet rules and which version it holds; the Connected Fleet card counts them as on current version / stale / not consuming, and warns loudly when enabled rules have zero confirmed consumers (including when no node reports status yet)
  • Rollback: disabling or deleting a rule in Auditty removes it from the fleet within seconds
  • Validated twice: rules are checked at authoring time (Auditty) and again on every node before applying, so a rule that reaches the fleet is one every node can run
  • Audited: every create, update, enable/disable, and delete is recorded in the Audit Log

Rule Actions

File-Level Actions (Control Interception)

intercept

Intercept logs from this workload

skip

Do not intercept logs from this workload (wins over intercept)

Mode Action (Control How an Intercepted Workload Is Read)

measure

Read this workload in shadow mode: every rule runs and Auditty reports what would have been suppressed, but every line reaches your log platform unchanged and nothing is written to the Vault

(absent)

Live: the suppress and preserve rules decide, suppressed lines are archived to the Vault and replaced by a summary

measure decides how a workload is read, not whether; intercept and skip decide that. A workload that no intercept rule selects is not measured either. A measure rule can carry a scope like any other and comes from any of the three sources; with no scope it measures every intercepted container on the node, which is exactly what the Measure first switch on the Fleet Rules page writes: one fleet rule named measure with action measure. Switching the fleet back to live disables that rule (it stays on the page, so the history of who switched and when is kept), and both directions take effect on every node within about five seconds, with no restart. A node whose own ConfigMap sets shadow_mode: true keeps measuring whatever the fleet switch says: the node setting is the same thing as a measure rule with no scope.

rules:
  - name: "measure-payments-first"
    action: measure
    scope:
      namespace: "payments"
    description: "Run every rule over payments but suppress nothing yet"

What a measured workload looks like

  • The Edge pod on the node logs Started observing logs in shadow mode; nothing is suppressed at INFO with namespace, workload, and the rule and rule_source that measure it (no rule fields when the node’s own shadow_mode setting did); a switch into shadow mode is Stopped log interception with reason: shadow_mode_changed followed by that line; a switch back to live is Stopped observing logs in shadow mode with the same reason, followed by Started log interception
  • The container’s output is left exactly as it is, and your log collector keeps reading it as before
  • auditty_events_shadow_suppressed_total says what would have been suppressed against auditty_events_shadow_processed_total; auditty_events_suppressed_total stays at zero for the workload. The Fleet Rules page shows, under each fleet rule, the share of measured lines it would have suppressed and on how many nodes
  • A node on Edge 1.7.5 or earlier does not know measure: it cannot read a rule set that contains it, keeps the rules it last received, warns after about 90 seconds that fleet rules are not reaching it, and the Connected Fleet card lists it as not on the current version with that error. Upgrade the node before measuring from Auditty

Line-Level Actions (Control Processing)

preserve

Keep these logs; they are always forwarded

suppress

Replace these lines with a suppression summary; the originals are archived to the Vault, searchable and one click away

Common Patterns

Pattern 1: Enable Namespace, Allow Opt-Out

Scenario: the platform team intercepts the whole production namespace, and lets teams opt specific workloads out.

ConfigMap (cluster-wide):

configMap:
  enable_rule_annotations: true
  rules:
    - name: "intercept-production"
      action: intercept
      scope:
        namespace: "production"
      description: "Monitor all production workloads"

Annotation (opt-out specific workload):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-workload
  namespace: production
spec:
  template:
    metadata:
      annotations:
        auditty.ai/rule.skip-me: |-
          name: skip-test-workload
          action: skip
          description: "Exclude this workload from interception"

Result: every production workload is intercepted except test-workload (skip > intercept).

Verify it took: the Edge pod on the same node as the workload logs one INFO line per container it leaves alone because a rule said so: Skipping log interception with namespace, workload, rule (the rule's name) and rule_source (annotation, config or fleet). You do not have to prove the absence of Started log interception:

kubectl logs -n auditty -l app.kubernetes.io/name=auditty-edge --max-log-requests=50 | grep "Skipping log interception" | grep test-workload

Pattern 2: Workload Opt-In (No Default Interception)

Scenario: nothing is intercepted by default; only workloads that explicitly opt in are.

ConfigMap:

rules: []

Annotation (opt-in):

metadata:
  annotations:
    auditty.ai/rule.monitor-me: |-
      name: intercept-this-workload
      action: intercept
      description: "Monitor this specific workload"

Result: only workloads with an intercept annotation are intercepted; teams have full control.

Note: Skip rules have higher precedence than intercept rules, so a ConfigMap skip cannot be overridden by an annotation intercept.

Pattern 3: Preserve Critical Errors by Content

Use case: Always keep error logs containing "database" or "payment".

rules:
  - name: "preserve-critical-errors"
    action: preserve
    scope:
      namespace: "production"
    match:
      any:
        - entryIncludes: "database connection failed"
        - entryIncludes: "payment processing error"
        - entryRegex: "ERROR.*timeout"
    description: "Never suppress critical errors"

Pattern 4: Preserve All High-Severity Logs

Use case: Ensure warnings and everything above are always preserved in production, regardless of other rules, including a suppress rule that would otherwise match them.

rules:
  - name: "preserve-high-severity"
    action: preserve
    scope:
      namespaceIncludes: "prod"
    match:
      severity: "warning"
    description: "Never suppress warnings and above in production"

Note: automatic rate suppression already leaves WARN and above alone (preserve_high_severity, on by default), but that protection is against automation only. A preserve rule with severity is a user rule: it also outranks any suppress rule, and can lower the floor to notice or info.

Pattern 5: Suppress Noise

Use case: Suppress debug logs and health-check noise; both stay recoverable from the Vault.

rules:
  - name: "suppress-debug"
    action: suppress
    scope:
      namespaceIncludes: "prod"
    match:
      entryIncludes: "DEBUG"
    description: "Suppress debug logs in production"

  - name: "suppress-health-checks"
    action: suppress
    match:
      entryRegex: "GET /health.*200 OK"
    description: "Suppress successful health check logs"

Pattern 6: Measure a New Suppress Rule Before It Suppresses

Scenario: A team wants to see what a suppress rule would remove from one namespace before any line is actually replaced by a summary.

rules:
  - name: "suppress-access-logs"
    action: suppress
    scope:
      namespace: "storefront"
    match:
      entryRegex: '"GET /[^"]*" 2\d\d'
    description: "Successful requests on the storefront"

  - name: "measure-storefront"
    action: measure
    scope:
      namespace: "storefront"
    description: "Shadow mode for storefront while the rule is tuned"

Result: Every storefront line still reaches your log platform. auditty_events_shadow_suppressed_total for the storefront workloads counts what suppress-access-logs would have taken, and the dashboard notes the measurement under its figures (the reduction card itself shows a projection only when the whole fleet is in shadow mode). Author the same two rules on the Fleet Rules page instead and the share appears under the suppress rule itself. When the number looks right, delete measure-storefront and the suppress rule goes live within about five seconds. To measure the whole fleet instead of one namespace, use the Measure first switch on the Fleet Rules page rather than writing the rule by hand.

Annotation Format

Annotations follow the pattern: auditty.ai/rule.<identifier>

Note: The name and description fields are optional.

Single Rule

Full rule with optional fields

Minimal Rule

Action only (simplest form)

Single Rule
annotations:
  auditty.ai/rule.my-rule: |-
    name: descriptive-name        # Optional
    action: skip                  # Required
    description: "Why this rule exists"  # Optional
Minimal Rule (action only)
annotations:
  auditty.ai/rule.skip-me: |-
    action: skip
Try Auditty on one workload (shadow mode by annotation)
annotations:
  auditty.ai/rule.measure-me: |-
    action: measure   # read in shadow mode; every line still reaches your platform

Multiple Conditions (OR logic)

Matches if any condition is true

Multiple Conditions (AND logic)

Matches only if all conditions are true

Multiple Conditions (OR logic)
auditty.ai/rule.errors: |-
  name: preserve-errors
  action: preserve
  match:
    any:
      - entryIncludes: "ERROR"
      - entryIncludes: "FATAL"
      - entryIncludes: "CRITICAL"
Multiple Conditions (AND logic)
auditty.ai/rule.specific: |-
  name: suppress-specific-noise
  action: suppress
  match:
    all:
      - entryIncludes: "cache"
      - entryIncludes: "warning"
Preserve by Severity (per-workload override)
auditty.ai/rule.keep-errors: |-
  name: preserve-all-errors
  action: preserve
  match:
    severity: "error"

Override example: If a platform-wide ConfigMap rule suppresses all DEBUG logs (action: suppress with entryIncludes: "DEBUG"), an application team can use an annotation preserve rule with severity: "error" so their errors are always forwarded, even when they contain the word "DEBUG". Preserve always has higher precedence than suppress.

Match Operators

entryIncludes (Simple String Match)

Fast, case-sensitive substring matching.

match:
  entryIncludes: "connection failed"

entryRegex (Pattern Matching)

For complex patterns. Use when entryIncludes isn't sufficient.

match:
  entryRegex: "HTTP [45][0-9]{2}"  # Matches HTTP 4xx/5xx errors

any (OR logic)

Matches if any condition is true.

match:
  any:
    - entryIncludes: "ERROR"
    - entryIncludes: "WARN"

all (AND logic)

Matches only if all conditions are true.

match:
  all:
    - entryIncludes: "database"
    - entryIncludes: "timeout"

not (negation)

Matches when the condition inside is false. Conditions written side by side in one match must all hold, so a not beside another condition carves an exception out of it.

match:
  entryIncludes: "health"     # health-check lines…
  not:
    entryIncludes: "failed"   # …except the ones that failed

severity (Hierarchical Level)

Matches logs at this severity level and above. Severity is auto-detected from all major log formats (JSON, logfmt, brackets, Python, Java, PHP, Ruby, Rust, and more), read from the first line of a multi-line entry. A line on stderr with no recognisable level counts as error, so severity: "error" also matches plain stderr output.

match:
  severity: "warning"  # Matches warning, error, critical, fatal, etc.

Severity hierarchy (lowest to highest):

trace/debug → info → notice → warning → error → critical → fatal/panic → alert → emergency

Setting severity: "warning" matches warning, error, critical, fatal, panic, alert, and emergency. Setting severity: "error" matches error, critical, fatal, panic, alert, and emergency. Common shorthands (warn, err, crit, emerg) are also recognized.

stream (K8s Output Stream)

Matches logs from a specific container output stream. Accepts "stdout" or "stderr".

match:
  stream: "stderr"  # Match logs written to stderr

Scope Patterns

Rules are scoped by namespace, workload (the pod's owning Deployment, StatefulSet, DaemonSet, Job or CronJob; a ReplicaSet or Job nothing owns is the workload itself), and container. Each supports an exact form and an Includes (substring) form, and they can be combined and composed with the boolean any/all/not operators.

Exact Match

Match a namespace/workload/container by name: case-insensitive, surrounding spaces ignored, and the value all matches everything

Substring Match

Match namespaces/workloads/containers by substring

Container Scope

Target a single container within a workload, fully central, no annotations

Exact Match
scope:
  namespace: "production"
  workload: "api-server"
  container: "app"          # Optional: target one container in the pod
# Names are compared case-insensitively; workload: all selects every workload
Substring Match
scope:
  namespaceIncludes: "prod"      # Matches prod-us, prod-eu
  workloadIncludes: "api-"       # Matches api-server, api-worker
  containerIncludes: "proxy"     # Matches istio-proxy, envoy-proxy

Container-Level Scoping (cluster-wide)

Cluster-wide ConfigMap rules can target an individual container with container / containerIncludes: no pod annotations required, so all rule configuration stays in the platform-managed ConfigMap. Rules that do not name a container are unaffected.

rules:
  # Suppress chatty sidecar logs only; leave the app container untouched
  - name: "suppress-sidecar-noise"
    action: suppress
    scope:
      namespace: "payments"
      workload: "api"
      container: "sidecar"
    match:
      severity: "info"

Rule Precedence

When multiple rules match, actions are evaluated in this order (higher precedence wins):

  1. preserve (highest) - Keep logs (cannot be overridden)
  2. skip - Don't monitor this workload
  3. intercept - Monitor this workload
  4. suppress (lowest) - Replace matching lines with a summary

measure sits outside this order because it does not compete with the others: whether a workload is read is decided by skip and intercept as above, and any measure rule that selects it, from the ConfigMap, a workload annotation or the fleet, reads it in shadow mode, so one team can try Auditty on its own workload with one annotation. There is no rule that turns measuring off for a workload another rule measures; remove or narrow the measure rule instead.

Key Points:

  • Higher precedence rules override lower ones
  • A ConfigMap skip rule cannot be overridden by an annotation intercept rule (skip > intercept)
  • A ConfigMap suppress rule can be overridden by an annotation preserve rule (preserve > suppress)
  • A fleet rule with the same name as a ConfigMap or annotation rule is ignored on that node; the local rule wins whatever its action

Example: a ConfigMap rule that suppresses lines containing DEBUG and an annotation rule that preserves them: the lines are preserved, because preserve outranks suppress.

Complete Example

ConfigMap Configuration

configMap:
  enable_rule_annotations: true
  cluster_name: "prod-us-west"

  rules:
    # Enable production namespace
    - name: "monitor-production"
      action: intercept
      scope:
        namespace: "production"

    # Skip staging
    - name: "skip-staging"
      action: skip
      scope:
        namespace: "staging"

    # Preserve all high-severity logs
    - name: "preserve-errors"
      action: preserve
      match:
        severity: "error"

    # Suppress debug in production
    - name: "suppress-debug"
      action: suppress
      scope:
        namespace: "production"
      match:
        entryIncludes: "DEBUG"

Deployment with Annotations

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-service
  namespace: production
spec:
  template:
    metadata:
      annotations:
        # Preserve payment-specific errors
        auditty.ai/rule.payment-errors: |-
          name: preserve-payment-errors
          action: preserve
          match:
            any:
              - entryIncludes: "payment failed"
              - entryIncludes: "transaction declined"
              - entryRegex: "card.*invalid"

        # Suppress noisy cache warnings
        auditty.ai/rule.cache-noise: |-
          name: suppress-cache-warnings
          action: suppress
          match:
            all:
              - entryIncludes: "cache"
              - entryIncludes: "miss"

Best Practices

  1. Start broad, refine narrow: Use ConfigMap for cluster-wide rules, annotations for workload-specific tuning
  2. Use entryIncludes when possible: It's faster than regex
  3. Preserve first, suppress later: when trying rules out, write the preserve rules for what matters first, then the suppress rules around them
  4. Document your rules: Always include a clear description
  5. Validate in non-prod: Test annotation rules in staging before production

Troubleshooting

Annotations Not Working?

1. Annotation rules require both enable_rule_annotations: true and edgeApi.enabled: true. Check both:

kubectl get configmap auditty-config -n auditty -o yaml | grep -E "enable_rule_annotations|enabled"

2. Verify RBAC permissions. This is granted to the Edge API service account, not the DaemonSet:

kubectl auth can-i get deployments --as=system:serviceaccount:auditty:auditty-edge-api

3. Check Edge logs for errors:

kubectl logs -n auditty -l app.kubernetes.io/name=auditty-edge --max-log-requests=50 --tail=50 | grep -i annotation

Did My Skip Rule Take?

Every container a rule tells Edge to leave alone gets one INFO line from the Edge pod on its node, the first time Edge sees the container running and again only if a different rule takes over or it was intercepted in between (Edge 1.7.5+):

Skipping log interception  {"namespace": "production", "workload": "test-workload", "rule": "skip-test-workload", "rule_source": "annotation"}
  • rule is the name in your rule; rule_source says where it was written: annotation (on the pod or its owner), config (the ConfigMap) or fleet (the Fleet Rules page)
  • These lines are INFO. Edge 1.7.5 logs at info by default; an install that set log_level: warn in its ConfigMap (the default before 1.7.5) must raise it to info to see them; it hot-reloads, no restart
  • No line and no Started log interception for the workload means no rule selected it at all: check the namespace scope of your intercept rule, not the skip
  • A skip added to a running workload takes effect within about a minute, no restart or rollout needed (Edge 1.7.5+): you will see Stopped log interception with reason: rule_change, then Skipping log interception. Before 1.7.5 annotations were read only when Edge first saw the container, so a new pod that logged before Edge had its annotations was intercepted under the node’s rules until its next restart
  • Started log interception for a workload you meant to skip means the skip rule did not reach Edge: see "Annotations Not Working?" above

Shadow Mode Not Taking (or Not Leaving)?

  • The line at the top of every Auditty page says where the fleet stands: nothing while every node is live, Shadow mode once every node measures, Shadow mode on N of M when only some nodes do, Entering shadow mode · a of b nodes or Going live · n of m nodes still measuring while nodes switch, and Shadow mode switched on · no node has applied it once the switch has been on for ten minutes without a node confirming it. Each node applies the switch within seconds and reports it within two minutes
  • A node that stays live after the switch is either not following fleet rules (remote_rules.enabled: false, or no way to reach Auditty; the Connected Fleet card lists it as not consuming) or older than Edge 1.7.6, which rejects a rule set with a measure action and keeps the rules it had; the card shows the rejection as the node’s last error
  • A node that stays in shadow mode after Go live has shadow_mode: true in its own ConfigMap, or a ConfigMap rule with action: measure that selects the workload. A local rule named measure also vetoes the fleet switch on that node; the Fleet Rules page shows it as overridden locally
  • Started observing logs in shadow mode; nothing is suppressed in the Edge pod’s log names the rule and rule_source when a measure rule decided, and carries neither when the node’s own shadow_mode: true did, so the source of an unexpected shadow mode is one kubectl logs away

Rule Not Matching?

  • Ensure entryIncludes string is exact (case-sensitive)
  • Test regex patterns with online tools before deploying
  • Check scope matches the namespace/workload correctly
  • Remember: annotations only affect the workload they're attached to

Summary

  • ConfigMap rules: Cluster-wide defaults managed by platform team
  • Annotation rules: Per-workload overrides managed by app teams
  • Fleet rules: Auditty-authored rules delivered to all nodes automatically, on by default
  • Precedence: preserve > skip > intercept > suppress (regardless of source); a local rule name vetoes the fleet rule of the same name
  • Shadow mode: a measure rule reads the workloads it selects without suppressing anything; the Fleet Rules page switches the whole fleet with one
  • Distributed control: Teams can preserve their logs even if platform suppresses them