Cloud & Infrastructure/Kubernetes Security

K8s Security - 10. audit runtime-security

정적 방어를 넘어 "지금 무슨 일이 일어나는가"를 잡는 법 — 감사와 런타임 보안

한 클러스터에서 침해가 일어났다. 공격자는 권한을 올리고 비밀을 빼갔지만, 발견은 며칠 였다. 아무도 실시간으로 "이상한 일이 돌아가고 있다"를 못 봤기 때문이다. 지금까지의 정적 방어 — RBAC·NetworkPolicy·Pod Security — 는 "들어오는 것"을 막는 데는 강하지만, 이미 들어와서 행동하는 것은 잡지 못한다. 이 빈을 메우는 두 축이 감사 로그(audit log)런타임 보안(Falco)이다. 전자는 "누가 무엇을 했나"를 사후에 기록하고, 후자는 "지금 커널에서 무슨 일이 일어나나"를 실시간으로 잡는다. 이 글은 03-k8s-security 영역의 마지막 주제로, 이 두 관측 축이 침해를 어떻게 잡고 재구성하는지를 따진다.

두 관측이 보는 시점이 다르다

audit log와 런타임 보안은 "무슨 일이 일어나는가"를 묻되, 시점소스가 다르다.

audit log 런타임 보안(Falco)
무엇을 보나 apiserver를 거친 API 요청 노드 커널의 syscall·프로세스
언제 사후(기록) 실시간(탐지)
잡는 것 "누가 언제 어떤 리소스를 만들/읽/지웠나" "컨테이너가 셸을 띄웠다, reverse shell"
못 잡는 것 API를 안 거친 행동(컨테이너 내 셸) API 수준 변경(RBAC 변조 등)은 2차적으로만

침해의 많은 단계가 API를 거치지 않는다 — 컨테이너 안에서 셸을 띄우고 syscall로 노드 정보를 빼내는 행동은 audit에 안 잡힌다. 반대로 RBAC 변조나 Secret 읽기는 API 요청이므로 audit에 잡히지만, 런타임의 관심사가 아니다. 그래서 둘이 짝이 되어야 "무슨 일이 일어나는가"의 전체가 보인다.

audit log — apiserver를 거친 모든 요청

kube-apiserver에 --audit-policy-file로 감사 정책을 주면, API 요청이 감사 이벤트로 기록된다. 각 이벤트엔 누가(user)·언제·무엇(verb/resource)·성공 여부·응답이 들어간다. (Kubernetes docs - Auditing) 정책의 핵심은 어떤 이벤트를 어느 수준까지 기록할까를 대상별로 차등하는 것이다.

# audit-policy.yaml — 대상·수준 차등 (Kubernetes 공식 문법)
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Secret 접근은 요청+응답 본문까지 전수 기록
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets"]
# 일반 Pod 조회는 메타데이터만
- level: Metadata
  resources:
  - group: ""
    resources: ["pods"]
# healthz 같은 빈번한 비-자원 요청은 기록 안 함
- level: None
  nonResourceURLs: ["/healthz", "/livez*"]

감사 수준은 네 단계다. 이 선택이 기록의 상세와 로그 용량을 결정한다.

수준 기록 내용 용량 적합
None 안 기록 0 민감하지 않은 빈도 높은 읽기
Metadata 요청 메타데이터(누가/언제/무엇) 작음 일반 Pod 조회
Request 메타데이터 + 요청 본문 중간 설정 객체 생성/수정
RequestResponse 메타데이터 + 요청 + 응답 본문 Secret 접근, 권한 변경(전수 추적)

"다 기록하자"는 곧 "디스크가 꽉 찬다"다. 모든 요청을 RequestResponse로 받으면 audit 로그가 클러스터 트래픽에 비례해 폭증하고, SIEM 비용이 감당 안 된다. 그래서 민감한 것(Secret, RBAC 변경)은 상세, 일반 읽기는 간소화, 빈번한 healthz는 제외가 audit 운용의 원칙이다. 감사는 또 단계(stage)별로도 기록된다 — ResponseComplete만 남기고 RequestReceived는 빼는(omitStages) 식으로 중복을 줄일 수 있다.

