2024. 6. 19. 13:18ㆍBACKEND/Docker & Kubernetes
안녕하세요.
이번 포스팅에서는 컨테이너 네트워킹에 대해 다뤄보겠습니다.
컨테이너는 물리 기기나 개념을 가상화하여 분리된 네트워킹 시스템을 만들어왔습니다.
물리적인 개념과 가상화된 내용을 비교하면서 Container Networking을 알아보도록 하겠습니다.
네트워크 스위칭과 라우팅, DNS, 네트워크 네임스페이스, 그리고 CNI까지 자세히 살펴보겠습니다.
Switch
네트워크 스위치는 동일한 네트워크 내에서 여러 장치를 연결하고,
각 장치 간의 데이터 전송을 효율적으로 관리하는 장치입니다.
스위치는 각 장치의 MAC 주소를 기반으로 데이터를 적절한 포트로 전달하여 네트워크 효율성을 높입니다.
네트워크 브리지는 여러 컴퓨터나 장치를 서로 연결해주는 장치로,
같은 네트워크 안의 여러 장치를 연결하여 데이터가 원활하게 오갈 수 있도록 돕는 장치입니다.
Pysical World
동일한 네트워크 상에 컴퓨터 A와 B가 있다고 가정해보겠습니다.
가령, 노트북과 데스크톱, 클라우드, VM 등이 될 수 있죠.
A와 B를 연결하려면 어떻게 해야 할까요?
두 시스템을 포함하는 네트워크를 생성하는 Switch로 두 시스템을 연결하면 됩니다.
Switch 에 각각 연결된 케이블이 필요하죠.
Container World
컨테이너도 동일합니다.
단, 두 개의 컨테이너의 네트워크를 연결하기 위해서 서로를 연결해줄 가상의 케이블 같은 게 필요합니다.
이 둘을 연결하려면 각 호스트에 네트워크 인터페이스가 필요합니다.
네트워크가 192.168.1.0
내 eth0
인터페이스를 스위치에 연결하는 데 사용한다고 해볼게요.
192.168.1.10
와 192.168.1.11
를 각 컴퓨터의 eth0에 할당합니다.
ip addr add 192.168.1.10/24 dev eth0
ip addr add 192.168.1.11/24 dev eth0
이렇게 eth0 에 특정 IP 주소로 주소를 할당시켜서 서로 통신할 수 있습니다.
여기서 스위치는 동일한 네트워크 내에서만 통신을 가능하게 합니다.
이번에는 서로 다른 네트워크 간의 통신을 고려해보도록 하겠습니다.
Router
다른 네트워크 192.168.2.0
에 시스템 C와 D가 있다고 가정해보겠습니다.
- System C: 192.168.2.10
- System D: 192.168.2.11
현재 라우팅 설정을 확인하려면 route
명령어를 사용할 수 있습니다.
이 명령어는 커널의 라우팅 테이블을 출력합니다.
$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
만약 라우팅 설정이 없다면, 시스템 B는 시스템 C에 접근할 수 없습니다.
이 경우, 시스템 B는 동일한 네트워크인 192.168.1.0
에만 접근할 수 있습니다.
서로 다른 네트워크에 설치된 두 컴퓨터는 어떻게 연결할 수 있을까요?
Pysical World
두 네트워크를 연결하려면 Router가 필요합니다.
라우터는 서로 다른 네트워크를 연결하는 역할을 합니다.
전체 네트워크를 집으로 비유 하자면,
네트워크가 하나의 방이고 Switch는 그 방의 문입니다.
Router는 집과 밖을 연결하는 집의 문과 같습니다.
방에 있는 사람은 방문 (Switch)을 통해 거실로 나와 집문(Router)을 통해 집 밖으로 나가는 거죠.
Container World
컨테이너에서도 동일합니다.
각 서버에 Gateway를 추가합니다.
외부 네트워크인 192.168.2.0
에 접근하고 싶다면, 라우터에 아래와 같이 설정을 추가할 수 있습니다.
$ ip route add 192.168.2.0/24 via 192.168.1.1
시스템 B에서 라우팅 설정을 다시 확인해보겠습니다.
# System B's routing configuration
$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.2.0 192.168.1.1 255.255.255.0 UG 0 0 0 eth0
192.168.1.0 네트워크에서 Router로 가는 IP인 192.168.1.1 이 게이트웨이로 설정되었습니다.
이제 시스템 B에서 시스템 C로의 통신이 가능합니다.
하지만, 시스템 B에서 시스템 C로의 요청은 가능하지만, 시스템 C에서 시스템 B로의 응답을 받을 수는 없습니다.
이를 위해 시스템 C에서도 시스템 B로 접근하기 위한 설정이 필요합니다.
$ ip route add 192.168.1.0/24 via 192.168.2.1
시스템 C의 라우팅 설정을 확인해보겠습니다.
# System C's routing configuration
$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.1.0 192.168.2.1 255.255.255.0 UG 0 0 0 eth0
🔗 Internet
위 네트워크를 인터넷에 연결하려면 어떻게 해야할까요?
동일한 방법으로 Router에 Internet과 연결하도록 설정합니다.
인터넷에 연결할 새로운 라우팅 테이블을 추가하면 됩니다.
$ ip route add 172.217.194.0/24 via 192.168.2.1
이제, 시스템 A와 시스템 B는 인터넷과 연결되는 상태가 되었습니다.
Default Gateway
이렇게 설정할 때, 문제가 발생합니다.
모든 시스템에서 이를 설정해야 한다는 것입니다.
실제 인터넷에는 무수히 많은 네트워크가 존재하기 때문에
각 네트워크를 위해 모든 IP 주소를 라우팅 테이블에 추가하고, 각 라우팅 설정마다 한 IP를 각각 설정하는 대신,
단일 테이블 엔트리와 IP 주소들이 정의된 기본 게이트웨이를 생성하면 됩니다.
$ ip route add default via 192.168.2.1
모든 요청은 기본 라우터로 전달되어 외부의 어떤 네트워크로도 갈 수 있습니다.
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.2.1 0.0.0.0 UG 0 0 0 eth0
0.0.0.0 192.168.2.1 0.0.0.0 UG 0 0 0 eth0
기본 게이트웨이를 default
대신 0.0.0.0
으로 명시되어 있는 경우를 확인할 수 있는데요.
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.2.1 0.0.0.0 255.255.255.0 UG 0 0 0 eth0
게이트웨이 필드가 0.0.0.0
이라면, 게이트웨이를 통할 필요 없다는 의미입니다.
예를 들어, 한 시스템이 동일한 네트워크에 존재하는 다른 시스템에 접근하려고 하면,
자체 네트워크에 있기 때문에 게이트웨이가 필요하지 않습니다.
게이트웨이는 여러개 일 수 있습니다.
가령 하나는 인터넷과 연결된 라우터, 다른 하나는 내부 프라이빗 네트워크와 연결된 라우터가 있을 때,
각 네트워크를 위한 서로 다른 진입 경로를 설정합니다.
Linux Server - Router
가상의 라우터를 설정하는 방법에 대해 알아보겠습니다.
Linux 서버를 라우터로 사용하고 싶을 때, 설정하는 방법입니다.
실제로 아래의 명령어를 수행할 일이 없겠지만,
컨테이너 네트워크에 대한 이해를 위한 내용입니다.
A, B, C 세 호스트를 보면, A와 B는 192.168.1.0
네트워크에 연결돼 있고,
B와 C는 192.168.2.0
네트워크에 연결돼 있습니다.
호스트 B는 eth0
와 eth1
, 두 인터페이스를 통해 양쪽 네트워크에 연결되어 있습니다.
이 때, A에서 C로 연결하려고 하면 아래와 같은 오류가 발생합니다.
# Host A
$ ping 192.168.2.5
Connect: Network is unreachable
A가 C로 요청을 보내려고 할 때 어디를 통해서 가는 지를 모르기 때문이죠.
즉, A가 C로 갈 때 B를 거치라는 설정이 필요합니다.
이를 가능하게 하기 위해선 호스트 B를 통해 접근할 수 있으며, 그 과정은 아래와 같습니다.
STEP 1. 라우팅 설정: A → B → C
호스트 A에서 B로 패킷을 전송할 수 있게 설정합니다.
# command in Host A
$ ip route add 192.168.2.0/24 via 192.168.1.6
이제 호스트 A에서 호스트 B를 통해 호스트 C로 요청이 전달될 수 있습니다.
다음으로는, 호스트 C에서 호스트 A로 응답을 보내려면 연결할 수 있게 설정해야 합니다.
STEP 2. 라우팅 설정: C → B → A
이번엔 호스트 C에서 A로 패킷을 전달할 수 있게 설정해야 합니다.
# command in Host C
$ ip route add 192.168.1.0/24 via 192.168.2.6
이제 ping을 다시 해보면 전송은 되지만 응답을 받을 수는 없습니다.
이는 Linux에서 기본적으로 하나의 인터페이스에서 다른 인터페이스로 포워딩을 허용하지 않기 때문입니다.
즉, eth0 로 요청된 내용은 항상 eth0로만 반환되도록 설정되어 있습니다.
현재는 eth0 로 들어온 요청이 eth1으로 입력되려고 하고 있죠.
A에서 C로 갈 때는 인입이 eth0 으로 입력되었으므로,
C에서 A로 응답을 보내려고 할 때는 eth1로 나갈 수 있도록 설정이 필요합니다.
(시스템 B 기준으로 인입될 때만 해당됩니다)
STEP 2. Allow ip_forward
해당 설정을 허용하려면 /proc/sys/net/ipv4/ip_forward
설정을 변경해야 합니다.
$ cat /proc/sys/net/ipv4/ip_forward
0 ← No Forward
기본 설정값은 0
입니다. 이를 1
로 변경해야 합니다.
$ echo 1 > /proc/sys/net/ipv4/ip_forward
1
영구 설정을 위해서는 /etc/sysctl.conf
파일에 다음 라인을 추가합니다.
net.ipv4.ip_forward=1
이제 호스트 A에서 C로, 그리고 C에서 A로의 통신이 가능합니다.
그럼 지금까지 Container 네트워킹에 대해 알아보았습니다.
'BACKEND > Docker & Kubernetes' 카테고리의 다른 글
Kubernetes Static Pods, 제대로 이해하기 (0) | 2024.07.10 |
---|---|
Kubernetes Storage, 제대로 이해하기 (1) | 2024.06.10 |
Docker Volume, 제대로 이해하기 (0) | 2024.06.03 |
Kubernetes Cluster Upgrade, 제대로 이해하기 (0) | 2024.04.24 |
📚 Kubernetes Series (1) | 2024.04.16 |
Backend Software Engineer
𝐒𝐮𝐧 · 𝙂𝙮𝙚𝙤𝙣𝙜𝙨𝙪𝙣 𝙋𝙖𝙧𝙠