How to run DPDK in k8s - One container in each pod

Page content

서로 다른 pod의 container에서 실행되는 DPDK process들도 다른 경우와 마찬가지로 DPDK runtime config 파일과 hugepage map 파일만 공유하면 hugepage를 공유할 수 있다.

2022-03-14-dpdk-hugepage-1c-2p-1.png

이 때 서로 다른 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

2022-03-14-dpdk-hugepage-1c-2p-2.png

Reference

https://github.com/cychong47/how-to-share-hugepage-in-k8s/tree/main/one-container-in-each-pod

#til #dpdk #hugepage