본문 바로가기
스터디 이야기/Kubernetes Advanced Networking Study

[KANS] 컨테이너 네트워크

by lakescript 2024. 9. 13.
더보기

이 스터디는 CloudNet@에서 진행하는 KANS 스터디를 참여하면서 공부하는 내용을 기록하는 블로그 포스팅입니다.

CloudNet@에서 제공해주는 자료들을 바탕으로 작성되었습니다.

컨테이너 네트워크

컨테이너는 네트워크 네임스페이스로 Host와 컨테이너간의 네트워크 격리 환경이 구성됩니다. 이때, 리눅스에서 방화벽 기능을 하는 iptable이 Host와 Container간의 통신에 관여합니다.

 

RED <-> BLUE 네트워크 네임스페이스간 통신

네트워크 네임스페이스 생성 시 Host와 구별됩니다.

 

실습

관리자 권한으로 전환

sudo su -

 

veth (가상 이더넷 디바이스) 생성

ip link add veth0 type veth peer name veth1

ip link 명령어를 통해 리눅스에서 가상 이더넷 페어(Virtual Ethernet Pair)를 생성합니다. veth0을 추가하며 veth1과 peer로 연결되는 인터페이스를 옵션으로 설정합니다.

veth 에서 v는 virtual 을 뜻 합니다. 즉 virtual ethernet 라는 의미입니다.

 

 

veth pair 정보 확인

ip -c link

ip 명령어를 통해 network interface가 생성된 것을 확인해보겠습니다.

veth1@veth0, veth0@veth1로 잘 생성된 것을 확인할 수 있는데, 이때 이름은 @를 사이에 두고 서로 peer라는 것을 의미합니다. 아직은 격리를 하지 않았기 때문에 host에서 확인이 가능합니다.

 

네트워크 네임스페이스 생성

ip netns add RED
ip netns add BLUE

 

네트워크 네임스페이스 확인

ip netns list

위의 명령어를 통해 netowkr namespace 목록을 확인해보겠습니다.

위에서 생성했던 BLUE와 RED가 보여지는 것을 확인하실 수 있습니다.

 

RED netns에 veth0 할당

ip link set veth0 netns RED

위에서 생성했던 network interface인 veth0을 RED Nerwork Namespace에 할당하겠습니다.

 

ip netns list

 

RED Network Namespace에 id가 할당되어있습니다.

 

ip -c link

pair 정보를 확인해보겠습니다.

이제 격리를 했기 때문에 호스트에서 목록에서 보이지 않고, veth1의 peer 정보가 변경된 것을 확인하실 수 있습니다.

ip netns exec RED ip -c a

격리한 RED Network Namespace에 접속하여 ip 정보를 확인해보겠습니다.

위에서 할당한 veth0의 인터페이스가 확인됩니다.

 

BLUE netns에 veth1 할당

ip link set veth1 netns BLUE

마찬가지로 BLUE Network Namespace에 veth1을 할당하겠습니다.

 

ip -c link

마찬가지로 호스트의 ip 목록을 확인해보면 veth1의 정보가 없는 것을 확인하실 수 있습니다.

 

ip netns exec BLUE ip -c a

격리한 BLUE Network Namespace에 접속하여 ip 정보를 확인해보면 할당되었던 veth1을 확인하실 수 있습니다.

 

veth0, veth1 상태 활성화

ip netns exec RED ip link set veth0 up
ip netns exec BLUE ip link set veth1 up

격리했던 Network Namespace에 할당한 veth0과 veth1을 활성화 시키도록 하겠습니다.

ip netns exec RED ip -c a

ip netns exec BLUE ip -c a

 

각각 state가 UP으로 활성화된 것을 확인하실 수 있습니다.

 

veth0, veth1 에 IP 설정

ip netns exec RED ip addr add 11.11.11.2/24 dev veth0
ip netns exec BLUE ip addr add 11.11.11.3/24 dev veth1

이제 통신을 확인해보기 위해 RED Network Namespace의 veth0에는 11.11.11.2/24, BLUE Network Namespace의 veth1에는 11.11.11.3/24를 할당해보겠습니다.

 

ip netns exec RED ip -c a

 

ip netns exec BLUE ip -c a

 

각각 정보를 확인해보면 IP가 할당된 것을 확인하실 수 있습니다.

 

현재 상태

현재 상태를 도식화하면 위의 이미지와 같습니다.

