Falco Runtime Security
Detect suspicious runtime behavior in your containers with Falco, the CNCF graduated threat detection engine.
Time: ~20 minutes Difficulty: Advanced
What You Will Learn
Section titled “What You Will Learn”- How Falco monitors system calls to detect threats
- Triggering real security alerts: shell access, sensitive file reads, network activity
- Reading Falco alerts in real time
- Understanding Falco rules and how they match syscall patterns
Prerequisites
Section titled “Prerequisites”Minikube driver note: Falco uses eBPF to hook into the Linux kernel. The Docker driver wraps everything in a container, which blocks eBPF access. Falco requires
--driver=kvm2or--driver=qemu2.
Check your current driver:
minikube profile listIf you see docker in the DRIVER column, you have two options:
Option A: Create a separate profile (keeps your existing cluster):
minikube start -p falco-lab --driver=qemu2 --cpus=4 --memory=8192When done, switch back: minikube profile minikube
Option B: Recreate your cluster with a compatible driver:
minikube deleteminikube start --driver=qemu2 --cpus=4 --memory=8192 --disk-size=40gminikube addons enable ingressminikube addons enable metrics-serverInstall Falco via Helm:
helm repo add falcosecurity https://falcosecurity.github.io/chartshelm repo updatehelm install falco falcosecurity/falco \ --namespace falco-system \ --create-namespace \ --set tty=true \ --set falcosidekick.enabled=false \ --set driver.kind=modern_ebpf \ --set resources.limits.memory=2Gi \ --set resources.requests.memory=512MiWait for Falco to be ready:
kubectl rollout status daemonset/falco -n falco-systemDeploy
Section titled “Deploy”Navigate to the demo directory:
cd demos/falcoCreate the namespace and target application:
kubectl apply -f manifests/namespace.yamlkubectl apply -f manifests/target-app.yamlVerify Falco is Running
Section titled “Verify Falco is Running”Check that Falco is logging events:
kubectl logs -l app.kubernetes.io/name=falco -n falco-system --tail=5You should see Falco initialization messages or event logs.
Trigger Security Alerts
Section titled “Trigger Security Alerts”This is the core of the demo. Open two terminals for this section.
Terminal 1: Watch Falco Logs
Section titled “Terminal 1: Watch Falco Logs”In the first terminal, watch Falco logs in real time:
kubectl logs -l app.kubernetes.io/name=falco -n falco-system -fKeep this running.
Terminal 2: Trigger Alerts
Section titled “Terminal 2: Trigger Alerts”In the second terminal, run these commands and watch the alerts appear in Terminal 1.
Alert 1: Shell Spawned in Container
Section titled “Alert 1: Shell Spawned in Container”kubectl exec -it deployment/web-app -n falco-demo -- /bin/shSwitch to Terminal 1. Falco fires “Terminal shell in container” alert.
Type exit to leave the shell.
Alert 2: Read Sensitive File
Section titled “Alert 2: Read Sensitive File”kubectl exec deployment/web-app -n falco-demo -- cat /etc/shadowWatch Terminal 1. Falco fires “Read sensitive file untrusted” alert.
Alert 3: Write to System Directory
Section titled “Alert 3: Write to System Directory”kubectl exec deployment/web-app -n falco-demo -- touch /bin/maliciousWatch Terminal 1. Falco fires “Write below binary dir” alert with ERROR priority.
Alert 4: Network Tool Execution
Section titled “Alert 4: Network Tool Execution”kubectl exec deployment/web-app -n falco-demo -- wget -qO- http://example.comFalco may fire alerts for unexpected network tool usage.
What is Happening
Section titled “What is Happening”manifests/ namespace.yaml # falco-demo namespace target-app.yaml # Simple nginx app: Deployment + Service (2 replicas)Falco runs as a DaemonSet on every node (one pod per node). It hooks into the Linux kernel via eBPF to monitor every system call made by processes in containers.
The detection pipeline:
Your Action -> Kernel Syscall -> Falco Rule Match -> Alertkubectl exec sh -> execve() -> "Terminal shell" -> WARNINGcat /etc/shadow -> open() -> "Sensitive file" -> WARNINGtouch /bin/malicious -> open(O_CREAT) -> "Write below /bin" -> ERRORwget ... -> execve() -> "Network tool" -> WARNINGHow Falco rules work:
When a syscall matches a rule condition, Falco generates an alert. For example:
- Rule: “Terminal shell in container”
- Condition: process spawned in container + process name is
shorbash - Priority: WARNING
- Output: Timestamp, container ID, pod name, namespace, command, user
The alert includes rich context: which pod, which container, what command, which user, and more. This makes it easy to investigate incidents.
Falco vs preventive security:
- Kyverno/OPA: Prevent bad configs from being deployed (admission control)
- Trivy/Grype: Scan images for vulnerabilities before deployment
- Falco: Detect threats at runtime, after the container is running
You need all three layers for defense in depth.
Experiment
Section titled “Experiment”-
Trigger package manager alert:
Terminal window kubectl exec deployment/web-app -n falco-demo -- apk add curlFalco detects package management in containers.
-
Inspect Falco’s built-in rules:
Terminal window kubectl exec -n falco-system daemonset/falco -- cat /etc/falco/falco_rules.yaml | head -100Scroll through to see default rules like “Write below root”, “Contact K8s API Server From Container”, and more.
-
Check all Falco events in the last 5 minutes:
Terminal window kubectl logs -l app.kubernetes.io/name=falco -n falco-system --since=5m | grep "Warning\|Error" -
Create a pod without securityContext and watch additional alerts:
Terminal window cat <<EOF | kubectl apply -f -apiVersion: v1kind: Podmetadata:name: test-podnamespace: falco-demospec:containers:- name: appimage: nginx:1.25.3-alpineEOFRun
kubectl exec -it test-pod -n falco-demo -- /bin/shand watch Falco fire alerts. -
Write a custom Falco rule:
Create a ConfigMap with a custom rule to detect when someone reads
/etc/passwd:apiVersion: v1kind: ConfigMapmetadata:name: falco-custom-rulesnamespace: falco-systemdata:custom-rules.yaml: |- rule: Read Passwd Filedesc: Detect reads to /etc/passwdcondition: >evt.type = open andfd.name = /etc/passwd andcontainer.id != hostoutput: "Passwd file read (user=%user.name command=%proc.cmdline file=%fd.name container=%container.name)"priority: WARNINGApply it and configure Falco to load it via Helm values.
Cleanup
Section titled “Cleanup”Delete the demo namespace:
kubectl delete namespace falco-demoTo remove Falco itself:
helm uninstall falco -n falco-systemkubectl delete namespace falco-systemFurther Reading
Section titled “Further Reading”See docs/deep-dive.md for a detailed explanation of how eBPF works, Falco’s rule engine, alert pipelines, integration with Falcosidekick for Slack/PagerDuty alerting, and building a runtime security strategy.
Next Step
Section titled “Next Step”Move on to OpenTelemetry & Distributed Tracing to see the full journey of a request across microservices with OpenTelemetry and Jaeger.