Deploy

Deploy the Reporter app to Kubernetes via Helm.

The Reporter is a read-only DaemonSet, the simplest way to evaluate 10x. It tails the same pre-analyzer stream the forwarder already sees and emits per-pattern cost metrics. It never touches the forwarder and logs never pass through it.

The engine never moves or stores log data. Its only write is per-pattern metrics, to a time-series backend the customer chooses (Prometheus, Datadog, Elastic, CloudWatch, and others). prometheus.log10x.com is an optional hosted backend for evaluation; air-gapped operation is supported.

Per node the chart runs a Fluent Bit tailer plus the 10x engine sidecar, about 250 MiB and 150m CPU. To actively cut volume, deploy the Receiver instead.

An agent can do all of this through the log10x MCP: deploy with log10x_advise_install, verify with log10x_doctor, or trial without deploying via log10x_poc_from_local and log10x_poc_from_siem. The manual Helm steps below do the same by hand.

Step 1: Prerequisites
Requirement Description
Log10x License A signed JWT from console.log10x.com (see licenseKey / licenseFile)
Helm Helm CLI installed
kubectl Configured to access your cluster
GitHub Token Optional, only if loading config/symbols from a private Git repo (create one)
Step 2: Add Helm Repository
helm repo add log10x https://log-10x.github.io/helm-charts
helm repo update
helm search repo log10x/reporter-10x

View all chart values:

helm show values log10x/reporter-10x
Step 3: Configure Deployment Settings

Create a new file called my-reporter.yaml in your working directory. This Helm values file will be used in all subsequent steps. At minimum, set the license JWT:

my-reporter.yaml
log10xLicenseJwt: "YOUR-LICENSE-JWT-HERE"
runtimeName: "my-reporter"

That's enough to run. The chart's defaults collect logs from all namespaces and ship them to the bundled 10x sidecar. The next steps add config sources, secrets, log-collection filters, and metric outputs.

Inline JWT is fine for evaluation

Passing the JWT inline is convenient for a first install, but the raw token then sits in your Helm release values (visible via helm get values). For production prefer the existing-secret mode shown in Step 5 below. The chart prints a reminder if it sees an inline JWT.

Step 4: Load Configuration

Load the 10x Engine config folder into the cluster using one of the methods below.

If you skip this step, the default configuration bundled with the 10x image is used.

An init container clones your configuration repository before each pod starts. Works with GitHub, GitLab, Bitbucket, or any HTTPS-accessible Git provider.

  1. Fork the Config Repository
  2. Create a branch for your configuration changes
  3. Edit the app configuration to match your metric output

Add to your Helm values:

my-reporter.yaml
config:
  git:
    enabled: true
    url: "https://github.com/YOUR-ACCOUNT/config.git"
    # branch: "main"          # Optional

# symbols:                    # Uncomment if using a symbol library
#   git:
#     enabled: true
#     url: "https://github.com/YOUR-ACCOUNT/symbols.git"

gitToken: "YOUR-GIT-TOKEN"

For production, store the token in a Kubernetes Secret rather than in the values file.

Mount an existing PersistentVolumeClaim that contains your configuration directory. This approach works in air-gapped environments and requires no external network access.

  1. Create a PVC containing your configuration files (cloned from the Config Repository)
  2. Reference it in your Helm values:
my-reporter.yaml
config:
  volume:
    enabled: true
    claimName: "my-config-pvc"

# symbols:
#   volume:
#     enabled: true
#     claimName: "my-symbols-pvc"
Step 5: Configure Secrets

The chart manages the Log10x license JWT via a Kubernetes Secret and mounts it as a file in the engine container (read via TENX_LICENSE_FILE). By default it creates the Secret from the log10xLicenseJwt value above:

my-reporter.yaml
log10xLicenseJwt: "YOUR-LICENSE-JWT-HERE"

licenseSecret:
  create: true              # Create a new Secret from `log10xLicenseJwt` (default)
  existingSecret: ""        # Or reference an existing Secret instead
  secretKey: "license-jwt"  # Key name inside the Secret

Using an existing Secret (recommended for production, keeps the JWT out of the values file):

my-reporter.yaml
log10xLicenseJwt: ""        # Leave empty when using an existing Secret

licenseSecret:
  create: false
  existingSecret: "my-log10x-secret"
  secretKey: "license-jwt"

Create the Secret out-of-band:

kubectl -n logging create secret generic my-log10x-secret \
  --from-literal=license-jwt=YOUR-LICENSE-JWT-HERE

Git access token: if Step 4 references a private repo, supply the token the same way:

my-reporter.yaml
gitToken: "YOUR-GIT-TOKEN"

Airgapped mode: for clusters with no path to the Log10x vendor gateway (security policy, isolated network), suppress every outbound call to it:

my-reporter.yaml
airgapped: true

