최근 업데이트일 2024-11-31
CNI 中 하나인 Calico에 대해서 집중적으로 알아보고자 한다. Calico의 구성요소와 Calico가 사용하는 protocol인 BGP에 대해서도 간단히 알아보자.
Calico
- CNI(Container Network Interface): Container, VM 환경에서 L3 기반 Virtual Network를 구축하게 도와주는 Tool
- Calico: 네트워크 보안과 라우팅 기능을 모두 지원하는 컨테이너 네트워킹 솔루션
- Calico는 BGP(Border Gateway Protocol)를 활용해 각 노드 간의 네트워크 경로를 설정하고 관리하며, 직접 라우팅 방식으로 트래픽을 전달한다.
- 필요에 따라 VXLAN과 같은 오버레이 네트워크도 사용할 수 있어 유연한 네트워크 구성이 가능하다.
- 또한, Kubernetes 네트워크 정책과 통합되어 컨테이너 간 트래픽을 세밀하게 제어하고, 서비스 간 네트워크 보안을 강화할 수 있다.
- 이러한 구조 덕분에 Calico는 대규모 클러스터 환경에서도 확장성과 안정성을 유지하며, 고성능의 네트워크 분리 및 격리 요구 사항을 충족시킬 수 있다.
Calico 구성요소
calico-node: 각 node 위에서 동작하는 DaemonSet 형태의 Pod로, Node의 Network namespace를 이용하여 네트워크 설정과 라우팅 처리를 담당한다. 내부에는 다음 세 가지 주요 컴포넌트가 포함되어 있다.
felix: Node의 네트워크 설정을 담당하는 핵심 컴포넌트
- 각 node에 할당된 Pod의 IP 대역이 BGP로 전파되면 정상적으로 통신할 수 있도록 Network Interface, routing table, iptables(IPVS 포함) 등을 설정한다.
- Node 내에서 Pod의 IP 및 라우팅 정보를 Linux 커널의 라우팅 테이블(Forwarding Information Base)에 등록하고,
- 설정한 Network 정보 및 수집한 Network 상태 정보는 etcd에 저장함으로써 다른 node로 전달한다.
bird: BGP 프로토콜을 통해 다른 노드와 라우팅 정보를 주고받는 daemon
- 각 Node의 Pod 라우팅 정보를 다른 Node에 전달하며, TCP 179 포트를 통해 mesh 구조로 연결된다.
- 라우팅 방식은 두 가지:
- Full mesh: 모든 node 간 직접 연결 (소규모 클러스터 적합)
- Route Reflector: 특정 node만 중계 역할 (대규모 클러스터 적합)
confd: calico-node 안에서 동작하는 구성 파일 관리 도구
- etcd 등 데이터 저장소에서 설정값을 받아 bird용 설정 파일을 생성한다.
- datastore로 지정된 저장소를 모니터링하다 설정 변경이 감지되면 bird에게 갱신을 트리거한다.
CNI Plugin: Cluster Networking을 위한 CNI 플러그인으로, Spec이 정해져 있으며 Node마다 실행파일 형식으로 제공된다.
- Pod가 생성될 때 쿠버네티스 Kubelet에 의해 호출되며, 해당 Pod에 네트워크 인터페이스를 생성하고, IP를 할당하며, 라우팅 및 정책 설정을 수행하는 역할을 한다.
/opt/cni/bin/ 경로에 binary 형태로 배포되며, kubelet이 Pod를 생성할 때 호출하여 Pod에 인터페이스를 연결하고 IPAM 플러그인과 협력해 IP를 할당한다.
IPAM Plugin: Pod의 IP 주소를 할당, 관리하는 플러그인으로, Pod가 생성될 때 적절한 CIDR 블록에서 IP 주소를 할당하고, Pod 삭제 시에는 해당 IP를 회수한다.
- IP 충돌 방지, IP 재사용, 할당 이력 추적 등의 역할을 담당한다.
calico-node 안의 felix와 함께 작동하며, 필요한 정보는 Datastore를 통해 주고받는다.
Datastore: Cluster Networking에 필요한 정보와 현재 상태를 저장하기 위한 Datastore를 요구하며 Kubernetes 또는 etcd 모드가 존재한다.
- Kubernetes: k8s api server를 통해 데이터를 저장하는 방식, RBAC 기능을 통해 Calico 리소스에 대한 접근을 제어할 수 있으며, Calico 리소스 업데이트에 대한 로깅이 가능하다.
- etcd: k8s가 아닌 플랫폼이거나 Multi-cluster에서 Calico를 사용해야 할 때 선택하며, k8s와 Calico 리소스를 분리할 수 있다.
- Typha: Datastore와 다른 component 사이에서 캐쉬 역할을 수행하며, 하나의 Datastore로부터 수많은 listener에게 데이터를 전달하는 Fan-out 형태를 갖는다.
- Deployment로 배치되어 Pod로 실행되며, 수천 노드 규모의 대형 클러스터에서 Datastore 부하를 줄이기 위해 사용한다.
- Optional Component로 Calico를 Default 모드로 설치할 경우, 비활성화된 상태로 배포된다.
calicoctl: Calico 리소스의 CRUD Operation을 위한 전용 CLI, Datastore에 접근 가능한 Host에서 사용 가능하다.
- 별도로 설치해야 하며, Binary 파일 혹은 Container로 배포되어 있다.
이제 Calico에서 핵심 역할을 수행하는 BGP가 실제로 어떻게 각 노드 간 라우팅 정보를 교환하며 동작하는지를 구체적으로 살펴보자.
BGP 개요
서로 다른 네트워크(AS, Autonomous System) 간에 경로 정보를 교환하기 위한 표준 라우팅 프로토콜로, 인터넷의 백본을 형성하는 핵심 기술
- BGP는 AS 간의 IP 경로 정보를 교환하여 어떤 목적지로 가는 트래픽을 어느 경로로 전달할지를 결정한다.
- 하나의 AS는 ISP나 대형 조직 내부의 네트워크를 의미하며, 각 AS는 고유한 ASN(Autonomous System Number)을 가진다.
- BGP는 이 ASN과 다양한 속성 정보를 기반으로 경로를 계산하고 선택한다.
- BGP Peering:
- BGP는 peer(BGP Speaker) 간에 TCP(179번 포트)로 연결을 맺고, NLRI(Network Layer Reachability Information) 및 경로 속성 정보를 주고받는다.
- 이 피어링은 AS 내부(iBGP) 또는 AS 외부(eBGP) 간에 형성될 수 있다.
- BGP는 여러 경로 중에서 최적의 경로를 선택하며, 주요 기준은 다음과 같다:
- AS Path: 경로를 거쳐간 AS들의 목록 (짧을수록 선호)
- Next Hop: 다음 목적지 IP
- Local Preference: 내부 우선순위 값
- MED(Multi Exit Discriminator): 동일 목적지에 대해 어떤 경로를 우선시할지 결정
- 특징
- 복잡한 네트워크 구조와 다양한 정책을 지원하며, 수천 개의 경로를 효율적으로 관리할 수 있도록 설계되었다.
- 반면, 경로 변경 시 수렴 시간이 길고 설정이 복잡하다는 단점도 존재한다.
BGP Peering은 동일 AS 내부(iBGP) 또는 다른 AS 간(eBGP)에 설정될 수 있다. Calico는 일반적으로 쿠버네티스 클러스터 내부 노드 간의 라우팅 정보를 교환하므로 iBGP 형태의 Full Mesh 또는 Route Reflector 구조를 사용한다.
Calico 내에서의 BGP의 동작 방식
Calico는 쿠버네티스 클러스터 내 각 노드가 Pod의 네트워크 범위(CIDR)를 서로 공유할 수 있도록 BGP를 사용한다. 각 노드에는 calico-node가 배포되며, 이 안의 bird 데몬이 BGP peer로 설정된 다른 노드들과 라우팅 정보를 주고받는다.
- Pod가 생성되면, 해당 Pod의 IP는 IPAM Plugin을 통해 할당되고, felix는 이 정보를 기반으로 Linux 커널의 Routing Table(FIB)에 해당 라우팅을 등록한다.
- confd는 Datastore(etcd 또는 Kubernetes API)를 감시하고 있다가 라우팅 정보가 변경되면 설정 파일을 갱신하고, bird 데몬에 이를 반영하라고 알린다.
- bird는 BGP를 통해 자신이 가진 Pod CIDR 정보(e.g. 10.244.1.0/24)를 다른 노드에 전파한다. 동시에 다른 노드로부터 받은 CIDR도 자신의 Routing Table에 반영한다.
- 결과적으로 모든 노드는 다른 노드의 Pod CIDR을 알고 있고, 해당 CIDR로 가는 경로를 자신 내부의 Routing Table에 보유하게 된다.
- 실제 통신 시, Node A의 Pod가 Node B의 Pod와 통신할 경우:
- 패킷은 Node A의 커널 Routing Table을 따라 Node B의 IP로 전송된다.
- Node B는 받은 패킷을 자신의 Pod로 전달한다. 중간에 VXLAN이 설정되어 있다면 overlay 터널링을 거쳐 전달된다.