NGINX Ingress Controller로 고급 TCP/UDP Load Balancing 및 WAF 통합

표준 Kubernetes Ingress 리소스는 Ingress Load Balancing 을 프로비저닝(Provisioning)하고 구성하는 데 적합하지만 Kubernetes를 Production 등급으로 만드는 데 필요한 사용자 정의 기능은 포함하지 않습니다. 사용자는 NGINX가 아닌 오류가 발생하기 쉽고 사용하기 어렵고 안전하지 않으며 세분화된 범위 지정이 없는 Annotation, ConfigMap 및 사용자 정의 템플릿을 사용해야 합니다. NGINX Ingress 리소스는 이 문제에 대한 해답입니다.

NGINX Ingress 리소스는 NGINX Open Source 및 NGINX Plus 기반 버전의 NGINX Ingress Controller 모두 사용할 수 있습니다. Ingress Load Balancing 의 구현을 간소화하는 기본 형식인 안전한 들여쓰기 스타일 구성을 제공합니다. 이 포스트에서는 NGINX Ingress Controller 1.11.0에 도입되어 WAF 및 Load Balancing 정책을 보다 쉽게 구성할 수 있는 두 가지 기능에 중점을 둡니다.

  • TransportServer 리소스 – TransportServer 리소스는 TCP, UDP 및 TLS Passthrough Load Balancing에 대한 구성을 정의합니다. Health Check, 상태 보고 및 Snippets 구성을 추가하여 TCP/UDP Load Balancing을 향상했습니다.
  • NGINX Ingress WAF 정책 – NGINX Ingress Controller와 함께 NGINX App Protect 3.0을 배포할 때 NGINX Ingress 리소스를 활용하여 특정 Kubernetes 서비스에 WAF 정책을 적용할 수 있습니다.

목차

1. TransportServer 리소스의 향상된 기능
1-1. TransportServer Snippets
1-2. Health Checks
1-3. ingressClassName로 여러 TransportServer 리소스 지원

2. Native NGINX App Protect를 사용하여 WAF 정책 정의
3. 릴리스 1.11.0의 다른 새로운 기능은 무엇입니까?
3-1. 더 많은 Annotation의 유효성 검사
3-2. 정책에 대한 상태 정보
3-3. Istio와의 호환성
3-4. Upstream Endpoint의 클러스터 IP 주소
4. 리소스

1. TransportServer 리소스의 향상된 기능

NGINX Ingress Controller 1.11.0은 다음 영역에서 TS(Transport Server) 리소스를 확장합니다.

1-1. TransportServer Snippets

NGINX Ingress Controller 1.8.0에서는 HTTP 기반 클라이언트에 대한 NGINX Ingress 구성을 기본적으로 확장할 수 있는 VirtualServer 및 VirtualServerRoute(VS 및 VSR) 리소스에 대한 구성 Snippets을 도입했습니다. 릴리스 1.11.0에는 TS 리소스에 대한 Snippets이 도입되어 있으므로 전체 범위의 NGINX 및 NGINX Plus 기능을 쉽게 활용하여 TCP/UDP 기반 서비스를 제공할 수 있습니다. 예를 들어 Snippets을 사용하여 IP 주소 및 범위를 사용하여 서비스에 액세스할 수 있는 클라이언트를 정의하는 지시문을 거부(deny) 및 허용(allow)을 정의할 수 있습니다.

apiVersion: k8s.nginx.org/v1alpha1
kind: TransportServer
metadata:
  name: cafe
spec:
  host: cafe.example.com
  serverSnippets: |
    deny  192.168.1.1;
    allow 192.168.1.0/24;
  upstreams:
  - name: tea
    service: tea-svc
    port: 80

1-2. Health Checks

Kubernetes 클러스터의 상태를 모니터링하기 위해 NGINX Ingress Controller는 애플리케이션 Pod에 로컬인 Kubernetes Probe를 고려할 뿐만 아니라 수동 Health Check을 통해 TCP/UDP 기반 Upstream 서비스 간의 네트워크 상태에 대한 탭을 유지하여 다음을 평가합니다. 진행 중인 트랜잭션의 상태 및 Active Health Check(NGINX Plus 전용)을 통해 Synthetic 연결 요청을 Endpoint를 주기적으로 Probe합니다.

Health Check은 회로 차단(Circuit Breaking) 및 애플리케이션 오류 처리에 매우 유용할 수 있습니다. Probe 간 간격, Probe timeout, Probe 간 지연 시간(delay time) 등을 설정하는 TS 리소스의 Health Check 필드에 있는 매개변수를 사용하여 Health Check를 사용자 정의할 수 있습니다.