With this set, the chart adds TENX_AIRGAPPED=true to the engine sidecar. The license JWT is verified locally against the embedded public key; no startup validation, no reporting to the vendor gateway, no user-attribute enrichment. Per-pattern metrics still flow to the customer's own time-series backend, and customer-configured outputs (Splunk, Datadog, Elastic, etc.) are unaffected. demo and limited license types cannot run airgapped. The engine warns and falls back to online if either is configured with airgapped: true.

Step 6: Log Collection

The bundled Fluent Bit tails container logs from every node. By default it collects logs from all namespaces. Restrict or filter what's collected via the values file:

Namespace scoping

my-reporter.yaml
# Only collect from these namespaces
includeNamespaces:
  - default
  - production
  - staging

# OR exclude noisy/system namespaces
excludeNamespaces:
  - kube-system
  - kube-public
  - kube-node-lease

Use one or the other. If includeNamespaces is set, ONLY those namespaces are collected; if excludeNamespaces is set, those are skipped. If both are empty, all namespaces are collected.

Pattern filtering (drop noisy log lines before they reach the 10x sidecar)

my-reporter.yaml
excludePatterns:
  - key: log
    regex: "^\\s*$"             # Drop empty lines
  - key: log
    regex: "health.?check"      # Drop health-check noise

includePatterns:
  - key: log
    regex: "ERROR|WARN"         # Only forward errors and warnings

Patterns use Fluent Bit's grep filter. key is the field to match against, regex is the regex.

Step 7: Deploy

Create your namespace (if needed) and install:

kubectl create namespace logging
helm install my-reporter log10x/reporter-10x \
  -f my-reporter.yaml \
  --namespace logging

The chart deploys a DaemonSet with two containers per node: fluent-bit (log tailer) and tenx (the 10x engine sidecar). They communicate over a shared Unix socket inside the pod.

Step 8: Verify

Verify the install in three phases: pods Ready → 10x processor alive → metrics flowing to the dashboard.

Phase A: pods Ready

kubectl -n logging wait --for=condition=Ready pod -l app.kubernetes.io/instance=my-reporter --timeout=5m

Phase B: 10x processor alive

The 10x engine runs in the tenx container alongside fluent-bit. Check the startup banner: the 🪵 / 🚀 / 📥 / 📈 lines confirm the engine wired up Fluent Bit's Forward input and is publishing metrics:

kubectl -n logging logs -l app.kubernetes.io/instance=my-reporter -c tenx --tail=200 | grep -E '🪵|🚀|📥|🚦|📈|📝'

Confirm Fluent Bit is tailing logs (look for [input:tail lines and event counts):

kubectl -n logging logs -l app.kubernetes.io/instance=my-reporter -c fluent-bit --tail=200 | grep -iE 'tail|forward|output'

Phase C: metrics flowing to the dashboard

The Reporter publishes per-pattern volume and cost metrics to your configured time-series backend. View them in the Reporter Dashboard; the dashboard updates within a few minutes of the first events.

With an agent, log10x_doctor confirms reporter detection and metric freshness, and log10x_baseline captures the starting per-pattern volume and cost.

Step 9: Teardown

Uninstall the Helm release:

helm -n logging uninstall my-reporter

Clean up any Secret you created out-of-band (the chart-created license Secret is reaped automatically; PVCs are reaped if they were chart-created):

kubectl -n logging delete secret my-log10x-secret --ignore-not-found

Verify nothing remains:

kubectl -n logging get all,configmap,secret,pvc -l app.kubernetes.io/instance=my-reporter

Delete the namespace (optional):

kubectl delete namespace logging --ignore-not-found
Quickstart Full Sample

Minimal-to-realistic values file. Runs against all namespaces except system ones, pulls its 10x config from a private Git repo, and uses an external Secret for the license JWT.

Save as my-reporter.yaml and apply with helm install my-reporter log10x/reporter-10x -f my-reporter.yaml -n logging.

my-reporter.yaml
log10xLicenseJwt: ""            # Provided via existing Secret below
runtimeName: "my-reporter"

licenseSecret:
  create: false
  existingSecret: "my-log10x-secret"
  secretKey: "license-jwt"

# Pull pipeline config + symbols from a private Git repo
config:
  git:
    enabled: true
    url: "https://github.com/YOUR-ACCOUNT/log10x-config.git"
symbols:
  git:
    enabled: true
    url: "https://github.com/YOUR-ACCOUNT/log10x-config.git"
    path: "tenx/my-app/symbols"
gitToken: "YOUR-GIT-TOKEN"

# Skip system namespaces
excludeNamespaces:
  - kube-system
  - kube-public
  - kube-node-lease

# Drop empty lines and health checks
excludePatterns:
  - key: log
    regex: "^\\s*$"
  - key: log
    regex: "health.?check"

# Resource overrides for high-volume nodes (>1000 containers/node)
tenx:
  resources:
    requests: { cpu: 200m, memory: 300Mi }
    limits:   { cpu: 500m, memory: 512Mi }
fluentbit:
  resources:
    requests: { cpu: 50m,  memory: 64Mi }
    limits:   { cpu: 200m, memory: 128Mi }

See the Reporter app guide for the full set of values and the matching local-install walkthrough.