Picture a stranger holding a shell inside one of your pods at 3 a.m. on a Tuesday. Your audit logs are huge and your detection rules generic: how long before anyone notices? A Kubernetes honeytoken answers with something almost naive. You drop a fake secret file into the pod, nobody has any reason to open it, and you get told the first time somebody does. That is what dynatrace-oss/koney automates: an operator that plants the decoys from a YAML resource and hands the watching to Tetragon (eBPF).

This post follows an operator’s questions: what must I decide before trying it, what will I see if it works, and where does the signal go? It is not one more install guide.

A caveat first. span.observer has neither installed nor run Koney. Everything comes from reading the README, docs/ALERT_SINKS.md and the repository samples (clone read on 8 November 2026, version 0.2.2 announced), plus Tetragon’s installation page. The README itself files Koney as an early-stage research project without official Dynatrace support. Keep it on a test cluster.

What a decoy buys you

A conventional detector hunts for suspicious behaviour and generates noise. A decoy flips that: it only reports what should never happen. The false-positive rate then depends on how disciplined your own tooling is, not on a threshold you tune. The authors call it cyber deception; for now only file-based decoys are handled, with deceptive HTTP endpoints promised for later.

Everything lives in a DeceptionPolicy resource, which answers three questions:

  • What do I plant? A filesystemHoneytoken: path, fake content, read-only or not.
  • How does it get into the container? Through volumeMount, containerExec, or kyvernoPolicy, which the README marks as not implemented.
  • Who watches? tetragon, kive (inode tracking) or none if you want the trap without the bell.

Before you start: three decisions for your Kubernetes honeytoken

The target. Koney works on Deployments with the volumeMount strategy, or on pods with containerExec. By the README, ReplicaSets, DaemonSets, StatefulSets and Jobs are not targeted. If your sensitive workload is a StatefulSet, this is not the right tool today.

The restart. With mutateExisting: true, objects already running receive the decoy too, which can force pod restarts. On a demo cluster it does not matter; elsewhere, false avoids the surprise.

Tetragon’s DNS. It must be installed with dnsPolicy=ClusterFirstWithHostNet, otherwise it cannot find Koney’s services. For the Dynatrace output you will also need a token with the openpipeline.events_security scope.

Setting the stage: Tetragon, then Koney

Tetragon first, following its installation page. It runs as a DaemonSet in kube-system:

helm repo add cilium https://helm.cilium.io helm repo update helm install tetragon cilium/tetragon -n kube-system --set dnsPolicy=ClusterFirstWithHostNet kubectl rollout status -n kube-system ds/tetragon -w 

The dnsPolicy setting comes from Koney’s README, which also offers a helm upgrade for an existing install. Mind that Tetragon ignores kube-system pods by default, so do not run your experiments there.

Koney comes next, through Helm (the README’s preferred route):

helm install koney --create-namespace -n koney-system --wait \ oci://ghcr.io/dynatrace-oss/koney/charts/koney --version 0.2.2 

A kubectl apply of dist/install.yaml from the v0.2.2 tag works too.

Reading the sample policy like a reviewer

The repository ships config/samples/deceptionpolicy-servicetoken.yaml, shown below. Rather than narrate it field by field, here is what deserves attention in review.

The Koney repository file deceptionpolicy-servicetoken.yaml: a DeceptionPolicy with a filesystemHoneytoken at /run/secrets/koney/service\_token, the demo.koney/honeytoken label selector, and the containerExec and tetragon strategies

  • The path is absolute and must not be a symlink: the README warns that Tetragon would then miss the access. A silent trap is worse than no trap.
  • Selection is by label (demo.koney/honeytoken: "true"). The policy is cluster-wide with no namespace, so a label that is too broad traps more pods than you meant to.
  • The container selector takes an exact name or the regex: and glob: prefixes.
  • strictValidation: true rejects the whole batch if a single decoy is invalid, which I prefer to a partial rollout.

On naming, the README leans on the Honeyquest study: a plausible but not-too-tempting name such as config.ini holds up better than a too-good-to-be-true passwords.txt. The repo has other templates (for example AWS credentials, deceptionpolicy-aws-credentials.yaml) that I have not read in detail.

Walking into your own trap

