Implement Kubernetes security scanning with Falco and OPA Gatekeeper for runtime protection

Advanced 45 min Jun 14, 2026 64 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up comprehensive Kubernetes security with Falco for runtime threat detection and OPA Gatekeeper for admission control policy enforcement. This tutorial covers installation, configuration, and custom security policies.

Prerequisites

  • Kubernetes cluster with admin access
  • Helm 3.x installed
  • kubectl configured
  • Basic understanding of Kubernetes security concepts

What this solves

Kubernetes clusters need layered security to detect runtime threats and enforce admission policies. Falco monitors system calls and container behavior for suspicious activity, while OPA Gatekeeper validates resources against security policies before deployment. Together they provide comprehensive protection against malicious workloads, privilege escalation, and policy violations.

Step-by-step installation

Install Helm for package management

Both Falco and Gatekeeper use Helm charts for installation. Install Helm first to manage the deployments.

curl https://get.helm.sh/helm-v3.12.0-linux-amd64.tar.gz -o helm.tar.gz
tar -zxvf helm.tar.gz
sudo mv linux-amd64/helm /usr/local/bin/helm
helm version

Add Helm repositories

Add the official repositories for Falco and Gatekeeper charts.

helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update

Install Falco for runtime security monitoring

Deploy Falco as a DaemonSet to monitor all nodes for suspicious activity. The default configuration includes rules for common threats.

kubectl create namespace falco-system
helm install falco falcosecurity/falco \
  --namespace falco-system \
  --set driver.kind=ebpf \
  --set falco.grpc.enabled=true \
  --set falco.grpcOutput.enabled=true

Install OPA Gatekeeper for admission control

Deploy Gatekeeper to validate all resource requests against defined policies before they reach the API server.

kubectl create namespace gatekeeper-system
helm install gatekeeper gatekeeper/gatekeeper \
  --namespace gatekeeper-system \
  --set replicas=3 \
  --set auditInterval=60

Verify installations

Check that both systems are running correctly across all nodes.

kubectl get pods -n falco-system
kubectl get pods -n gatekeeper-system
kubectl get validatingadmissionwebhooks

Configure security policies and rules

Create custom Falco rules

Add detection rules for your specific environment. This example detects unauthorized network connections.

apiVersion: v1
kind: ConfigMap
metadata:
  name: falco-custom-rules
  namespace: falco-system
data:
  custom_rules.yaml: |
    - rule: Unexpected outbound connection
      desc: Detect unexpected outbound network connections
      condition: >
        outbound and not fd.typechar=4 and not fd.typechar=6 and 
        not proc.name in (curl, wget, apt, yum, dnf) and
        not container.image.repository in (docker.io/library/alpine, gcr.io/distroless)
      output: >
        Unexpected outbound connection (command=%proc.cmdline connection=%fd.name 
        user=%user.name container=%container.name image=%container.image.repository)
      priority: WARNING
      tags: [network, outbound]
    
    - rule: Privileged container spawned
      desc: Detect containers running with privileged access
      condition: >
        spawned_process and container and proc.vpid=1 and 
        container.privileged=true
      output: >
        Privileged container spawned (command=%proc.cmdline user=%user.name 
        container=%container.name image=%container.image.repository)
      priority: CRITICAL
      tags: [container, privilege]
kubectl apply -f falco-custom-rules.yaml

Create Gatekeeper constraint templates

Define reusable policy templates that can be applied to different resource types.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: requiresecuritycontext
spec:
  crd:
    spec:
      names:
        kind: RequireSecurityContext
      validation:
        properties:
          runAsNonRoot:
            type: boolean
          readOnlyRootFilesystem:
            type: boolean
          allowPrivilegeEscalation:
            type: boolean
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package requiresecuritycontext
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.runAsNonRoot
          msg := "Container must run as non-root user"
        }
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.readOnlyRootFilesystem
          msg := "Container must use read-only root filesystem"
        }
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.allowPrivilegeEscalation != false
          msg := "Container must not allow privilege escalation"
        }
kubectl apply -f require-security-context-template.yaml

Apply security context constraints

Use the template to enforce security contexts on all pods in production namespaces.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: RequireSecurityContext
metadata:
  name: must-have-security-context
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces: ["production", "staging"]
  parameters:
    runAsNonRoot: true
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
kubectl apply -f security-context-constraint.yaml

Create resource limit template

Prevent resource exhaustion attacks by requiring CPU and memory limits on all containers.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: requireresources
spec:
  crd:
    spec:
      names:
        kind: RequireResources
      validation:
        properties:
          limits:
            type: array
            items:
              type: string
          requests:
            type: array
            items:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package requireresources
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          required := input.parameters.limits
          provided := container.resources.limits
          missing := required[_]
          not provided[missing]
          msg := sprintf("Container missing required resource limit: %v", [missing])
        }
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          required := input.parameters.requests
          provided := container.resources.requests
          missing := required[_]
          not provided[missing]
          msg := sprintf("Container missing required resource request: %v", [missing])
        }
kubectl apply -f require-resources-template.yaml

Apply resource limit constraints

Enforce CPU and memory limits on all production workloads.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: RequireResources
metadata:
  name: must-have-resource-limits
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces: ["production", "staging"]
  parameters:
    limits: ["cpu", "memory"]
    requests: ["cpu", "memory"]
kubectl apply -f resource-limits-constraint.yaml

Set up monitoring and alerting

Configure Falco alerts

Set up webhook notifications to send security alerts to your monitoring system.

apiVersion: v1
kind: ConfigMap
metadata:
  name: falco-config-override
  namespace: falco-system
