LabHub
배우기 러닝패스 코스

CCA — 실리움 인증 어소시에이트 · Gateway API·사이드카 없는 메시·BGP · 이론

Gateway API 와 노드당 Envoy — Cilium 서비스 메시의 구조

LabHub 에서 이어서 보기

한 줄 요약

Cilium 은 Gateway API 리소스를 CiliumEnvoyConfig 로 번역해 노드마다 하나 있는 Envoy 에 싣고, eBPF 가 서비스 포트에 들어온 트래픽을 그 Envoy 로 가로챕니다. 파드마다 사이드카를 붙이지 않는 이 구조가 sidecarless 메시이고, 암호화는 WireGuard 나 IPsec 으로 노드 사이에서 투명하게 겁니다.

왜 이게 필요했나

Ingress 리소스는 호스트와 경로로 나누는 것까지만 표준이었습니다. 가중치로 트래픽을 나누거나 헤더를 고치거나 URL 을 다시 쓰려면 컨트롤러마다 다른 어노테이션을 써야 했고, 그 어노테이션은 다른 컨트롤러로 옮기면 동작하지 않았습니다. HTTP 와 HTTPS 만 다루고 TCP·UDP 는 표준에 없었으며, 여러 팀이 한 로드밸런서를 나눠 쓰는 클러스터에는 맞지 않았습니다. Cilium 문서는 이런 점들을 Ingress 의 한계로 정리하고, Kubernetes SIG-Network 가 후속으로 설계한 Gateway API 를 그 답으로 둡니다.

메시 쪽에도 같은 종류의 문제가 있었습니다. 파드마다 사이드카 프록시를 붙이면 L7 기능은 얻지만 파드 수만큼 프록시가 늘어납니다. Cilium 은 IP·TCP·UDP 처리를 eBPF 로 커널 안에서 하고, HTTP·gRPC·DNS 같은 애플리케이션 프로토콜만 Envoy 로 넘기는 구조를 처음부터 택했습니다. CCA 의 Service Mesh 도메인(16%)은 이 구조의 이유와 Gateway API 의 이점, 그리고 암호화 옵션을 묻습니다.

어떻게 동작하나

Gateway API 리소스와 역할 분리

Gateway API 는 역할 중심(role-oriented)으로 설계됐습니다. 문서가 드는 세 역할은 인프라 제공자(Infrastructure Provider), 클러스터 운영자(Cluster Operator), 애플리케이션 개발자(Application Developer)입니다. GatewayClass 는 어떤 구현이 게이트웨이를 맡는지(Cilium 은 cilium), Gateway 는 리스너(프로토콜·포트)와 어느 네임스페이스의 Route 를 받을지, HTTPRoute 는 매칭 규칙과 백엔드를 적습니다. 개발자는 자기 네임스페이스에 Route 만 만들고 Gateway 설정은 건드리지 못하게 권한을 나눌 수 있습니다.

apiVersion: gateway.networking.k8s.io/v1kind: HTTPRoutemetadata:  name: example-route-1spec:  parentRefs:  - name: cilium-gw            # 어느 Gateway 에 붙는가  rules:  - matches:    - path: {type: PathPrefix, value: /echo}    backendRefs:    - {kind: Service, name: echo-1, port: 8080, weight: 50}    - {kind: Service, name: echo-2, port: 8090, weight: 50}

backendRefsweight 가 트래픽 분할입니다. 문서의 예제는 50/50 으로 시작해 99/1 로 바꾸며 카나리와 A/B 시나리오에 쓴다고 설명합니다. 어노테이션이 아니라 표준 필드라 다른 구현으로 옮겨도 그대로 동작합니다.

Cilium 은 Gateway API v1.6.1 의 GatewayClass·Gateway·HTTPRoute·GRPCRoute·TLSRoute·BackendTLSPolicy·ReferenceGrant 를 지원하고 Core 적합성 시험을 통과했으며, TCPRoute·UDPRoute·ListenerSet 은 CRD 를 설치했을 때만 켜집니다. 전제 조건은 kubeProxyReplacement=truel7Proxy=true(기본값)이고, gatewayAPI.enabled=true 로 컨트롤러를 켭니다. 기본으로는 LoadBalancer 타입 서비스를 만들며, 1.16 부터는 호스트 네트워크로 직접 노출할 수도 있습니다.

다른 Ingress 컨트롤러와 무엇이 다른가

문서가 "가장 큰 차이" 라고 부르는 것은 구현이 CNI 와 얼마나 붙어 있느냐입니다. 보통의 컨트롤러는 Deployment 나 DaemonSet 으로 따로 떠서 LoadBalancer 서비스로 노출됩니다. Cilium 의 Ingress·Gateway API 는 네트워크 스택의 일부라서, 서비스 포트에 트래픽이 도착하면 eBPF 코드가 가로채 TPROXY 로 Envoy 에 넘깁니다. 그 결과 CiliumNetworkPolicy 가 인그레스로 들어오고 나가는 트래픽에도 적용됩니다.

