반응형

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를 설치하고 위 절차를 따라하는 꼼수가 있기는 하다.

 

 

+ Recent posts