ExplanationKubernetes

Cilium Gateway API 외부 트래픽 진입점 선택하기

Cilium Gateway API의 데이터 경로를 이해하고 LoadBalancer, NodePort, hostNetwork 중 환경에 맞는 외부 노출 방식을 선택합니다.

업데이트 검증 근거 자료이 페이지 편집

핵심 요약

  • Cilium Gateway API는 Gateway와 HTTPRoute를 Envoy 설정으로 변환하고, Cilium eBPF 데이터 경로가 외부 연결을 노드별 Envoy로 전달하는 구조임
  • 외부 진입점은 기본 LoadBalancer Service, 외부 장비가 노드 포트를 조회하는 NodePort, 노드 포트에 직접 바인딩하는 hostNetwork 중 하나로 결정해야 함
  • 멀티 컨트롤 플레인은 Kubernetes API의 가용성 문제이고 애플리케이션 외부 트래픽의 가용성과는 별도 설계 대상임
  • 클라우드 공인 IP가 eth0에 보이지 않아도 공급자 SDN·가상 네트워크가 노드 vNIC와 연결할 수 있으므로 VM에서 관측한 목적지와 공급자 요구사항을 먼저 확인해야 함
  • 운영 전에는 주소 할당뿐 아니라 라우팅·광고, 보안 정책, 클라이언트 IP 신뢰 경계, 장애 제거 방식까지 함께 검증해야 함

Gateway API는 역할과 데이터 경로를 분리함

  • Gateway API는 인프라 소유자와 애플리케이션 소유자의 책임을 분리하는 API임

    • 플랫폼 팀은 GatewayClass와 Gateway에서 구현체, 리스너, TLS 종료 지점을 관리함
    • 애플리케이션 팀은 HTTPRoute와 GRPCRoute에서 호스트·경로와 백엔드 연결을 관리함
  • Cilium에서는 일반적인 인그레스 컨트롤러 Deployment를 한 번 더 통과하는 구조로 이해하면 안 됨

    • Cilium operator가 Gateway API 리소스를 검증하고 CiliumEnvoyConfig로 변환함
    • 각 노드의 eBPF 데이터 경로가 Service 또는 호스트 포트로 들어온 패킷을 Envoy에 투명하게 전달함
    • Envoy가 L7 라우팅과 TLS 종료를 수행한 뒤 백엔드 Service로 새 연결을 생성함

Cilium Gateway API control plane and data plane

공통 전제조건을 먼저 고정함

  • 관련 문서의 예시는 검증일 기준 Cilium 1.20.1과 Gateway API 1.6.1을 기준으로 작성함

    • 실제 적용 시 설치된 Cilium 버전의 공식 문서와 업그레이드 가이드를 먼저 확인해야 함
    • CiliumGatewayClassConfig는 v2alpha1이므로 릴리스 간 변경 가능성이 있음
  • Cilium Gateway API에는 kube-proxy replacement와 L7 proxy가 필요함

values-cilium-gateway.yaml
kubeProxyReplacement: true
l7Proxy: true
gatewayAPI:
    enabled: true
  • Gateway API CRD는 Cilium 설치 전에 호환 버전으로 설치해야 함
kubectl apply --server-side \
  -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.1/standard-install.yaml

helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --values values-cilium-gateway.yaml
  • 설치 직후에는 설정값과 컨트롤러 상태를 함께 확인해야 함
cilium status --wait
kubectl -n kube-system exec ds/cilium -- \
  cilium-dbg config --all | rg 'KubeProxyReplacement|EnableL7Proxy'
kubectl get gatewayclass cilium

외부 노출 방식은 네트워크 소유권으로 선택함

환경권장 진입 방식주소를 제공하는 주체핵심 조건
관리형 클라우드 LB 연동LoadBalancer Service클라우드 컨트롤러Service 감시와 LB 생성 권한 필요
사내·베어메탈 VIPLB IPAM + BGP 또는 L2Cilium + 라우터/L2IP 할당과 네트워크 광고를 모두 구성
기존 외부 LBNodePort 또는 hostNetwork외부 LB 운영 계층노드 대상·포트·헬스 체크 동기화 필요
노드별 클라우드 공인 IPhostNetwork공급자 SDN + DNS노드별 IP 연결과 장애 DNS 제거 필요
  • LB IPAM은 IP를 할당할 뿐 외부 네트워크에 경로를 만들지 않음

    • 라우터가 BGP를 지원하면 Cilium BGP Control Plane으로 Service VIP를 광고함
    • 같은 L2 네트워크에서 VIP를 제공하면 L2 Announcements로 ARP 또는 NDP 응답을 제공함
    • 공급자 SDN이 서로 다른 공인 IP를 각 노드 vNIC에 연결하면 LB IPAM 대신 hostNetwork와 외부 DNS를 사용함
  • hostNetwork와 기본 LoadBalancer Service 모드는 상호 배타적임

    • hostNetwork는 리스너를 선택 노드의 모든 인터페이스에 노출함
    • TCPRoute와 UDPRoute가 필요하면 현재 제약을 확인하고 Service 기반 모드를 우선 검토해야 함

하나의 Gateway 계약을 공통 기준으로 사용함

  • 외부 노출 방식이 달라도 Gateway와 HTTPRoute의 애플리케이션 계약은 유지할 수 있음
gateway-and-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
    name: public
    namespace: edge
spec:
    gatewayClassName: cilium
    listeners:
        - name: https
          protocol: HTTPS
          port: 443
          hostname: "*.example.com"
          tls:
              mode: Terminate
              certificateRefs:
                  - kind: Secret
                    name: wildcard-example-com
          allowedRoutes:
              namespaces:
                  from: Selector
                  selector:
                      matchLabels:
                          gateway-access: public
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
    name: shop
    namespace: shop
spec:
    parentRefs:
        - name: public
          namespace: edge
    hostnames: ["shop.example.com"]
    rules:
        - matches:
              - path:
                    type: PathPrefix
                    value: /
          backendRefs:
              - name: shop-web
                port: 8080
  • 네임스페이스 간 연결에는 양쪽의 명시적 허용이 필요함
    • Gateway.spec.listeners.allowedRoutes가 Route 네임스페이스를 허용해야 함
    • 다른 네임스페이스의 Service나 Secret을 참조하면 대상 측 ReferenceGrant가 필요함

보안과 클라이언트 IP 경계를 함께 설계함

  • Cilium 정책에서는 외부에서 Envoy까지와 Envoy에서 백엔드까지를 별도 흐름으로 허용해야 함

    • 첫 번째 구간은 일반적으로 world에서 ingress identity로 들어오는 흐름임
    • 두 번째 구간은 ingress identity에서 애플리케이션 identity로 나가는 흐름임
  • 외부 LB가 추가되면 실제 클라이언트 IP를 누가 보증하는지 정해야 함

    • L4 LB가 소스 IP를 보존하면 Cilium 기본 remote address 동작을 유지함
    • 신뢰하는 L7 LB가 X-Forwarded-For를 추가하면 노드 방화벽에서 LB만 허용하고 trusted hop 수를 정확히 설정함
    • 인터넷에서 Envoy로 직접 접근 가능한 상태에서 임의의 X-Forwarded-For를 신뢰하면 IP 기반 정책과 감사 로그가 우회될 수 있음

주소보다 실제 요청 경로를 검증함

  • Programmed=True는 설정이 생성됐다는 의미이며 인터넷에서 도달 가능하다는 보장은 아님
kubectl get gateway -A
kubectl describe gateway -n edge public
kubectl get httproute -A
kubectl get svc -n edge
kubectl -n kube-system logs ds/cilium-envoy --since=10m
  • 검증은 외부 관측 지점에서 DNS·TCP·TLS·HTTP 순서로 수행해야 함
dig +short shop.example.com
nc -vz shop.example.com 443
openssl s_client -connect shop.example.com:443 -servername shop.example.com </dev/null
curl --fail-with-body --resolve shop.example.com:443:203.0.113.10 \
  https://shop.example.com/healthz

참고 문서