Running Falco and k3s at the edge with 64-bit ARM
Falco is an open source tool that peeks into the internals of your system to detect and report on syscall and network activity. It was originally built at Sysdig and later donated to the CNCF where it's doing well as an Incubator project with an active community.
My understanding of Falco from Sysdig's CTO is that it's designed to be the last-line of defence in systems where the focus is usually put on preventative measures. Falco stands in to report on anomalies and unexpected behaviour.
When running k3s at an edge location, it may be difficult to gain physical access to servers, and there may be partial connectivity available.
Pictured above: a net-booted Raspberry Pi cluster running on a purpose-designed industrial unit "BitScope Cluster Blade" by BitScope Designs
By default there are three possible event sources for Falco:
- The kernel and a number of syscalls
- eBPF - faster than kernel access, but not available everywhere
- Userland using PTRACE(2) - for potential use with SaaS products like AWS Lambda
These events can be sent to a webhook such as an OpenFaaS function for remediation at the edge, or alerting and decision-making in a centralised action-centre in the cloud. As a generic event-sink, data can be ingested directly from the Kubernetes API, but a smart device such as a door-lock could also send data such as the current temperature, or unexpected motion picked up from an accelerometer.
Conceptual architecture: event detection from the Kernel, eBPF, the k3s API with alerting and remediation via OpenFaaS.
In this guide I'll show you how to configure Falco to run at the edge with k3s on an ARM64 host such as the Ampere eMAG® provided by Equinix Metal (Equinix provide credits for open source projects hosted by the CNCF), an AWS Graviton instance, or a Raspberry Pi 4.
Tutorial
We'll start off by flashing Ubuntu Linux to the SD card, then adding k3s, finally we'll install Falco and configure k3s to send it events.
Download the Operating System
You will need a Raspbery Pi 4. I am using a device with 4GB of RAM, but 2GB will also work.
Download the Ubuntu 20.04.01 image using the link for the Raspberry Pi 4.
You can get the image here: https://ubuntu.com/download/raspberry-pi
Now use Etcher.io or dd
to write the server OS image to your Raspberry Pi's SD card.
First boot
Note: Unlike with RaspiOS, SSH is enabled by default.
Boot up the machine and find it on your network using nmap
:
nmap -sP 192.168.0.0/24
Log in and change the password from ubuntu
to whatever you like:
ssh ubuntu@192.168.0.101
Next, copy over your SSH key:
ssh-copy-id ubuntu@192.168.0.101
Prepare for k3s
Edit /firmware/boot/cmdline.txt
and add to the first line, don't add any line-breaks:
cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory
This enables cgroups which are required to set limits for containers. The step is taken from my tutorial for Raspbian: Will it cluster? k3s on your Raspberry Pi
Reboot your RPi:
sudo reboot
Install k3s with k3sup
Use my k3sup tool to your workstation to install k3s over SSH. Do not run this on the RPi itself.
curl -sLS https://get.k3sup.dev | sudo sh
Now install via k3sup install
:
k3sup install --ip 192.168.0.101 --user ubuntu \
--channel latest
The --channel
command installs Kubernetes 1.19.
Install Falco and its dependencies
Log back into the RPi via SSH.
A fork of the upstream project is required to run on 64-bit ARM at present, but I expect these changes to be merged back in soon. A maintainer has provided a .deb file:
sudo apt-get -y install linux-headers-$(uname -r) dkms
DKMS is required to build a Kernel module. This is one of the ways that Falco can instrument your system.
You can also build from source using the
build/aarch64
branch.
Install Falco's binary and let it build its kernel module:
wget https://fs.fntlnz.wtf/falco/aarch64-builds/falco-0.26.1-48%2Bf82d905-aarch64.deb
sudo dpkg -i ./falco-0.26.1-48+f82d905-aarch64.deb
Silence some errors in the falco config file.
Edit /etc/falco/falco.yaml
and replace the following:
syscall_event_drops:
actions:
- log
- alert
rate: .03333
max_burst: 10
With:
syscall_event_drops:
actions:
- ignore
rate: .03333
max_burst: 10
This turns off some noise that I was seeing from the ARM-64 version.
Enable it upon boot-up:
sudo systemctl enable falco \
&& sudo systemctl start falco
You can find the various pre-loaded rules for falco at /etc/falco/rules/
ls /etc/falco/rules/
falco.yaml
falco_rules.local.yaml
falco_rules.yaml
k8s_audit_rules.yaml
Simulate a Falco event
Before configuring Kubernetes to send events to Falco, we can send a sample event that will trigger one of the built-in alerts.
cat >> sample-event.json <<EOF
{"kind":"Event","apiVersion":"audit.k8s.io/v1beta1","metadata":{"creationTimestamp":"2018-10-25T13:58:49Z"},"level":"Request","timestamp":"2018-10-25T13:58:49Z","auditID":"841d3e6d-90d2-43df-8da4-684738bee3d5","stage":"ResponseComplete","requestURI":"/api/v1/namespaces","verb":"create","user":{"username":"system:anonymous","groups":["system:masters","system:authenticated"]},"sourceIPs":["192.168.99.1"],"objectRef":{"resource":"namespaces","name":"foo","apiVersion":"v1"},"responseStatus":{"metadata":{},"code":201},"requestObject":{"kind":"Namespace","apiVersion":"v1","metadata":{"name":"foo","creationTimestamp":null},"spec":{},"status":{"phase":"Active"}},"requestReceivedTimestamp":"2018-10-25T13:58:49.730588Z","stageTimestamp":"2018-10-25T13:58:49.736141Z","annotations":{"authorization.k8s.io/decision":"allow","authorization.k8s.io/reason":""}}
EOF
Invoke the event via Falco's REST API:
curl http://127.0.0.1:8765/k8s-audit --data-binary @sample-event.json -H "Content-Type: application/json"
Trigger an event from k3s
An additional source we can add is the events from the Kubernetes audit log. This feature has to be turned on via the k3s systemd definition.
Create a folder for audit events:
sudo mkdir -p /var/lib/rancher/audit
Download audit-policy.yaml
to /var/lib/rancher/audit
wget https://raw.githubusercontent.com/falcosecurity/evolution/master/examples/k8s_audit_config/audit-policy.yaml
sudo cp audit-policy.yaml /var/lib/rancher/audit/
Create a webhook config file:
export IP=192.168.0.23
cat << EOF | sudo tee /var/lib/rancher/audit/webhook-config.yaml
apiVersion: v1
kind: Config
clusters:
- name: falco
cluster:
server: http://$IP:8765/k8s-audit
contexts:
- context:
cluster: falco
user: ""
name: default-context
current-context: default-context
preferences: {}
users: []
EOF
Edit /etc/systemd/system/k3s.service
and add these lines to the end:
'--kube-apiserver-arg=audit-log-path=/var/lib/rancher/audit/audit.log' \
'--kube-apiserver-arg=audit-policy-file=/var/lib/rancher/audit/audit-policy.yaml' \
'--kube-apiserver-arg=audit-webhook-config-file=/var/lib/rancher/audit/webhook-config.yaml' \
Now reload:
sudo systemctl daemon-reload && \
sudo systemctl restart k3s
My favourite use-case from the docs was detecting AWS secret keys stored in ConfigMaps. Of course, we all know confidential data belongs inside Vault or Kubernetes Secrets which can be encrypted at rest.
Let's try it out?
Run this from your laptop:
kubectl create configmap aws-creds \
--from-literal aws_access_key_id=AKES20LNOA
Now check the logs from Falco:
sudo journalctl -u falco --lines 100
Oct 13 16:55:42 ubuntu falco[89818]: 16:55:24.207932928: Warning K8s configmap with private credential (user=system:admin verb=create configmap=aws-creds-1 config={"aws_access_key_id":"AKES20LNOA"})
You can find this example under "Kubernetes Audit Rules" in the Falco docs.
Expand the k3s cluster
You can add additional nodes into the k3s cluster by installing Ubuntu as we did for the first node, then running the k3sup join
command.
k3sup join --ip $IP -user ubuntu \
--server-ip 192.168.0.101
k3s also supports High-Availability and fail-over of the master nodes using a SQL backend or an embedded version of etcd.
Wrapping-up
Full disclosure: Sysdig is a client of OpenFaaS Ltd
We now have Ubuntu 20.04.01, Kubernetes with k3s and Falco all built for 64-bit ARM running on our Raspberry Pi.
It's now over to you to explore Falco more, and to fine-tune your Kubernetes rules.
I also want to give a shout out to my friend fntlnz who is the Falco maintainer that helped me get a working build of Falco on 64-bit ARM. It took us several days to get here.
Recommendations
It took me quite a while to figure out how to get this to work, but it was nice when everything clicked into place. So be warned, the Falco documentation still refers to "Dynamic Auditing" which was removed and deprecated in Kubernetes and the upstream instructions don't cover k3s yet, or any release newer than 1.13.
I hope to see the team at Sysdig spend some time updating the documentation and examples for newer Kubernetes releases and for an official 64-bit ARM binary to be made available soon.
Taking it further
The easier way to get security and other insights, just like the open source Falco project is to use Sysdig's paid product. You can find a step-by-step tutorial by Dan here: K3s + Sysdig: Deploying and securing your cluster… in less than 8 minutes!
You may also like my walk-through video: Installing Ubuntu and k3s to my Raspberry Pi 4
Find out more about the tools: