How to run DPDK in k8s - One container in each pod
서로 다른 pod의 container에서 실행되는 DPDK process들도 다른 경우와 마찬가지로 DPDK runtime config 파일과 hugepage map 파일만 공유하면 hugepage를 공유할 수 있다.
이 때 서로 다른 pod가 같은 DPDK runtime config 파일들과, hugepage map 파일을 공유하기 위해 두 개 pod가 함께 사용할 수 있는 hostPath
를 이용한다. hostPath
는 pod가 실행되는 node의 파일 시스템을 이용하여 volume을 만든다. 그러므로 서로 다른 pod가 동일 node에서 실행되는 경우에만 pod가 hugepage를 공유할 수 있다.
DPDK runtime config
두 개 pod에서 hostPath
를 이용하여 DPDK runtime config 파일을 공유를 위한 volume을 만든다.
volumes:
- name: dpdk-config
hostPath:
path: /tmp/dpdk-config
Two containers in a single pod 경우와 마찬가지로, 각 container에서는 위 volume을 /var/run/dpdk
위치에 마운트 시킨다.
- name: container-1
volumeMounts:
- mountPath: /var/run/dpdk
name: dpdk-config
- name: container-2
volumeMounts:
- mountPath: /var/run/dpdk
name: dpdk-config
hugetlbfs
서로 다른 pod가 hugetlbfs를 공유하기 위해 host의 hostPath
를 사용한다. 이때 emptyDir
을 사용하는 경우와 달리 pod간 공유할 hugetlbfs를 hostPath
에서 만들기 위해 node에 이미 hugetlbfs
로 마운트 된 경우를 사용해야 한다.
리눅스에서는 boot 인자로 지정한 default hugepage size에 해당하는 hugepage는 /dev/hugepages
에 마운트 된다.
$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-5.13.0-1021-oracle root=UUID=b69068ad-8c25-4bc9-ae7f-e6f8103b9c97 ro default_hugepagesz=2M hugepagesz=2M hugepages=20 console=tty1 console=ttyS0 nvme.shutdown_timeout=10 libiscsi.debug_libiscsi_eh=1 crash_kexec_post_notifiers
위 경우 default_hugepagesz=2M
옵션을 이용하여 2MB를 default hugepage로 사용한 경우로 이 hugepage 들이 마운트 된 위치를 다음과 같이 확인할 수 있다.
$ grep hugetlbfs /proc/mounts
hugetlbfs /dev/hugepages hugetlbfs rw,relatime,pagesize=2M 0 0
pod에서 node의 hugetlbfs
를 사용하기 위해 다음과 같이 node의 /dev/hugepages
사용하는 volume을 만든다. (pod에서 별도로 hugetlbfs를 만들지 않고, node에 이미 마운트 된 hugetlbfs
를 사용하므로, emptyDir
을 이용한 hugepage를 만들 필요 없다)
volumes:
- name: dev-hp
hostPath:
path: /dev/hugepages
그리고 2개 pod내 container들은 각자 이 volume을 자신의 /dev/hugepages
에 마운트 한다.
- name: container-1
volumeMounts:
- mountPath: /dev/hugepages
name: dev-hp
- name: container-2
volumeMounts:
- mountPath: /dev/hugepages
name: dev-hp
이제 각 pod 의 container에서 각각 DPDK primary process와 secondary process를 실행시키면 두 개 DPDK process들은 hugepage를 이용하여 DPDK가 제공하는 ring 등을 사용하여 서로 통신할 수 있다.
root@hugepage-2c-2p-1:~/dpdk# ./dpdk-simple_mp -l 0-1 -n 1 --proc-type=primary
EAL: Detected CPU lcores: 4
EAL: Detected NUMA nodes: 1
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'VA'
EAL: No available 32768 kB hugepages reported
EAL: No available 64 kB hugepages reported
EAL: No available 1048576 kB hugepages reported
EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:03.0 (socket 0)
eth_virtio_pci_init(): Failed to init PCI device
EAL: Requested device 0000:00:03.0 cannot be used
TELEMETRY: No legacy callbacks, legacy socket not created
APP: Finished Process Init.
simple_mp > Starting core 1
root@hugepage-2c-2p-2:~/dpdk# ./dpdk-simple_mp -l 2-3 -n 1 --proc-type=secondary
EAL: Detected CPU lcores: 4
EAL: Detected NUMA nodes: 1
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket_20_6d504b91042f
EAL: Selected IOVA mode 'VA'
EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:03.0 (socket 0)
Device 0000:00:03.0 is not driven by the primary process
EAL: Requested device 0000:00:03.0 cannot be used
APP: Finished Process Init.
Starting core 3
core 1: Received 'hi'
simple_mp >
simple_mp > send hi
simple_mp >
이때 node의 /dev/hugepages
디렉토리를 확인하면 container에서 실행된 DPDK application들이 생성한 hugepage map 파일을 확인할 수 있다.
$ ls -al /dev/hugepages/
total 4096
drwxr-xr-x 2 root root 0 Mar 14 14:49 .
drwxr-xr-x 19 root root 3820 Mar 14 09:29 ..
-rw------- 1 root root 2097152 Mar 14 14:50 rtemap_0
-rw------- 1 root root 2097152 Mar 14 14:50 rtemap_1
DPDK process의 실행 인자 --file-prefix
를 이용하여 hugepage map 파일의 prefix를 변경해 보면 node의 /dev/hugepages
위치에 생성된 hugepage map 파일이 container가 생성한 것을 확인할 수 있다.
root@hugepage-2c-2p-1:~/dpdk# ./dpdk-simple_mp -l 0-1 -n 1 --proc-type=primary --file-prefix=simple_mp
EAL: Detected CPU lcores: 4
EAL: Detected NUMA nodes: 1
...
Starting core 1
simple_mp >
root@hugepage-2c-2p-2:~/dpdk# ./dpdk-simple_mp -l 2-3 -n 1 --proc-type=secondary --file-prefix=simple_mp
EAL: Detected CPU lcores: 4
EAL: Detected NUMA nodes: 1
EAL: Detected static linkage of DPDK
EAL: Multi-process socket /var/run/dpdk/simple_mp/mp_socket_45_6d552daffb0f
EAL: Selected IOVA mode 'VA'
EAL: Probe PCI driver: net_virtio (1af4:1000) device: 0000:00:03.0 (socket 0)
Device 0000:00:03.0 is not driven by the primary process
EAL: Requested device 0000:00:03.0 cannot be used
APP: Finished Process Init.
simple_mp >
$ ls -al /dev/hugepages/
total 8192
drwxr-xr-x 2 root root 0 Mar 14 14:51 .
drwxr-xr-x 19 root root 3820 Mar 14 09:29 ..
-rw------- 1 root root 2097152 Mar 14 14:50 rtemap_0
-rw------- 1 root root 2097152 Mar 14 14:50 rtemap_1
-rw------- 1 root root 2097152 Mar 14 14:52 simple_mpmap_0
-rw------- 1 root root 2097152 Mar 14 14:52 simple_mpmap_1
$ grep HugePages_ /proc/meminfo
HugePages_Total: 20
HugePages_Free: 16
HugePages_Rsvd: 0
HugePages_Surp: 0
단, pod가 모두 삭제되어도 위 hugepage map file이 삭제되지 않으므로, 사용된 hugepage는 해제되지 않는다(해제되는 조건은???)
$ sudo rm -rf /dev/hugepages/*
[sudo] password for cychong:
$ grep HugePages_ /proc/meminfo
HugePages_Total: 20
HugePages_Free: 20
HugePages_Rsvd: 0
HugePages_Surp: 0
Simplified view
Reference
https://github.com/cychong47/how-to-share-hugepage-in-k8s/tree/main/one-container-in-each-pod
#til #dpdk #hugepage