근묵자흑
Learning eBPF : Falco 본문
앞선 eBPF 스터디에서는 작은 프로그램을 Linux 커널에 올리고, 특정 동작이 일어날 때 실행한 뒤, 수집한 정보를 일반 프로그램으로 전달하는 과정을 살펴봤다. 이번에는 그 구성이 실제 보안 도구인 Falco에서 어떻게 사용되는지 확인했습니다.
기존에 작성해 둔 원본 falco 룰을 가져와, 직접 실행할 학습용 룰을 cylance-study-rules.yaml로 작성했습니다. 이 파일의 탐지 조건이 어디에서 실행되는지, eBPF가 수집한 정보가 어떻게 경보로 바뀌는지를 따라갔다. 이어서 플러그인으로 다른 종류의 정보를 연결하고, Kubernetes에 Helm으로 룰을 배포하는 과정을 블로그로 작성했습니다.
1. Falco에서 eBPF는 무엇을 맡을까요?
먼저 커널과 사용자 공간을 나누어 보면 이해하기 쉽습니다. 커널은 파일, 프로세스, 네트워크 같은 운영체제 자원을 관리합니다. 사용자 공간은 우리가 실행하는 일반 프로그램이 동작하는 영역입니다. Falco의 본체도 사용자 공간에서 실행됩니다.
프로그램이 파일을 열거나 다른 프로그램을 실행하려면 커널에 작업을 요청합니다. 이런 요청을 시스템 호출이라고 합니다. 예를 들어 openat은 파일 열기, execve는 프로그램 실행과 관련된 요청입니다.
Falco의 eBPF 프로그램은 이런 동작을 커널에서 관찰하고 이벤트를 만듭니다. 이후 Falco 본체가 이벤트를 해석하고 YAML에 적힌 조건과 비교합니다. 따라서 “eBPF 기반 탐지”라고 하더라도 YAML의 보안 조건 전체를 커널 안에서 실행하는 것은 아닙니다.

| 구간 | 하는 일 |
|---|---|
| 커널의 eBPF 프로그램 | 필요한 동작을 관찰하고 인자·결과 등의 정보를 이벤트로 구성합니다. |
| libscap | 커널 쪽 수집 장치에서 이벤트를 읽어 옵니다. |
| libsinsp | 이벤트를 해석하고 프로세스·열린 파일의 상태를 관리합니다. |
| Falco 룰 엔진 | 이벤트에서 값을 꺼내 YAML의 조건을 평가합니다. |
| 출력 처리 | 조건에 맞는 이벤트를 사람이 읽을 문장이나 JSON 경보로 만듭니다. |
여기서 libscap과 libsinsp는 별도 서버가 아니라 Falco가 사용하는 라이브러리입니다. 이름을 외우기보다는 각각 이벤트를 가져오는 부분, 이벤트의 의미와 상태를 정리하는 부분으로 읽으면 됩니다. 실제 코드도 이벤트 읽기 → 룰 평가 → 출력 순서로 이어집니다. Falco 이벤트 처리 소스
앞서 배운 eBPF 개념과 연결하기
Falco에는 미리 빌드된 eBPF 수집 프로그램이 포함되어 있습니다. 시작할 때 로더가 대상 커널에 맞게 준비하고, 커널의 안전성 검사를 통과한 프로그램을 관측 지점에 연결합니다.
| 앞서 배운 개념 | Falco에서 사용되는 모습 |
|---|---|
| 관측 지점에 연결하기 | 시스템 호출이나 프로세스 실행 시점에 수집 프로그램이 실행되도록 연결합니다. |
| 맵 | 수집 대상, 처리할 프로그램의 연결 정보, 통계 등을 저장합니다. |
| tail call | 한 eBPF 프로그램이 다른 eBPF 프로그램으로 처리를 넘겨 이벤트 구성을 나눕니다. |
| ring buffer | 커널에서 만든 이벤트를 사용자 공간으로 전달하는 순환형 저장 공간입니다. |
| BTF와 CO-RE | 커널 구조체의 형식 정보를 이용해 메모리 접근 위치를 대상 커널에 맞춥니다. |
| verifier | 커널이 eBPF 프로그램을 받아들이기 전에 안전성을 검사합니다. |
일반적인 시스템 호출 처리에서는 호출 번호를 보고 그 이벤트를 구성할 프로그램으로 처리를 넘깁니다. 앞서 학습한 맵과 tail call이 여기에 사용됩니다. 다만 성공한 프로그램 실행은 이번 버전에서 sched_process_exec라는 별도 관측 지점을 사용합니다. Falco에 표시되는 이벤트 이름이 execve라고 해서 모든 이벤트가 같은 커널 경로에서 수집되는 것은 아닙니다. 시스템 호출 처리 소스, 성공한 실행 수집 소스
파일 경로는 어떻게 알게 될까요?
파일을 연 뒤 읽을 때 프로그램은 매번 경로를 전달하지 않습니다. 커널이 돌려준 파일 번호를 사용합니다. 예를 들어 read(3, ...)만 보면 3번이 어떤 파일인지 알기 어렵습니다.
libsinsp는 앞서 발생한 파일 열기와 닫기 등을 반영해 이 관계를 관리합니다. 그래서 뒤의 이벤트에서도 fd.name 같은 필드로 파일 경로를 확인할 수 있습니다. 이처럼 룰이 보는 값에는 현재 이벤트뿐 아니라 그 시점까지 정리한 상태도 반영됩니다.

