인프라/Kubernetes

[쿠버네티스] Nginx Gateway Fabric 정리 및 설치

Hun's blog 2026. 9. 2. 21:00

Nginx Gateway Fabric 개요

NGINX Gateway Fabric(NGF)는 Gateway API를 구현한 구현체다. Kubernetes 커뮤니티가 유지하던 ingress-nginx의 지원 종료 이후, Gateway API로 전환하기 위한 대안으로 주목받고 있다.

 

NGF는 컨트롤 플레인과 데이터 플레인으로 역할을 확실히 나누고 있다. 컨트롤 플레인은 Gateway, HTTPRoute 등 Kubernetes 리소스를 지속적으로 감시하며,  데이터 플레인에 필요한 설정과 컴포넌트를 동적으로 구성한다. 데이터 플레인은 실제 트래픽 흐르고 처리하는 영역으로 Nginx 인스턴스 가 포함된다.

 

NGF는 기존 Ingress처럼 LoadBalancer나 NodePort 뒤에서 트래픽을 라우팅하지만, 라우팅 규칙과 컨트롤러 설정을 한 곳에 모아두는 모놀리식 한 구조가 아니라는 점에서 차이가 있다.

 

이번 글에서는 NGF의 기본 개념을 간단히 살펴본 뒤, Host 라우팅 방식으로 설정하고 MetalLB와 연결하는 과정, 마지막으로 /etc/hosts 설정까지 실습해 볼 예정이다.

 

Nginx Gateway Fabric 아키텍처

앞서 언급했듯이 NGF는 컨트롤 플레인(Control Plane)과 데이터 플레인(Data Plane)으로 나눌 수 있다. 인프라 담당자나 개발자가 Gateway, HTTPRoute와 같은 리소스를 적용하면, 컨트롤 플레인이 이를 지속적으로 감시하고 데이터 플레인 구성을 동적으로 반영한다.

 

클라이언트들의 요청은 데이터 플레인의 NGINX 인스턴스를 거쳐 라우팅 된다. 이 과정에서 Gateway는 NGINX 인스턴스를 구성하는 역할을, HTTPRoute는 실제 라우팅 규칙을 정의하는 역할을 담당한다고 보면 된다.

출처: https://www.f5.com/company/blog/nginx/announcing-nginx-gateway-fabric-release-1-2-0

 

Gateway API vs Ingress

Gateway API의 구현체인 NGF 와 Ingress의 구현체인 ingress-nginx는 리소스를 작성하는 방식에서 가장 큰 차이를 보인다.

Ingress 는 하나의 리소스 안에 라우팅 대상과 규칙을 함께 정의하는 방식이라, Controller가 이를 해석해 트래픽을 처리한다. 즉, 외부 요청이 어떤 서비스로 전달되어야 하는지에 대한 설정을 Ingress 리소스에 직접 작성해야 한다.

 

예를 들어 Ingress-nginx 는 아래와 같이 작성할 수 있다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-service
            port:
              number: 80

 

이 방식은 중앙집중식으로 관리할 수 있다는 장점이 있다. 반면 협업 측면에서는 아쉬운 부분도 있다. 개발자 측에서 라우팅 규칙이 자주 바뀌는 경우, 인프라 엔지니어가 매번 설정을 수정해야 하기 때문이다.

 

또한 모놀리식한 구조에서는 작은 휴먼 에러도 큰 장애로 이어질 수 있다. 특히 클러스터의 진입점을 다루는 설정인 만큼, 더욱 민감하게 관리할 필요가 있다.

 

이러한 이유로 Gateway API 방식에서는 기능을 여러 리소스로 나누었고, NGF 역시 다음과 같은 리소스 구조를 따른다.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: sample-gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    hostname: app.example.com
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: sample-httproute
spec:
  parentRefs:
  - name: sample-gateway
  hostnames:
  - app.example.com
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: app-service
      port: 80

 

이렇게 리소스의 역할을 나눔으로써, 인프라 엔지니어와 개발자 간의 책임과 역할을 확실히 할 수 있으며, 모놀리식 방식에 따른 리스크도 줄일 수 있다. 

 

이해하기 쉽도록 다음 그림을 참고하기를 바란다.

출처: https://blog.nginx.org/blog/5-things-to-know-about-nginx-gateway-fabric

 


Nginx Gateway Fabric 실습

이번 실습은 Helm 으로 진행할 예정이며, 진입점을 위한 LoadBalancer 혹은 NodePort 가 필요하다. 필자는 MetalLB로 진행할 예정이다.

사전 준비

Gateway API 리소스는 쿠버네티스 표준으로 정의되어 있지 않으므로 따로 설치를 진행해야한다.

kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v2.6.7" | kubectl --kubeconfig .kube/config apply -f -

설치

helm chart를 설치하기에 앞서 Gateway 리소스 부터 정의하겠다. Gateway 를 정의하는 방법은 매니패스트를 만들고 kubectl apply 를 하든가, helm value에 gateways 배열에 기입하는 방법이 있다.

 

여기서는 후자로 진행한다.

# 데이터 플레인 Service 노출 방식.
# 기본값이 type: LoadBalancer 이므로 MetalLB 가 IP 를 할당한다.
# nginx:
#   service:
#     type: NodePort
#     nodePorts:
#       - port: 30080
#         listenerPort: 80

gateways:
  - name: nginx-gateway
    namespace: kube-system
    spec:
      gatewayClassName: nginx
      listeners:
        - name: http
          port: 80
          protocol: HTTP
          allowedRoutes:
            namespaces:
              from: All

 

이제 helm chart 를 배포해 보자. OCI 레지스트리로 배포되므로 레포를 추가할 필요는 없다.

helm upgrade --install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric `
  --version 2.6.7 `
  --namespace nginx-gateway `
  --create-namespace `
  --values helm/nginx-gateway-fabric/values.yaml

 

정상적으로 설치가 되었다면 kube-system 네임스페이스와 nginx-gateway 네임스페이스에 각각 다음과 같은 파드와 서비스가 생겼을 것이다.

 

서비스를 잘 보면 nginx-gateway-nginx에 외부 IP가 부여된 모습을 볼 수 있다. 즉 이 부분이 데이터 플레인이 되고 ngf-nginx-gateway-fabric이 컨트롤 플레인이 되는 것으로 이해하면 된다.

라우팅 규칙 정의

지금 까지는 외부 로드밸런서를 통해 외부에 진입점을 여는 Gateway를 만들었다면 지금부터는 내부 서비스로의 라우팅을 위한 라우팅 규칙을 정의할 것이다.

 

필자의 클러스터에는 이미 Grafana 대시보드가 설치되어 있으므로 Grafana에 라우팅 규칙을 만들어서 Host 기반 라우팅을 설정할 예정이다.

 

참고로 라우팅 규칙은 애플리케이션의 영역에 가까움으로 Grafana IaC와 함께 보관하면 좋다.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: grafana-route
  namespace: monitoring
spec:
  parentRefs:
  - name: nginx-gateway
    namespace: kube-system
    sectionName: http
  hostnames:
  - "grafana.virtualbox.io"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: prometheus-grafana
      port: 80

 

설정을 마쳤다면, HTTPRoute 리소스로 다음과 같이 설정되었을 것이다.

 

접속 및 확인

Host 기반 라우팅으로 설정했으므로, DNS 서버 혹은 로컬 DNS 매핑이 필요하다.

필자의 실습환경은 윈도우 11 이므로 C:\Windows\System32\drivers\etc에 '192.168.56.20 grafana.virtualbox.io'를 추가했다.

 

 

이제 접속해 보니 정상적으로 Grafana에 접근이 되었다!