본문 바로가기
DevOps/cilium

[Cilium Study] Cilium Service Mesh 2

by 서어켜엉 2025. 8. 20.

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 로 접근할 때,

즉, 같은 도메인을 쓰더라도, 경로에 따라 다른 서비스로 연결되는 구조이다.

 

TLS 종료

TLS 종료란, HTTPS 암호화를 Ingress에서 풀어서 (복호화), 백엔드로 전달하는 방식.

  1. Client -> Ingress
    • 사용자는  https://example.com 으로 접근
    • 이 때 브라우저는 TLS(SSL) 인증서를 확인하고, 암호화된 HTTPS 연결을 설정
  2. Ingress 에서 인증서 처리
    • Ingress Controller (Nginx, HAProxy, Cilium 등)에 TLS 인증서가 설치되어 있음.
    • Ingress가 클라이언트의 암호화된 요청을 받아 복호화(Decryption) 수행
  3. 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