Gateway API 지원

Gateway API 지원 (Gateway API Support)

Gateway API는 Ingress 객체의 후속을 설계하기 위한 Kubernetes SIG-Network 서브프로젝트예요. Cilium은 Gateway API v1.6.1을 지원하며 모든 Core conformance 테스트를 통과해요.

출처: Gateway API Support

본문

Gateway API란 무엇인가요? (What is Gateway API?)

Gateway API는 Ingress 객체의 후속을 설계하기 위한 Kubernetes SIG-Network 서브프로젝트예요. Kubernetes에서 서비스 네트워킹을 모델링하는 리소스 집합이며, 역할 중심적이고 이식 가능하며 표현력 있고 확장 가능하도록 설계됐어요.

자세한 내용은 Gateway API 사이트를 참고해주세요.

Cilium Gateway API 지원 (Cilium Gateway API Support)

Cilium은 아래 리소스에 대해 Gateway API v1.6.1을 지원하며, 모든 Core conformance 테스트를 통과해요.

  • GatewayClass
  • Gateway
  • HTTPRoute
  • GRPCRoute
  • TLSRoute
  • BackendTLSPolicy
  • ReferenceGrant
  • ListenerSet
  • TCPRoute
  • UDPRoute

추가로 Cilium은 CiliumGatewayClassConfig CRD를 제공하며, 이를 GatewayClass.parametersRef에서 참조할 수 있어요.

영상

Cilium의 Gateway API 지원에 대해 더 알고 싶다면 eCHO 에피소드 58 "Cilium Service Mesh and Ingress"를 확인해보세요.

사전 요구사항 (Prerequisites)

  • Cilium은 kubeProxyReplacement=true로 kube-proxy 교체가 구성되어야 해요. 자세한 내용은 kube-proxy replacement를 참고해주세요.
  • Cilium은 l7Proxy=true(기본 활성화)로 L7 프록시가 활성화되어야 해요.
  • Gateway의 Service에 도착한 트래픽은 TPROXY 커널 기능을 사용해 Envoy로 투명하게 전달돼요. 기본 bpf.tproxy=false에서는 TPROXY가 iptables로 구현되므로, 노드는 L7 프록시 시스템 요구사항에 나열된 netfilter 모듈과 함께 iptables를 제공해야 해요. 일부 배포판은 기본적으로 이를 제공하지 않아서, Gateway에 대한 연결이 Envoy에 도달하지 못한 채 타임아웃될 수 있어요. eBPF 기반 bpf.tproxy=true(베타)는 이 iptables 의존성을 제거해요.
  • 기본적으로 Cilium Gateway API 컨트롤러는 LoadBalancer 유형의 서비스를 만들므로, 환경이 이를 지원해야 해요. 또는 Cilium 1.16부터 호스트 네트워크에서 Cilium L7 프록시를 직접 노출할 수 있어요.

설치 (Installation)

Gateway API v1.6.1의 아래 CRD들이 반드시 설치되어야 해요.

  • GatewayClass
  • Gateway
  • HTTPRoute
  • GRPCRoute
  • BackendTLSPolicy
  • ReferenceGrant
  • TLSRoute

설치 단계는 이 문서들을 참고해주세요. 또는 아래 스니펫을 사용할 수도 있어요.

experimental 릴리스 채널에는 standard 릴리스 채널의 모든 것과 일부 실험 리소스/필드가 포함돼 있어요. 현재 experimental로 표시된 기능(예: HTTPRoute 리소스의 HTTPRoute Retry)이 필요하다면 해당 CRD를 설치해야 해요. 실험 기능 전체 목록은 experimental GEP 목록을 참고해주세요.

기존 설치를 업데이트하는 경우, 항상 먼저 Upgrade Guide를 확인해서 새 버전에 필요한 breaking changes, deprecated 기능, 중요한 구성 업데이트를 검토해주세요. Cilium 1.20 업그레이드의 경우, Gateway API CRD를 업데이트하기 전에 업그레이드 가이드의 Gateway API v1.6.1과 TLSRoute 참고 사항을 검토하세요.

필요한 CRD 집합은 다음과 같이 설치할 수 있어요:

kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_gateways.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_backendtlspolicies.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_tlsroutes.yaml

kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_gatewayclasses.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_gateways.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_httproutes.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_referencegrants.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_grpcroutes.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_backendtlspolicies.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml

TCPRoute, UDPRoute 또는 ListenerSet CRD는 선택 사항이며, 이 기능을 사용하려면 해당 CRD 리소스를 설치해야 해요. 설치하지 않으면 Cilium은 이 기능들에 대한 지원을 비활성화해요.

선택적 CRD 집합은 다음과 같이 설치할 수 있어요:

kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_listenersets.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_tcproutes.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/standard/gateway.networking.k8s.io_udproutes.yaml

kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_listenersets.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_tcproutes.yaml
kubectl apply --server-side -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.6.1/config/crd/experimental/gateway.networking.k8s.io_udproutes.yaml

CRD가 설치되면 Helm 또는 Cilium CLI를 사용해 Cilium Gateway API 컨트롤러를 활성화해주세요.

최신 버전의 Cilium CLI를 설치해볼게요. Cilium CLI는 Cilium 설치, Cilium 설치 상태 검사, 다양한 기능(예: clustermesh, Hubble) 활성화/비활성화에 사용할 수 있어요.

CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}

CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "arm64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-darwin-${CLI_ARCH}.tar.gz{,.sha256sum}
shasum -a 256 -c cilium-darwin-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-darwin-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-darwin-${CLI_ARCH}.tar.gz{,.sha256sum}

전체 릴리스 페이지를 참고해주세요.

Helm으로 활성화하기 — Cilium Gateway API Controller는 helm 플래그 gatewayAPI.enabled를 true로 설정해서 활성화할 수 있어요. 새 설치에 대해서는 Installation using Helm을 참고해주세요.

helm upgrade cilium cilium/cilium --version 1.20.2 \
   --namespace kube-system \
   --reuse-values \
   --set kubeProxyReplacement=true \
   --set gatewayAPI.enabled=true
kubectl -n kube-system rollout restart deployment/cilium-operator
kubectl -n kube-system rollout restart ds/cilium

helm upgrade cilium oci://quay.io/cilium/charts/cilium 1.20.2 \
   --namespace kube-system \
   --reuse-values \
   --set kubeProxyReplacement=true \
   --set gatewayAPI.enabled=true
kubectl -n kube-system rollout restart deployment/cilium-operator
kubectl -n kube-system rollout restart ds/cilium

Cilium CLI로 활성화하기 — Cilium Gateway API Controller는 아래 명령으로 활성화할 수 있어요.

$ cilium upgrade 1.20.2 \
    --set kubeProxyReplacement=true \
    --set gatewayAPI.enabled=true

다음으로 Cilium agent와 operator의 상태를 확인할 수 있어요:

$ cilium status

참조 (Reference)

Cilium Ingress와 Gateway API가 다른 Ingress 컨트롤러와 다른 점 (How Cilium Ingress and Gateway API differ from other Ingress controllers)

Cilium의 Ingress 및 Gateway API 지원과 다른 Ingress 컨트롤러 사이의 가장 큰 차이점 중 하나는 구현이 CNI와 얼마나 밀접하게 연결돼 있는지예요. Cilium에서는 Ingress와 Gateway API가 네트워킹 스택의 일부이므로, 다른 Ingress나 Gateway API 컨트롤러와는 다르게 동작해요 (심지어 Cilium 클러스터에서 실행되는 다른 Ingress/Gateway API 컨트롤러라도요).

다른 Ingress/Gateway API 컨트롤러는 일반적으로 클러스터에 Deployment나 DaemonSet으로 설치되고, Loadbalancer Service 등으로 노출돼요 (물론 Cilium이 이를 활성화할 수도 있어요).

Cilium의 Ingress 및 Gateway API 구성은 Loadbalancer나 NodePort 서비스로 노출되거나, 선택적으로 호스트 네트워크에서도 노출될 수 있어요. 하지만 이 모든 경우에 트래픽이 Service의 포트에 도착하면 eBPF 코드가 트래픽을 가로채서 (TPROXY 커널 기능을 사용해) Envoy로 투명하게 전달해요.

