项目仓库:https://github.com/yunwei37/Eunomia
4.5. 容器追踪模块设计
4.5.1. 容器信息数据结构
目前我们的容器追踪模块是基于进程追踪模块实现的,其数据结构为:
struct container_event {
struct process_event process;
unsigned long container_id;
char container_name[50];
};
容器追踪模块由container_tracker
实现
struct container_tracker : public tracker_with_config<container_env, container_event>
{
struct container_env current_env = {
0 };
struct container_manager &this_manager;
std::shared_ptr<spdlog::logger> container_logger;
container_tracker(container_env env, container_manager &manager);
void start_tracker();
void fill_event(struct process_event &event);
void init_container_table();
void print_container(const struct container_event &e);
void judge_container(const struct process_event &e);
static int handle_event(void *ctx, void *data, size_t data_sz);
};
同时我们添加了一个manager类来控制tracker。
struct container_manager
{
private:
struct tracker_manager tracker;
std::mutex mp_lock;
std::unordered_map<int, struct container_event> container_processes;
friend struct container_tracker;
public:
void start_container_tracing(std::string log_path)
{
tracker.start_tracker(std::make_unique<container_tracker>(container_env{
.log_path = log_path,
.print_result = true,
}, *this));
}
unsigned long get_container_id_via_pid(pid_t pid);
};
4.5.2. 容器追踪实现
容器追踪模块的ebpf代码服用了process追踪模块的ebpf代码,因此这里我们只介绍用户态下对数据处理的设计。
当内核态捕捉到进程的数据返回到用户态时,我们调用judge_container()
函数,判断该进程是否归属于一个container,其具体实现为:
void container_tracker::judge_container(const struct process_event &e)
{
if (e.exit_event)
{
this_manager.mp_lock.lock();
auto event = this_manager.container_processes.find(e.common.pid);
// remove from map
if (event != this_manager.container_processes.end())
{
event->second.process.exit_event = true;
print_container(event->second);
this_manager.container_processes.erase(event);
}
this_manager.mp_lock.unlock