Kubernetes Audit Log Security with Falco on OVHcloud MKS


Enhancing Kubernetes Security: Detecting Threats in OVHcloud Managed Kubernetes (MKS) Audit Logs with Falco

kubernetes-certified

Keeping your Kubernetes environments secure isn’t just about scanning containers or managing RBAC — it’s about understanding what’s actually happening inside your clusters.

One of the most powerful sources of truth for this? Kubernetes Audit Logs.

In this post, we’ll show how to use Falco, the open source, cloud-native runtime security tool, to detect potential security threats in real time by streaming your OVHcloud Managed Kubernetes (MKS) audit logs into Falco.


What You’ll Learn

By the end of this guide, you’ll know how to:

  • Deploy an OVHcloud Logs Data Platform (LDP)
  • Create a data stream within LDP
  • Connect your MKS cluster to that stream (to send its audit logs)
  • Use the Falco k8saudit-ovh plugin to process those logs in real time
  • Test Falco rules to detect suspicious Kubernetes activity

Prerequisites

You’ll need:

  • An active OVHcloud Managed Kubernetes (MKS) cluster
  • A running instance of Falco

If you don’t have Falco set up yet, check out the Near Real-Time Threat Detection with Falco on OVHcloud MKS guide first.

Step 1. Deploy the Logs Data Platform (LDP)

The OVHcloud Logs Data Platform (LDP) is a managed service for collecting, processing, analyzing, and storing logs across your OVHcloud products.

To monitor your Kubernetes audit logs, we’ll start by deploying an LDP instance.

  1. Log in to the OVHcloud Control Panel
  2. In the top navigation, click Bare Metal Cloud → Logs Data Platform
  3. Choose a plan — Standard (free)or Enterprise, depending on your needs
  4. Select a region close to you — for US customers, choose US - East (Vinthill) or US - West (Hillsboro)
  5. Click Order, follow the setup steps, and wait a few minutes for deployment to complete
  6. Once it’s ready, refresh the page, click your new LDP instance, set a password, and click Save
deploy-your-logs-platform

Step 2. Create a Data Stream and Retrieve the WebSocket URL

Your MKS audit logs will be stored and streamed through a data stream.

  1. In your LDP instance, go to the Data Stream tab
  2. Click Add Data Stream
  3. Choose a descriptive name — for example: my-mks-cluster-audit-logs
create-your-data-stream

    4. Fill in the description (required)   
    5. Enable WebSocket broadcasting  
    6. Click Save

add-your-data-stream

Now, to retrieve the WebSocket URL:

  1. Go back to the Data Stream tab
  2. Click the ⋯ (three dots) next to your new stream
  3. Select Monitor in real time
  4. In the upper-right corner, click ActionCopy WebSocket address

You’ll get a URL like this: wss://bhsxxx.logs.ovh.com/tail/?tk=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx

Save it — you’ll need it for Falco.
 

retrieve-your-websocket

Step 3. Connect Your MKS Cluster to the LDP Data Stream

Now we’ll stream your cluster’s audit logs to the LDP data stream.

  1. In the OVHcloud Control Panel, click Public CloudManaged Kubernetes Service
  2. Select your Kubernetes cluster
  3. Open the Logs tab
  4. Click Subscribe
connect-mks-cluster

    5.    Click Add Data Stream, choose your LDP instance, then select the stream you just created
    6.    Click Subscribe

Your MKS audit logs are now flowing into LDP 

add-mks-cluster

Step 4. Retrieve MKS Audit Logs with Falco

Falco can analyze incoming events against a set of rules, triggering alerts when suspicious activity occurs.

The k8saudit-ovh plugin allows Falco to consume your MKS audit logs directly from the LDP stream over WebSocket.

Whenever a user or component runs a kubectl command in your MKS cluster, Falco will detect the action in near real time and raise alerts if it matches any defined rules.

retrieve-mks-audit-logs

Configure Falco

Create a values.yaml file:

tty: true
kubernetes: false

# Just a Deployment with 1 replica (instead of a Daemonset) to have only one Pod that pulls the MKS Audit Logs from a OVHcloud LDP
controller:
  kind: deployment
  deployment:
    replicas: 1

