Cloudnet Cilium 4주차 스터디를 진행하며 정리한 글입니다.
이번 포스팅에서는 Cilium LB-IPAM 기능을 활용하여 Kubernetes 서비스에 External IP를 자동 할당하는 방법을 실습합니다.
LB-IPAM
LB-IPAM은 Cilium이 LoadBalancer 타입 서비스에 IP 주소를 직접 할당해주는 기능입니다.
LoadBalancer IPAM은 LoadBalancer 서비스에 할당할 External IP 풀을 정의하고, 서비스에 자동으로 부여하는 역할을 합니다.
BGP Control Plane과 연동하면 할당된 IP를 BGP를 통해 외부 라우터에 광고할 수 있습니다.
L2 Announcements / L2 Aware LB를 사용하면 L2 브로드캐스트 방식으로 IP를 광고하여 같은 L2 네트워크의 외부 장치가 접근할 수 있습니다.
LB-IPAM은 기본적으로 활성화되어 있지만, IP 풀(CiliumLoadBalancerIPPool)이 생성되기 전까지는 동작하지 않습니다.

Cilium LB IPAM 실습
서비스에 할당할 External IP 범위를 CiliumLoadBalancerIPPool로 생성합니다.
webpod 서비스를 LoadBalancer 타입으로 변경하여 LB-IPAM이 External IP를 자동 할당하도록 합니다.
실행 결과, webpod 서비스에 192.168.10.211과 같은 External IP가 자동 할당된 것을 확인할 수 있습니다.
root@k8s-ctr:~# kubectl get CiliumLoadBalancerIPPool -A
No resources found
# cilium ip pool 생성
root@k8s-ctr:~# cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2" # v1.17 : cilium.io/v2alpha1
kind: CiliumLoadBalancerIPPool
metadata:
name: "cilium-lb-ippool"
spec:
blocks:
- start: "192.168.10.211"
stop: "192.168.10.215"
EOF
ciliumloadbalancerippool.cilium.io/cilium-lb-ippool created
root@k8s-ctr:~# kubectl api-resources | grep -i CiliumLoadBalancerIPPool
ciliumloadbalancerippools ippools,ippool,lbippool,lbippools cilium.io/v2 false CiliumLoadBalancerIPPool
# IP 풀에 사용 가능한 IP 개수와 충돌 여부를 확인
root@k8s-ctr:~# kubectl get ippools
NAME DISABLED CONFLICTING IPS AVAILABLE AGE
cilium-lb-ippool false False 5 24s
# webpod 서비스를 LoadBalancer Type 변경 설정
root@k8s-ctr:~# kubectl patch svc webpod -p '{"spec":{"type":"LoadBalancer"}}'
service/webpod patched
root@k8s-ctr:~# kubectl get svc webpod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
webpod LoadBalancer 10.96.215.249 192.168.10.211 80:32549/TCP 104m
할당된 IP(192.168.10.211)로 클러스터 내부 노드(k8s-ctr)에서 직접 curl 요청을 보내 보았습니다.
그 결과, 응답 본문에서 Hostname 값이 서비스의 파드 이름으로 출력되고,
RemoteAddr 값이 172.20.0.84:52208과 같이 Cilium Pod 네트워크 대역(172.20.x.x)임을 확인할 수 있었습니다.
이를 통해 클러스터 내부에서는 LB-IPAM이 할당한 External IP로 정상적으로 통신이 가능함을 알 수 있습니다.
이번에는 클러스터 내부 Pod(curl-pod)에서 동일한 External IP로 접근했습니다.
응답에는 Hostname: webpod-697b545f57-9ns5w와 같은 파드 이름이 출력되었고,
RemoteAddr 값이 172.20.0.215:58548로 표시되었습니다.
이 역시 Cilium Pod 네트워크 대역이므로, 서비스 파드 입장에서 요청이 클러스터 내부에서 온 것임을 알 수 있습니다.
# LBIP로 curl 요청 확인 : k8s 노드들에서 LB EXIP로 통신 가능!
root@k8s-ctr:~# kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
192.168.10.211
root@k8s-ctr:~# LBIP=$(kubectl get svc webpod -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
root@k8s-ctr:~# curl -s $LBIP
Hostname: webpod-697b545f57-mn7r5
IP: 127.0.0.1
IP: ::1
IP: 172.20.0.154
IP: fe80::ccdc:27ff:fe5d:45de
RemoteAddr: 172.20.0.84:52208
GET / HTTP/1.1
Host: 192.168.10.211
User-Agent: curl/8.5.0
Accept: */*
root@k8s-ctr:~# kubectl exec -it curl-pod -- curl -s $LBIP
Hostname: webpod-697b545f57-9ns5w
IP: 127.0.0.1
IP: ::1
IP: 172.20.2.152
IP: fe80::a43c:f7ff:fe42:d57a
RemoteAddr: 172.20.0.215:58548
GET / HTTP/1.1
Host: 192.168.10.211
User-Agent: curl/8.14.1
Accept: */*
root@k8s-ctr:~# kubectl exec -it curl-pod -- curl -s $LBIP | grep Hostname
Hostname: webpod-697b545f57-mn7r5
root@k8s-ctr:~# kubectl exec -it curl-pod -- curl -s $LBIP | grep RemoteAddr
RemoteAddr: 172.20.0.215:53770
root@k8s-ctr:~# kubectl get ippools
NAME DISABLED CONFLICTING IPS AVAILABLE AGE
cilium-lb-ippool false False 4 4m18s
root@k8s-ctr:~# kubectl get ippools -o jsonpath='{.items[*].status.conditions[?(@.type!="cilium.io/PoolConflict")]}' | jq
{
"lastTransitionTime": "2025-08-09T18:52:40Z",
"message": "5",
"observedGeneration": 1,
"reason": "noreason",
"status": "Unknown",
"type": "cilium.io/IPsTotal"
}
{
"lastTransitionTime": "2025-08-09T18:52:41Z",
"message": "4",
"observedGeneration": 1,
"reason": "noreason",
"status": "Unknown",
"type": "cilium.io/IPsAvailable"
}
{
"lastTransitionTime": "2025-08-09T18:52:41Z",
"message": "1",
"observedGeneration": 1,
"reason": "noreason",
"status": "Unknown",
"type": "cilium.io/IPsUsed"
}
이번 실습을 통해 Cilium LB-IPAM을 사용하여 LoadBalancer 타입 서비스에 External IP를 자동 할당하는 방법을 확인했습니다.
현재 상태에서는 클러스터 내부 노드 또는 Pod에서만 External IP로 접근이 가능하고, 외부(예: 라우터, 다른 서버)에서는 접근 시도 시 응답이 오지 않습니다.
그 이유는 LB-IPAM이 IP를 할당하는 역할만 하기 때문이며, 외부 네트워크에서 해당 IP로 트래픽을 전달하려면 추가 설정이 필요합니다.
외부 접근을 가능하게 하려면 다음 중 하나를 구성해야 합니다.
- BGP 광고
- Cilium BGP Control Plane을 통해 외부 라우터에 192.168.10.211 경로를 알림
- L2 Announcements / L2 Aware LB
- 동일 L2 네트워크에 ARP/NDP 브로드캐스트를 전송해 해당 IP를 알림
다음 포스팅에서는 L2 Announcements에 대해 알아보겠습니다.
'스터디 > Cilium' 카테고리의 다른 글
| [Cilium] BGP Control Plane (5) | 2025.08.17 |
|---|---|
| [Cilium] L2 Announcements (4) | 2025.08.10 |
| [Cilium] Overlay Network (Encapsulation) mode (0) | 2025.08.10 |
| [Cilium] Native Routing Mode (1) | 2025.08.10 |
| [Cilium] CoreDNS, NodeLocal DNSCache, Cilium Local Redirect Policy (6) | 2025.08.03 |