Kubernetes cluster 운영 환경에서 Pod간 주고 받은 IP packet을 tcpdump하는 방법을 알아보겠다.
방식 A: Container 내부에 tcpdump 프로그램을 설치하고, Container 내부에서 직접 tcpdump 명령을 수행
$ kubectl exec -n my-namespace my-pod -c my-container -it -- bash
(In-Container) $ apt install -y tcpdump
... 중간 생략 ...
##
## 참고: Kubernetes Pod 내부의 기본 NIC은 eth0이다.
## 만약, Multus CNI를 사용해서 Multi-NIC을 사용하는 경우라면,
## eth0 이외에 net1, net2 같은 이름으로 NIC이 있을 것이다.
## 따라서, 내가 운영하는 CNI가 1개인지 또는 어떤 종류의 CNI이 인지에 따라
## NIC의 이름이 다를 수 있으니까, ifconfig 명령 또는 `ip a` 같은 명령으로
## NIC 이름을 확인하고 tcpdump 명령을 수행해야 한다.
##
(In-Container) $ tcpdump -i eth0 -w my-capture.pcap
... 중간 생략 ...
위와 같이 생성한 pcap 파일은 Pod 외부에서 볼 수 없기 때문에
1) Pod 내부에서 scp 명령으로 외부로 옮겨주던지
2) 또는 NFS, Ceph storage 같은 PV를 이용하여 저장하는 것을 권장한다.
방식 B: Worker node에서 특정 Pod의 namespace를 이용하여 tcpdump 명령을 수행
예제를 이용하여 설명해보겠다.
'productpage' Pod가 주고 받은 IP packet을 tcpdump하려는 상황을 가정해보자.
우선 'productpage' Pod가 어느 worker node에 있는지 확인한다.
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
... 중간 생략 ...
productpage-v1-6b746f74dc-xfjdz 2/2 Running 0 2d17h 10.244.2.4 worker-1
... 중간 생략 ...
'productpage' pod가 worker-1 node에 있으니까, worker-1에 ssh 접속하여 아래의 스크립트를 수행한다.
##
## Filename : run-tcpdump.sh
##
#!/usr/bin/bash
container_id=$(docker container ls | grep k8s_istio-proxy_productpage | awk '{ print $1 }')
echo "Container ID: $container_id"
container_pid=$(docker inspect -f '{{.State.Pid}}' $container_id)
echo "Container PID: $container_pid"
nsenter -t $container_pid -n /bin/bash -xec 'tcpdump -i any -w productpage-envoy-any.pcap'
## NOTE: After running this script to capture the packet,
## Use the packet filter as 'tls or http' with your Wireshark program !
위 `run-tcpdump.sh` 스크립트를 수행하고 나서 만들어진 pcap 파일을 Wireshark으로 열어본다.
그런데, 위 "방식 A, 방식 B"는 Kubernetes를 사용했을 때나 가능한 얘기이고,
OCP(Openshift Container Platform)을 사용하는 경우라면 위 방식으로 container 내부의 network packet을 dump할 수 없다 !!!
왜? OCP, OKD Cluster의 Worker Node에는 'docker' command가 없다.
그러면 어떻게 하는가?
아래와 같이 "방식 C"를 따라해야 한다.
방식 C: OCP의 Node에서 특정 Pod의 namespace를 이용하여 tcpdump 명령을 수행
예제를 이용하여 설명해보겠다.
(worker2 node에 Pod가 구동되어 있다고 가정하고 설명한다)
##
## Working Location: Bastion Node, or PC (MacBook)
##
$ oc debug node/worker1.andrew.space
Starting pod/worker1.andrew.space-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.10.11.12
If you don't see a command prompt, try pressing enter.
sh-4.4# chroot /host
sh-4.4# container_id=$(crictl ps | grep my-example-app | awk '{ print $1 }')
sh-4.4# echo $container_id
378f096238fdd
sh-4.4# container_pid=$(crictl inspect $container_id | jq '.info.pid')
sh-4.4# echo $container_pid
3458673
sh-4.4# nsenter -t $container_pid -n /bin/bash -xec 'tcpdump -i eth0'
... TCPDUMP 출력 결과 생략 ...
만약, OCP 또는 OKD Cluster를 구축할 때, OS를 CoreOS를 사용한 경우라면
위와 같이 `nsenter -t .... 'tcpdump -i eth0'` 명령을 사용할 수 없다.
왜냐고?
CoreOS는 TCPDUMP 명령을 가지고 있지 않기 때문이다. ㅠㅠ
단, 임시로 CoreOS에 tcpdump command를 설치하고 위 절차를 따라하는 꼼수가 있기는 하다.