또한 NGINX Ingress Controller에서 Health Probe의 Upstream 서비스 및 Pod 대상을 설정할 수 있습니다. 이는 Upstream 애플리케이션의 Health가 애플리케이션의 여러 Downstream 구성 요소를 모니터링하는 다른 프로세스 또는 하위 시스템에 의해 다른 Listener에 노출되는 상황에서 유용합니다.

1-3. ingressClassName로 여러 TransportServer 리소스 지원

TS 리소스를 업데이트하고 적용할 때 구성이 유효하고 해당 Ingress Controller 배포에 성공적으로 적용되었는지 확인하는 것이 유용합니다. 릴리스 1.11.0에는 TS 리소스에 대한 ingressClassName 필드 및 상태 보고(Status Reporting)가 도입되었습니다. ingressClassName 필드는 여러 배포가 있는 환경에서 특정 Ingress Controller 배포에 의해 TS 리소스가 처리되도록 합니다.

하나 또는 모든 TS 리소스의 상태를 표시하려면 kubectl get transportserver 명령을 실행합니다. 출력에는 상태(유효 또는 무효), 최신 업데이트 이유 및 (단일 TS의 경우) 사용자 정의 메시지가 포함됩니다.

$ kubectl get transportserver
  NAME      STATE   REASON           AGE
  dns-tcp   Valid   AddedOrUpdated   47m

$ kubectl describe transportserver dns-tcp
. . .
Status:
  Message:  Configuration for default/dns-tcp was added or updated
  Reason:   AddedOrUpdated
  State:    Valid

여러 TS 리소스가 동일한 Host/Listener에 대해 경합하는 경우 NGINX Ingress Controller는 가장 오래된 Time Stamp가 있는 TS 리소스를 선택하여 해당 상황에서 결정적인 결과를 보장합니다.

2. Native NGINX App Protect를 사용하여 WAF 정책 정의

NGINX Ingress 리소스는 구성을 더 쉽고 유연하게 할 뿐만 아니라 트래픽 제어(traffic control)를 다른 팀에 위임하고 VSR(VirtualServerRoute) 리소스에 정의된 대로 애플리케이션 하위 경로를 소유한 사용자에게 더 엄격한 권한 제한을 부과할 수 있습니다. 적합한 팀에게 적합한 Kubernetes 리소스에 대한 액세스 권한을 부여함으로써 NGINX Ingress 리소스는 네트워킹 리소스에 대한 세밀한 제어(fine‑grained control)를 제공하고 사용자가 손상되거나 해킹될 경우 애플리케이션에 대한 잠재적 피해를 줄입니다.

릴리스 1.11.0에서는 이러한 이점을 Kubernetes 배포에서 NGINX App Protect 구성으로 확장하기 위해 Native Web Application Firewall(WAF) 정책 객체를 도입했습니다. 이 정책은 릴리스 1.8.0에 도입된 APLogConf 및 APPolicy 객체를 활용하며 VirtualServer(VS) 및 VSR 리소스 모두에 연결할 수 있습니다. 즉, 보안 관리자는 VSR 리소스를 사용하여 입력 구성의 전체 범위에 대한 소유권을 보유하는 동시에 VSR 리소스를 참조하여 다른 팀에 보안 책임을 위임할 수 있습니다.

다음 예에서 waf-prod 정책은 webapp-prod Upstream으로 라우팅되는 사용자에게 적용됩니다. 여러 팀이 소유한 Namespaces 간에 /v2 경로에 대한 보안 책임을 위임하기 위해 강조 표시된 route 지시문은 VSR 리소스를 참조합니다.

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: webapp
spec:
  host: webapp.example.com
  policies:
  - name: waf-prod 
  tls:
    secret: app-secret
  upstreams:
  - name: webapp-prod
    service: webapp-svc
    port: 80
  routes:
  - path: /v2
    route: test/test
  - path: /v1
    action:
      pass: webapp-prod

테스트 Namespaces를 관리하는 팀은 해당 Namespaces의 VSR 리소스를 사용하여 자체 매개변수 및 WAF 정책을 설정할 수 있습니다.

apiVersion: k8s.nginx.org/v1
kind: VirtualServerRoute
metadata:
  name: test 
  namespace: test
spec:
  host: webapp.example.com
  upstreams:
  - name: webapp 
    service: webapp-test-svc
    port: 80
  subroutes:
  - path: /v2
    policies:
    - name: waf-test
    action:
      pass: webapp

이 예제에서는 tenant를 Namespaces로 구분하고 테스트 Namespaces의 webapp-test-svc 서비스에 대해 다른 WAF 정책을 적용합니다. 리소스를 다른 팀에 위임하고 객체로 캡슐화하여 Production 애플리케이션을 중단하지 않고 새로운 기능 테스트하는 방법을 보여줍니다.

3. 릴리스 1.11.0의 다른 새로운 기능은 무엇입니까?

