GKE에서 Calico CNI 사용하기

김도영
Cloud Villains
Published in
13 min readJun 24, 2022

Why?

Project Calico는 Kubernetes에서 사용하는 네트워크 정책 엔진입니다.

최근 Kubernetes 네트워크를 정책 기반으로 사용할 필요가 생겨 다양한 NPP(Network Policy Provider)중에서 대표적인 CNI인 Calico에 대해서 조사하게 되었습니다.

목표

GKE Calico CNI는 어떻게 사용하는지, GKE에서 이용 가능한 Calico CNI와 Default CNI는 어떤 차이가 있는지 알아보겠습니다.

먼저 Calico를 알아보기 전에 GKE Cluster 종류에 대해서 알아볼 필요가 있습니다. GKE Cluster는 트래픽을 전달하는 방법에 따라서 2가지 Cluster로 구분이 됩니다.

Alias IP Range를 사용해 트래픽을 전달하는 방법인 VPC Native Cluster가 있고 VPC Network Custom Static 경로를 사용하는 Route Based Cluster가 있습니다.

VPC Native Cluster

VPC Native Cluster로 GKE를 생성하면 아래와 같이 VPC-native traffic routing 부분이 Enabled이 되며

Cluster 생성 시 설정한 podCIDR와 serviceCIDR에 대해서 아래와 같이 Routing이 생성됩니다.

하지만 여기서 의문!

Destination이 특정 Node위에 있는 Pod IP인 트래픽인 경우. 위 Routing대로 Next hop인 custom-vpc로 향하게 될 것입니다. 하지만 custom-vpc로 도착한 트래픽은 해당 Pod IP가 어떤 Node에 위치하는지 알 수 없음으로 길을 잃게 될 것입니다.

그렇다면 특정 Pod에게 트래픽을 보냈을 때, 어떻게 Routing 정보만 가지고 Pod 위치를 알 수 있을까? 더 정확하게 말하면 Pod가 위치해 있는 Node를 어떻게 알고 찾아갈 수 있까? 라고 의문이 들 수도 있습니다.

여기서 VPC Native Cluster의 장점이 나타납니다. 앞에서 언급을 했지만 VPC Native Cluster는 Alias IP Range를 사용합니다.

아래와 같이 GKE의 Node는 Alias IP Range가 붙게 되며 이 Alias IP Range는 자신이 가지고 있는 Pod IP 대역을 나타냅니다.

즉, custom-vpc로 도착한 트래픽은 Node의 Alias IP Range를 보고 Destination Pod가 위치하고 있는 Node를 알 수 있으며 트래픽은 Pod가 위치한 Node에게 갈 수 있게 되고 통신이 이루어지는 것입니다. 동일한 VPC 내에 위치하기만 하면 VM 일지라도 Pod와 통신이 가능한 구성입니다.

Route based Cluster

Route based Cluster로 생성하게 되면 아래와 같이 VPC-native traffic routing이 Disabled가 되며

podCIDR에 대해서는 아래와 같이 Node 별로 Routing이 생성됩니다.
Node마다 Routing이 생성되는 이유는 간단합니다. Alias IP를 사용하지 않기 때문에 VPC가 아닌 바로 Node로 트래픽을 보내야 하기 때문입니다. 또한 Route based Cluster는 Service 대역대 관련해서는 GCP Route에 Routing이 따로 생성하지 않습니다.

GKE에서 Calico CNI를 사용

이번에는 GKE Calico CNI를 사용하는 방법에 대해서 알아보겠습니다.

사용 방법은 매우 간단합니다. 아래 이미지와 같이 Networking > Enable Kubernetes Network Policy를 Check만 해주면 알아서 설치해 주므로 매우 쉽게 Calico CNI를 사용할 수 있습니다.

이렇게 설치된 GKE의 Calico CNI와 일반적인 Calico CNI와 어떤 차이점이 있을까요? 이 차이점에 대해서 알아보겠습니다.
(기본적인 Calico에 대해서 알아보고 싶으면 링크를 참조해 주세요.)

첫 번째, GKE Calico는 Calico의 IPAM을 사용하지 않는다

GKE Node에 직접 들어가 cni 설정 파일을 확인해 보면 Calico ipam이 아닌 local-host ipam을 사용한다는 것을 확인할 수 있습니다.

두 번째, GKE는 Overlay Network를 사용하지 않는다.

IPAM을 사용하지 않음으로 calicoctl get ippool -o wide라는 명령어로는 확인이 불가하며 또한 각 Node에는 Overlay 네트워크 통신을 가능하게 해주는 Tunnel이라는 인터페이스도 존재하지 않습니다.

세 번째, BGP를 사용하지 않는다.