audit log가 사후 조사와 컴플라이언스의 유일한 기반이라는 점도 중요하다. 침해 뒤 "공격자가 무엇을 했나"를 시간순으로 재구성하려면 이 로그밖에 없다. PCI-DSS·GDPR·HIPAA가 audit log 보존을 요구하는 이유다. 없으면 사후 조사가 불가능하다.

Falco — 커널 수준 이상 행동을 실시간으로

audit이 API 수준이라면, Falco(CNCF Graduated)는 노드의 커널 수준을 본다. eBPF로 syscall과 프로세스 이벤트를 관찰해 "컨테이너가 갑자기 셸을 띄웠다", "reverse shell이 열렸다", "권한 상승을 시도한다" 같은 이상 행동을 실시간 탐지한다. (Falco docs - Rules)

# Falco 규칙 — 컨테이너 내 셸 탐지 (Falco 공식 문법)
- rule: Terminal shell in container
  desc: 컨테이너 안에서 인터랙티브 셸이 실행됨
  condition: >
    container and proc.name in (bash, sh, zsh, dash)
    and k8s.ns.name startswith "prod-"
    and not k8s.labels contains "debug"
  output: >
    Shell spawned in container
    (user=%user.name container=%container.name
     namespace=%k8s.ns.name command=%proc.cmdline)
  priority: WARNING

조건(condition)은 Falco의 필드(proc.name, container, k8s.ns.name, evt.type 등)로 짠다. container가 참이면 호스트가 아닌 컨테이너 안에서 일어난 사건이라는 뜻이고, k8s.* 필드로 namespace·라벨까지 조건에 넣을 수 있다. Falco가 규칙 위반을 감지하면 output 양식으로 경고를 내보내고, 이게 SIEM이나 PagerDuty로 간다.

침해 사고 타임라인 — audit와 Falco가 짝일 때

두 축이 침해 사고에서 어떻게 보완하는지를 타임라인으로 보면 왜 둘 다 필요한지 보인다.

flowchart TD
    T0["T+0: 공격자 컨테이너 침투"] -->|Falco| AL1["셸 실행 실시간 경고"]
    T1["T+5분: 비밀 탈취 시도"] -->|audit| AL2["Secret get 기록"]
    T2["T+10분: RBAC 상승 시도"] -->|audit| AL3["RoleBinding create 기록"]
    AL1 -. 즉시 .-> RESP["대응 시작: Pod 격리"]
    AL2 -. 사후 .-> INVEST["조사: 무엇을 읽었나"]
    AL3 -. 사후 .-> SCOPE["영향 범위 파악"]

Falco가 실시간으로(셸 실행 경고) 빠른 대응의 발단을 만들고, audit log가 사후로(무엇을 읽었나, 무엇을 만들었나) 영향 범위를 재구성한다. 둘이 합쳐야 "잡고 이해하는" 전체 사이클이 된다. 하나만 있으면 — Falco만 있으면 경고는 오는데 "뭘 뺏겼나"를 모르고, audit만 있으면 사건은 기록되는데 너무 늦게 발견한다.

Falco 규칙 설계 — 오탐과 누락의 줄다리기

규칙 설계가 Falco 운용의 숙련 영역이다. 너무 관대하면 공격을 놓치고, 너무 엄격하면 정상 행동까지 경고하는 오탐이 폭증해 알림 피로가 온다. 좋은 규칙의 원칙은 세 가지다:

  • 조건을 좁혀라 — "컨테이너에서 셸"보다 "프로덕션 namespace의 비-디버그 컨테이너에서 셸"로. 위 예시처럼 k8s.ns.name과 라벨로 범위를 좁힌다.
  • known-good을 빼라 — CI나 Job 컨테이너는 셸을 정상적으로 쓰므로 제외 조건(not k8s.labels contains "debug")을 넣는다.
  • 점진 전환 — 새 규칙은 먼저 경고만(warn-only) 내보내 오탐율을 관찰하고, 안정되면 alert로 올린다.

규칙을 깔아놓고 끝이 아니라, 지속적으로 오탐과 누락을 조율해야 한다.

런타임 도구 지형 — eBPF가 대세인 이유

Falco 외에도 런타임 보안 도구는 여럿이다:

  • Tetragon(Cilium 계열): eBPF 기반. 탐지뿐 아니라 정책 시행(차단)까지. (Tetragon)
  • Tracee(Aqua): eBPF 기반 탐지. (Tracee)
  • 기존 HIDS(OS 수준 에이전트).

