쿠버네티스는 컨테이너, 파드, 서비스, 노드 사이에서 발생하는 네트워크를 처리하기 위해 ip 할당, 라우팅 정책, 로드 밸런싱, 그리고 스위칭을 적극적으로 활용합니다. 특히 우리가 앞에서 살펴보았던 하나의 호스트 내에서 다중화되었거나 격리된 환경에서의 네트워크 처리는 반드시 필요합니다.
오늘은 쿠버네티스의 실질적인 네트워크에 들어가기에 앞서 쿠버네티스 네트워크를 찾아보면 만날 수 있는 개념 혹은 패키지들에 대해 알아보고자 합니다.
이전 글 목차
https://dev-whoan.xyz/111, 네트워크로 시작하는 쿠버네티스 — 내가 데이터를 보낸다면
https://dev-whoan.xyz/112, 네트워크로 시작하는 쿠버네티스 - Network Namespace
https://dev-whoan.xyz/113, 네트워크로 시작하는 쿠버네티스 - Docker Network
사전 준비물
ubuntu 22.04 * 2이 필요합니다. 저는 “내가 데이터를 보낸다면”에서 사용한 network ubuntu 2대를 사용하겠습니다.
- 네트워크를 Host Only에서 bridged로 변경해 주세요.
iptables
iptables는 kube-proxy에서 사용할 수 있는 프록시 모드 중 하나입니다. 이를 통해 쿠버네티스에서 컨트롤 플레인의 서비스, 엔드포인트 슬라이스 오브젝트의 추가와 제거를 감시합니다. 또한 각 서비스의 Cluster IP와 Port에 대한 트래픽을 캡처하고, 서비스의 백엔드 세트 중 하나로 redirect 합니다.
iptables는 리눅스의 Netfliter 프레임워크를 활용하여 패킷을 제어하는 패키지입니다. iptables는 방화벽, NAT, 라우팅 등을 주로 수행합니다. iptables는 이러한 동작을 수행하기 위해 Chain이라 불리는 Rule Group을 설정합니다.
- input: 시스템으로 들어오는 패킷을 처리합니다.
- forward: 다른 네트워크 인터페이스로 전달되는 패킷을 처리합니다.
- output: 시스템에서 나가는 패킷을 처리합니다.
이러한 체인은 테이블에 속하게 되는데, 주요 테이블은 다음과 같습니다.
- filter: drop, accept 등 패킷 필터링을 수행합니다.
- nat: network address translation에 대한 처리를 수행합니다.
- mangle: 헤더 변경 등 패킷의 수정을 처리합니다.
- raw: 패킷 추적을 비활성화하거나 설정합니다.
그러면 ubuntu 22.04 시스템을 바탕으로, iptables를 확인해 보겠습니다.
network@network01:~$ sudo iptables --list
Chain INPUT (policy DROP)
target prot opt source destination
ufw-before-logging-input all -- anywhere anywhere
...
Chain FORWARD (policy DROP)
target prot opt source destination
ufw-before-logging-forward all -- anywhere anywhere
...
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ufw-before-logging-output all -- anywhere anywhere
...
기본적인 input, forward, output 체인을 확인할 수 있으며 추가적으로 ufw(방화벽) 관련 chain도 확인하실 수 있습니다.
실제로 iptables의 동작을 확인해보기 위해 network01 시스템에 nginx를 설치하고 확인해 보겠습니다.
network@network01:~$ sudo apt-get update && sudo apt-get install nginx
## network02
network@network02:~$ curl 192.168.1.83
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.
Thank you for using nginx.
이제 network01 시스템에서 80 포트로 들어오는 모든 패킷을 drop 하는 설정을 한 뒤, 다시 확인해 보겠습니다.
network@network01:~$ sudo iptables -A INPUT -p tcp --dport 80 -j DROP
network@network02:~$ curl 192.168.1.83
^C # 정상적인 연결이 안됨
## 연결 요청이 들어왔나 보기 위해 tcpdump를 활용해 봅시다.
## request는 있지만, reply가 없는것을 확인할 수 있습니다.
network@network01:~$ sudo tcpdump -i enp0s1 tcp port 80
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp0s1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
00:42:20.647819 IP 192.168.1.84.52202 > network01.http: Flags [S], seq 2687585736, win 64240, options [mss 1460,sackOK,TS val 4045880976 ecr 0,nop,wscale 7], length 0
00:42:21.660618 IP 192.168.1.84.52202 > network01.http: Flags [S], seq 2687585736, win 64240, options [mss 1460,sackOK,TS val 4045881985 ecr 0,nop,wscale 7], length 0
00:42:23.672601 IP 192.168.1.84.52202 > network01.http: Flags [S], seq 2687585736, win 64240, options [mss 1460,sackOK,TS val 4045884000 ecr 0,nop,wscale 7], length 0
network02의 ip만을 허용한다면 어떻게 될까요?
network@network01:~$ sudo iptables -A INPUT -s 192.168.1.84 -j ACCEPT
network@network01:~$ sudo iptables --list
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere anywhere tcp dpt:http
ACCEPT all -- 192.168.1.84 anywhere
network@network02:~$ curl 192.168.1.83
^C
그래도 연결이 되지 않습니다. 왜 연결이 안 되는 걸까요?
## 다른 테스트를 위해 INPUT 설정을 초기화 합니다.
network@network01:~$ sudo iptables --flush INPUT
network@network01:~$ sudo iptables --list INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
network@network01:~$ sudo iptables -A INPUT -s 192.168.1.84 -j ACCEPT
network@network01:~$ sudo iptables -A INPUT -p tcp --dport 80 -j DROP
network@network01:~$ sudo iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 192.168.1.84 anywhere
DROP tcp -- anywhere anywhere tcp dpt:http
위와 같이 network02 시스템에서 nginx에 접근을 요청하면 정상적으로 html이 출력되는 것을 확인할 수 있습니다. 그 이유는 iptables의 규칙은 설정된 순서대로 우선순위를 갖기 때문입니다.
Forward 체인을 확인해 보기 위해 Host OS에서 network 02로 요청을 보낸다면, network 01 시스템의 nginx로 연결해 보도록 하겠습니다.
## ip 패킷에 대한 forwarding을 허용합니다.
network@network02:~$ sudo sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
network@network02:~$ sudo sysctl -p
## 80포트로 들어오는 패킷을 network 01로 라우팅 합니다.
network@network02:~$ sudo iptables --table nat --append PREROUTING \\
--proto tcp --dport 80 \\
--jump DNAT --to-destination 192.168.1.83:80
PREROUTING을 추가했습니다. 이는 들어오는 패킷을 현재 시스템에서 처리하지 않고, 다음 destination으로 jump 함을 의미합니다. network 02 시스템에 대해 curl요청을 보내면, 아무 반응이 없습니다. 잠시 멈추시어 그 이유를 생각해 보시기 바랍니다.
## network 01로 패킷을 forwarding 합니다.
network@network02:~$ sudo iptables --append FORWARD --proto tcp \\
--destination 192.168.1.83 --dport 80 --jump ACCEPT
## 패킷 중 목적지 IP가 network 01의 80포트인 패킷의 출발지 IP를 192.168.1.84로 변경합니다.
network@network02:~$ sudo iptables --table nat --append POSTROUTING \\
--proto tcp --destination 192.168.1.83 --dport 80 \\
--jump SNAT --to-source 192.168.1.84
iptables에는 LOG를 통해 규칙에 대한 패킷을 기록할 수 있습니다. 한번 위 동작에 대해 로그를 확인해 봅시다.
## iptables는 순서를 갖기 때문에, 기존의 FORWARD 규칙을 삭제하고 다시 설정합니다.
network@network02:~$ sudo iptables --append FORWARD \\
--destination 192.168.1.83 --proto tcp \\
--dport 80 --jump LOG \\
--log-prefix "Forward to ->Network 01 Nginx: " --log-level 4
network@network02:~$ sudo iptables --append FORWARD --proto tcp \\
--destination 192.168.1.83 --dport 80 \\
--jump ACCEPT
## 기본적으로 /var/log/syslog를 통해 iptables의 로그를 확인할 수 있습니다.
network@network02:~$ tail -f /var/log/syslog
...
Dec 3 04:15:48 network02 kernel: [13070.401666] Forward to ->Network 01 NginxIN=enp0s1 OUT=enp0s1 MAC=2a:14:0f:0a:0d:2e:... SRC=192.168.1.2 DST=192.168.1.83 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=51098 DPT=80 WINDOW=65535 RES=0x00 SYN URGP=0
...
- 우리가 설정한 다른 규칙들에도 LOG를 남겨보세요.
output 체인의 경우 다음과 같이 설정할 수 있습니다. 한번 직접 실습해 보시길 바랍니다.
sudo iptables --append OUTPUT --proto tcp|udp --dport PORT --jump DROP|ACCEPT|LOG
IPVS
IPVS는 쿠버네티스에서 사용할 수 있는 프록시 모드 중 하나입니다. 이를 통해 쿠버네티스 서비스와 엔드포인트 슬라이스를 감시하고, netlink 인터페이스를 호출해 IPVS 규칙을 생성하고, 이를 쿠버네티스와 주기적으로 동기화합니다. 이 제어 루프를 통해 IPVS를 원하는 상태로 일치하도록 보장합니다.
특히 IPVS의 경우 SNAT, DNAT에 대한 지원이 없기 때문에 필요에 따라 iptables와 함께 사용해야 합니다.
쿠버네티스에서 IPVS 모드를 이용할 경우 다음의 기능을 사용할 수 있습니다.
- 라운드 로빈, Least Connection 기반의 로드 밸런싱
- iptables의 경우 백엔드를 임의로 선택합니다. 즉, iptables의 경우 선택된 파드가 응답하지 않으면 연결이 실패하지만, IPVS는 다른 백엔드 파드로 재시도합니다.
- Cluster IP와 NodePort에 대한 라우팅
IPVS 실습을 위해 ipvs admin 패키지를 설치하고, 라운드 로빈을 활성화해 줍니다.
## network 01
network@network01:~$ sudo sysctl -w net.ipv4.ip_forward=1
network@network01:~$ sudo apt-get install ipvsadm -y
network@network01:~$ lsmod | grep "ip_vs"
network@network01:~$ sudo modprobe ip_vs
network@network01:~$ sudo modprobe ip_vs_rr
network@network01:~$ lsmod | grep "ip_vs"
ip_vs_rr 20480 0
ip_vs 196608 2 ip_vs_rr
nf_conntrack 196608 6 xt_conntrack,nf_nat,xt_nat,nf_conntrack_netlink,xt_MASQUERADE,ip_vs
nf_defrag_ipv6 24576 2 nf_conntrack,ip_vs
libcrc32c 16384 6 nf_conntrack,nf_nat,btrfs,nf_tables,raid456,ip_vs
## network 01에서는 nginx 컨테이너를 두 개 띄워줍니다.
network@network01:~$ sudo docker run -d --name nginx1 -p 8080:80 nginx
network@network01:~$ sudo docker run -d --name nginx2 -p 8081:80 nginx
## 이후 각 컨테이너에 요청을 보내면 아래의 응답이 오도록 컨테이너를 수정합니다.
network@network01:~$ curl localhost:8080
nginx 8080 container
network@network01:~$ curl localhost:8081
nginx 8081 container
## network 02
network@network02:~$ sudo sysctl -w net.ipv4.ip_forward=1
network@network02:~$ sudo apt-get install ipvsadm -y
network@network02:~$ lsmod | grep "ip_vs"
network@network02:~$ sudo modprobe ip_vs
network@network02:~$ sudo modprobe ip_vs_rr
network@network02:~$ lsmod | grep "ip_vs"
ip_vs_rr 20480 0
ip_vs 196608 2 ip_vs_rr
nf_conntrack 196608 6 xt_conntrack,nf_nat,xt_nat,nf_conntrack_netlink,xt_MASQUERADE,ip_vs
nf_defrag_ipv6 24576 2 nf_conntrack,ip_vs
libcrc32c 16384 6 nf_conntrack,nf_nat,btrfs,nf_tables,raid456,ip_vs
이후 network 02 시스템에서 다음의 작업을 수행해야 합니다.
## 패킷 라우팅을 허용합니다.
network@network02:~$ sudo sysctl -w net.ipv4.ip_forward=1
## 커널의 Connection을 Track하는 기능을 활성화 합니다.
## IPVS의 경우 커널 수준의 로드 밸런싱이기 때문에, 연결이 추적 불가할 때 NAT가 불가합니다.
## 이를 통해 클라이언트의 요청으로 생성된 연결을 추적하고
## 추적된 연결의 응답 패킷을 적절히 라우팅 합니다.
network@network02:~$ sudo sysctl -w net.ipv4.vs.conntrack=1
network@network02:~$ sudo iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.83 --dport 8080 -j MASQUERADE
network@network02:~$ sudo iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.83 --dport 8081 -j MASQUERADE
network@network02:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
network@network02:~$ sudo iptables -t nat -L POSTROUTING
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE tcp -- anywhere 192.168.1.83 tcp dpt:http-alt
MASQUERADE tcp -- anywhere 192.168.1.83 tcp dpt:tproxy
network@network02:~$ sudo ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.84:80 rr
-> 192.168.1.83:8080 Masq 1 1 1
-> 192.168.1.83:8081 Masq 1 1 0
한번 각 설정을 off 한 다음, tcpdump로 직접 상태를 보며 무엇이 문제인지 확인해 보세요.
Host OS에서 Network 02로 요청을 보낼 때, 로드 밸런싱이 정상적으로 동작하는 것을 확인할 수 있습니다.
$ curl 192.168.1.84
nginx 8080 container
$ curl 192.168.1.83:8080
nginx 8080 container
$ curl 192.168.1.83:8081
nginx 8081 container
$ curl 192.168.1.84
nginx 8081 container
$ curl 192.168.1.84
nginx 8080 container
ipvs 실습의 경우 round robin만 활용했습니다. 이외의 방식 (Least Connection)도 한번 직접 수행해 보시면 좋을 것 같습니다.
Overlay 네트워크
Overlay 네트워크는 기존의 네트워크 상위에 논리 네트워크를 만들고, IP 주소와 트래픽 제어를 수행하는 기술입니다. 쿠버네티스에서는 Overlay 네트워크를 통해 Pod의 연결을 지원합니다.
IPIP (IP in IP)
IPIP는 IP 패킷을 다른 IP 패킷 안에 캡슐화하는 기술입니다.
좌측 그림이 일반적인 IP 패킷이라면, 오른쪽 그림은 IPIP를 나타냅니다. Outer IP Header를 추가하여 IP를 캡슐화하는 기술인데, 이때 Outer IP Header는 일반적인 IP Header와 동일합니다.
바꿔 말하면, 새로운 IP Header를 추가하여 출발지와 목적지 등을 새롭게 설정할 수 있습니다.
IPIP를 적용한 Overlay 네트워크에서는 컨테이너의 값을 Inner IP Header로 설정하여 원 출발지/목적지로 설정하고, Outer IP Header에는 컨테이너를 운영하는 시스템(노드)을 Outer IP Header로 설정하여 캡슐화를 진행합니다.
그러나 IP를 다른 IP 패킷 안에 캡슐화하기 때문에, 패킷의 최대 크기 Maximum Transmission Unit (MTU)를 조절해야 하거나, 네트워크 오버헤드로 인해 성능이 줄어들 수 있습니다. 또한 다중 테넌트를 지원하지 않기 때문에 대규모 환경에서는 VXLAN 등을 이용해야 합니다.
IPIP를 통해 Network 시스템에 가상의 대역을 갖는 ip를 생성하고, 통신을 수행해 보겠습니다.
## Network 01
network@network01:~$ sudo ip tunnel add ipip0 mode ipip local 192.168.1.83 remote 192.168.1.84
network@network01:~$ sudo ip link set ipip0 up
network@network01:~$ sudo ip addr add 10.0.0.1/24 dev ipip0
network@network01:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 1a:df:51:84:a5:4a brd ff:ff:ff:ff:ff:ff
inet 192.168.1.83/24 metric 100 brd 192.168.1.255 scope global dynamic enp0s1
valid_lft 7034sec preferred_lft 7034sec
inet6 fe80::18df:51ff:fe84:a54a/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:d6:7e:70:ed brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
4: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
5: ipip0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
link/ipip 192.168.1.83 peer 192.168.1.84
inet 10.0.0.1/24 scope global ipip0
valid_lft forever preferred_lft forever
inet6 fe80::5efe:c0a8:153/64 scope link
valid_lft forever preferred_lft forever
network@network01:~$ ping 10.0.0.2 -c 3
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=18.6 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=6.06 ms
64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=12.4 ms
--- 10.0.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2011ms
rtt min/avg/max/mdev = 6.064/12.346/18.572/5.106 ms
## Network 02
network@network02:~$ sudo ip tunnel add ipip0 mode ipip local 192.168.1.84 remote 192.168.1.83
network@network02:~$ sudo ip link set ipip0 up
network@network02:~$ sudo ip addr add 10.0.0.2/24 dev ipip0
network@network02:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 2a:14:0f:0a:0d:2e brd ff:ff:ff:ff:ff:ff
inet 192.168.1.84/24 metric 100 brd 192.168.1.255 scope global dynamic enp0s1
valid_lft 5621sec preferred_lft 5621sec
inet6 fe80::2814:fff:fe0a:d2e/64 scope link
valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: ipip0@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN group default qlen 1000
link/ipip 192.168.1.84 peer 192.168.1.83
inet 10.0.0.2/24 scope global ipip0
valid_lft forever preferred_lft forever
inet6 fe80::5efe:c0a8:154/64 scope link
valid_lft forever preferred_lft forever
## Network 01이 관리중인 ipip로 요청을 보내보면, 정상적으로 동작하는걸 확인할 수 있습니다.
network@network02:~$ curl 10.0.0.1:8080
nginx 8080 container
VXLAN
Virtual eXtensible LAN의 약자로, 네트워크 가상화의 표준(standard)으로, UDP를 활용하여 L2의 이더넷 프레임을 캡슐화합니다. UDP를 활용하기 때문에 L3를 기반으로 하며, 캡슐화를 통해 L2 네트워크를 생성합니다. 쉽게 말하면 물리 네트워크 위에 가상의 L2 네트워크를 만드는 기술입니다.
- Inner L2 Frame: VXLAN 내에서 통신하는 원래의 트래픽입니다.
- VXLAN Header: VXLAN 네트워크 정보를 포함합니다.
- Outer UDP Header: 캡슐화된 VXLAN 트래픽을 전송하기 위해 사용하며, 포트 4789번을 가집니다. 캡슐화를 효율적으로 처리하는 데 사용됩니다.
- Outer IP Header: 물리 네트워크의 L3 헤더로, 캡슐화된 트래픽을 목적지로 전송하기 위한 헤더입니다. 실제 라우팅 가능한 IP 네트워크에서 트래픽을 전달하는 역할을 수행합니다.
- Outer L2 Header: 물리 네트워크의 L2 헤더입니다. 캡슐화된 트래픽이 물리 네트워크의 스위치 혹은 라우터에 전달될 때 사용됩니다.
VXLAN은 Multicast 혹은 Unicast 방식으로 가상 네트워크에서 통신을 수행합니다.
Multicast는 224.0.0.0 ~ 239.255.255.255 대역에 대해 그룹을 생성하고, 같은 그룹의 장치들끼리 트래픽을 주고받을 수 있도록 합니다. 즉, VXLAN이 사용하는 VTEP인 VXLAN을 관리하는 시스템인 네트워크 장치 간 통신이 가능하게 합니다. Multicast의 경우, 위 주소가 Outer IP Header의 목적지 주소가 되며, Unicast의 경우 다른 VTEP의 물리적 IP 주소가 Outer IP Header의 목적지 주소가 됩니다. VXLAN의 가상 네트워크는 Inner IP Header에 담겨 실제 통신에 사용됩니다. VTEP는 Underlay 네트워크인 물리 네트워크와 Overlay 네트워크인 VXLAN 인터페이스가 될 수 있습니다.
그럼 이제 VXLAN을 통해 Overlay 네트워크를 구성하고, 마찬가지로 docker 컨테이너로 접근해 보겠습니다.
Multicast의 경우, vxlan의 endpoint group을 지정해 주면 IGMP (Internet Group Management Protocol)를 통해 자동으로 구성이 수행됩니다.
- 멀티캐스트 트래픽은 사용 중인 스위치/라우터가 멀티캐스트 라우팅을 지원하고, IGMP 메시지를 처리할 수 있을 때 전달됩니다.
## Network 01
network@network01:~$ sudo ip link add vxlan0 type vxlan id 241203 \\
dev enp0s1 group 239.1.1.1 \\
dstport 4789
network@network01:~$ sudo ip addr add 10.1.1.1/24 dev vxlan0
network@network01:~$ sudo ip link set vxlan0 up
network@network01:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 1a:df:51:84:a5:4a brd ff:ff:ff:ff:ff:ff
inet 192.168.1.83/24 metric 100 brd 192.168.1.255 scope global dynamic enp0s1
valid_lft 4498sec preferred_lft 4498sec
inet6 fe80::18df:51ff:fe84:a54a/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:d6:7e:70:ed brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:d6ff:fe7e:70ed/64 scope link
valid_lft forever preferred_lft forever
4: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
7: veth3d8b49d@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether ea:4e:ad:f8:e2:ae brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e84e:adff:fef8:e2ae/64 scope link
valid_lft forever preferred_lft forever
10: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 96:70:45:03:fc:fb brd ff:ff:ff:ff:ff:ff
inet 10.1.1.1/24 scope global vxlan0
valid_lft forever preferred_lft forever
inet6 fe80::9470:45ff:fe03:fcfb/64 scope link
valid_lft forever preferred_lft forever
network@network01:~$ ping 10.1.1.2 -c 4
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=13.5 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=1.74 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=1.23 ms
64 bytes from 10.1.1.2: icmp_seq=4 ttl=64 time=1.12 ms
--- 10.1.1.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3015ms
rtt min/avg/max/mdev = 1.124/4.396/13.496/5.258 ms
## Network 02
network@network02:~$ sudo ip link add vxlan0 type vxlan id 241203 \\
dev enp0s1 group 239.1.1.1
network@network02:~$ sudo ip addr add 10.1.1.2/24 dev vxlan0
network@network02:~$ sudo ip link set vxlan0 up
network@network02:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 2a:14:0f:0a:0d:2e brd ff:ff:ff:ff:ff:ff
inet 192.168.1.84/24 metric 100 brd 192.168.1.255 scope global dynamic enp0s1
valid_lft 6691sec preferred_lft 6691sec
inet6 fe80::2814:fff:fe0a:d2e/64 scope link
valid_lft forever preferred_lft forever
3: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
9: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN group default qlen 1000
link/ether 0a:ec:bb:3d:3d:f8 brd ff:ff:ff:ff:ff:ff
inet 10.1.1.2/24 scope global vxlan0
valid_lft forever preferred_lft forever
inet6 fe80::8ec:bbff:fe3d:3df8/64 scope link
valid_lft forever preferred_lft forever
network@network02:~$ ping 10.1.1.1 -c 4
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=2.41 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=2.50 ms
64 bytes from 10.1.1.1: icmp_seq=3 ttl=64 time=6.22 ms
64 bytes from 10.1.1.1: icmp_seq=4 ttl=64 time=7.82 ms
--- 10.1.1.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3017ms
rtt min/avg/max/mdev = 2.409/4.738/7.822/2.352 ms
## 아래 명령은 두 개의 shell을 접속하여 수행해 보세요.
network@network02:~$ curl 10.1.1.1:8080
nginx 8080 container
# 나머지 하나의 Shell 에서는 tcpdump를 수행하여 확인해봅시다.
network@network02:~$ sudo tcpdump -i enp0s1 udp port 4789 -n
[sudo] password for network:
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp0s1, link-type EN10MB (Ethernet), snapshot length 262144 bytes
11:44:56.662220 IP 192.168.1.84.56103 > 192.168.1.83.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.2.39200 > 10.1.1.1.8080: Flags [S], seq 156139928, win 64860, options [mss 1410,sackOK,TS val 318379903 ecr 0,nop,wscale 7], length 0
11:44:56.663992 IP 192.168.1.83.39249 > 192.168.1.84.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.1.8080 > 10.1.1.2.39200: Flags [S.], seq 169487905, ack 156139929, win 65160, options [mss 1460,sackOK,TS val 1355529330 ecr 318379903,nop,wscale 7], length 0
11:44:56.664049 IP 192.168.1.84.56103 > 192.168.1.83.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.2.39200 > 10.1.1.1.8080: Flags [.], ack 1, win 507, options [nop,nop,TS val 318379905 ecr 1355529330], length 0
11:44:56.664133 IP 192.168.1.84.56103 > 192.168.1.83.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.2.39200 > 10.1.1.1.8080: Flags [P.], seq 1:78, ack 1, win 507, options [nop,nop,TS val 318379905 ecr 1355529330], length 77: HTTP: GET / HTTP/1.1
11:44:56.665779 IP 192.168.1.83.39249 > 192.168.1.84.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.1.8080 > 10.1.1.2.39200: Flags [.], ack 78, win 509, options [nop,nop,TS val 1355529331 ecr 318379905], length 0
11:44:56.665998 IP 192.168.1.83.39249 > 192.168.1.84.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.1.8080 > 10.1.1.2.39200: Flags [P.], seq 1:237, ack 78, win 509, options [nop,nop,TS val 1355529331 ecr 318379905], length 236: HTTP: HTTP/1.1 200 OK
11:44:56.665998 IP 192.168.1.83.39249 > 192.168.1.84.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.1.8080 > 10.1.1.2.39200: Flags [P.], seq 237:258, ack 78, win 509, options [nop,nop,TS val 1355529331 ecr 318379905], length 21: HTTP
11:44:56.666018 IP 192.168.1.84.56103 > 192.168.1.83.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.2.39200 > 10.1.1.1.8080: Flags [.], ack 237, win 506, options [nop,nop,TS val 318379907 ecr 1355529331], length 0
11:44:56.666040 IP 192.168.1.84.56103 > 192.168.1.83.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.2.39200 > 10.1.1.1.8080: Flags [.], ack 258, win 506, options [nop,nop,TS val 318379907 ecr 1355529331], length 0
11:44:56.666452 IP 192.168.1.84.56103 > 192.168.1.83.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.2.39200 > 10.1.1.1.8080: Flags [F.], seq 78, ack 258, win 506, options [nop,nop,TS val 318379907 ecr 1355529331], length 0
11:44:56.674543 IP 192.168.1.83.39249 > 192.168.1.84.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.1.8080 > 10.1.1.2.39200: Flags [F.], seq 258, ack 79, win 509, options [nop,nop,TS val 1355529340 ecr 318379907], length 0
11:44:56.674574 IP 192.168.1.84.56103 > 192.168.1.83.4789: VXLAN, flags [I] (0x08), vni 241203
IP 10.1.1.2.39200 > 10.1.1.1.8080: Flags [.], ack 259, win 506, options [nop,nop,TS val 318379915 ecr 1355529340], length 0
Unicast를 활용한 내용과 VXLAN의 아이피 CIDR을 서로 다르게 설정한 통신도 한번 수행해 보시기 바랍니다.
마치며
오늘은 다음 주제인 Pod와 서비스 간 통신을 시작하기에 앞서 쿠버네티스에서 네트워크를 구성하는데 기본적인 내용을 다루어보았습니다.
느리다면 느린, 길다면 긴 3주 동안 쿠버네티스의 네트워크를 바라보기 위한 필수적인 내용을 다루었습니다. 읽어주신 모든 분께 도움이 되었으면 합니다.
감사합니다.
참고
- https://kubernetes.io/docs/reference/networking/virtual-ips/
- https://www.cisco.com/c/ko_kr/support/docs/ios-nx-os-software/nx-os-software/200262-Configure-VxLAN-Flood-And-Learn-Using-Mu.html
- https://en.wikipedia.org/wiki/Virtual_Extensible_LAN
- https://www.cloudflare.com/ko-kr/learning/network-layer/what-is-igmp/
'DevOps > Kubernetes' 카테고리의 다른 글
네트워크로 시작하는 쿠버네티스 - 컨테이너 통신, 도커 네트워크 (0) | 2024.11.21 |
---|---|
네트워크로 시작하는 쿠버네티스 - 컨테이너간 통신, Network Namespace (2) | 2024.11.14 |
네트워크로 시작하는 쿠버네티스 - 내가 데이터를 보낸다면 (2) | 2024.11.14 |
쿠버네티스가 쉬워지는 컨테이너 이야기가 어렵다면 - cgroup, cpu 편 (0) | 2024.11.11 |