falco:
  rule_matching: all
  rules_files:
    - /etc/falco/k8s_audit_rules.yaml
    - /etc/falco/rules.d
  plugins:
    - name: k8saudit-ovh
      library_path: libk8saudit-ovh.so
      open_params: "gra<x>.logs.ovh.com/tail/?tk=<ID>" # Replace with your LDP Websocket URL
    - name: json
      library_path: libjson.so
      init_config: ""
  # Plugins that Falco will load. Note: the same plugins are installed by the falcoctl-artifact-install init container.
  load_plugins: [k8saudit-ovh, json]

driver:
  enabled: false
collectors:
  enabled: false

# use falcoctl to install automatically the plugin and the rules
falcoctl:
  artifact:
    install:
      enabled: true
    follow:
      enabled: true
  config:
    indexes:
    - name: falcosecurity
      url: https://falcosecurity.github.io/falcoctl/index.yaml
    artifact:
      allowedTypes:
        - plugin
        - rulesfile
      install:
        resolveDeps: false
        refs:
      follow:
        refs:

Install or update Falco with Helm:

$ helm install falco --create-namespace --namespace falco --values=values.yaml falcosecurity/falco

This command will install the latest version of Falco, with the k8saudit-ovh and json plugins, and create a new falco namespace:

$ helm install falco --create-namespace --namespace falco --values=values.yaml falcosecurity/falco

NAME: falco
LAST DEPLOYED: Mon Feb 10 10:15:20 2025
NAMESPACE: falco
STATUS: deployed
REVISION: 1
NOTES:
No further action should be required.

or, if Falco is already deployed:

$ helm update falco --create-namespace --namespace falco --values=values.yaml falcosecurity/falco

You can check if the Falco pods are correctly running:

$ kubectl get pods -n falco

NAME                                      READY   STATUS    RESTARTS   AGE
falco-6b8bc77d8b-v24jr                    2/2     Running   0          96s
falco-falcosidekick-67877d6946-4hmbn      1/1     Running   0          96s
falco-falcosidekick-67877d6946-tpjk6      1/1     Running   0          96s
falco-falcosidekick-ui-78b96fd57d-4wb6q   1/1     Running   0          96s
falco-falcosidekick-ui-78b96fd57d-v7rnm   1/1     Running   0          96s
falco-falcosidekick-ui-redis-0            1/1     Running   0          96s

 

Wait and execute the command again if the pods are in “Init” or “ContainerCreating” state.

Once all pods are running, view the logs:

kubectl logs -l app.kubernetes.io/name=falco -n falco -c falco

You should see something like:

$ kubectl logs -l app.kubernetes.io/name=falco -n falco -c falco