data:
  falco.yaml: |
    rules_file:
      - /etc/falco/falco_rules.yaml
      - /etc/falco/falco_rules.local.yaml
      - /etc/falco/k8s_audit_rules.yaml
      - /etc/falco/rules.d
    
    json_output: true
    json_include_output_property: true
    
    http_output:
      enabled: true
      url: "http://webhook-service.monitoring.svc.cluster.local:8080/falco"
      user_agent: "falco/0.35.0"
    
    priority: WARNING
    
    syscall_event_drops:
      actions:
        - log
        - alert
      rate: 0.1
      max_burst: 1000
kubectl apply -f falco-config-override.yaml
kubectl rollout restart daemonset/falco -n falco-system

Create alerting webhook service

Deploy a simple webhook receiver to process Falco alerts and forward them to your notification system.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: security-webhook
  namespace: monitoring
spec:
  replicas: 2
  selector:
    matchLabels:
      app: security-webhook
  template:
    metadata:
      labels:
        app: security-webhook
    spec:
      containers:
      - name: webhook
        image: falcosecurity/falcosidekick:2.25.0
        ports:
        - containerPort: 2801
        env:
        - name: WEBHOOK_URL
          value: "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK"
        - name: DEBUG
          value: "true"
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: security-webhook
  namespace: monitoring
spec:
  selector:
    app: security-webhook
  ports:
  - port: 8080
    targetPort: 2801
  type: ClusterIP
kubectl create namespace monitoring
kubectl apply -f webhook-deployment.yaml

Monitor Gatekeeper violations

Create a monitoring dashboard to track policy violations and system health.

apiVersion: v1
kind: ServiceMonitor
metadata:
  name: gatekeeper-metrics
  namespace: gatekeeper-system
spec:
  selector:
    matchLabels:
      app: gatekeeper
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: gatekeeper-alerts
  namespace: gatekeeper-system
spec:
  groups:
  - name: gatekeeper.rules
    rules:
    - alert: GatekeeperViolations
      expr: increase(gatekeeper_violations_total[5m]) > 10
      for: 2m
      labels:
        severity: warning
      annotations:
        summary: "High number of Gatekeeper policy violations"
        description: "{{ $value }} policy violations detected in the last 5 minutes"
    
    - alert: GatekeeperDown
      expr: up{job="gatekeeper"} == 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "Gatekeeper is down"
        description: "Gatekeeper admission controller is not responding"
kubectl apply -f gatekeeper-monitoring.yaml

Test security policies

Test Gatekeeper admission control

Verify that policies block non-compliant workloads by trying to deploy a pod without required security context.

apiVersion: v1
kind: Pod
metadata:
  name: insecure-test-pod
  namespace: production
spec:
  containers:
  - name: test
    image: nginx:latest
    ports:
    - containerPort: 80
kubectl apply -f test-insecure-pod.yaml

This should fail with a message about missing security context and resource limits.

Test compliant pod deployment

Deploy a pod that meets all security requirements.

apiVersion: v1
kind: Pod
metadata:
  name: secure-test-pod
  namespace: production
spec:
  containers:
  - name: test
    image: nginx:latest
    ports:
    - containerPort: 80
    securityContext:
      runAsNonRoot: true
      runAsUser: 1000
      readOnlyRootFilesystem: true
      allowPrivilegeEscalation: false
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 200m
        memory: 256Mi
    volumeMounts:
    - name: tmp
      mountPath: /tmp
    - name: var-cache
      mountPath: /var/cache/nginx
  volumes:
  - name: tmp
    emptyDir: {}
  - name: var-cache
    emptyDir: {}
kubectl apply -f test-secure-pod.yaml

Generate test security events

Trigger Falco rules to verify runtime monitoring works correctly.

# Create a test pod that will trigger Falco rules
kubectl run falco-test --image=alpine --rm -it --restart=Never -- sh

Inside the container, run commands that should trigger alerts:

ps aux netstat -an find /etc -name "passwd" wget google.com exit

Verify your setup

# Check Falco is detecting events
kubectl logs -n falco-system -l app.kubernetes.io/name=falco --tail=50

Verify Gatekeeper policies are active

kubectl get constraints kubectl get constrainttemplates

Check for policy violations

kubectl describe RequireSecurityContext must-have-security-context kubectl describe RequireResources must-have-resource-limits

Test webhook connectivity

kubectl logs -n monitoring -l app=security-webhook
Important: Falco generates many events in a typical cluster. Configure appropriate filters and alert thresholds to avoid notification fatigue while ensuring critical security events are not missed.

Common issues

SymptomCauseFix
Falco pods failing to starteBPF driver not supportedUse --set driver.kind=module instead of ebpf
Gatekeeper blocking all podsConstraint too restrictiveAdd namespace exclusions or adjust match criteria
High CPU usage from FalcoToo many syscall eventsTune rules and add filters for noisy processes
Webhook not receiving alertsNetwork policy blocking trafficAllow egress from Falco namespace to webhook service
Policies not applyingGatekeeper not readyWait for all admission webhooks to be ready

Advanced configuration

Performance tuning: In high-traffic clusters, consider using Falco's gRPC output with a separate collector service to reduce resource usage and improve alert processing efficiency.

For production deployments, also consider integrating with Kubernetes RBAC for comprehensive access control and OpenTelemetry monitoring for complete observability across your security stack.

Next steps

Running this in production?

Need this managed? Running this at scale adds a second layer of work: capacity planning, failover drills, cost control, and on-call. See how we run infrastructure like this for European teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.