일반적인 kubernetes 환경에서 Calico CNI는 각 Node끼리 BGP를 통해서 Pod IP 대역을 공유하지만 GKE는 각 Node끼리 Pod 대역대 공유를 BGP를 통해서 하지 않습니다.

​직접 Node에 들어가 Process를 확인해 보면 BGP 프로토콜을 이용해 대역대를 광고하는 bird라는 Process가돌고 있지 않음을 확인할 수 있으며, 자연스럽게 confd도 사용할 필요가 없게 돼 confd Process도 없는 것을 알 수 있습니다.

통신 흐름

그렇다면 BGP를 사용하지 않고 GKE Calico는 어떠한 방식으로 Pod끼리 통신을 하게 되는 것일까요? 이해를 돕기 위해 Calico CNI를 사용하고 있는 GKE 아키텍처를 그려보았습니다.

설명을 하자면 Node1은 pod 10.84.1.0/24 대역대를 지니고 있고, Node2는 pod 10.84.2.0/24 대역대를 지니고 있습니다. 그리고 각 Route에는 각 Pod IP로 들어오면 가상 인터페이스인 cali로 들어가라는Routing이 잡혀있습니다. 여기서 포인트는 Node의 GCP NI에 Pod의 IP 대역대가 Alias IP로 추가가 되어있다는 것입니다.

Node마다 Alias IP가 없는 상태라면

이해를 돕기 위해 Alias IP가 없는 상태에 대해서 먼저 알아보겠습니다.
아래 이미지처럼 Node마다 Alias IP가 없는 상태에서 「pod4 → pod2」로 트래픽을 보낸다고 하면

pod2의 IP는 자신 Pod 대역이 아님으로 eth0으로 보내 것이며, GCP Route에 따라 해당 트래픽은 다시 calico-cluster-vpc로 이동을 할 것입니다. 하지만 Destination이 10.84.1.0/24 대역대를 가진 트래픽은 어떠한 정보도 없기 때문에 어떤 Node로 가야 할지 알 수가 없게 됩니다. 그럼으로써 해당 Packet은 Drop 처리가 될 것입니다.

Node마다 Alias IP가 있다면

이번에는 Alias IP로 Pod IP 대역을 가지고 있는 Node인 경우를 살펴보겠습니다. 먼저 아래 이미지를 보면 pod4번에서 보낸 트래픽이 pod2번까지 문제 없이 도달하고 있는 것을 알 수 있습니다. 왜 도달할 수 있을까요?

흐름을 따라가 보면 먼저 pod4에서 10.84.1.13으로 트래픽을 보내는 경우, 자신의 IP 대역대가 아님으로 eth0으로 보낼 것이고, eth0으로 나온 트래픽은 GCP Routes를 통해서 calilco-cluster-vpc로 가고 calilco-cluster-vpc 갔더니 10.84.1.13 IP가 포함되는 대역대인 10.84.1.0/24 대역대를 Alias IP로 가지고 있는 Node1이 있으므로 해당 패킷은 Node1로 들어가게 되고 Node1에서는 10.84.1.13으로 가려면 cali2로 가라는 Routing이 존재함으로 결국엔 pod2까지 패킷이 도달할 수 있는 것입니다.

​즉, GKE는 Alias IP를 사용하는 native VPC인 경우에만 GKE에서 제공하는 Calico CNI를 사용할 수 있으며, 이로 인해 BGP로 각 Node가 IP를 주고받지 않아도 되고 overlay 네트워크 또한 필요 없게 되는 것입니다.

Pod와 GCE 통신은 어떻게

다른 VPC에 존재하는 GCE(VM)와 Pod 간 통신도 크게 다르지 않게 아래와 같이 이루어집니다.

BGP 연동

그렇다면 GKE Calico 사용 중에 온프렘의 서버와 BGP를 통해서 IP 대역대를 연계하고 싶은 경우엔 어떻게 해야 할까요? 기존 Calico CNI처럼 BGPPeer Object를 생성해서 BPG Session을 맺어야 하는 것일까요?

하지만 이 방법은 GKE Calico는 BGP를 지원하지 않아 불가능합니다. 그렇다면 어떻게 해야 할까요?

답은 간단합니다. 이러한 경우에는 그냥 GCP VPN을 사용해서 온프레미스(또는 타 Provider)와 BGP 연결을 맺으면 됩니다. 온프레미스와 VPN을 통해 BGP 세션을 맺음으로써 GCP Route에는 온프레미스 대역대 Routing 정보가 추가될 것이며 Pod는 GCP Routes를 통해 온프레미스의 특정 서버까지 트래픽을 보낼 수 있게 될 것입니다.

GKE Calico CNI와 GKE Default CNI와 차이점