Host와 격리된 network namespace인 RED와 BLUD에 각각 veth0과 veth1를 할당하고, 각각 IP를 부여하여 통신할 준비를 마쳤습니다. 이제 각각 namespace에 접근해서 서로에게 통신하는 것을 확인해보겠습니다.

 

[터미널2] RED Network Namespace 접근

nsenter --net=/var/run/netns/RED

 

RED Nerwork Namespace에 접근하여 해당 네임스페이스 내에서 네트워크 관련 명령어를 실행할 수 있게 합니다.

[터미널3] BLUE Network Namespace 접근

nsenter --net=/var/run/netns/BLUE

 

BLUE Nerwork Namespace에 접근하여 해당 네임스페이스 내에서 네트워크 관련 명령어를 실행할 수 있게 합니다.

 

 

 

[터미널1] Host의 Routing Table 확인

ip -c route

network namespace를 격리했기 때문에 host의 routing table은 RED, BLUE에서 조회했을 때와 다르게 보여집니다.

 

[터미널2] RED Network Namespace Routing Table 확인

ip -c route

RED Network Namespace의 route 정보를 확인해보겠습니다. (격리했기 때문에 자신의 routing table만 나오게 됩니다.)

 

[터미널3] BLUE Network Namespace Routing Table 확인

ip -c route

BLUE Network Namespace의 route 정보를 확인해보겠습니다. (격리했기 때문에 자신의 routing table만 나오게 됩니다.)

 

[터미널1] host에서 network namespace 나열

lsns -t net

lsns 명령어를 통해 type을 net로 설정하여 network namespace만 나열합니다.

 

[터미널3] ping 통신 확인을 위해 tcpdump 실행

tcpdump -i veth1

tcpdump를 사용하여 veth1 인터페이스에서 네트워크 패킷을 캡처하고 확인해보겠습니다.

현재는 어떠한 통신도 없었기 때문에 비어있습니다.

 

[터미널2] Ping 통신

ping 11.11.11.3 -c 1

 

BLUE Network Namespace의 veth1 IP인 11.11.11.3으로 icmp 통신을 보내보도록 하겠습니다.

 

[터미널3] ping 통신 확인 

 

[터미널3] ping 통신 확인  - 해석

 

RED ← Bridge(br0) → BLUE 간 통신

 

만약 pod나 container가 n개가 있다고 하면 peer pair는 n*n개로 매우 복잡해집니다. 그렇기에 중간에 hub의 역할을 하는 bridge를 두어 한곳으로 받아서 전달하는 것이 효율성이 좋습니다. 

실습

네트워크 네임스페이스 및 veth 생성

ip netns add RED
ip link add reth0 type veth peer name reth1
ip link set reth0 netns RED
ip netns add BLUE
ip link add beth0 type veth peer name beth1
ip link set beth0 netns BLUE

reth는 red ethernet이고, beth는 blue ethernet의 약자입니다.

 

네트워크 네임스페이스 및 veth  확인

ip netns list

ip -c link

ip netns exec RED ip -c a

ip netns exec BLUE ip -c a

 

bridge 정보 확인

brctl show

위의 명령어를 통해 bridge 정보를 확인해보겠습니다.

아직 bridge를 생성하지 않아 아무것도 보이지 않습ㄴ디ㅏ.

 

br0 브리지 생성

ip link add br0 type bridge

br0라는 이름으로 bridge type인 network interface를 생성합니다.

 

bridge 정보 확인

brctl show

bridge를 생성했으니 정보를 확인해보겠습니다.

 

reth1 beth1 을 br0 연결

ip link set reth1 master br0
ip link set beth1 master br0

위에서 설정해놓은 reth1과 beth1을 br0로 변경합니다.

 

bridge 정보 확인

brctl show br0

다시 한번 br0의 정보를 확인해보겠습니다.

interfaces에 beth1과 reth1이 설정된 것을 확인하실 수 있습니다.

 

네트워크 인터페이스의 상태 확인

ip -br -c link

네트워크 인터페이스의 상태를 간결하게 출력해보겠습니다.

br0라는 interface가 생성된 것을 확인하실 수 있습니다.

 

reth0 beth0 에 IP 설정 및 활성화, br0 활성화