이 때문에 Falco는 룰에 직접 등장하는 이벤트 외에도 프로세스와 파일 상태를 유지하는 데 필요한 이벤트를 수집합니다. 룰 변경이 필요한 수집 종류에 영향을 줄 수는 있지만, YAML 조건 자체가 eBPF 프로그램으로 바뀌는 것은 아닙니다.
2. cylance-study-rules.yaml은 어떻게 경보가 될까요?
실제 작성하고 실행한 cylance-study-rules.yaml 에는 학습용 룰 6개와 매크로 3개로 구성했습니다.. 임시 파일과 명령을 대상으로 실행·파일 열기를 확인하는 구성입니다.
아래 code는 cylance-study-rules.yaml의 내용 중 매크로라는 문법이며, 참고는 falco docs를 보고 작성하시면 됩니다.
매크로는 여러 룰에서 반복해서 사용하는 조건에 이름을 붙인 것입니다. 실습 파일은 필요한 매크로를 같은 파일 안에 선언합니다. 실행 여부를 확인하는 정의는 다음과 같습니다.
- macro: study_spawned_process
condition: evt.type in (execve, execveat) and evt.rawres = 0
여기서는 “프로그램 실행이 성공한 이벤트”라는 뜻입니다. 프로그램이 시작된 뒤 수행하려던 작업까지 성공했다는 의미는 아닙니다. 원본을 별도로 비교할 때는 같은 실행 조건을 spawned_process라는 이름으로 제공했습니다.
시작할 때 읽는 룰과 실행 중 들어오는 이벤트
cylance-study-rules.yaml은 이벤트가 생길 때마다 처음부터 다시 읽는 파일이 아닙니다. Falco가 시작하거나 룰을 다시 불러올 때 조건을 준비해 두고, 실행 중에는 들어오는 이벤트를 그 조건에 대입합니다. 아래 그림은 두 시점을 나누어 보여줍니다.

