簡體   English   中英

將 eBPF sockops 程序附加到特定的容器 cgroup

[英]Attach eBPF sockops program to a specific container cgroup

我想將一個 eBPF sockops 程序附加到特定的 kube.netes pod。 我正在使用bpf_prog_attach()助手,如下所示:

err = bpf_prog_attach(sockops_prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS, 0);

這是我附加到 SOCKOPS 鈎子的 BPF 程序:

#include <linux/in.h>
#include <linux/tcp.h>

#include <linux/bpf.h>
#include <sys/socket.h>

#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>

char LICENSE[] SEC("license") = "GPL";

// sock_ops_map maps the sock_ops key to a socket descriptor
struct {
  __uint(type, BPF_MAP_TYPE_SOCKHASH);
  __uint(max_entries, 65535);
  __type(key, struct sock_key);
  __type(value, __u64);
} sock_ops_map SEC(".maps");

// `sock_key' is a key for the sockmap
struct sock_key {
  __u32 sip4;
  __u32 dip4;
  __u32 sport;
  __u32 dport;
} __attribute__((packed));

// `sk_extract_key' extracts the key from the `bpf_sock_ops' struct
static inline void sk_extract_key(struct bpf_sock_ops *ops,
                                  struct sock_key *key) {
  key->dip4 = ops->remote_ip4;
  key->sip4 = ops->local_ip4;
  key->sport = (bpf_htonl(ops->local_port) >> 16);
  key->dport = ops->remote_port >> 16;
}

SEC("sockops")
int bpf_add_to_sockhash(struct bpf_sock_ops *skops) {
  __u32 family, op;

  family = skops->family;
  op = skops->op;
  bpf_printk("Got new operation %d for socket.\n", op);

  switch (op) {
    case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
    case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
      if (family == AF_INET) {
        struct sock_key key = {};
        sk_extract_key(skops, &key);
        int ret = bpf_sock_hash_update(skops, &sock_ops_map, &key, BPF_NOEXIST);
        if (ret != 0) {
          bpf_printk("Failed to update sockmap: %d\n", ret);
        } else {
          bpf_printk("Added new socket to sockmap\n");
        }
      }
      break;
    default:
      break;
  }
  return 0;
}

在上面,當我為/sys/fs/cgroup/unified cgroup 提供 cgroup_fd 時,程序運行 - eBPF 程序被加載,打印語句運行。

但是,當我將特定的 cgroup 用於 Kube.netes pod(將cgroup_fd用作/sys/fs/cgroup/unified/kubepods-burstable-podad4348c2_ac53_4c09_a9dc_c207a6c68dec.slice:cri-containerd:30a47e8e847277317a29ff7bdcf5bf03391ff79b847be647120d285f62a0f7e6 5bf03391ff79b847be647120d285f62a0f7e6 ,然后程序仍然成功附加,但我不要得到打印語句。

附加到子 cgroup 的 SOCKOPS 掛鈎有問題嗎? 或者特定 kube.netes pod 的 cgroup 是否與unified/中的不同?

看來問題出在目錄名稱中。 在我的系統上,每個 kube.netes pod 都有兩個對應的目錄。 例如,在我的例子中,ID 為ad4348c2-ac53-4c09-a9dc-c207a6c68dec的 kube.netes pod 有以下兩個 cgroup 目錄:

$  ls | grep ad4348c2_ac53_4c09_a9dc_c207a6c68dec
kubepods-burstable-podad4348c2_ac53_4c09_a9dc_c207a6c68dec.slice:cri-containerd:30a47e8e847277317a29ff7bdcf5bf03391ff79b847be647120d285f62a0f7e6
kubepods-burstable-podad4348c2_ac53_4c09_a9dc_c207a6c68dec.slice:cri-containerd:3a4af0e09c0e7e506fef59b92cbeb008b0a3e66d442e54e5ca5ded642841a335

可以使用以下命令找到正確的 cgroup(或通過檢查 pod 的 json 輸出):

$ kubectl get pods -A -o custom-columns=PodName:.metadata.name,PodUID:.metadata.uid,ContainerID:.status.containerStatuses[0].containerID
PodName                                                            PodUID                                 ContainerID
frontend-b74f77687-sd8rf                                           ad4348c2-ac53-4c09-a9dc-c207a6c68dec   containerd://3a4af0e09c0e7e506fef59b92cbeb008b0a3e66d442e54e5ca5ded642841a335

因此,Pod 附加和檢查套接字消息的正確 cgroup 將是kubepods-burstable-podad4348c2_ac53_4c09_a9dc_c207a6c68dec.slice:cri-containerd:3a4af0e09c0e7e506fef59b92cbeb008b0a3e66d442e54e5ca5ded642841a335

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM