Cilium K8S Ingress Support 소개
- Cilium은 IngressClassName이 cilium인 표준 Kubernetes Ingress 리소스 정의를 사용한다.
- 경로기반 라우팅 및 TLS 종료에 사용할 수 있다. 이전 버전과의 호환성을 위해 cilium 값을 가지는 kubernetes.io/ingress.class annotation도 지원이 된다.
- Ingress Controller는 Load Balancer 유형의 서비스를 생성하므로, 사용자 환경에서 이를 지원해야 한다.
- Cilium을 사용하면 Ingress 리소스에 대한 Load Balancer(LB) 모드를 지정할 수 있다.
- dedicated : Ingress 컨트롤러는 Ingress에 대한 전용 LB를 생성한다.
- shared : Ingress 컨트롤러는 모든 Ingress 리소스에 대해 공유 LB를 사용한다.
- 공유 모드는 클러스터 내 모든 Ingress 리소스에서 단일 LB 구성을 공유하여 리소스를 절약하는 반면, 전용 모드는 리소스 간의 잠재적 충돌(ex - path prefix)을 방지하는데 도움이 된다.
- Ingress 리소스에 대한 Load Balancer 모드를 변경할 수 있다.
- 모드가 변경되면 Ingress 리소스에 대한 새로운 LB IP가 할당되어, 재구성 중에 Ingress 백엔드에 대한 활성 연결이 종료될 수 있다.
경로 기반 라우팅
Ingress 같은 L7 레벨에서, URL 경로(path) 에 따라 요청을 서로 다른 백엔드 서비스로 라우팅하는 방식
예를 들어, 사용자가 https://example.com 로 접근할 때,
- https://example.com/api/ → api-service (백엔드 API 서버)
- https://example.com/web/ → web-service (프론트엔드 웹 서버)
- https://example.com/chat/ → chat-service (채팅 서버)
즉, 같은 도메인을 쓰더라도, 경로에 따라 다른 서비스로 연결되는 구조이다.
TLS 종료
TLS 종료란, HTTPS 암호화를 Ingress에서 풀어서 (복호화), 백엔드로 전달하는 방식.
- Client -> Ingress
- 사용자는 https://example.com 으로 접근
- 이 때 브라우저는 TLS(SSL) 인증서를 확인하고, 암호화된 HTTPS 연결을 설정
- Ingress 에서 인증서 처리
- Ingress Controller (Nginx, HAProxy, Cilium 등)에 TLS 인증서가 설치되어 있음.
- Ingress가 클라이언트의 암호화된 요청을 받아 복호화(Decryption) 수행
- Ingress -> 백엔드 서비스(Pod)
- Ingress 내부 Pod(Service)와는 HTTP 또는 다시 TLS로 재암호화 해서 통신할 수 있음.
- 이때 백엔드 Pod는 TLS를 몰라도 되며, Ingress가 대신 인증서를 처리
Pod 마다 인증서를 설치하고 TLS를 처리하면 복잡하고 리소스 낭비가 되기 때문에 Ingress 에서 한번만 인증서를 처리하는 방식
Cilium Ingress & Gateway API VS Other Ingress Controller
- Cilium의 Ingress 및 Gateway API 지원이 다른 Ingress 컨트롤러와 큰 차이점 중 하나는 "구현이 CNI와 얼마나 밀접하게 연결되어 있는가?" 이다. Cilium의 경우 Ingress와 Gateway API는 네트워킹 스택의 일부이므로 다른 Ingress 또는 Gateway API 컨트롤로와는 다른 방식으로 작동한다.
- 다른 Ingress 및 Gateway API 컨트롤러는 일반적으로 클러스터에 Deployment 또는 데몬셋으로 설치되며, Loadbalancer Service 또는 이와 유사한 서비스를 통해 노출된다.
- Cilium Ingress 및 Gateway API 구성은 Loadbalancer 또는 NodePort 서비스를 통해 노출되거나, 선택적으로 Host network에서도 노출될 수 있다. 이 모든 경우에 트래픽이 서비스의 포트에 도착하면 eBPF 코드가 트래픽을 가로채 투명하게 Envoy에 전달한다.
- 이는 Client IP visibility 같은 문제에 영향을 미치며, 다른 입력 컨트롤러에 대한 Cilium의 Ingress 또는 Gateway API와 다르게 작동한다.
- 또한 Cilium의 네트워크 정책 엔진이 Ingress에서 들어오는 트래픽 경계와 트래픽에 CiliumNetworkPolicy 를 적용할 수 있도록 한다.
Client IP visibility 문제?
주로 로드 밸런서, 프록시, 서비스 메스 같은 중간 계층을 거칠 때 원래 클라이언트 IP가 서비스 애플리케이션까지 제대로 전달되지 않는 문제.
다른 Ingress 컨트롤러에서는 X-Forwarded-For 나 PROXY protocol 같은 메커니즘을 써서 복구를 해야한다.
Cilium Ingress 같은 경우는
- L4모드 (NodePort, DirectRouting, BGP 등) 에서는 원본 Client IP를 Pod 까지 전달하는 기능을 제공한다.
- 커널 eBPF 에서 NAT 동작을 제어하기 때문.
- L7 Ingress 모드 (Envoy 기반)의 경우는 다른 Ingress 컨트롤러와 마찬가지로 X-Forwarded-For 헤더에 Client IP를 넣어서 전달 한다.
- 애플리케이션에서 X-Forwarded-For 헤더를 신뢰해야 한다.
실습
# cilium 설치 시 아래 파라미터 적용되어 있음
## --set ingressController.enabled=true
## --set ingressController.loadbalancerMode=shared
## --set loadBalancer.l7.backend=envoy \
cilium config view | grep -E '^loadbalancer|l7'
# ingress 에 예약된 내부 IP 확인 : node(cilium-envoy) 별로 존재
kubectl exec -it -n kube-system ds/cilium -- cilium ip list | grep ingress
# cilium-envoy 확인
kubectl get pod -n kube-system -l k8s-app=cilium-envoy -owide
kc describe pod -n kube-system -l k8s-app=cilium-envoy