NGINX Ingress Controller 1.11.0을 통해 유연하고 강력하며 사용하기 쉬운 Production 등급 Ingress Controller를 제공하기 위한 노력을 계속하고 있습니다. WAF 및 TS 개선 사항 외에도 릴리스 1.11.0에는 다음과 같은 개선 사항이 포함되어 있습니다.

3-1. 더 많은 Annotation의 유효성 검사

릴리스 1.10.0에 도입된 Annotation 유효성 검사의 개선 사항을 기반으로 이제 다음과 같은 Annotation을 추가적으로 유효성 검사하고 있습니다.

Annotation검증
nginx.org/client-max-body-sizeMust be a valid offset
nginx.org/fail-timeoutMust be a valid time
nginx.org/max-connsMust be a valid non‑negative integer
nginx.org/max-failsMust be a valid non‑negative integer
nginx.org/proxy-buffer-sizeMust be a valid size
nginx.org/proxy-buffersMust be a valid proxy buffer spec
nginx.org/proxy-connect-timeoutMust be a valid time
nginx.org/proxy-max-temp-file-sizeMust be a valid size
nginx.org/proxy-read-timeoutMust be a valid time
nginx.org/proxy-send-timeoutMust be a valid time
nginx.org/upstream-zone-sizeMust be a valid size

Ingress 리소스가 적용될 때 Annotation 값이 유효하지 않으면 Ingress Controller는 리소스를 거부하고 NGINX에서 해당 구성을 제거합니다.

3-2. 정책에 대한 상태 정보

kubectl get policy 명령은 이제 정책의 상태(유효 또는 무효)와 (단일 TS의 경우) 사용자 정의 메시지 및 최신 업데이트 이유를 보고합니다.

$ kubectl get policy
  NAME              STATE   AGE
  webapp-policy     Valid   30s

$ kubectl describe policy webapp-policy
. . .
Status:
  Message:  Configuration for default/webapp-policy was added or updated
  Reason:   AddedOrUpdated
  State:    Valid

3-3. Istio와의 호환성

이제 NGINX Ingress Controller를 Istio Service Mesh 내에서 실행되는 애플리케이션의 Ingress Controller로 사용할 수 있습니다. 이를 통해 사용자는 해결 방법에 의존하지 않고 Istio 기반 환경에서 NGINX Ingress Controller가 제공하는 고급 기능을 계속 사용할 수 있습니다. 이 통합에는 두 가지 요구 사항이 있습니다.

  • NGINX Ingress Controller 배포에 Istio Sidecar 주입
  • 하나의 HTTP 호스트 헤더만 Backend로 전송됩니다.

첫 번째 요구 사항을 충족하려면 NGINX Ingress Deployment 파일의 Annotation 필드에 다음 항목을 포함합니다.

annotations: 
  traffic.sidecar.istio.io/includeInboundPorts: "" 
  traffic.sidecar.istio.io/excludeInboundPorts: "80,443"         
  traffic.sidecar.istio.io/excludeOutboundIPRanges: "10.90.0.0/16,10.45.0.0/16"     sidecar.istio.io/inject: 'true'

두 번째 요구 사항은 requestHeaders 필드의 동작을 변경하여 달성됩니다. 이전 릴리스에서는 다음 구성을 사용하여 $host 및 지정된 값인 bar.example.com이라는 두 개의 호스트 헤더가 Backend로 전송되었습니다.

apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
  name: foo 
spec:
  host: foo.example.com
  upstreams:
  - name: foo
    port: 8080
    service: backend-svc
    use-cluster-ip: true
  routes:
  - path: "/"
    action:
      proxy:
        upstream: foo
        requestHeaders:
          set:
          - name: Host
            value: bar.example.com

릴리스 1.11.0 이상에서는 지정된 값만 전송됩니다. $host를 보내려면 requestHeaders 필드를 완전히 생략하십시오.

3-4. Upstream Endpoint의 클러스터 IP 주소

이제 NGINX Ingress Controller 구성의 Upstream Endpoint를 Pod Endpoint의 개별 IP 주소 대신 서비스/클러스터 IP 주소로 채울 수 있습니다. NGINX Ingress Controller가 트래픽을 Cluster‑IP 서비스로 라우팅하도록 하려면 VS 또는 VSR 구성의 Upstream 섹션에 use-cluster-ip: true 필드를 포함합니다.

upstreams:
  - name: tea
    service: tea-svc
    port: 80
    use-cluster-ip: true
  - name: coffee
    service: coffee-svc
    port: 80
    use-cluster-ip: true

4. 리소스

NGINX Open Source로 NGINX Ingress Controller를 사용해 보려면 릴리스 소스 코드를 얻거나 DockerHub에서 미리 Bluild된 컨테이너를 다운로드할 수 있습니다.

또는 NGINX Ingress Controller의 최신 소식을 빠르게 전달 받고 싶으시면 아래 뉴스레터를 구독하세요.