콤퓨우터/필기: KodeKloud CKA 강의

204. Network Namespaces

파란화면 2024. 5. 17. 00:45
반응형

Network Namespace 개념은 리눅스 컨테이너에서 네트워크 분리를 위해 사용되는 기술이다.

컨테이너는 Process Namespace로 격리되어 있어서, 컨테이너 위에서 돌아가는 프로세스만 볼 수 있다. 컨테이너 위에서 ps aux를 찍어 보면 CMD로 구동되는 프로세스의 PID가 1임을 볼 수 있다.
하지만 호스트에서 ps aux를 찍어 보면, 해당 프로세스의 PID가 전혀 다른 값으로 들어가 있는 것을 볼 수 있다.

즉 같은 프로세스가 컨테이너 내부와 외부에서 전혀 다른 PID를 가지고 있는 것이다.

네트워크 네임스페이스도 비슷하다. 호스트에는 Routing 및 ARP Table이 존재한다.
하지만 컨테이너 생성 시에는 네트워크 네임스페이스가 생성되며, 컨테이너 내부에서는 호스트의 네트워크 관련 정보를 전혀 볼 수 없다.
또한, 컨테이너는 네트워크 네임스페이스 내부에서 자신의 가상 인터페이스 (veth0), 라우팅 테이블, ARP 테이블을 가지고 있다.

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

ip netns add name으로 네트워크 네임스페이스를 수동으로 생성할 수 있다.
ip netns로 네트워크 네임스페이스를 볼 수 있다.

호스트에서는, ip link로 인터페이스 목록을 볼 수 있다. 네트워크 네임스페이스 내부의 인터페이스 목록은 어떻게 볼 수 있을까?

  • ip netns exec name ip link 를 실행하면 된다.
  • 혹은, ip -n name link를 할 수도 있겠다.

ARP Table이나 Routing Table 역시 비슷하게 볼 수 있다.

  • ip netns exec name arp
  • ip netns exec name route

두 네트워크 네임스페이스를 연결하기

가상 이더넷 쌍을 이용하여 두 네트워크 네임스페이스 redblue를 연결해 보자. ("Virtual Cable" 또는 "Pipe")

  • veth-red와 veth-blue 인터페이스를 생성한다.

    • ip link add veth-red type veth peer name veth-blue
  • 각각의 인터페이스를 네트워크 네임스페이스에 할당한다.

    • ip link set veth-red netns red
    • ip link set veth-blue netns blue
  • ip addr 명령어로 각 네임스페이스의 인터페이스에 IP를 할당한다.

    • ip -n red addr add 192.168.15.1 dev veth-red
    • ip -n blue addr add 192.168.15.2 dev veth-blue
  • ip link set up 명령어로 인터페이스를 올린다.

    • ip -n red link set veth-red up
    • ip -n blue link set veth-blue up
  • 이제 통신이 작동한다.

    • ip netns exec red ping 192.168.15.2
    • red 네트워크 네임스페이스의 ARP 테이블에는 veth-blue의 MAC주소와 IP가 기록된다.
      • ip netns exec red arp
    • blue 네트워크 네임스페이스의 ARP 테이블에는 veth-red의 MAC주소와 IP가 기록된다.
    • 호스트에서 arp를 실행해보면, 이 네트워크 네임스페이스 내부의 ARP 정보는 전혀 확인할 수 없다.

여러 네트워크 네임스페이스를 브리지로 연결하기

현실에서 여러 호스트를 이더넷으로 연결하려면 스위치를 사용한다.
마찬가지로 가상세계에서 여러 네트워크 네임스페이스를 가상 이더넷으로 연결하려면 가상 스위치를 사용하면 된다.

리눅스의 브리지(Bridge)를 이용하여 이를 구현할 수 있다.

  • 호스트에서 ip link add vnet0 type bridge를 하여 브리지를 생성한다.

    • 호스트의 입장에서는 이것은 하나의 인터페이스이다. ip link를 찍어 보면 목록에 lo, eth0과 함께 나온다.
      • 하지만 네트워크 네임스페이스에 있어서는 스위치처럼 기능한다.
    • 일단 ip link set dev vnet0 up으로 링크를 올려준다.
  • 기존 단계에서 사용했던 link들은 삭제해준다. (ip -n red link del veth-red)

  • 이제 veth-red와 veth-red-br 간의 peer를 만들어주고, veth-red 인터페이스를 네트워크 인터페이스에 할당한다.

    • ip link add veth-red type veth peer name veth-red-br
    • ip link set veth-red netns red
  • 이제 veth-red-br을 브리지에 연결시켜주어야 한다. 이를 위해,

    • ip link set veth-red-br master vnet0 처럼, master를 vnet0으로 지정한다.
  • 나머지 과정은 위와 동일하다.

    • ip addr 명령어로 각 네임스페이스의 인터페이스에 IP를 할당한다.
      • ip -n red addr add 192.168.15.1 dev veth-red
      • ip -n blue addr add 192.168.15.2 dev veth-blue
    • ip link set up 명령어로 인터페이스를 올린다.
      • ip -n red link set veth-red up
      • ip -n blue link set veth-blue up

호스트와 브리지 간 통신

이 브리지라는 것은 호스트 입장에서는 네트워크 인터페이스이다. 그렇기에 호스트에서 vnet0에 IP를 할당해주기만 하면 호스트에서 브리지 네트워크 간에 서로 통신이 가능하다.
ip addr add 192.168.15.254/24 dev vnet0

브리지에서 바깥 네트워크로 나가기

호스트의 eth0이 192.168.1.2/24라고 해 보자. pink 네임스페이스(192.168.15.1/24)에서 eth0과 연결된 LAN의 192.168.1.3에 접속하려면 어떻게 해야 할까?

pink 네임스페이스에서 192.168.1.0/24에 대한 라우팅 정보, 이를테면 게이트웨이를 알아야 한다.
ip netns exec blue ip route add 192.168.1.0/24 via 192.168.15.254를 해 주면, 이제 192.168.15.1에서 192.168.1.0/24로 패킷이 나갈 수 있다.

하지만, 패킷이 다시 돌아올 수는 없다. 외부 네트워크는 192.168.15.0/24를 모르기 때문이다.
따라서 NAT를 설정해주어야 한다.

iptables를 이용하여 NAT 기능을 추가할 수 있다.
iptables -t nat -A POSTROUTING -s 192.168.15.0/24 -j MASQUERADE

인터넷에 연결하기

지금 pink의 라우팅 테이블에는 목적지 192.168.15.0/24, 192.168.1.0/24에 대한 정보밖에 없기 때문에, ping 8.8.8.8을 하면 Network is unreachable이 나올 것이다.

ip netns exec pink ip route add default via 192.168.15.5로, 기본 라우트를 192.168.15.254로 잡아주면, 패킷이 외부로 나갈 수 있다.

외부 네트워크에서 브리지에 물린 네임스페이스로 inbound

192.168.15.0/24의 라우팅 정보를 외부 네트워크의 라우팅 테이블에 올리는 방법이 있긴 한데 이것은 별로 효율적인 방식은 아니다.
이것보다는 포트포워딩을 해 주는 것이 현실적이다.
iptables -t nat -A PREROUTING --dport 80 --to-destination 192.168.15.2:80 -j DNAT

반응형