Falco — проект CNCF для обнаружения аномалий в работающей системе. Он не сканирует образы, а перехватывает системные вызовы ядра и проверяет их по набору правил. В контейнерах это особенно полезно: образ может быть чистым, но внутри пода внезапно запускается оболочка или читается /etc/shadow. Ниже — установка в Kubernetes, разбор правил, исключения для ложных срабатываний и диагностика типовых сбоев.
Как Falco получает события
Источников событий три. Драйвер ядра, он же kmod, требует заголовков установленного ядра. eBPF-проба работает через bpf() и не собирает модуль, но привязана к версии ядра. Третий вариант, modern_ebpf, использует CO-RE и BTF и переносится между ядрами без пересборки. В Kubernetes выбирают именно его: ядра 5.8 и новее поддерживаются, а обновление узла не ломает загрузку.
Falco работает в режиме обнаружения: он фиксирует событие, но не блокирует процесс. Блокировка — задача admission-контроллеров, seccomp и AppArmor, и это стоит проговорить со службой безопасности заранее. Зато обнаружение не вмешивается в работу приложения и не может уронить прод.
Установка в Kubernetes
Официальный Helm-чарт создаёт DaemonSet, сервисный аккаунт, RBAC и falcoctl для обновления правил. Минимальные значения: modern_ebpf, tty=true и tolerations, чтобы поды попали на системные узлы.
В managed-кластерах с запретом привилегированных подов драйвер не загрузится. Там нужны плагины: они читают журнал аудита Kubernetes и не требуют доступа к ядру.
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm upgrade --install falco falcosecurity/falco \
--namespace falco --create-namespace \
--set driver.kind=modern_ebpf --set tty=true
kubectl -n falco get pods -o wide
Проверка движка и правил
Убедитесь, что поды в Running, а в логах нет ошибок загрузки драйвера. Команда falco —list=syscall печатает доступные события и поля; пустой вывод означает, что драйвер не инициализировался.
Затем проверьте правила: falco -L выводит активные правила с приоритетами. Если список короче ожидаемого, часть файлов не прочиталась или перекрыта более поздним определением.
kubectl -n falco logs ds/falco --tail=80
kubectl -n falco exec ds/falco -- falco --version
kubectl -n falco exec ds/falco -- falco --list=syscall | head
kubectl -n falco exec ds/falco -- falco -L | wc -l
Анатомия правила
Правило — YAML-объект с условием на языке фильтров Sysdig. Условие собирается из макросов и списков: макрос заменяет фрагмент выражения, список — перечисление значений. Так не приходится дублировать длинные наборы путей и имён процессов.
Поля делятся на группы: evt.* описывает событие, proc.* — процесс, fd.* — дескриптор, container.* и k8s.* — окружение. Условие вычисляется для каждого события, поэтому тяжёлые проверки выносят в начало цепочки.
- rule: Оболочка в контейнере с терминалом
desc: Интерактивный shell внутри пода
condition: >
spawned_process and container and shell_procs
and proc.tty != 0
output: >
shell=%proc.name pod=%k8s.pod.name ns=%k8s.ns.name
image=%container.image.repository cmd=%proc.cmdline
priority: WARNING
tags: [container, shell, mitre_execution]
В output подставляются поля в формате %field. Чем их больше, тем полезнее событие, но тем тяжелее логи. Приоритеты идут от EMERGENCY до DEBUG; на практике рабочий диапазон начинается с WARNING.
Продолжение того же правила с исключением выглядит так:
exceptions:
- name: debug_pods
fields: [k8s.ns.name, k8s.pod.name]
comps: [=, =]
values:
- [debug, troubleshooting]
Свои правила и обновление
Файлы пользователя кладут в /etc/falco/rules.d/, чарт монтирует каталог из ConfigMap. Файлы читаются по алфавиту, поэтому числовой префикс задаёт порядок. После правки под перезапускают: не все сборки умеют перечитывать правила на лету.
Наборы правил удобнее ставить через falcoctl: он тянет OCI-артефакт falco-rules, проверяет подпись и раскладывает файлы.
falcoctl artifact install falco-rules
falcoctl artifact info falco-rules
kubectl -n falco create configmap falco-local \
--from-file=custom_rules.yaml
kubectl -n falco rollout restart ds/falco
Ложные срабатывания
Шум — главная причина, по которой Falco отключают через месяц. Сначала соберите статистику: какие правила срабатывают чаще всего и в каких пространствах имён. Потом добавьте исключения: они не выключают правило, а вырезают известные комбинации полей.
Для правки чужого правила используйте override с append: так вы не копируете условие целиком и не теряете обновления из upstream.
- rule: Terminal shell in container
override:
exceptions: append
exceptions:
- name: ci_runners
fields: [k8s.ns.name]
comps: [=]
values:
- [ci]
Куда отправлять события
По умолчанию события идут в stdout в читаемом виде. В кластере это неудобно: лог пода быстро уходит в ротацию. Включите JSON и отправьте события через falcosidekick — он умеет Slack, Elasticsearch, Loki, Kafka и webhook.
Если внешние сервисы запрещены, пишите в файл на узле или в syslog. gRPC-порт наружу не открывайте: встроенной аутентификации у него нет.
helm upgrade --install falco falcosecurity/falco \
--set falcosidekick.enabled=true \
--set falcosidekick.config.loki.hostport=http://loki:3100 \
--set falcosidekick.config.slack.webhookurl=... \
--set falcosidekick.webui.enabled=false
Диагностика
Типовые сбои: CrashLoopBackOff из-за отсутствия BTF, пустой поток событий из-за фильтра по пространству имён, задержки из-за переполнения кольцевого буфера. Для метрик включите webserver на порту 8765.
- проверьте версию ядра и наличие /sys/kernel/btf/vmlinux;
- сравните число событий до и после фильтра namespace;
- посмотрите, не растёт ли счётчик потерь;
- убедитесь, что правила не перекрыты более поздним файлом.
POD=$(kubectl -n falco get pod -l app.kubernetes.io/name=falco -o jsonpath='{.items[0].metadata.name}')
kubectl -n falco port-forward pod/$POD 8765:8765
curl -s localhost:8765/metrics | grep -iE 'event|drop'
kubectl -n falco logs ds/falco | grep -iE 'btf|driver'
Чек-лист внедрения
- драйвер проверен на всех типах узлов;
- настроен JSON и внешний приёмник;
- правила версионируются в git;
- есть исключения для CI и отладки;
- настроены алерты на потери событий;
- раз в квартал пересматривается шум.
Итог
Falco закрывает разрыв между сканированием образов и реальным поведением контейнера. Он не заменяет seccomp и сетевые политики, но даёт раннее предупреждение там, где статические проверки бессильны.
Начните с одного пространства имён и соберите статистику за неделю. Такой порядок снижает риск, что через месяц систему отключат из-за шума. Правила стоит пересматривать вместе с изменениями в приложении.