How to enter network namespaces of other containers from a pod in K8s?
Mon 30 December 2019 | Last updated on Tue 06 December 2022You might be in a situation where you need to troubleshoot the networking stack on a container where you don't have the tools necessary. Or you might need to figure out which veth belongs to a container. For both these scenarios you will need to be able to get into the network namespace of another container. This blog post describes how to get into the network namespace of another container by running a privileged container on the same K8s node.
At a high-level the following steps are needed:
- Deploy a privileged container
- Find out the PID of the target container
- Use
nsenter
to enter namespace of target container and relate veth
1. Deploy a privileged container
First, we'll need to deploy a container that uses host networking and has privileges to enter namespaces. Note that this container has full access to node host networking stack and all other containers, potential security concern.
The image that we'll be using is samos123/docker-toolbox
, which can be found
on GitHub:samos123/docker-toolbox.
Create the file debug-pod.yaml
with the following contents:
apiVersion: v1
kind: Pod
metadata:
name: debug-pod
labels:
app: debug
spec:
hostNetwork: true
hostPID: true
containers:
- name: debug-pod
image: samos123/docker-toolbox:latest
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
volumeMounts:
- name: dockersock
mountPath: "/var/run/docker.sock"
securityContext:
privileged: true
capabilities:
add: ["NET_ADMIN"]
volumes:
- name: dockersock
hostPath:
path: /var/run/docker.sock
Create the pod by running:
kubectl apply -f debug-pod.yaml
Verify you can access docker of the host:
docker ps
2. Find the PID of the target container
The target container is the container of which you want to find the namespace
and corresponding interface. You can use docker ps --filter name=nginx
to
list all containers that have the nginx in their name.
Now use the container ID to get the PID of the container:
pid=$(docker inspect --format '{{.State.Pid}}' $containerID)
3. Enter the container network namespace
nsenter
can be used to enter the namespace using the PID:
nsenter -t $pid -n ip a
You will notice that there is an eth0@ifX
interface inside the container
network namespace. The X
tells you the interface index on the host network.
This index can then be used to figure out which veth belongs to the container.
Run the following commands to find the veth interface:
ifindex=$(nsenter -t $pid -n ip link | sed -n -e 's/.*eth0@if\([0-9]*\):.*/\1/p')
veth=$(ip -o link | grep ^$ifindex | sed -n -e 's/.*\(veth[[:alnum:]]*@if[[:digit:]]*\).*/\1/p')
echo $veth
I've created a script in the following repo: samos123/docker-veth