이들이 eBPF로 모인 이유는, eBPF가 커널 안에서 안전하게 돌아가는 프로그램이라 오버헤드가 낮고 커널 모듈(재부팅 필요, 충돌 위험)과 달리 런타임에 로드·언로드된다는 점 때문이다. Cilium과 같은 기술 기반이다. Tetragon이 눈에 띄는 건 "탐지에서 한 걸 더 가 차단까지" 한다는 점 — Falco는 기본적으로 탐지·경고지만, Tetragon은 eBPF로 syscall을 실시간 차단할 수 있다.

직접 확인하기

# Kubernetes 1.36 — audit log가 켜져 있는지 (apiserver 정적 파드)
kubectl -n kube-system get pod -l component=kube-apiserver -o yaml | grep -A5 audit

확인할 것: --audit-policy-file 플래그가 있으면 audit이 켜진 것. kind 기본 클러스터는 보통 off, kubeadm은 구성 가능.

# Falco(Helm 설치 후) 실시간 경고
kubectl logs -n falco -l app.kubernetes.io/name=falco -f

Falco 설치·규칙 세부 설정과 Tetragon의 차단 정책은 각 공식 문서로 실측.

흔히 묻는 것, 흔히 틀리는 것

오해 정정
"audit log는 단순 디버그 로그다" 컴플라이언스·사후 조사의 기반. 전략적 기록
"Falco가 audit log를 대체한다" 보완. audit=API 사후, Falco=커널 실시간. 다른 축
"모든 요청을 RequestResponse로 기록한다" 용량 폭증. 정책으로 수준·대상 설계 필수
"런타임 보안은 컨테이너 안에서만" 커널 수준. 노드 탈출 시도까지 잡음
"침해는 정적 방어로 다 막힌다" 이미 들어온 후 행동은 정적으로 못 잡음. 런타임 필요
"eBPF 도구는 커널 모듈이다" eBPF는 런타임에 로드되는 안전한 프로그램. 모듈(재부팅)과 다름

요약 — 이 글의 결론

  • audit log와 런타임 보안이 "관측/대응" 축 — 정적 방어(RBAC·정책·Pod Security)를 넘어 사후 추적실시간 탐지를 더한다.
  • audit log는 apiserver의 모든 요청을 기록. 사후 조사·컴플라이언스의 유일한 기반. 수준(None/Metadata/Request/RequestResponse)으로 용량과 추적성의 균형을 잡고, 대상별로 차등 설계해야 "디스크 폭증"을 피한다.
  • Falco/Tetragon/Tracee(eBPF 기반)가 커널 수준 이상 행동을 실시간 탐지 — 셸 실행·reverse shell·권한 상승. 정적 방어가 못 잡는 진행 중 침해를 잡는다.
  • 둘의 협력: Falco(실시간 경고) + audit(사후 재구성)가 짝. 침해를 잡고 이해하려면 둘 다.
  • Falco 규칙 설계는 오탐·누락의 줄다리기. 조건 좁히기·known-good 제외·warn-only 점진 전환이 원칙.
  • eBPF가 런타임 도구의 대세 — 커널 단, 낮은 오버헤드, Cilium과 같은 기반. Tetragon은 탐지 너머 차단까지.

생각해 볼 문제

  1. 공격자가 컨테이너 안에서 reverse shell을 띄웠다. audit log에 잡히나? Falco에는?
  2. audit log를 모든 요청 RequestResponse로 기록했다. 3개월 뒤 생기는 문제는?
  3. 침해 후 사후 조사에서 "공격자가 어떤 Secret을 읽었나"를 알려면 어느 로그가 필요한가? 어느 audit 수준이었어야 잡힐까?
  4. Falco 규칙을 너무 엄격하게 해 두었다. 생기는 문제(오탐)와 운영 대응은?
  5. eBPF 기반 런타임 도구가 커널 모듈보다 운영상 유리한 점.
  6. audit log + Falco를 SIEM에 통합한다. 침해 시 자동 대응(예: Pod 격리)까지 엮으려면? 자동 대응의 위험은?
  7. Tetragon이 "차단까지" 한다는 게 Falco 대비 주는 이점과, 동시에 감수해야 할 위험을 각각 말하라.

참고