반응형

eBPF(Extended Berkeley Packet Filter)

 

요약

- eBPF는 커널 내 가상 머신의 한 종류입니다.

- bpf() 시스템 콜을 통해서 유저 스페이스와 eBPF 프로그램이 통신할 수 있습니다.

 

 

eBPF란 무엇인가?

 

 

https://ebpf.io/what-is-ebpf/

 

 

 

 

 

 

 

 

 

 

Android 에서

Android에서는 부팅 시 eBPF 프로그램을 로드하여 커널 기능을 확장하는 eBPF 로더 및 라이브러리가 포함되어 있습니다. eBPF로더는 커널, 모니터링 또는 디버깅에서 통계를 수집하는데 사용할 수 있습니다.

 

eBPF 정보

eBPF는 사용자 제공 eBPF 프로그램을 실행하는 커널 내 가상머신입니다. 이러한 프로그램을 커널의 프로브나 이벤트에 연결하여 유용한 통계를 수집하고 풍부한 데이터 구조에 결과를 저장할 수 있습니다.

 프로그램은 bpf(2) syscall을 사용하여 커널로 로드되며 사용자가 eBPF 머신 명령의 바이너리 Blob으로 제공합니다.

 Android 빌드 시스템은 뒤에서 설명하는 간단한 빌드 파일 구문을 사용하여 C 프로그램을 eBPF로 컴파일하는 기능을 지원합니다.

 

 즉, C 프로그램을 eBPF로 컴파일 할 수 있습니다. eBPF는 커널 내 가상머신의 한 종류입니다.

 

 Linux 커널 v3.18부터 eBPF란 기능이 생겼습니다. 유의미하게 쓸 수 있는 버전은 v.4.9 이후 부터입니다. 이를 고수준언어에서 활용하게해주는 BCC 툴킷이 있습니다.

 eBPF는 x86-64와 arm64의 공통점을 따온 것 처럼 보이는 별도의 어셈블리 언어입니다. 실제로 이런 코드를 사람이 직접 작성하지는 않습니다. 단지 성능 측정을 위한 C 언어 코드를 작성하면 이를 eBPF 프로그램으로 트랜스파일합니다. (BCC 툴체인의 기능)

 

 여기서 트랜스파일이라 함은 한 언어로 작성된 소스코드를 비슷한 수준의 추상화(Abstraction)를 가진 다른 언어로 변환하는 것을 말합니다. 출처:  [이러쿵저러쿵]

 

 이 eBPF 프로그램을 bpf() 시스템 콜을 통해서 linux 커널에 전달하면 해당 내용을 커널 안의 샌드박스형태의 인터프리터 - JVM 처럼 다른 프로그램을 실행시켜주는 VM - 로 동작합니다. 다만 커널에서 돌릴 것이라 몇가지 검증을 합니다. (동작 중에 크래시날 만한 코드가 있는지 확인합니다.)

 - 아무 함수나 부를 수 있는 건 아닙니다.

 - 스택이나 메모리 접근 방식도 제한됩니다. (직접 선언한 값이나 스택으로 넘어온 값에 대하여 참조하는 일부 값만 접근가능합니다)

 - 데이터는 미리 선언한 일종의 해시맵에만 저장할 수 있스빈다.

 

이 eBPF 프로그램은 몇가지 데이터를 수집할 수 있습니다.

 - 시스템 콜, 혹은 커널 내에서의 함수 호출

 - 유저 스페이스 (유저 프로그램) 내의 함수 호출

 - 프로그램에서 정의한 트레이싱 지점 (python 이나 JVM, node.js 같은 고수준 언어/프레임워크에서 주로 제공합니다)

 

 유저 스페이스에서는 이미 동작 중인 eBPF 프로그램과 통신해서 동작을 수정하거나 - 예를 들어 측정 대상을 추가 - 현재까지 수집된 데이터를 가져가거나 할 수 있습니다. (이 역시 bpf() 시스템 콜을 통해서 이뤄집니다)

 

 결국,  bpf() 시스템 콜을 통해서 유저 스페이스와 eBPF 프로그램이 통신이 가능하게 되는 것 입니다.

 

 

BCC (eBPF Compiler Collection)

 eBPF는 성능 측정을 위한 훌륭한 기능을 제공합니다. 하지만 이를 위해서는 C언어를 이용해서 프로그램을 짜고 데이터를 주고 받아야 합니다. 이런 변접함을 줄이기 위해서 BCC를 이용합니다. BCC를 사용하면 아래와 같은 방법으로 성능 분석을 할 수 있습니다.

 1. C 코드로 성능 데이터 수집하는 코드 작성

 2. Python이나 go 혹은 lua로 1에서 작성한 데이터를 eBPF 프로그램으로 생성합니다. 만약 필터링이 필요한 경우 - 특정 프로세스나 스레드로 제한하는 등 - 1의 프로그램을 전송하기 전에 수정합니다.

 3. BCC 컴파일 (1의 코드를 eBPF 프로그램으로 변환) 후 커널에 로드

 4. eBPF 프로그램을 추가로 데이터 측정할 곳에 연결합니다.

 

(1) -> BCC 컴파일 ((1)의 코드를 eBPF 프로그램으로 변환) -> 커널의 로드 -> 해당 eBPF 프로그램을 추가로 데이터 측정할 곳에 연결

 

 이 과정을 마친 후에는 커널에 있는 eBPF 프로그램과 유저 스페이스에 있는 프로그램이 통신할 수 있습니다. 주기적으로 현재까지의 데이터를 가져와서 통계를 보여주거나 아니면 추가로 특정 데이터를 수집하거나 하는 일을 할 수 있습니다.

 

왜 유용한가?

 

 

출처/참고자료

https://source.android.com/devices/architecture/kernel/bpf?hl=ko 

 

https://blog.ifunfactory.com/2018/03/29/linux-%EA%B2%8C%EC%9E%84-%EC%84%9C%EB%B2%84-%EC%84%B1%EB%8A%A5-%EB%B6%84%EC%84%9D%EC%97%90-ebpf-bcc-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0/

반응형