글 작성자: 근삼이

Kubernetes를 설치하여 사용할때 항상 CNI를 설치해야 core-DNS서비스가 정상동작하고, 네트워크 폴리시 등의 보안 정책을 적용할 수 있었기에, 그냥 무의식적으로 설치하여 사용했었는데 막상 다시한번 내가 쿠버네티스를 제대로 이해하고 있는가? 를 되돌아보다 보니, 가장 중요하고 기본적인 지식인 네트워크 부분을 제대로 이해하지 않고 대충 넘어갔던것이 아닌가 하는 생각이 들었다.

다중노드 및 대규모 클러스터 환경에서 올바른 컨테이너로 트래픽을 전달하기 위해서 사용한다고만 개념적으로 이해하고 있었지, istio와 같은 서비스메시를 이해하기 시작하면서 명확한 그 개념에 대해서 혼돈이 오기 시작했다.

그래서 오늘은 가장 대표적으로 많이 사용되는 Calico CNI 플러그인을 분석해 보면서 다른 CNI들과 비교하는 시간을 가져볼까 한다.

CNI는 정확하게 무엇인가

“리눅스 컨테이너를 위한 네트워킹“

CNI 공식 GitHub(https://github.com/containernetworking/cni )에 따르면, CNCF 프로젝트 중 하나인 CNI(Container Network Interface)는 컨테이너 간의 네트워킹을 제어할 수 있는 플러그인을 만들기 위한 표준이다. 컨테이너의 발전이 가속화 됨에 따라 다양한 형태로 컨테이너 런타임과 오케스트레이터 사이의 네트워크 계층을 구현하는 방식이 다양하게 분리되어 각자만의 방식으로 발전하게 되는 것을 피하기 위해 공통된 인터페이스를 제공하기 위해 만들어 졌다고 한다. 네트워크 인터페이스의 사실상 표준으로 사용되는 듯 하다.

Kubernetes에서의 CNI와 CNI 플러그인

쿠버네티스 뿐 아니라 컨테이너 런타임을 포함하고 있는 다양한 플랫폼들(Apache Mesos, Amazone ECS, rkt, Cloud Foundry)들은 네트워크 인터페이스로 이미 CNI를 사용하고 있다. 하지만 CNI는 말 그대로 표준으로써의 역할을 할 뿐, 특정 서비스에 어울리는 기능을 구현해 내기 위해서는 CNI를 활용한 추가적인 기능개발을 통해 서비스에 적용해야 할 것이다. CNI 문서에서는 이러한 구현을 3rd party plugins, 쿠버네티스 문서에서는 network plugin, 또 다른 문서들에서는 cni network providers 혹은 그냥 cni 로 지칭하여 부르기도 한다. 마땅히 특정 단어로 부르도록 정해진 것이 아닌건지 싶다. 생각해 보면 위에 나열된 단어중 특별히 어떤 단어를 대입시켜 보아도 크게 이상하지는 않지만, 단지 CNI 라는 이름만으로 부르기에는 부족하게 느껴지고, 무엇보다 쿠버네티스의 설정이 바라보고 있는 이들의 이름은 cni plugin 으로 보이기에, 나는 앞으로 ‘서드파티 CNI 플러그인’ 이라고 부를 생각이다. 아래는 쿠버네티스의 CNI 설정파일인 /etc/cni/net.d 내의 설정파일 내용인데, 해당 설정파일내에서도 특정 CNI 플러그인의 내용을 지칭할때 “plugins” 라는 표현을 사용했다.

{
  "name": "k8s-pod-network",
  "cniVersion": "0.3.0",
  "plugins": [
    {
      "type": "calico",
      "log_level": "info",
      "datastore_type": "kubernetes",
      "nodename": "127.0.0.1",
      "ipam": {
        "type": "host-local",
        "subnet": "usePodCidr"
      },
      "policy": {
        "type": "k8s"
      },
      "kubernetes": {
        "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
      }
    },
    {
      "type": "portmap",
      "capabilities": {"portMappings": true}
    }
  ]
}

사실 이것이 무엇으로 불리든 큰 상관은 없지만, 확실하게 표현을 정하고 문서를 작성해야 이후에도 헷갈리지 않을듯 하여 이름을 정해 보았다. 하여간 쿠버네티스는 기본적으로 매우 제한적인 네트워크 기능만을 제공하는 kubenet 이라는 자체 CNI 플러그인을 기본제공한다. 그 이외에도 Calico, Weave, Cilium 등과 같은 다양한 서드파티 CNI 플러그인들이 존재한다.

서드파티 CNI 플러그인을 왜 쓸까

위에서 설명한 기본제공 CNI 플러그인으로 kubenet이 존재하는데, 다양한 서드파티 CNI 플러그인들을 사용하는 이유는 무엇일까?

서드파티 CNI들이 제공하는 다양한 기능들(Network Policy, Public 클라우드와의 통합, 대규모 트래픽에 대한 안정성 등)이 이유일 수도 있지만, 무엇보다 기본제공되는 kubenet의 기능이 너무 부족하기 때문이다. kubenet은 그 자체로는 컨테이너간의 노드간 교차 네트워킹조자 지원하지 않는다.

CNI 플러그인의 네트워크 모델

CNI 플러그인들은 매우 다양한 지표를 통해 비교하고 분류할 수 있지만, 본질적 기능인 컨테이너 및 노드간의 통신을 중개할 때 사용하는 네트워크 모델을 어떤 것을 사용하는지에 따라 가장 크게 분류해 볼 수 있다. CNI 플러그인들은 크게 두 가지 형식의 네트워크 모델을 사용하는데

  • VXLAN(Virtual Extensible LAN)IP-in-IP 프로토콜을 사용하는 오버레이 네트워크 모델과
  • BGP(Border Gateway Protocal)을 사용하는 비-오버레이 네트워크 모델이 있다.

먼저 오버레이 네트워크에 대해서 살펴보자면, 기본 개념은 실제로는 복잡할 수 있는 엔드포인트 간의 네트워크 구조를 추상화하여 네트워크 통신 경로를 단순화 하는 것 이다.

오버레이 네트워크는 3계층을 넘어서 구축된 네트워크 간에 있는 엔드포인트의 노드간의 통신이 일어날때 패킷을 한겹 캡슐화 하여 통신시켜서, 2계층에서(같은 LAN에서) 통신이 일어나는 것처럼 통신할 수 있도록 하는 기술이다.

Overlay Network는 기본적으로 ①패킷을 encapsulation 해서 통신 노드간에 가상 Tunnel을 생성하고, 각 노드에 위치한 가상의 터널의 Endpoint(Virtual Tunnel EndPoint : aka… VTEP)를 통해 ②캡슐화 된 패킷을 전달하는 방식을 활용하여 복잡한 네트워크 환경에서의 통신을 추상화 한다.

Calico를 기준으로는 현재 두 가지 방식의 Overlay Network가 지원되는데, vxlan 프로토콜을 사용하는 방식과 IP-in-IP 프로토콜을 사용하는 방식이 있다. 조사해 본 결과로는 vxlan이 IP-in-IP 프로토콜에 비해 범용성이 있는(IP-in-IP 프로토콜은 Azure 클라우드와 같은 특정 환경에서는 사용이 어렵다고 한다) 대신 성능이 IP-in-IP 프로토콜에 비해 근소하게 뒤떨어진 모습을 보여준다고 한다. 하지만 매우 극단적인 트래픽이 아닌 이상 차이를 실감하기 어려운 정도의 수준이어서 오버레이 네트워크를 사용할 때 가장 기본적으로 사용되는 방식이다.

오버레이 네트워크를 사용하면 거의 대부분의 환경에서 기존 네트워크 환경에 영향 없이 CNI 환경을 구성할 수 있지만, BGP 프로토콜을 사용하는 방식에 비해 패킷을 캡슐화 할때 CPU 등의 자원도 소모하고 패킷의 전체 크기에서 캡슐화를 위해 사용하는 영역 만큼 패킷 당 송/수신 할 수 있는 데이터의 양이 줄어들어 상대적으로 비효율 적인 단점도 있다.

 

BPG 기반의 오버레이는 통신이 발생하는 노드간에 bgp 프로토콜을 사용하는 소프트웨어 라우터의 구현을 통해서 최적의 경로 정보를 현재 엔드포인트들의 상태를 따라서 동적으로 감지하여 적용할 수 있다는 전제를 통해 구현되는 네트워크 모델이다.

BGP 프로토콜을 사용하여 CNI를 구성하면, HA를 위해 클러스터 구성 노드들간의 서브넷이 다르게 구성되어 있는 경우 상위의 물리 라우터에도 별도의 설정을 해주어야 하고, 통신이 가능한 대역에서 여러 클러스터를 활용하거나 별도의 외부 서비스들을 운영하는 경우 네트워크 대역이 겹치지 않도록 관리를 해주어야 하고, 그렇기 때문에 퍼블릭 클라우드 등에서의 구성이 자유롭지 않은 등의 단점이 있다.(상단 라우터의 설정을 임의로 수정하는 것이 어렵기 때문)

하지만 별도의 패킷 가상화 없이 기존에 네트워크에서 사용하던 직관적인 라우팅 방식을 이용함으로써 클러스터 외부에서도 Ingress나 Service의 도움 없이 POD에 접근 할 수 있게 되고, 통일화 된 보안 설정 관리 및 디버깅/로깅의 용이성과 더불어 오버레이 네트워크에 비해 성능이 좋다는 구분되는 장점도 분명하게 존재한다.

CNI에서 Overlay Network vs BGP 네트워크 모델 요약

두 네트워크 모델 중에서는 BGP기반의 모델이 성능적으로 더 빠르고 안정적인 모습을 보여준다. 패킷에 대한 캡슐/복호화 과정에서 발생하는 오버헤드가 없기 때문이다.

하지만, BGP기반의 방식은 노드간의 서브넷이 다를 경우 물리적인 라우터 장비의 설정을 변경해주어야 하는 환경 의존성이 분명하게 존재하고, 이 단점은 특히 퍼블릭 클라우드에서 쿠버네티스 환경을 구성할 때 치명적인 단점으로 계산된다.

따라서, 본인의 클러스터를 구성하는 환경에 따라서 적절한 네트워크 모델을 선택하여 적용하는 것이 바람직 하다.

CNI 플러그인들 비교

CNI 플러그인들은 그 종류가 매우 다양하고 많기 때문에 모든 플러그인들을 놓고 비교할 수는 없지만, 본 글에서는 대표적으로 많이 사용하는 몇 가지 플러그들의 기능 지원 표를 통해 비교해 본다.

그래서 어떤 CNI 플러그인을 사용해야 하나?

사실 이 주제는 구동하는 환경과 상황에 따라 다르다. 라고 말할 수 밖에 없다. 각각의 CNI플러그인들이 가지고 있는 평균적인 퍼포먼스 수치는 명확하게 비교할 수 있으나, 지원하는 기능이나 특장점들이 모두 제각각 다르기 때문에 특정 CNI만을 사용하기 보다는 각각의 기능에 맞추어서 여러가지 CNI를 혼합하여 사용하는 것이 일반적이기도 하고, 워낙 빠르게 진보하고 있는 분야이다 보니 당장 내일 더 획기적인 기능을 가진 플러그인이 나타날 수 도 있기 때문이다.

하지만 글을 작성하고 있는 시점인 2021년 10월 기준으로는 Calico CNI플러그인이 가장 보편적이고 다양한 기능을 제공하면서 성능적으로도 매우 준수하고, 다른 CNI플러그인과의 결합을 통한 확장성 또한 잘 구현이 되어 있다고 말할 수 있다. (이 내용은 자원 사용량, 네트워크 속도, 기능 확장성등을 벤치마크한 여러 게시물들과 필자의 짧은 테스트 경험을 기반으로 전달하는 내용이기에 다소 주관적일 수 있으니 참고로만 여겨주었으면 한다.)

반응형