이번에는 Network Policy Enable을 안 했을 경우(GKE Calico가 아닌 경우) 사용되는 Default CNI Cluster와는 어떤 차이점이 있는지 알아보겠습니다. 일단 Document를 확인해 보면 Default CNI도 Calico와 동일하게 Virtual Route Table에 의해서 통신이 이루어지며, Calico와 다르게 Bridge가 생성이 되고 Bridge를 통해서 내부 Pod들이 통신이 된다고 기술되어 있습니다. 하지만 실제로 구성을 해보면 crb0의 Bridge는 존재하지 않습니다.

​또한 각 Node에 들어가 CNI 설정 정보를 보면 ptp로 통신한다는 것까지 알 수 있습니다. 개인적인 생각으론 GKE Calico와 GKE Default CNI의 차이점은 Proxy arp 기능 활성화 여부와 Label을 이용한 트래픽 제한하는 Network Policy 가능 사용 여부인 것 같습니다.

Proxy arp

Proxy arp를 간단하게 설명하자면 ARP 프로토콜을 이용해서 대신 MAC 주소를 알아와 주는 기능입니다. GKE Calico는 이 기능이 활성화되어있고 Default CNI는 비활성화로 Proxy arp가 아닌 직접 ARP를 Request를 해서 MAC 주소를 알아옵니다.

​Proxy arp는 가상 인터페이스에 설정하며, 확인은 아래 명령어로 확인이 가능합니다.

$ cat /proc/sys/net/ipv4/conf/[pod의 가상 인터페이스 ID]/proxy_arp

이처럼 GKE Default CNI는 0이며, GKE Calico CNI는 1로 되어있다는 것을 알 수 있습니다. Proxy arp를 사용 중인 Calico는 Pod 내부 route에 169.254.1.1로 가도록 Routing이 추가되어있고

​TcpDump를 통해 확인해 보면 Ping 통신을 했을 시 169.254.1.1로 ARP Request, Reply를 받는 것을 확인할 수 있습니다.

​그에 반해 Default CNI에서 Pod의 Route는 아래와 같으며

​TcpDump로 확인했을 때, 직접 ARP Request를 보내고 상대 Pod에게 직접 Mac 주소를 Reply를 받습니다.

Network Policy

Network Policy란 간단하게 Pod마다 Firewall이 있다고 생각하면 될 것 같습니다. 아키텍처는 아래와 같은 형태입니다.

간단하게 Network Policy의 기능인 Ingress Network Policy와 Egress Network Policy에 대해서 알아보겠습니다.

Ingress Network Policy

먼저 Network policy가 설정이 안 되어있는 상황에서 아래 명령어로 Pod와 Service를 생성합니다.

그리고 아래와 같이 NetworkPolicy를 생성한 다음

Test pod로 접근을 해보면 아래와 같이 Timeout이 발생합니다.

​그렇다면 방금 전에 생성한 NetworkPolicy에 대해 어떤 설정이 들어가 있는지 자세히 살펴보겠습니다.

Ingress에 대해서 Label 「app: foo」를 가진 Pod만 허용한다고 기술되어 있고 대상은 「app: hello」 label을 가진 pod 라는 것을 짐작할 수 있습니다.
Test Pod가 접근했을 시 Timeout이 발생한 이유는 Test Pod에 「app: foo」 label이 없었기 때문입니다.「app: foo」 label 추가 후 다시 통신을 해보면 문제 없이 통신이 통신이 가능한 것을 확인할 수 있습니다.

Egress Network Policy

Egress Network Policy는 특정 Pod에서 나가는 트래픽을 제한할 수 있습니다.Ingress와 생성 방법은 크게 다른 점은 없습니다.
먼저 아래 명령어로 pod와 service를 배포 후

아래와 같이 Egress를 제한하는 NetworkPolicy를 생성하면

​아래와 같이 통신이 안 되는 것을 알 수 있습니다.

Networkpolicy를 자세히 살펴보면「app: foo」 label을 지닌 pod가 「app: hello」 label을 지닌 pod로 가는 트래픽을 제한하겠다는 의미인 것을 유추 할 수 있습니다.

정리

VPC Native Cluster의 GKE 생성을 하면 Node에 Pod 대역이 Alias IP로 붙게 되며, 이 Alias IP가 붙음으로써 Pod와 Pod 통신 또는 Pod와 VM 통신 시 문제 없이 통신이 된다는 것을 알아보았습니다. 또한 기존 Calico와 다르게 BGP와 Network Overlay를 사용하지 않는데 그 이유는 Alias IP가 있으므로 굳이 사용할 필요가 없어서 였습니다. 그리고 GKE Calico 와 GKE Default CNI와 차이는 Proxy ARP와 Network Policy 기능의 유무였습니다.

메가존클라우드 GCP Team

메가존클라우드 GCP Team이 궁금하다면 다음 링크를 확인해 주세요!

https://ctc.oopy.io/gcp_sa_group_info

--

--