그림에서 YAML은 룰 엔진으로, 실행 정보는 커널에서 이벤트 해석 부분으로 들어옵니다. 룰과 이벤트는 서로 다른 입력이며 사용자 공간의 평가 단계에서 만납니다. 그림은 주요 처리 순서를 설명한 것으로, 모든 초기화 함수나 내부 스레드를 나열한 호출 기록은 아닙니다.
룰을 준비하는 과정은 다음과 같습니다.
- 읽을 파일을 정합니다.
rules_files에 지정한 파일·디렉터리를 읽습니다.-r옵션을 사용했다면 명시한 룰 목록을 사용합니다. Helm 실습에서는cylance-study-rules.yaml의 내용을 ConfigMap의60-study.yaml항목으로 넣어 Pod의/etc/falco/rules.d/60-study.yaml에 전달했습니다. 저장소 파일명과 Pod 안 파일명은 이처럼 다를 수 있습니다. - 조건을 해석합니다.
falco_engine::load_rules()에서 룰 로딩을 시작하고, 매크로 이름을 실제 조건으로 풀어 줍니다. 이 파일의study_spawned_process도 실행 이벤트 종류와 반환값을 비교하는 식으로 바뀝니다. 참조하는 매크로가 준비되지 않으면 로딩 오류가 납니다. - 비교할 항목을 준비합니다.
proc.name같은 필드에서 값을 꺼내는 처리와in,contains, AND·OR 같은 비교를 사용자 공간에서 평가할 수 있는 형태로 만듭니다. eBPF 코드를 생성하는 단계가 아닙니다. - 이벤트 종류별로 후보를 나눕니다. 실행 이벤트에서 볼 룰, 파일 열기에서 볼 룰 등을 구분합니다. 종류를 제한하지 않은 룰도 함께 고려합니다. 모든 이벤트마다 54개 조건 전체를 무조건 같은 방식으로 검사하는 구조는 아닙니다.
실행 중에는 libsinsp가 이벤트를 해석하고 상태를 갱신한 뒤, 해당 이벤트의 후보 룰이 요구하는 필드 값을 꺼내 비교합니다. 값의 제공 여부도 이벤트 종류에 따라 다릅니다. 이번 chmod 실행 경보에서는 proc.name이 있었지만 열린 파일을 뜻하는 fd.name은 비어 있었습니다. 어느 룰의 조건에 맞지 않으면 그 룰의 경보를 만들지 않을 뿐, 이미 갱신한 상태를 버리거나 다른 룰까지 무조건 건너뛰는 것은 아닙니다.
룰 준비와 별도로, 수집 설정에는 활성 룰과 상태 관리에 필요한 이벤트 종류가 반영됩니다. 즉 YAML은 커널에서 무엇을 수집할지에 영향을 줄 수 있지만, chmod 이름 비교는 사용자 공간에 남습니다. 룰 로딩 진입점, 이벤트별 룰 분류
chmod 실행을 처음부터 따라가기
실습 파일의 Study Cylance File Permissions Command 조건은 다음과 같습니다.
condition: >
study_spawned_process and proc.name = chmod
and proc.args contains /tmp/falco-study/permissions.txt
이 조건을 풀어 쓰면 “프로그램 실행이 성공했고, 이름이 chmod이며, 인자에 정해 둔 임시 파일 경로가 있는가?”라는 뜻입니다. chmod 640 /tmp/falco-study/permissions.txt를 실행하면 다음 순서로 처리됩니다.
- Linux가
chmod프로그램을 실행합니다. - eBPF 프로그램이 성공한 실행 시점에서 이름과 인자 등의 정보를 수집합니다.
- 이벤트가 버퍼를 거쳐 Falco로 전달됩니다.
- libsinsp가 프로세스 상태를 갱신하고
proc.name,proc.args등의 값을 제공합니다. - 룰 엔진이 실행 성공, 프로그램 이름, 인자의 파일 경로 조건을 비교합니다.
- 일치하면 룰의
output형식에 맞춰 경보를 만듭니다.
커널 쪽 수집 프로그램이 “권한 변경 공격”이라고 판정한 것은 아닙니다. 실행 이벤트를 만들었고, 사용자 공간의 룰이 그 이벤트에 의미를 부여한 것입니다.
룰은 이벤트를 순서대로 기억하는 명령문이 아닙니다
Falco는 YAML을 읽어 매크로를 풀고, 필드 비교와 AND·OR 조건으로 평가할 수 있는 형태를 만듭니다. 이벤트 종류에 따라 평가할 룰의 범위도 나눕니다. 이 작업은 사용자 공간에서 수행됩니다. 룰 로딩 소스
원본 BashRC 룰은 다음 조건을 동시에 요구합니다.
프로그램 실행 성공
AND 인자에 .bashrc 또는 .bash_profile 포함
AND 파일 열기 이벤트
AND 쓰기 가능한 방식으로 열기
작성 의도는 “프로그램이 실행된 뒤 설정 파일을 수정하는 상황”일 수 있습니다. 하지만 이 조건은 앞뒤 사건을 연결하지 않습니다. 현재 이벤트 하나가 실행 이벤트이면서 파일 열기 이벤트여야 합니다. 이번 매크로 정의에서는 두 조건이 동시에 성립하지 않습니다.
실습에서도 임시 .bashrc에 실제로 데이터를 썼지만 원본 경보는 없었습니다. 별도 관측 룰에서는 파일 열기와 14바이트 쓰기를 확인했습니다. 따라서 이 경우는 입력을 실행하지 못한 것이 아니라 조건의 조합을 다시 살펴봐야 하는 사례입니다.

