Running tcpdump inside an OpenShift pod to capture network traffic
Environment
- Red Hat OpenShift Container Platform (RHOCP)
- 4
- Azure Red Hat OpenShift (ARO)
- 4
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
-
For OpenShift 3 clusters, please refer to How to use tcpdump or other system-level commands inside OpenShift v3 pod?
-
For ROSA or OSD clusters, if cluster owner has missing permissions to follow this procedure, please refer to Running a tcpdump container as a sidecar on ROSA/OSD/ARO clusters.
-
For OpenShift 4 clusters, 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's also possible to configure a SSH bastion host in AWS: Deploying a Bastion along side your OpenShift 4.x cluster on AWS. -
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 community ksniff with OpenShift 4.
Using tcpdump with no SSH access to nodes
-
Open a debug shell on the
nodewhere the targetpodis running:$ oc debug node/<nodename>If you use 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 you can enter the pod namespace.In 4.8 and lower, 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"In 4.9 and higher, follow these steps instead:
# 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}" -
Before running the
tcpdumpcommand, you need to determine the name of the correct interface to use. You can list all the interfaces within thepodby runningip aortcpdump -Das shown below.# nsenter $nsenter_parameters -- chroot /host ip aOr
# nsenter $nsenter_parameters -- tcpdump -D -
Once you have 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 your 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 you are ready to end 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. You can also replacetcpdumpcommand with any other command you want 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 crio, 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