이전 게시글에서는 Mount, pid, namespace, ipc, cgroup를 사용한 격리 방법에 대해 작성하였습니다.
이번에는 네트워크 네임스페이스를 통해 격리하고 컨테이너 간의 통신 방법에 대해 작성하겠습니다.
네트워크 네임스페이스란?
[BLOG]
네트워크 네임스페이스는 논리적인 네트워크 네임스페이스를 만들고 라우팅, 가상IP 등 네트워크 구성요소를 조합하여 논리적으로 네트워크를 격리시킵니다. 네트워크를 논리적으로 격리시킴으로써 호스트 네트워크에 직접적인 영향을 최소화합니다.
RED <> BLUE 네트워크 네임스페이스 간 통신
Step 1) veth (가상 이더넷) 생성
# veth 생성
$ ip link add veth0 type veth peer name veth1
# 생성한 veth를 확인합니다
$ ip -c link
$ ip -c addr
현재는 생성만 진행했으므로 DOWN 상태가 맞습니다.
Step 2) 네트워크 네임스페이스 생성하고 생성한 veth를 각각의 네임스페이스로 이동합니다.
$ ip netns add RED
$ ip netns add BLUE
# 생성된 네임스페이스 확인
$ ip netns list
$ ip link set veth0 netns RED
$ ip link set veth1 netns BLUE
명령어를 수행하기 전에는 아래와 같이 ip -c a 에서 veth0,1 을 확인할 수 있었지만 네트워크 네임스페이스로 옮긴 후에는 로컬 네임스페이스에서는 조회되지 않습니다.
각 네트워크 네임스페이스에서 질의를 통해 위에서 생성한 veth 인터페이스를 확인할 수 있습니다.
Step 3) 각 네트워크의 상태를 활성화하고 IP를 부여합니다.
$ ip netns exec RED ip link set veth0 up
$ ip netns exec BLUE ip link set veth1 up
# 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
# ip 할당 확인
$ ip netns exec RED ip -c a
$ ip netns exec BLUE ip -c a
Step 4) 각 네트워크 네임스페이스로 진입 후 통신 테스트
[터미널 1번]
$ nsenter --net=/var/run/netns/RED
$ ip -c a
[터미널 2번]
$ nsenter --net=/var/run/netns/BLUE
$ ip -c a
[터미널 1,2번 iptables 정책 조회]
RED > BLUE icmp 테스트
RED < Bridge > BLUE 간 통신
Step 1) 네트워크 네임스페이스 생성 및 veth 생성
# 네트워크 네임스페이스 생성
$ ip netns add RED
$ ip netns add BLUE
# veth 생성
$ ip link add reth0 type veth peer name reth1
$ ip link add beth0 type veth peer name beth1
# veth 이동
$ ip link set reth0 netns RED
$ ip link set beth0 netns BLUE
# 확인
$ ip netns list
$ ip netns exec RED ip -c a
$ ip netns exec BLUE ip -c a
Step 2) 브릿지 확인 및 브릿지 생성
# 브릿지 확인
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242948d9a64 no
# 브릿지 생성
$ ip link add br0 type bridge
생성한 브릿지 확인
Step 3) reth0, beth0 에 ip 할당 및 생성된 인터페이스 모두 활성화
# reth1, beth1에 br0 연결
$ ip link set reth1 master br0
$ ip link set beth1 master br0
# 각 인터페이스에 ip 할당
$ 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
ip link set br0 up
Step 4) 네트워크 네임스페이스 진입
$ nsenter --net=/var/run/netns/RED
$ nsenter --net=/var/run/netns/BLUE
[1번 : RED, 2번: Bridge, 3번: BLUE]
Step 5) 통신 테스트
RED에서 BLUE를 dst로 icmp 패킷을 보냅니다.
tcp dump를 확인해보면 br0 까지는 요청이 도착하지만 beth0까지 도착하지 않습니다.
추가로 iptables를 통해 확인해보면 forward 정책에 의해 패킷이 드랍되고 있는 것을 확인할 수 있습니다.
차단 룰셋을 확인하기 위해 br0의 iptables 정책을 확인합니다.
$ iptables -t filter -S
$ iptables -t nat -S
reth0에서 beth0으로 통신이 되기 위해서는 아래 그림과 같이 [reth0 > prerouting > forward > postrouting > beth0] 의 통신 flow를 통하게 되는데 위에서 확인한 것과 같이 br0(bridge)의 forward 정책이 DROP으로 설정되어 있어, br0를 통과하지 못하였습니다.
Step 6) br0 iptables 정책 수정
Forward 가 ACCEPT 될 수 있도록 정책을 수정해보겠습니다.
Docker 관련한 모든 트래픽을 0.0.0.0 to 0.0.0.0으로 허용하는 정책 또는 Forward 정책을 Drop > Accept로 변경하여,
정책을 변경합니다.
# Docker 관련 통신을 모두 허용하는 정책
$ iptables -t filter -I DOCKER-USER -j ACCEPT
# FORWAD 정책을 DROP > ACCEPT로 변경
$ iptables -t filter -P FORWARD ACCEPT
정책 변경 후 통신 테스트를 시도하여 정상적으로 통신되는 것을 확인합니다.
'Linux' 카테고리의 다른 글
[KANS] 컨테이너 격리 (3) | 2024.08.30 |
---|---|
[Linux] Symbolic link 안전하게 제거하기 (0) | 2024.07.18 |
[Linux] nginx로 blue green 배포 흉내내기 (0) | 2024.07.11 |