Running tcpdump inside an OpenShift pod to capture network traffic
Environment
- Red Hat OpenShift Container Platform (RHOCP)
- 4
tcpdump
Issue
- Need to do packet capture using
tcpdumpfrom inside an OpenShiftpod. - Is it possible to use commands in a container via
nsenterto capture information with tools that are not built into thepod?
Resolution
When it is needed to run tcpdump in a different way, or if the following method does not work, please check the following solutions:
-
If it is needed to run
tcpdumpfrom a node and not from a pod, refer to runningtcpdumpfrom a RHEL CoreOS OpenShift node -
If the following procedure does not run successfully and still the
SSHaccess to thenodesis available, please consider the solution running tcpdump inside a OpenShift 4 pod with SSH access to the nodes. It is also possible to configure a SSH bastion host in AWS: deploying a bastion along side OpenShift 4 cluster on AWS. -
For ROSA, OSD and ARO clusters, if cluster owner has missing permissions to follow this procedure, please refer to running a
tcpdumpcontainer as a sidecar on ROSA/OSD/ARO clusters. -
An automated tool called
ksniffis also available (although not directly supported by Red Hat). Steps on how to use it are documented here: packet capture inside Pod using communityksniffwith OpenShift 4.
Using tcpdump within a pod with no SSH access to nodes
-
Open a debug shell on the
nodewhere the targetpodis running:$ oc debug node/<nodename>If using a custom debug image, make sure that
tcpdumpandnsenterare available in it.Note1: It is NOT required to run
chroot /hostandtoolboxin currently supported OpenShift versions. Theoc debug node/<nodename>hastcpdumpalready.Note2: Take note of the
namespacecreated for the debugpod, it will be used in the coming steps. -
Build the required
nsenterparameters so that can enter the pod namespace:In currently supported OpenShift versions (4.9 and higher), follow these steps:
# NAME=<pod-name> # NAMESPACE=<pod-namespace> # pod_id=$(chroot /host crictl pods --namespace ${NAMESPACE} --name ${NAME} -q) # ns_path="/host$(chroot /host bash -c "crictl inspectp $pod_id | jq '.info.runtimeSpec.linux.namespaces[]|select(.type==\"network\").path' -r")" # nsenter_parameters="--net=${ns_path}"In 4.8 and lower (currently not supported), follow these steps:
# NAME=<pod-name> # NAMESPACE=<pod-namespace> # pod_id=$(chroot /host crictl pods --namespace ${NAMESPACE} --name ${NAME} -q) # pid=$(chroot /host bash -c "runc state $pod_id | jq .pid") # nsenter_parameters="-n -t $pid" -
Before running the
tcpdumpcommand, it is needed to determine the name of the correct interface to use. It is possible to list all the interfaces within thepodby runningip aortcpdump -Das shown below:# nsenter $nsenter_parameters -- chroot /host ip aOr
# nsenter $nsenter_parameters -- tcpdump -D -
Once having the interface name, start the
tcpdumpin the container's networknamespaceusing command below. Make sure to replace${INTERFACE}with the relevant interface name found in the earlier step (or set the variable to the correct value in the shell).# nsenter $nsenter_parameters -- tcpdump -nn -i ${INTERFACE} -w /host/var/tmp/${HOSTNAME}_$(date +\%d_%m_%Y-%H_%M_%S-%Z).pcap ${TCPDUMP_EXTRA_PARAMS}Press
ctrl+cwhen ready to end the capture and list the generated file(s):# ls /host/var/tmp/*.pcapNote: See this page for more details on using the
tcpdumpcommand: capturing network packets with tcpdump. It is also possible to replacetcpdumpcommand with any other command needed to run from thepod'snetworknamespace. -
Before exiting the debug pod, open a new terminal and copy the
.pcapfile generated :$ oc project <debugPodNamespace> $ oc get pods NAME READY STATUS RESTARTS AGE ip-10-z-yyy-xxxus-west-2computeinternal-debug 1/1 Running 0 97s $ oc cp ip-10-z-yyy-xxxus-west-2computeinternal-debug:/host/var/tmp/<filename>.pcap <filename>.pcap -
Once the
.pcapfile is copied, it can be removed from thenodeby running this from the debugpod:# rm /host/var/tmp/<filename>.pcap
Root Cause
Most container engines, including CRI-O, use kernel network namespaces to implement networking isolation layer in the containers. Therefore, the way to run command in the networking context of a container is to enter its networking namespace by means of nsenter. This solution describes how to do it, focusing on tcpdump example.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Comments