The best test is to play the attacker on a throwaway pod, following the README scenario:

  1. Apply the sample: kubectl apply -f https://raw.githubusercontent.com/dynatrace-oss/koney/main/config/samples/deceptionpolicy-servicetoken.yaml
  2. Label your pod: kubectl label pod POD_NAME demo.koney/honeytoken=true
  3. Open the fake secret: kubectl exec -it POD_NAME -- cat /run/secrets/koney/service_token
  4. Watch the output: kubectl logs -n koney-system -l control-plane=controller-manager -c alerts -f --since 1h | jq

Before reading the decoy, confirm it is in place: the policy’s status exposes the PolicyValid, DecoysDeployed and CaptorsDeployed conditions, and the pod carries a koney/changes annotation summarising the traps installed.

The alert lands in the controller’s alerts container, one JSON line per access. Here is the README example, shortened:

Koney JSON alert taken from the README: trap\_type filesystem\_honeytoken, path /run/secrets/koney/service\_token, pod koney-demo-deployment in the koney-demo namespace, process /usr/bin/cat

What helps the on-call engineer is the process field: binary and arguments. A cat from a kubectl exec you just typed is not as serious as an unexpected curl.

Where the signal goes

Only one sink is documented in docs/ALERT_SINKS.md: Dynatrace Security Events. The repository’s procedure: create the token (openpipeline.events_security scope), store it with the environment URL in a Secret in koney-system (keys apiToken and apiUrl), then declare a DeceptionAlertSink resource.

The Koney repository file deceptionalertsink-dynatrace.yaml: a DeceptionAlertSink in koney-system, secretName dynatrace-api-token, severity HIGH

Severity runs from CRITICAL to LOW, defaulting to HIGH. Events go to /platform/ingest/v1/security.events with, among others, event.provider: Koney, finding.severity and k8s.pod.name. Create the Secret from the command line and keep the value out of Git.

Two admitted blind spots: I have not tested this forwarding, and the pages I read do not say how to use these events on the Dynatrace side (queries, alerts). No other sink (Slack, email, webhook) is documented; failing that, reading the alerts container logs remains the simple option.

What can go wrong

  • Maturity: the README speaks of a research project, a v1alpha1 API and behaviour that may change without notice.
  • Noise: a backup, an antivirus or an inventory agent sweeping the disk will open your decoy. Pick a path your tools never visit. That is my own advice, not something the repo confirms.
  • Tetragon too broad: its tracing policy knows nothing of namespaces and targets every pod in the cluster; with a container pattern, every container in the pod.
  • AGPL-3.0 licence: commercial use is allowed, but a distributed derivative stays AGPL, including when offered as a network service. The README’s summary is no substitute for the text: have legal review it.
  • Removal: delete the DeceptionPolicy and DeceptionAlertSink resources first, or the finalizers block the uninstall.
  • Unknowns: performance, behaviour under load, the latest published version.

Best practices

  • A dedicated cluster, and mutateExisting: false if restarts bother you.
  • Never a real secret in fileContent: the content is fake by design.
  • Treat every alert as an incident to qualify: which pod, which process, who opened the session. For the traffic around it, see eBPF network visibility with Cilium and Hubble.
  • Apply least privilege everywhere, agents included: securing an MCP server covers the reasoning, and runtime process exposure completes the picture.

Frequently asked questions

Does a Kubernetes honeytoken replace intrusion detection?

No. It gives a very quiet signal, but only against an intruder who opens the decoy. Your other controls are still needed.

Is Koney a supported Dynatrace product?

No. The repository sits in the dynatrace-oss organisation, and the README’s last line states it is a research project without official support.

Is Tetragon mandatory?

For the tetragon strategy, yes. The README also describes kive and none, the latter planting the decoy without watching it.

Conclusion

Koney turns an old defender’s reflex, the fake secret that rings when touched, into a declarative object. Whether a research project earns a place on your test bench is your call: test in isolation, choose the path with care and read the licence before going further.

span.observer is an independent community blog, not affiliated with Dynatrace LLC or the Koney project. Trademarks belong to their owners. Koney is a research project with no official support: check commands and options in the official documentation before any trial.

Originally published on span.observer. French version: https://span.observer/fr/honeytoken-kubernetes-koney-tetragon/.