ip netns exec RED  ip addr add 11.11.11.2/24 dev reth0
ip netns exec BLUE ip addr add 11.11.11.3/24 dev beth0
ip netns exec RED  ip link set reth0 up; ip link set reth1 up
ip netns exec BLUE ip link set beth0 up; ip link set beth1 up

이제 RED와 BLUE의 network interface인 reth0과 beth0에 ip를 설정하고, 활성화 시켜줍니다.

 

ip link set br0 up

이어서 bridge인 br0도 활성화 시켜줍니다.

 

네트워크 인터페이스의 상태 확인

ip -br -c addr

다시한번 network interface의 상태와 ip를 확인해보겠습니다.

모두 상태가 up으로 활성화된 것을 확인하실 수 있고, IP가 설정된 것을 확인하실 수 있습니다.

[터미널2] RED Network Namespace

nsenter --net=/var/run/netns/RED

새로운 터미널을 열어서 RED Network namespace에 접근합니다.

 

[터미널3] BLUE Network Namespace

nsenter --net=/var/run/netns/RED

새로운 터미널을 열어서 BLUE Network namespace에 접근합니다.

 

 

[터미널1] host의 ping 통신 전 사전 설정

iptables -t filter -S | grep '\-P'

위의 명령어를 사용하여 iptables 정보 확인해보겠습니다.

FORWARD가 DROP인 것을 확인하실 수 있습니다.

여기서 FORWARD 체인은 시스템을 경유하여 다른 네트워크로 전달되는 패킷을 처리합니다. DROP으로 되어 있는 이유는 기본적으로 시스템이 라우터 역할을 하지 않도록 하여 불필요한 트래픽을 차단하기 위한 것입니다. 만약 시스템이 다른 네트워크로 트래픽을 전달하는 라우터나 게이트웨이 역할을 해야 한다면 설정해놔야 합니다. (여기서는 docker를 설치했기 때문에 DROP으로 설정되어있습니다.)

cat /proc/sys/net/ipv4/ip_forward

추가로 ip_forward가 되는지 확인하기 위해 위의 명령어를 실행합니다.  이때,  0은 off(불가능), 1은 on(가능)을 의미합니다.

 

tcpdump -l -i br0

통신 패킷을 확인하기 위해 br0에 tcpdump를 설정합니다.

 

[터미널3] BLUE Network Namespace ping 통신 전 사전 설정

tcpdump -l -i beth0

beth0의 네트워크 패킷을 살펴보기 위해 tcpdump를 설정합니다.

 

[터미널2] RED Network Namespace Ping Test

ping -c 1 11.11.11.3

RED Network Namespace에서 BLUE Network Namespace의 IP인 11.11.11.3으로 icmp 통신을 보내보도록 하겠습니다.

 

[터미널1] host의 tcpdump 확인

11.11.11.2에서 11.11.11.3으로 요청을 보내는 패킷만 보여지는 것이 확인됩니다.

 

[터미널3] BLUE Network Namespace의 tcpdump 확인

beth0에서는 어떠한 패킷도 확인되지 않습니다.

 

즉, host nerwork namespace의 bridge namespace의 iptable에 forward할 때 DROP이 되게 됩니다. (위에서 FORWARD가 DROP인 것을 확인했습니다.)

 

[터미널1] host network namespace에서 iptables 설정 추가 

iptables -t filter -I DOCKER-USER -j ACCEPT

docker로 인해 FORWARD가 DROP이 된것이라, iptables의 filter table에 DOCKER-USER라는 체인에 권한을 추가합니다.

 

iptables -t filter -S

iptables의 정보를 확인해보면 아래처럼 DOCKER-USER의 권한이 추가된 것을 확인하실 수 있습니다.

 

[터미널2] RED Network Namespace Ping Test

ping -c 1 11.11.11.3

다시 RED Network Namespace에서 BLUE Network Namespace의 IP인 11.11.11.3으로 icmp 통신을 보내보도록 하겠습니다.

 

[터미널1] host의 tcpdump 확인

request외에 reply(응답)이 전송된것을 확인하실 수 있습니다. 

 

 

'스터디 이야기 > Kubernetes Advanced Networking Study' 카테고리의 다른 글

[KANS] Service - ClusterIP, NodePort  (1) 2024.09.28
[KANS] Calico CNI  (1) 2024.09.19
[KANS] Kubernetes Flannel CNI  (1) 2024.09.08
[KANS] Pod - pause container  (4) 2024.09.05