경보 이름과 실제 관측 사실을 나누어 보기
다른 대표 룰에서도 같은 방식으로 명령, 이벤트, 조건을 대조했습니다.
| 원본 룰 | 실제 입력과 결과 | 조건이 확인하는 사실 |
|---|---|---|
| Base64 | base64 직접 실행은 0건, bash -c ': /usr/bin/base64'는 1건 |
명령 문자열에 bin/base64가 있는지 확인합니다. 뒤의 명령은 base64를 실행하지 않습니다. |
| Permissions | 실제 권한 변경과 chmod --help 모두 1건 |
권한 변경 결과가 아니라 특정 이름의 프로그램 실행을 확인합니다. |
| BashRC | 임시 .bashrc에 쓰기 수행, 원본 0건 |
실행과 파일 열기를 한 이벤트에 요구하는 조건이 충돌합니다. |
| Hosts | 쓰기 가능하게 열고 닫기만 해도 1건 | 쓰기 가능한 열기와 실제 내용 변경은 다릅니다. |
| Bash History | 임시 history 파일을 한 번 읽었는데 5건 | 파일 경로 조건이 열기·조회·읽기·닫기 등 여러 이벤트에 일치했습니다. |
Base64의 경우 이번 직접 실행에서 proc.cmdline은 실행 파일의 절대 경로가 아니라 base64 ... 형태였습니다. 반면 실행하지 않은 경로 문자열을 bash 인자에 넣으면 bin/base64 조건이 일치했습니다. 프로그램 이름, 실행 경로, 인자는 서로 다른 정보이므로 탐지하려는 대상에 맞는 필드를 골라야 합니다.
Hosts 원본 테스트는 별도로 격리한 파일 보기 환경에서 수행해 실제 시스템 파일을 보호했습니다. History의 경보 개수는 읽기 이벤트까지 수집한 이번 설정의 결과이며, 다른 수집 설정에서도 항상 5건이라는 의미는 아닙니다.
조건에 맞은 이벤트는 어떻게 출력될까요?
실습 파일의 권한 명령 룰에 선언한 출력은 다음과 같습니다.
output: "Study permissions command | evt_type=%evt.type user_uid=%user.uid process=%proc.name proc_exepath=%proc.exepath command=%proc.cmdline args=%proc.args"
%proc.cmdline은 경보가 발생한 이벤트의 값으로 채워집니다. 룰의 condition은 경보를 낼지 결정하고, output은 그 경보를 어떻게 설명할지 정합니다. 출력 문구를 바꾸는 것과 탐지 조건을 바꾸는 것은 별개의 작업입니다.
Falco는 일치한 룰 이름, 이벤트 출처, 중요도와 함께 문장을 구성해 출력 큐로 넘깁니다. JSON 출력을 사용하면 rule, source, output, output_fields 같은 항목을 확인할 수 있습니다. 출력 처리 소스
조금 더 안쪽을 보면 falco_outputs::handle_event()가 일치한 이벤트를 받아 %proc.name 같은 자리를 실제 값으로 채웁니다. 그 결과를 잠시 보관하는 출력 큐에 넣으면 별도의 출력 담당 스레드가 꺼내 설정된 목적지로 전달합니다. 이번 표준 출력 구성에서는 완성된 경보 문자열을 한 줄씩 기록했습니다.
Helm 실습에서 해당 명령을 실행한 경보의 일부를 발췌하면 다음과 같습니다. 이벤트 종류·프로그램 이름·인자는 룰의 출력 정의에 있고, 반환값은 append_output이라는 추가 출력 설정으로 기록했습니다.
{
"rule": "Study Cylance File Permissions Command",
"source": "syscall",
"priority": "Notice",
"output_fields": {
"evt.type": "execve",
"evt.rawres": 0,
"proc.name": "chmod",
"proc.args": "640 /tmp/falco-study/permissions.txt"
}
}
이 로그에서는 실행이 성공했고, 이름과 인자까지 실습 룰에 일치했다는 것을 확인할 수 있습니다. 파일 권한이 바뀌었다는 결과는 담겨 있지 않습니다. 또한 output_fields는 모든 커널 정보를 통째로 저장한 것이 아니라 출력에 요청한 필드들입니다. 조건을 진단하려면 확인할 값을 출력에 포함해야 합니다.
Kubernetes에서는 Falco가 컨테이너의 표준 출력에 쓴 내용을 컨테이너 실행 환경이 로그로 수집하고, 이를 kubectl logs로 조회했습니다. 원본 YAML이 Kubernetes 로그 저장소에 직접 쓰는 구조는 아닙니다. 장기 보관과 검색은 별도 로그 수집·저장 구성이 맡습니다. 룰 로드 성공, 조건 일치, 출력 성공, 로그 보관은 각각 다른 확인 지점입니다. 출력 큐가 가득 차는 경우처럼 조건이 일치해도 로그를 전달하지 못하는 상황이 있으므로, 경보가 없을 때는 조건뿐 아니라 수집·출력 상태도 함께 살펴봐야 합니다.
3. 플러그인은 어디에 연결될까요?
앞의 cylance-study-rules.yaml은 Falco가 기본으로 제공하는 시스템 호출 필드를 사용했습니다. 따라서 이 룰을 적용하는 데 Cylance 전용 플러그인이나 새 eBPF 프로그램은 필요하지 않았습니다. 이번에는 다른 종류의 입력이 같은 탐지·출력 과정으로 어떻게 연결되는지 확인하기 위해 falcosecurity/plugins의 공식 k8saudit 플러그인을 사용했습니다.
eBPF 이벤트와 감사 이벤트는 출발점이 다릅니다
Kubernetes 감사 이벤트는 API 서버에 누가 어떤 요청을 했는지 기록한 데이터입니다. 예를 들어 ConfigMap 생성 요청에는 사용자, 대상 namespace, 요청 종류, 응답 코드가 담깁니다. k8saudit는 이 JSON을 읽어 Falco 룰이 비교할 수 있는 값을 제공합니다. 프로세스가 어느 Pod에 속하는지 보강하는 플러그인과는 역할이 다릅니다.
| 구분 | 앞의 eBPF 실습 | 이번 공식 플러그인 실습 |
|---|---|---|
| 입력 | 커널에서 관찰한 프로그램 실행·파일 접근 | HTTP로 전송한 테스트용 Kubernetes 감사 JSON |
| 사용자 공간에서 하는 일 | 이벤트를 읽고 프로세스·파일 상태를 해석합니다. | k8saudit가 JSON을 읽고 필요한 값을 꺼냅니다. |
| 룰의 이벤트 출처 | source: syscall |
source: k8s_audit |
| 조건에 사용하는 값 | proc.name, fd.name 등 |
ka.user.name, ka.verb 등 |
| 조건 일치 후 | Falco가 경보를 구성해 표준 출력에 기록합니다. | 같은 Falco의 경보 출력 기능을 사용합니다. |
여기서 플러그인이 연결되는 곳은 커널이 아니라 Falco의 사용자 공간 입력·필드 해석 부분입니다. 이번 감사 이벤트는 eBPF 버퍼를 거치지 않습니다. 또한 JSON에 “생성 성공”이 적혀 있다는 사실과 실제 API 서버에서 그 작업이 일어났다는 사실은 구분해야 합니다. 실습에서는 API 서버 대신 테스트 전송기가 만든 JSON을 보냈습니다.
라이브러리 로드와 룰 로드는 별개입니다
Linux에서 Falco는 플러그인을 .so 공유 라이브러리로 불러옵니다. 이번에는 libk8saudit.so를 설치했고, 실행 중인 Falco에서 이벤트 입력과 필드 추출 기능이 등록된 것을 확인했습니다. 플러그인 이름은 k8saudit이고, 이 플러그인이 제공하는 이벤트 출처 이름은 k8s_audit입니다.
| 설정 | 역할 |
|---|---|
plugins |
라이브러리 경로, 초기화 설정, 입력 주소를 선언합니다. |
load_plugins |
선언한 플러그인 중 실제로 사용할 이름을 지정합니다. |
rules_files |
Falco가 읽을 룰 파일이나 디렉터리를 지정합니다. |
룰의 source |
그 룰이 평가할 이벤트 출처를 지정합니다. |
required_plugin_versions |
룰에 필요한 플러그인 버전을 확인합니다. 라이브러리를 내려받는 설정은 아닙니다. |
따라서 플러그인 파일만 설치해도 탐지 룰이 자동으로 생기는 것은 아닙니다. 이번에는 공식 플러그인과 별도로 k8saudit-study-rules.yaml을 작성해 로드했습니다. 공식 기본 룰 전체를 사용한 것은 아니며, 해당 기본 룰에서 추가로 요구하는 json 플러그인도 이번 구성에는 넣지 않았습니다. 공식 룰 의존성 안내
# k8saudit-study-rules.yaml
- required_plugin_versions:
- name: k8saudit
version: 0.18.0
- rule: Study K8s Audit Input Witness
desc: Observe synthetic study audit inputs, including inputs not matching the detection rule.
source: k8s_audit
condition: ka.auditid startswith falco-study-audit-
output: "Study audit input (id=%ka.auditid stage=%ka.stage verb=%ka.verb user=%ka.user.name resource=%ka.target.resource ns=%ka.target.namespace code=%ka.response.code)"
priority: DEBUG
- rule: Study K8s Audit ConfigMap Create
desc: Match a successful synthetic ConfigMap creation by the study user in the study namespace, not proof of an attack.
source: k8s_audit
condition: >
ka.auditid startswith falco-study-audit-
and ka.stage = ResponseComplete and ka.verb = create
and ka.target.resource = configmaps and ka.target.namespace = falco-plugin-study
and ka.user.name = study-user and ka.response.code = 201
output: "Study configmap creation (id=%ka.auditid user=%ka.user.name name=%ka.target.name ns=%ka.target.namespace code=%ka.response.code)"
priority: NOTICE
HTTP 입력은 어떻게 룰과 로그로 이어질까요?
실습 경로는 테스트 전송기 → Kubernetes Service → k8saudit의 HTTP 수신부 → 필드 추출 → Falco 룰 평가 → 표준 출력 → Pod 로그입니다. Service는 요청을 Falco Pod로 전달할 뿐, 감사 내용을 분석하지는 않습니다. JSON을 해석해 룰에 값을 제공하는 것은 플러그인이고, 조건을 비교해 경보를 만드는 것은 Falco입니다.
플러그인은 입력의 값을 다음 필드로 제공합니다.
| 감사 JSON 안의 항목 | 룰에서 읽는 필드 | 실습에서 비교한 값 |
|---|---|---|
auditID |
ka.auditid |
falco-study-audit-로 시작하는 실습 표시 |
stage |
ka.stage |
처리가 끝난 단계인 ResponseComplete |
verb |
ka.verb |
생성 요청인 create |
user.username |
ka.user.name |
study-user |
objectRef.resource |
ka.target.resource |
configmaps |
objectRef.namespace |
ka.target.namespace |
falco-plugin-study |
responseStatus.code |
ka.response.code |
생성 성공을 뜻하는 201 |
실제 탐지 룰의 출처와 조건은 다음과 같습니다.
source: k8s_audit
condition: >
ka.auditid startswith falco-study-audit-
and ka.stage = ResponseComplete and ka.verb = create
and ka.target.resource = configmaps and ka.target.namespace = falco-plugin-study
and ka.user.name = study-user and ka.response.code = 201
Falco는 k8s_audit 이벤트에서 위 조건을 비교합니다. 모두 맞으면 룰의 output에 선언한 %ka.user.name 같은 자리를 실제 값으로 채우고, 룰 이름과 출처를 포함한 JSON 경보를 출력합니다. 이후 Pod 로그에서 rule: Study K8s Audit ConfigMap Create, source: k8s_audit와 출력 필드를 확인했습니다. 이는 지정한 형태의 감사 입력이 조건에 맞았다는 뜻이며, ConfigMap 생성 자체를 공격으로 판정한 룰은 아닙니다.
이처럼 입력 수집과 값 해석은 달라져도, “필드로 조건을 비교하고 일치한 결과를 출력한다”는 구조는 앞의 시스템 호출 룰과 같습니다.
4. Kubernetes에서는 Helm으로 어떻게 배포할까요?
Kubernetes에서도 커널 수집과 사용자 공간 룰 평가라는 구분은 같습니다. 달라지는 것은 Falco와 설정 파일을 노드에 배치하고 변경하는 방식입니다. 이번 Helm 배포에서 Falco는 DaemonSet, 즉 대상 노드마다 Pod를 배치하는 형태로 실행됐습니다. 룰은 customRules 값으로 전달했고, 차트가 이를 ConfigMap이라는 설정 저장 리소스로 만들었습니다. 이 내용이 Pod 안의 /etc/falco/rules.d에 파일로 연결되고, Falco의 rules_files 설정이 그 디렉터리를 읽었습니다.
배포가 되었다는 판단에는 ConfigMap 생성만으로 부족합니다. 파일 전달, Falco의 룰 로드, 실제 입력에 대한 경보 출력까지 이어지는지 확인해야 합니다. 실제 사용한 설정에서 수집 방식과 룰 경로를 정하는 부분은 아래와 같습니다.
driver:
kind: modern_ebpf
falco:
rules_files: [/etc/falco/rules.d]
json_output: true
공식 k8saudit 플러그인을 Helm으로 배포
3장에서 설명한 공식 k8saudit 플러그인은 Falco 0.44.1과 Helm 차트 9.1.0으로 배포했습니다. 플러그인은 0.18.0 버전으로 고정했습니다. 기존 eBPF 센서는 유지하고 falco-plugin-study namespace에 별도 falco-audit-study Helm 릴리스를 설치했습니다. 외부 입력을 받는 역할이므로 모든 노드에 하나씩 배치하지 않고, Pod 하나를 유지하는 Deployment로 구성했습니다. 이 Pod에서는 syscall 수집을 끄고 k8s_audit 출처만 활성화했습니다.
controller:
kind: deployment
driver:
enabled: false
falcoctl:
config:
artifact:
install:
refs: [k8saudit:0.18.0]
falco:
plugins:
- name: k8saudit
library_path: /usr/share/falco/plugins/libk8saudit.so
init_config:
useAsync: true
open_params: http://:9765/k8s-audit
load_plugins: [k8saudit]'k8s > learning-ebpf' 카테고리의 다른 글
| Learning eBPF 7장 : eBPF Program and Attachment Types (0) | 2026.08.29 |
|---|---|
| Learning eBPF 6장 : eBPF Verifier (2) | 2026.08.22 |
| Learning eBPF 5장 : CO-RE, BTF, libbpf (0) | 2026.08.15 |
| Learning eBPF : cloudflare/ebpf_exporter (0) | 2026.08.08 |
| Learning eBPF ch4 : The bpf() System Call (4) | 2026.08.01 |