이것은 클라이언트 IP 가시성 같은 것에 영향을 주는데, 이는 Cilium의 Ingress/Gateway API 지원에서 다른 Ingress 컨트롤러와 다르게 동작해요.

또한 Cilium의 Network Policy 엔진이 Ingress로 향하는 트래픽과 Ingress에서 나오는 트래픽에 CiliumNetworkPolicy를 적용할 수 있게 해줘요.

Cilium의 ingress 구성과 CiliumNetworkPolicy (Cilium's ingress config and CiliumNetworkPolicy)

Cilium을 통해 백엔드 서비스로 향하는 Ingress 및 Gateway API 트래픽은 노드별 Envoy 프록시를 통과해요.

노드별 Envoy 프록시에는 eBPF 정책 엔진과 상호작용하고 트래픽에 대한 정책 조회를 수행할 수 있는 특수 코드가 있어요. 이를 통해 Envoy는 Ingress(및 Gateway API) 트래픽과 GAMMA나 L7 Traffic Management를 통한 동서(east-west) 트래픽 모두에 대해 Network Policy enforcement point가 될 수 있어요.

하지만 ingress 구성에는 추가 단계가 하나 더 있어요. Ingress나 Gateway API를 위해 Envoy에 도착한 트래픽은 Cilium의 Policy 엔진에서 특별한 ingress 아이덴티티로 지정돼요.

클러스터 외부에서 온 트래픽은 (클러스터에 IP CIDR 정책이 없다면) 보통 world 아이덴티티로 지정돼요. 즉 Cilium Ingress에는 실제로 두 개의 논리적 Policy enforcement point가 있다는 뜻이에요 — 트래픽이 ingress 아이덴티티에 도착하기 전과, 노드별 Envoy를 빠져나가려는 그 이후예요.

즉, 클러스터에 Network Policy를 적용할 때는 두 단계 모두 허용되는지, 그리고 world에서 ingress로, ingress에서 클러스터 안의 아이덴티티(위 이미지의 productpage 아이덴티티 등)로 트래픽이 허용되는지 확인하는 게 중요해요.

Ingress에 대한 자세한 내용은 Ingress and Network Policy Example을 참고해주세요. 단, 같은 원칙이 Gateway API에도 적용돼요.

소스 IP 가시성 (Source IP Visibility)

참고

기본적으로 Cilium ingress 구성(Ingress와 Gateway API 모두)의 소스 IP 가시성은 대부분의 설치에서 그냥 동작해야 해요. 요구사항과 관련 설정에 대한 자세한 내용은 이 섹션을 읽어주세요.

백엔드가 실제 요청이 어떤 IP 주소에서 왔는지 추론할 수 있는 것은 대부분의 애플리케이션에서 중요해요.

기본적으로 Cilium의 Envoy 인스턴스는 일반적인 규칙을 사용해 인입 HTTP 연결의 보이는 소스 주소를 X-Forwarded-For 헤더에 추가하도록 구성돼 있어요. 즉 기본적으로 Cilium은 신뢰된 홉(hop) 수를 0으로 설정해서, Envoy가 X-Forwarded-For 목록 안의 값이 아니라 연결이 열린 주소를 사용하도록 해요. 이 개수를 늘리면 Envoy가 목록의 오른쪽에서부터 세어 n 번째 값을 사용하게 돼요.

Envoy는 또한 X-Forwarded-For를 기반으로 결정된 신뢰된 클라이언트 주소가 무엇이든 X-Envoy-External-Address 헤더로 설정해요.

기본적으로 Cilium은 Ingress를 포함한 Layer 7 기능에 대한 정책을 적용할 때 연결 클라이언트의 소스 IP를 사용해요. 트래픽의 소스가 X-Forwarded-For 헤더를 주입하는 것을 신뢰한다면(예: 클라우드 로드 밸런서 사용 시), values 파일의 gatewayAPI 또는 ingressController 섹션에서 useRemoteAddress를 false로 설정해 Envoy가 X-Forwarded-For 헤더에 인코딩된 클라이언트 IP에서 온 트래픽으로 취급하도록 강제할 수 있어요.

자세한 내용은 Envoy X-Forwarded-For headers 문서를 참고해주세요.

참고

Cilium ingress(Ingress든 Gateway API든)를 사용하는 백엔드는 X-Forwarded-For와 X-Envoy-External-Address 헤더만 보면 돼요 (많은 HTTP 라이브러리가 이를 투명하게 처리해요).

Loadbalancer 또는 NodePort Service의 externalTrafficPolicy

Cilium의 ingress 지원(Ingress와 Gateway API 모두)은 종종 Loadbalancer나 NodePort Service를 사용해 Envoy DaemonSet을 노출해요.

이런 경우 Service 객체에는 클라이언트 IP 가시성과 특히 관련된 필드인 externalTrafficPolicy 필드가 하나 있어요.

관련 설정 두 가지가 있어요:

  • Local: 노드는 소스 IP를 마스커레이드하지 않고 로컬 노드에서 실행 중인 파드로만 트래퇵을 라우팅해요. 그렇기 때문에 kube-proxy를 사용하는 클러스터에서는 이것이 소스 IP 가시성을 보장하는 유일한 방법이에요. externalTrafficPolicy: local의 계약의 일부에는 노드가 포트를 연다는 것(externalTrafficPolicy: Local이 설정되면 Kubernetes가 자동으로 설정하는 healthCheckNodePort)도 있으며, 로컬 파드가 실행 중인 노드에서는 http://<nodeIP>:<healthCheckNodePort>/healthz 요청이 200을 반환하고, 그렇지 않은 노드에서는 200이 아닌 값을 반환해요. Cilium은 일반 Loadbalancer Service에 대해 이를 구현하지만, Cilium ingress 구성(Ingress와 Gateway API 모두)에서는 조금 다르게 동작해요.
  • Cluster: 노드는 클러스터 전체의 모든 엔드포인트로 균등하게 라우팅해요. 여기에는 몇 가지 다른 효과가 있어요. 첫째, 업스트림 로드 밸런서는 아무 노드로나 트래픽을 보내도 백엔드 파드에 도달할 것으로 기대하며, 노드는 소스 IP를 마스커레이드할 수도 있어요. 즉 많은 경우 externalTrafficPolicy: Cluster는 백엔드 파드가 소스 IP를 보지 못할 수 있다는 뜻이에요.

Cilium의 경우, Envoy를 노출하는 Service로 향하는 모든 ingress 트래픽은 항상 로컬 노드로 가고, 항상 Linux Kernel TPROXY 함수(백엔드로 패킷을 투명하게 전달)를 사용해 Envoy로 전달돼요.

즉 Cilium ingress 구성(Ingress와 Gateway API 모두)의 경우, 두 externalTrafficPolicy 경우 모두에서 조금 다르게 동작해요.

참고

두 externalTrafficPolicy 경우 모두에서 트래픽은 클러스터의 아무 노드에나 도착해서, 소스 IP를 그대로 유지한 채 Envoy로 전달돼요.

또한 Cilium의 Envoy를 노출하는 모든 Service에 대해, Cilium은 externalTrafficPolicy: Local이 설정되면 클러스터의 모든 노드가 healthCheckNodePort 검사를 통과하도록 보장해서, 외부 로드 밸런서가 올바르게 전달하게 해요.

하지만 Cilium의 ingress 구성(Ingress와 Gateway API 모두)의 경우, 백엔드 파드에 소스 IP를 보이게 유지하기 위해 externalTrafficPolicy: Local을 구성하는 것은 필요하지 않아요 (X-Forwarded-For와 X-Envoy-External-Address 필드 덕분이에요).

TLS 패스스루와 소스 IP 가시성 (TLS Passthrough and source IP visibility)

Ingress와 Gateway API 모두 TLS 패스스루 구성을 지원해요 (Ingress는 어노테이션, Gateway API는 TLSRoute 리소스). 이 구성은 여러 TLS 패스스루 백엔드가 로드 밸런서에서 동일한 TLS 포트를 공유할 수 있게 해주며, Envoy가 TLS 핸드셰이크의 Server Name Indicator(SNI) 필드를 검사해서 그 값을 사용해 TLS 스트림을 백엔드로 전달해요.

하지만 Envoy가 TLS 스트림의 TCP 프록시를 수행하므로, 이것은 소스 IP 가시성에 문제가 돼요.

어떤 일이 벌어지냐면, TLS 트래픽이 Envoy에 도착해서 TCP 스트림을 종료하고, Envoy가 client hello를 검사해 SNI를 찾은 다음 전달할 백엔드를 선택하고, 새 TCP 스트림을 시작해 다운스트림(외부) 패킷 안의 TLS 트래픽을 업스트림(백엔드)으로 전달해요.

이것은 새 TCP 스트림이므로, 백엔드 입장에서는 소스 IP가 Envoy예요 (Cilium 구성에 따라 보통 Node IP예요).

참고

TLS 패스스루를 수행할 때 백엔드는 전달된 TLS 스트림의 소스로 Cilium Envoy의 IP 주소를 보게 돼요.

호스트 네트워크 모드 (Host network mode)

참고

Cilium 1.16+부터 지원돼요

호스트 네트워크 모드를 사용하면 호스트 네트워크에서 Cilium Gateway API Gateway를 직접 노출할 수 있어요. 이는 LoadBalancer Service를 사용할 수 없는 경우(개발 환경이나 클러스터 외부 로드 밸런서가 있는 환경 등)에 유용해요.

참고

  • Cilium Gateway API 호스트 네트워크 모드를 활성화하면 LoadBalancer 유형 Service 모드가 자동으로 비활성화돼요. 둘은 상호 배타적이에요.
  • 리스너는 모든 인터페이스(IPv4는 0.0.0.0, IPv6는 ::)에서 노출돼요.
  • 호스트 네트워크 모드는 TCPRoute와 UDPRoute와 호환되지 않아요. 이들의 트래픽은 Envoy를 우회해서 Gateway가 생성한 Service에 직접 도달하는데, 이 Service는 보통 구성된 Gateway 리스너 포트를 LoadBalancer Service로 노출해요. 호스트 네트워크 모드를 활성화하면 이 Service가 NodePort Service로 바뀌며, Gateway 리스너에 구성된 포트가 아니라 노드 포트 범위에서 무작위로 할당된 포트를 받게 돼요.

호스트 네트워크 모드는 Helm으로 활성화할 수 있어요:

gatewayAPI:
  enabled: true
  hostNetwork:
    enabled: true

활성화하면 Gateway의 호스트 네트워크 포트는 spec.listeners.port로 지정할 수 있어요. 포트는 Gateway 리소스마다 고유해야 하며, 1023보다 높은 포트 번호를 선택해야 해요 (Bind to privileged port 참고).

경고

잘못 구성하면 포트 충돌이 발생할 수 있다는 점을 유의해주세요. 각 gateway에 대해 Gateway API 리스너가 노출되는 모든 Cilium 노드에서 아직 사용 가능한 고유 포트를 구성하세요.

gateway의 GatewayStatusAddress 필드는 최대 16개의 주소를 가질 수 있어요. 호스트 네트워크 모드가 활성화된 Cilium은 일관성을 위해 노드 주소를 자동으로 정렬해서, 동일한 주소가 선택되도록 보장해요.

특권(privileged) 포트 바인딩 (Bind to privileged port)

기본적으로 Cilium L7 Envoy 프로세스는 out-of-the-box로 Linux 능력(capabilities)이 없어서 특권 포트에서 수신할 수 없어요.

1023 이하의 포트를 선택한다면, Helm 값 envoy.securityContext.capabilities.keepCapNetBindService=true를 구성하고 해당 Cilium Envoy 컨테이너에 NET_BIND_SERVICE 능력을 추가해야 해요 (Helm values로요):

  • 독립 DaemonSet 모드: envoy.securityContext.capabilities.envoy
  • 임베디드 모드: securityContext.capabilities.ciliumAgent

호스트 네트워크 모드에서 특권 포트 바인딩을 허용하려면 다음 Helm 값들을 구성해주세요:

gatewayAPI:
  enabled: true
  hostNetwork:
    enabled: true
envoy:
  enabled: true
  securityContext:
    capabilities:
      keepCapNetBindService: true
      envoy:
      # Add NET_BIND_SERVICE to the list (keep the others!)
      - NET_BIND_SERVICE

gatewayAPI:
  enabled: true
  hostNetwork:
    enabled: true
envoy:
  securityContext:
    capabilities:
      keepCapNetBindService: true
securityContext:
  capabilities:
    ciliumAgent:
    # Add NET_BIND_SERVICE to the list (keep the others!)
    - NET_BIND_SERVICE

노드 부분 집합에 Gateway API 리스너 배포하기 (Deploy Gateway API listeners on subset of nodes)

Cilium Gateway API Envoy 리스너는 노드의 특정 부분 집합에서만 노출할 수 있어요. 이는 호스트 네트워크 모드와 결합해서만 동작하며, Helm values의 노드 레이블 셀렉터로 구성할 수 있어요:

gatewayAPI:
  enabled: true
  hostNetwork:
    enabled: true
    nodes:
      matchLabels:
        role: infra
        component: gateway-api

이렇게 하면 구성된 레이블과 일치하는 Cilium 노드에서만 Gateway API Envoy 리스너가 배포돼요. 빈 셀렉터는 모든 노드를 선택하며 모든 Cilium 노드에서 계속 기능을 노출해요.

Gateway API 주소 지원 (Gateway API Addresses Support)

Cilium Gateway는 Gateway API 스펙이 제공하는 Addresses를 지원해요. spec.addresses 필드는 gateway의 IP 주소를 지정하는 데 사용돼요.

참고

이 기능은 IPAddress 유형의 주소만 지원하며, LB-IPAM과 함께 동작해요. 자세한 내용은 LoadBalancer IP Address Management (LB IPAM) 문서를 참고해주세요.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
spec:
  addresses:
  - type: IPAddress
    value: 172.18.0.140
  gatewayClassName: cilium
  listeners:
  - allowedRoutes:
      namespaces:
        from: Same
    name: web-gw
    port: 80
    protocol: HTTP

위 구성의 출력은 다음과 같아요:

$ kubectl get gateway my-gateway
NAME         CLASS    ADDRESS        PROGRAMMED   AGE
my-gateway   cilium   172.18.0.140   True         2d7h

이미 spec.infrastructure.annotations에서 io.cilium/lb-ipam-ips를 사용해 IP를 지정하고 있다면, spec.addresses 필드는 무시돼요.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
spec:
  infrastructure:
    annotations:
      io.cilium/lb-ipam-ips: "172.18.0.141"
  addresses: # This will be ignored
  - type: IPAddress
    value: 172.18.0.140
  gatewayClassName: cilium
  listeners:
  - allowedRoutes:
      namespaces:
        from: Same
    name: web-gw
    port: 80
    protocol: HTTP

위 구성의 출력은 다음과 같아요:

$ kubectl get gateway my-gateway
NAME         CLASS    ADDRESS        PROGRAMMED   AGE
my-gateway   cilium   172.18.0.141   True         2d7h

참고

향후 어느 시점에 io.cilium/lb-ipam-ips의 사용이 더 이상 사용되지 않을(deprecate) 예정이고, 그 이후로는 spec.addresses가 설정되지 않으면 이 어노테이션은 무시될 거예요. 두 경우 모두 Cilium agent 로그에 경고 로그가 추가되고, Gateway에는 경고 Condition이 배치돼요.

예제 (Examples)

Cilium의 Gateway API 기능을 사용하고 활용하는 방법은 아래 예제 중 하나를 참고해주세요:

  • HTTP 예제
  • HTTPS 예제
  • gRPC 예제
  • Traffic Splitting 예제
  • HTTP Header Modifier 예제
  • GatewayClass Parameters 지원
  • Default TLS Certificate
  • BackendTLSPolicy 예제
  • Access Logs
  • ListenerSet 지원

더 많은 예제는 업스트림 저장소에서 찾을 수 있어요.

문제 해결 (Troubleshooting)

이 페이지는 Gateway API의 다양한 메커니즘과 문제 해결 방법을 안내해요.

Troubleshooting Ingress & Service Mesh 페이지의 Generic 및 Setup Verification 단계를 반드시 따라주세요.

리소스 확인하기 (Checking resources)

  • Gateway 리소스 확인
$ kubectl get gateway -A
NAMESPACE                   NAME                 CLASS    ADDRESS          PROGRAMMED   AGE
website                     http-gateway         cilium   172.21.255.202   True         5h
webshop                     tls-gateway          cilium   172.21.255.203   True         5h

앞선 명령은 클러스터의 모든 Gateway에 대한 개요를 반환해요. 다음을 확인해주세요:

  • Gateway가 프로그래밍됐나요?
    • 프로그래밍된 Gateway란 Cilium이 그에 대한 구성을 준비했다는 뜻이에요.
    • Programmed true 표시가 없다면 Cilium 구성에서 Gateway API가 활성화됐는지 확인해주세요.
  • Gateway에 주소가 있나요?
    • kubectl get service로 서비스를 확인할 수 있어요.
    • Gateway에 주소가 있다면 LoadBalancer 서비스가 gateway에 할당됐다는 뜻이에요.
    • IP가 나타나지 않는다면 LoadBalancer 구현이 빠졌을 수 있어요.
  • 클래스가 cilium인가요?
    • Cilium은 cilium 클래스의 Gateway만 프로그래밍해요.
  • Gateway API 리소스 유형(Gateway, HTTPRoute 등)이 발견되지 않으면 Gateway API CRD가 설치됐는지 확인해주세요.

kubectl describe gateway로 문제를 더 자세히 조사할 수 있어요.

$ kubectl describe gateway <name>

  Conditions:
    Message:               Gateway successfully scheduled
    Reason:                Accepted
    Status:                True
    Type:                  Accepted
    Message:               Gateway successfully reconciled
    Reason:                Programmed
    Status:                True
    Type:                  Programmed
    [...]
  Listeners:
    Attached Routes:  2
    Conditions:
      Message:               Listener Ready
      Reason:                Programmed
      Status:                True
      Type:                  Programmed
      Message:               Listener Accepted
      Reason:                Accepted
      Status:                True
      [...]

gateway의 일반 상태와 구성된 리스너의 상태를 볼 수 있어요.

리스너 상태는 리스너에 성공적으로 연결된 라우트 수를 표시해요.

gateway와 listener 모두에 대한 상태 조건을 볼 수 있어요:

  • Accepted: Gateway 구성이 수락됐어요.
  • Programmed: Gateway 구성이 Envoy에 프로그래밍됐어요.
  • ResolvedRefs: 참조된 모든 시크릿이 발견됐고 사용 권한이 있어요.

이 조건 중 하나라도 false로 설정되면, Message와 Reason 필드가 더 많은 정보를 제공해요.

  • HTTPRoute 리소스 확인

Gateway가 동작하면 라우트를 확인해서 올바르게 구성됐는지 검증할 수 있어요. 라우트 상태를 확인하는 방법은 gateway 리소스 상태를 확인하는 것과 비슷해요.

이 지침은 HTTPRoute용으로 작성됐지만, 다른 라우트 유형에도 적용돼요.

$ kubectl get httproute -A
NAMESPACE                 NAME              HOSTNAMES         AGE
website                   homepage          www.example.org   17m
webshop                   catalog-service                     17m
webshop                   cart-service                        17m

더 많은 정보를 얻으려면 kubectl describe httproute <name>을 입력해주세요.

$ kubectl describe httproute <name>
Status:
  Parents:
    Conditions:
      Last Transition Time:  2023-06-05T15:11:53Z
      Message:               Accepted HTTPRoute
      Observed Generation:   1
      Reason:                Accepted
      Status:                True
      Type:                  Accepted
      Last Transition Time:  2023-06-05T15:11:53Z
      Message:               Service reference is valid
      Observed Generation:   1
      Reason:                ResolvedRefs
      Status:                True
      Type:                  ResolvedRefs
    Controller Name:         io.cilium/gateway-controller
    Parent Ref:
      Group:  gateway.networking.k8s.io
      Kind:   Gateway
      Name:   same-namespace

Status는 특정 HTTPRoute와 관련된 조건들을 나열해요. 조건은 gateway에 대한 부모 참조별로 나열돼요. 라우트를 여러 gateway에 연결했다면 여러 항목이 나타나요. 조건에는 Reason, Type, Status, Message가 포함돼요. Type은 조건 유형을 나타내고, Status는 조건 유형이 충족되는지 여부를 boolean으로 나타내요. 선택적으로 Message가 조건에 대한 추가 정보를 제공해요.

다음 조건 유형을 주목해주세요:

  • Accepted: HTTPRoute 구성이 올바르고 수락됐어요.
  • ResolvedRefs: 참조된 서비스가 발견됐고 유효한 참조예요.

이 중 하나라도 false로 설정되면 Message와 Reason 필드를 살펴보면 더 많은 정보를 얻을 수 있어요.

  • Cilium Operator 로그 확인

Cilium Operator 로그에는 추가 디버깅 정보가 있을 수 있어요. 예를 들어 필요한 CRD(Custom Resource Definitions)가 설치되지 않으면 오류가 기록돼요:

$ kubectl logs -n kube-system deployments/cilium-operator | grep gateway
level=error msg="Required GatewayAPI resources are not found, please
refer to docs for installation instructions" error="customresourcedefinitions.apiextensions.k8s.io \"gatewayclasses.gateway.networking.k8s.io\" not found
customresourcedefinitions.apiextensions.k8s.io \"gateways.gateway.networking.k8s.io\" not found
customresourcedefinitions.apiextensions.k8s.io \"httproutes.gateway.networking.k8s.io\" not found
customresourcedefinitions.apiextensions.k8s.io \"referencegrants.gateway.networking.k8s.io\" not found
customresourcedefinitions.apiextensions.k8s.io \"grpcroutes.gateway.networking.k8s.io\" not found
customresourcedefinitions.apiextensions.k8s.io \"tlsroutes.gateway.networking.k8s.io\" not found" subsys=gateway-api

흔한 실수 (Common mistakes)

경고

Gateway API는 Kubernetes에 최근에 추가된 것이며, Cilium 프로젝트는 아직 많은 사용자 피드백을 받지 못했어요. 이 섹션에 아직 나열되지 않은 문제를 만난다면 이 목록에 여러분의 문제를 추가하는 PR을 여는 것을 고려해보세요.

  • 백엔드 서비스가 존재하지 않아요.
    • 백엔드 서비스가 발견됐는지 확인하려면 kubectl describe httproute <name>을 실행하고 conditions 필드를 검사해주세요:
Parents:
  Conditions:
    Last Transition Time:  2023-06-06T13:55:10Z
    Message:               Service "backend" not found
    Observed Generation:   1
    Reason:                BackendNotFound
    Status:                False
    Type:                  ResolvedRefs
    Last Transition Time:  2023-06-06T13:55:10Z
    Message:               Accepted HTTPRoute
    Observed Generation:   1
    Reason:                Accepted
    Status:                True
    Type:                  Accepted
  Controller Name:         io.cilium/gateway-controller
  • parentRefs 아래에 지정된 gateway가 존재하지 않아요.
    • gateway가 발견됐는지 확인하려면 kubectl describe httproute <name>을 실행하고 conditions 필드를 검사해주세요:
Parents:
  Conditions:
    Last Transition Time:  2023-06-06T13:56:40Z
    Message:               Gateway.gateway.networking.k8s.io "my-gateway" not found
    Observed Generation:   2
      Reason:                InvalidHTTPRoute
      Status:                False
      Type:                  Accepted

기본 메커니즘: 높은 수준 개요 (Underlying mechanics: a high level overview)

Cilium 배포에는 Gateway API 리소스를 처리하는 두 부분이 있어요: Cilium agent와 Cilium operator예요.

Cilium operator는 모든 Gateway API 리소스를 감시하고 리소스가 유효한지 검증해요. 리소스가 유효하면 operator가 이를 accepted로 표시해요. 그러면 Cilium Envoy Configuration 리소스로의 변환 과정이 시작돼요.

그 다음 Cilium agent가 Cilium Envoy Configuration 리소스를 가져와요.

Cilium agent는 이 리소스들을 사용해 내장 Envoy 또는 Envoy DaemonSet에 구성을 공급해요. Envoy가 트래픽을 처리해요.

더 알아보기 (Learn more)