kubectl get svc,ep -n kube-system cilium-envoy
kubectl get svc,ep -n kube-system cilium-ingress

LB-IPAM 설정 후 확인 : CiliumL2AnnouncementPolicy
# 현재 L2 Announcement 활성화 상태
cilium config view | grep l2
kubectl get ippools -o jsonpath='{.items[*].status.conditions[?(@.type!="cilium.io/PoolConflict")]}' | jq

# L2 Announcement 정책 설정
cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2alpha1"
kind: CiliumL2AnnouncementPolicy
metadata:
name: policy1
spec:
interfaces:
- eth1
externalIPs: true
loadBalancerIPs: true
EOF
# 현재 리더 노드 역할 확인
kubectl -n kube-system get lease/cilium-l2announce-kube-system-cilium-ingress -o yaml | yq

# K8S 클러스터 내부 LB EX-IP로 호출 가능
LBIP=$(kubectl get svc -n kube-system cilium-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo $LBIP
arping -i eth1 $LBIP -c 2

# k8s 외부 노드(router)에서 LB EX-IP로 호출 가능 확인
sshpass -p 'vagrant' ssh vagrant@router sudo arping -i eth1 $LBIP -c 2

Ingress HTTP Example
# Deploy the Demo App : 공식 문서는 release-1.11 로 ARM CPU 에서 실패한다. 1.26 버전을 높여서 샘플 배포 할 것!
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.26/samples/bookinfo/platform/kube/bookinfo.yaml
# istio 와 다르게 사이드카 컨테이너가 없다 1/1 , NodePort와 LoadBalancer 서비스 없다.
kubectl get pod,svc,ep
#
kc describe ingressclasses.networking.k8s.io
kubectl get ingressclasses.networking.k8s.io
NAME CONTROLLER PARAMETERS AGE
cilium cilium.io/ingress-controller <none> 16m
# Basic ingress for istio bookinfo demo application, which can be found in below
cat << EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: basic-ingress
namespace: default
spec:
ingressClassName: cilium
rules:
- http:
paths:
- backend:
service:
name: details
port:
number: 9080
path: /details
pathType: Prefix
- backend:
service:
name: productpage
port:
number: 9080
path: /
pathType: Prefix
EOF
# Adress 는 cilium-ingress LoadBalancer 의 EX-IP
kubectl get svc -n kube-system cilium-ingress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cilium-ingress LoadBalancer 10.96.154.81 192.168.10.211 80:32046/TCP,443:31695/TCP 154m
kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
basic-ingress cilium * 192.168.10.211 80 33s
kc describe ingress
Host Path Backends
---- ---- --------
*
/details details:9080 (172.20.1.59:9080)
/ productpage:9080 (172.20.1.202:9080)
# 호출 확인
LBIP=$(kubectl get svc -n kube-system cilium-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo $LBIP
# 실패하는 호출이 있는가?
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/ # 200
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/details/1 # 200
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/ratings # 404

# router에서 호출
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/
curl -so /dev/null -w "%{http_code}\n" http://$LBIP/details/1
sshpass -p 'vagrant' ssh vagrant@router curl -s http://$LBIP/
sshpass -p 'vagrant' ssh vagrant@router curl -s http://$LBIP/details/1 -v
#...
#< server: envoy
#< date: Sat, 16 Aug 2025 09:57:38 GMT
#< content-length: 178
#< x-envoy-upstream-service-time: 20
sshpass -p 'vagrant' ssh vagrant@router curl -s http://$LBIP/ratings

'DevOps > cilium' 카테고리의 다른 글
| [Cilium Study] Mutual Authentication (0) | 2025.08.23 |
|---|---|
| [Cilium Study] Cilium Service Mesh 3 (0) | 2025.08.20 |
| [Cilium Study] Cilium Service mesh 1 (0) | 2025.08.17 |
| [Cilium Study] BGP / Cluster mesh 비교 (4) | 2025.08.17 |
| [Cilium Study] Cluster mesh (3) | 2025.08.17 |