이때 Envoy 에 도착한 트래픽은 정책 엔진에서 특별한 ingress 아이덴티티를 받습니다. 바깥에서 온 트래픽은 보통 world 아이덴티티이므로, 정책 판단 지점이 두 곳이 됩니다. world 에서 ingress 로 들어오는 단계와, ingress 에서 백엔드 아이덴티티로 나가는 단계입니다. 기본 거부 정책을 걸었는데 게이트웨이가 막히면 이 두 단계 중 하나를 허용하지 않은 것입니다.

내부 동작은 두 부분으로 나뉩니다. Cilium operator 가 Gateway API 리소스를 감시해 유효성을 검사하고 accepted 로 표시한 뒤 CiliumEnvoyConfig 로 번역합니다. Cilium agent 는 그 CiliumEnvoyConfig 를 읽어 내장 Envoy 또는 Envoy DaemonSet 에 설정을 줍니다. 트래픽은 Envoy 가 처리합니다.

사이드카가 없는 메시

노드당 Envoy 하나를 쓰는 구조는 동서(east-west) 트래픽에도 같은 방식으로 적용됩니다. GAMMA 는 HTTPRoute 의 parent 를 Gateway 가 아니라 Service 로 두는 방식인데, Cilium 은 그 Service 로 가는 L7 트래픽을 가로채 노드당 Envoy 로 라우팅합니다. Cilium 은 현재 Service 와 같은 네임스페이스에 있는 producer Route 만 지원합니다. L7 을 쓰지 않는 트래픽은 Envoy 를 거치지 않고 eBPF 데이터패스로 바로 갑니다. 사이드카 방식과 견주면 프록시 수가 파드 수가 아니라 노드 수에 비례하고, 애플리케이션 파드를 재시작하지 않고 L7 기능을 켜고 끌 수 있습니다.

암호화 옵션 — WireGuard, IPsec, mTLS

Cilium 은 Cilium 이 관리하는 엔드포인트 사이의 트래픽을 IPsec, WireGuard, 또는 ztunnel(베타)로 투명하게 암호화합니다. WireGuard 를 켜면 각 노드의 agent 가 다른 모든 노드와 WireGuard 터널을 맺고, 노드마다 키 쌍을 만들어 공개키를 CiliumNode 리소스의 network.cilium.io/wg-pub-key 어노테이션으로 배포합니다. 터널 엔드포인트는 UDP 51871 이고, 같은 노드 안의 트래픽은 암호화하지 않습니다(어차피 노드에서 볼 수 있어 이득이 없기 때문). 커널에 WireGuard 지원이 있어야 하며 encryption.enabled=true, encryption.type=wireguard 로 켭니다. IPsec 은 키를 Kubernetes 시크릿으로 배포하며, 1.18 부터는 터널 캡슐화 뒤에 암호화해 정책용 아이덴티티까지 감춥니다.

Mutual Authentication(베타)은 SPIFFE/SPIRE 로 워크로드 아이덴티티를 발급해 mTLS 핸드셰이크를 일반 연결 밖에서(out-of-band) 수행합니다. 문서는 인증과 기밀성을 함께 얻으려면 암호화(WireGuard 또는 IPsec)를 켜야 한다고 적습니다. 즉 Cilium 의 mTLS 는 아이덴티티 검증이고, 실제 암호화는 노드 사이 터널이 맡습니다.

현장에서 만나는 모습

NGINX Ingress 에서 Cilium Gateway API 로 옮기는 팀이 가장 먼저 부딪히는 것은 어노테이션입니다. 문서는 구현별 어노테이션을 그대로 옮기는 일은 드물고, 요청·응답 조작, 트래픽 분할, 헤더·쿼리·메서드 기반 라우팅은 Gateway API 의 표준 필드로 바꾸라고 안내합니다. 권장 순서는 범위와 단계를 정하고, 기존 어노테이션을 분류하고, 같은 뜻의 Gateway API 리소스를 만들어 병행 검증한 뒤, 트래픽을 점진적으로 옮기고, 안정된 뒤 Ingress 를 지우는 것입니다.

WireGuard 를 켠 뒤 "처음 몇 패킷이 평문으로 나갔다" 는 보고도 있습니다. 문서의 알려진 문제 항목이 바로 그것입니다. 목적지 IP 가 원격 Cilium 엔드포인트라는 정보가 전파되기 전에는 클러스터 바깥으로 간주해 평문으로 보냅니다. encryption.strictMode 를 켜거나 world 로 나가는 이그레스를 정책으로 막는 것이 문서가 제시하는 대응입니다.

다음 이론에서 볼 것

바로 이어지는 이론에서는 Gateway 가 받은 LoadBalancer IP 와 파드 CIDR 을 클러스터 바깥 라우터가 어떻게 알게 되는지, 즉 BGP Control Plane 과 Egress Gateway 를 봅니다. 참고: [Gateway API Support](https://docs.cilium.io/en/stable/network/servicemesh/gateway-api/gateway-api/), [Traffic Splitting Example](https://docs.cilium.io/en/stable/network/servicemesh/gateway-api/splitting/), [Migrating from Ingress to Gateway](https://docs.cilium.io/en/stable/network/servicemesh/ingress-to-gateway/ingress-to-gateway/), [WireGuard Transparent Encryption](https://docs.cilium.io/en/stable/security/network/encryption-wireguard/), [Mutual Authentication](https://docs.cilium.io/en/stable/network/servicemesh/mutual-authentication/mutual-authentication/).