지난 시간에 tencentVPC 및 extension 패키지에 대해서 살펴보았다. 스터디를 진행하였을 때, 전반적으로 기본 사항이 되는 netlink를 알아야겠다는 의견이 있었고, 이에 내가 그 부분을 맡게 되었다.
netlink는 정말 어디에서나 쓴다...
Netlink는 사용자 모드에서 커널 영역의 네트워크 관련 기능에 접근할 수 있게 해주는 인터페이스이다!
인터페이스라는 말이 참.. 추상적인데, 그냥 커널에서 네트워크 부분을 건드릴 수 있는 소켓을 제공하는 것이다. 결국 통신 네트워크를 만드려면 NIC 같은 물리 장비를 조절해야하니 커널 영역과 통신해야하는 것이다.
(소켓은 네트워크 프로그래밍에서 사용되는 엔드포인트)
네트워크 구축을 위해서는 서브넷 ,Ip 할당, 네임스페이스, 네트워크 인터페이스(veth, bridge) 등 생성이 필요하다.
이 때 리눅스 터미널에서 ip 명령어들을 사용하게 되는데 예를 들자면 아래의 명령어 같은 것이다.
ip route add 192.168.150.0/24 via 192.168.100.12 dev eth2
ip netns add A
ip link add dummy0 type dummy
"github.com/vishvananda/netlink"
Flannel의 대부분의 패키지에서 import해서 사용하는 netlink는 Linux 커널의 netlink 인터페이스를 Golang에서 쉽게 사용할 수 있도록 구현한 라이브러리다. 이 라이브러리를 사용하면 Linux의 netlink 기능을 직접 제어할 수 있고, 이는 우리가 터미널에서 사용하는 ip 명령어와 같은 일을 수행한다.
Flannel은 Pod간 통신을 위해 노드당 Subnet을 만들고.. 파드에 IP를 배정하고 라우트 테이블을 추가하고.. 가상 인터페이스(NIC)등을 만들어줘야하므로 당연히 netlink를 쓸 수 밖에 없다. 물론 VxLAN도 만들 수 있다.
Flannel은 VxLAN을 사용해서 파드간 통신을 구축한다. 그렇다면 VxLAN 이란 무엇일까?
기존의 LAN은 대표적으로 2가지 한계가 있었다.
1. VLAN ID가 12비트로 설계되어 네트워크 분할이 4096개로 제한
2. 이더넷 케이블 유선 연결이라 물리적으로 한계를 가짐
그런데 가상화 기술이 발달하고 클라우드 시대가 되면서.. 데이터센터는 여러 지역에 분산되고 해당 데이터센터의 컴퓨팅 리소스를 빌려서 사용하게 되며 더 많은 네트워크 분할이 필요하게 되었다.
특히나 쿠버네티스에서는 파드는 노드에 스케줄링되고, 물리적으로 떨어져있는 노드끼리 통신하기 위해서는 먼저 노드끼리 네트워크 연결이 되어있어야한다. 이를 LAN으로 구현하기에 한계가 있으니, 각 노드에 VxLAN Interface를 생성해서 IP로 연결되게 만드는 것이다..!
Pod A(10.0.1.2) -> Pod B(10.0.1.3) 통신 시도
VXLAN이 패킷을 감싸서 Node1(192.168.1.10) -> Node2(192.168.1.11)로 전송
Node2에서 패킷을 풀어서 Pod B에 전달
결국 VXLAN은 클라우드의 물리적 제약을 극복하고 가상의 LAN을 만들어서
마치 모든 노드가 같은 네트워크에 있는 것처럼 만들어주는 기술
netlink 라이브러리는 vxlan 만들 때 예를 들어서 아래와 같이 사용할 수 있다.
vxlan := &netlink.Vxlan{
LinkAttrs: netlink.LinkAttrs{Name: "flannel.1"},
VxlanId: 1,
VtepDevIndex: eth0.Attrs().Index,
Port: 8472,
}
err := netlink.LinkAdd(vxlan)
if err != nil {
log.Fatalf("Failed to create vxlan interface: %v", err)
}
netlink.LinkSetUp(vxlan)
실제 netlink go library 코드를 일부 봐보자!
라우트 추가하는 함수 RouteAdd는 주석으로 ip route add 와 같다고 친절히 설명하고 있다
그럼 얘는 또 어떻게 kernel영역까지 내려가서 network 설정을 할까..했더니 바로 밑에 나온다.
unix 패키지를 쓰는데 unix 계열 운영 체제의 시스템 호출을 Go 함수로 제공하여, Go 프로그램이 커널의 기능에 접근할 수 있다.
결국 이런 패키지들을 잘 활용하여.. 파드간 네트워크 구축을 위해 여기저기서 netlink 라이브러리를 호출하는것이다.