반응형

 

가끔 kubernetes에서 istio를 사용하다보면, Pod 내부의 iptables 구성 상태가 어떠한지 궁금할 때가 있다.

매번 여기저기 명령 찾아서 짜집기하고 있었는데, 이렇게 하니까 찾는 시간도 오래 걸리고, 나의 기억도 오래가지 않아서 여기에 메모를 하고 필요할 때마다 아래 명령을 copy & paste 해야겠다.

 

(이 명령은 Istio README.md에도 있으니까, 좀더 깊게 볼려면 Istio README.md에서 찾아보길~)

 

##
## pod의 container id 확인하기
##

$ ns=ns-a

$ podnm=ratings-v1-587d5cfb9-mxhxc

$ container_id=$(kubectl get pod -n ${ns} ${podnm} -o jsonpath="{.status.containerStatuses[?(@.name=='istio-proxy')].containerID}" | sed -n 's/docker:\/\/\(.*\)/\1/p')

$ echo $container_id
6dbeeb047da9149f0735943cd95885a156dbdc766b48145c40e7346ea7f6bcfb


##
## 어떤 worker node에서 ratings-v1 pod가 구동되어 있는지 확인하기
##

$ kubectl get -n ns-a pod -l app=ratings -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP               NODE      NOMINATED NODE   READINESS GATES
ratings-v1-587d5cfb9-mxhxc   2/2     Running   0          2d17h   10.244.91.198    node-73   <none>           <none>
ratings-v1-587d5cfb9-s6g6r   2/2     Running   0          2d17h   10.244.142.131   node-75   <none>           <none>


##
## ratings-v1 pod가 구동된 worker node에 ssh 접속하기
##

$ ssh root@node-73

##
## NOTE: worker node에 접속했으면, 위에서 알아냈던 container_id를 아래와 같이 설정하고
##       아래 명령 순서대로 실행한다.
##

[root@node-73 ~]$ container_id=6dbeeb047da9149f0735943cd95885a156dbdc766b48145c40e7346ea7f6bcfb

[root@node-73 ~]$ cpid=$(docker inspect --format '{{ .State.Pid }}' $container_id)


##
## Worker Node의 nsenter 명령을 이용하여 Container 내부의 iptables 정보를 조회한다.
##
[root@node-73 ~]$ nsenter -t $cpid -n iptables -L -t nat -n -v --line-numbers -x

Chain PREROUTING (policy ACCEPT 118222 packets, 7093320 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1      118224  7093440 ISTIO_INBOUND  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain INPUT (policy ACCEPT 118224 packets, 7093440 bytes)
num      pkts      bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 10650 packets, 924376 bytes)
num      pkts      bytes target     prot opt in     out     source               destination
1         400    24000 ISTIO_OUTPUT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain POSTROUTING (policy ACCEPT 10650 packets, 924376 bytes)
num      pkts      bytes target     prot opt in     out     source               destination

Chain ISTIO_INBOUND (1 references)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15008
2           0        0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:22
3           0        0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15090
4      118222  7093320 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15021
5           0        0 RETURN     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:15020
6           2      120 ISTIO_IN_REDIRECT  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain ISTIO_IN_REDIRECT (3 references)
num      pkts      bytes target     prot opt in     out     source               destination
1           2      120 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15006

Chain ISTIO_OUTPUT (1 references)
num      pkts      bytes target     prot opt in     out     source               destination
1           3      180 RETURN     all  --  *      lo      127.0.0.6            0.0.0.0/0
2           0        0 ISTIO_IN_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1            owner UID match 1337
3           0        0 RETURN     all  --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner UID match 1337
4         397    23820 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner UID match 1337
5           0        0 ISTIO_IN_REDIRECT  all  --  *      lo      0.0.0.0/0           !127.0.0.1            owner GID match 1337
6           0        0 RETURN     all  --  *      lo      0.0.0.0/0            0.0.0.0/0            ! owner GID match 1337
7           0        0 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0            owner GID match 1337
8           0        0 RETURN     all  --  *      *       0.0.0.0/0            127.0.0.1
9           0        0 ISTIO_REDIRECT  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain ISTIO_REDIRECT (1 references)
num      pkts      bytes target     prot opt in     out     source               destination
1           0        0 REDIRECT   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            redir ports 15001

[root@node-73 ~]$

 

 

위 iptables 구성에 관한 이론 및 개념 설명은 아래 blog를 참고하길~

 

 

iptables and netfilter

iptables의 Chain(Rule) & Table 구조 iptables는 다수의 Chain(예: PREROUTING, INPUT, OUTPUT, POSTROUTING, FORWARD)과 그 Chain에 정의된 Rule, 그리고 각 Chain에는 다수의 Table(raw, mangle, nat, filter,..

andrewpage.tistory.com

 

'kubernetes' 카테고리의 다른 글

Kubernetes Metrics Server 설치  (0) 2021.11.26
[TODO] Read - Istio Memo  (0) 2021.11.23
Kubernetes imagePullSecret 설정  (0) 2021.11.19
kubectl 명령 예제 & JSON 포맷으로 출력하기  (0) 2021.11.17
Setup Kubernetes Using Ansible  (0) 2021.11.15
반응형

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