Mon Feb 10 09:15:35 2025:    /etc/falco/k8s_audit_rules.yaml | schema validation: ok
Mon Feb 10 09:15:35 2025: Hostname value has been overridden via environment variable to: my-pool-1-node-921b61
Mon Feb 10 09:15:35 2025: The chosen syscall buffer dimension is: 8388608 bytes (8 MBs)
Mon Feb 10 09:15:35 2025: Starting health webserver with threadiness 2, listening on 0.0.0.0:8765
Mon Feb 10 09:15:35 2025: Loaded event sources: syscall, k8s_audit
Mon Feb 10 09:15:35 2025: Enabled event sources: k8s_audit
Mon Feb 10 09:15:35 2025: Opening 'k8s_audit' source with plugin 'k8saudit-ovh'
{"hostname":"my-pool-1-node-921b61","output":"09:15:40.698757000: Warning K8s Operation performed by user not in allowed list of users (user=csi-cinder-controller target=csi-6afb06dce281b86b7bab718b5d966dc261b2b1554941ae449519a128cb2e3fb3/volumeattachments verb=patch uri=/apis/storage.k8s.io/v1/volumeattachments/csi-6afb06dce281b86b7bab718b5d966dc261b2b1554941ae449519a128cb2e3fb3/status resp=200)","output_fields":{"evt.time":1739178940698757000,"ka.response.code":"200","ka.target.name":"csi-6afb06dce281b86b7bab718b5d966dc261b2b1554941ae449519a128cb2e3fb3","ka.target.resource":"volumeattachments","ka.uri":"/apis/storage.k8s.io/v1/volumeattachments/csi-6afb06dce281b86b7bab718b5d966dc261b2b1554941ae449519a128cb2e3fb3/status","ka.user.name":"csi-cinder-controller","ka.verb":"patch"},"priority":"Warning","rule":"Disallowed K8s User","source":"k8s_audit","tags":["k8s"],"time":"2025-02-10T09:15:40.698757000Z"}
{"hostname":"my-pool-1-node-921b61","output":"09:15:57.508657000: Warning K8s Operation performed by user not in allowed list of users (user=yacht target=my-pool-1.18051c0a88716868/events verb=patch uri=/api/v1/namespaces/default/events/my-pool-1.18051c0a88716868 resp=403)","output_fields":{"evt.time":1739178957508657000,"ka.response.code":"403","ka.target.name":"my-pool-1.18051c0a88716868","ka.target.resource":"events","ka.uri":"/api/v1/namespaces/default/events/my-pool-1.18051c0a88716868","ka.user.name":"yacht","ka.verb":"patch"},"priority":"Warning","rule":"Disallowed K8s User","source":"k8s_audit","tags":["k8s"],"time":"2025-02-10T09:15:57.508657000Z"}
{"hostname":"my-pool-1-node-921b61","output":"09:15:57.807013000: Warning K8s Operation performed by user not in allowed list of users (user=yacht target=my-pool-1/nodepools verb=update uri=/apis/kube.cloud.ovh.com/v1alpha1/nodepools/my-pool-1/status resp=200)","output_fields":{"evt.time":1739178957807013000,"ka.response.code":"200","ka.target.name":"my-pool-1","ka.target.resource":"nodepools","ka.uri":"/apis/kube.cloud.ovh.com/v1alpha1/nodepools/my-pool-1/status","ka.user.name":"yacht","ka.verb":"update"},"priority":"Warning","rule":"Disallowed K8s User","source":"k8s_audit","tags":["k8s"],"time":"2025-02-10T09:15:57.807013000Z"}

The logs confirm that Falco k8saudit-ovh plugin and the k8saudit rules have been loaded correctly.

Step 5. Testing Falco

To make sure everything works, let’s trigger one of Falco’s default rules — Attach/Exec Pod:

- rule: Attach/Exec Pod
  desc: >
    Detect any attempt to attach/exec to a pod
  condition: kevt_started and pod_subresource and (kcreate or kget) and ka.target.subresource in (exec,attach) and not user_known_exec_pod_activities
  output: Attach/Exec to pod (user=%ka.user.name pod=%ka.target.name resource=%ka.target.resource ns=%ka.target.namespace action=%ka.target.subresource command=%ka.uri.param[command])
  priority: NOTICE
  source: k8s_audit
  tags: [k8s]

In one terminal, tail Falco logs:

$ kubectl logs -l app.kubernetes.io/name=falco -n falco -c falco -f

In another terminal, create an NGINX Pod and exec into it:

$ kubectl run nginx --image=nginx

$ kubectl exec -it nginx -n hello-app -- cat /etc/shadow

Within seconds, Falco should log something like:

...
{"output":"Notice Attach/Exec to pod (user=kubernetes-admin pod=nginx resource=pods ns=default action=exec command=cat)","priority":"Notice","rule":"Attach/Exec Pod","source":"k8s_audit"}
...

Success! Falco is detecting actions based on MKS audit log events.

Wrapping Up

Audit logs are a goldmine for Kubernetes security — but too often, they sit unused.
With the k8saudit-ovh plugin, you can now turn those logs into actionable, real-time insights using Falco, directly integrated with OVHcloud MKS and Logs Data Platform.
You can visualize alerts in the Falcosidekick UI, write custom rules for your own environment, or even integrate with Talon to automate remediation actions.
And while we demonstrated this on OVHcloud MKS, you can run the same Falco setup on other Kubernetes environments — even locally.


Ready to Get Started?

Contact us