K8s Gateway API(NGF) & Istio: Pod 간 mTLS 적용 가이드

본 포스트에서는 NGINX Gateway Fabric(NGF)을 Gateway API의 구현체로 사용하여 외부 트래픽을 수신하고, 이를 Istio 사이드카와 연동하여 Pod 간 완벽한 mTLS 통신 환경을 구축하는 과정을 다룹니다. 특히 Istio의 PeerAuthentication을 STRICT 모드로 설정하여 평문 통신을 강제로 차단하고, Gateway API의 핵심 기능인 URLRewrite 필터를 활용해 서비스 메시 내부에서 올바른 인증서 로딩과 라우팅이 이루어지도록 구성하는 가이드를 제시합니다.

목차

1. 환경 구성
2. Istio Sidecar 적용
3. NGINX Gateway Fabric + App 구성
4. Istio Sidecar mTLS 구성
5. 결론

1. 환경 구성

  • kubernetes: v1.32.2
  • NGINX Gateway Fabric : 2.2.2
  • Istio : 1.28.1

2. Istio Sidecar 적용

먼저 Istio Sidecar를 적용하여 Envoy Proxy를 통해 통신할 수 있도록 구성합니다.

kubectl label namespace application istio-injection=enabled  

해당 Namespace 전체에 Sidecar를 Injection 할 수 있도록 구성하였습니다.

3. NGINX Gateway Fabric + App 구성

먼저 백엔드가 될 애플리케이션을 배포합니다.

NGINX Deployment를 구성하였습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: coffee
  namespace: application
spec:
  replicas: 2
  selector:
    matchLabels:
      app: coffee
  template:
    metadata:
      labels:
        app: coffee
    spec:
      containers:
      - name: nginx
        image: nginx 
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: coffee-svc
  namespace: application
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP 
    name: nginx
  selector:
    app: coffee

NGINX Gateway Fabric를 통하여 접속할 수 있도록 Gateway와 HTTPRoute를 구성합니다.

먼저 SSL 통신을 위한 서버 인증서를 추가합니다.

kubectl create secret tls server-tls-secret \
  --cert=server.crt \
  --key=server.key -n application

기본적으로 443 포트를 리스닝하는 Gateway 구성입니다.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: edge-gateway
  namespace: application
spec:
  gatewayClassName: nginx
  listeners:
  - name: https-listener
    port: 443 
    protocol: HTTPS
    hostname: "devopschan.com"
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: server-tls-secret

HTTPRoute를 구성합니다.

mTLS 환경에서 URLRewrite를 사용하는 이유는, Gateway가 트래픽을 백엔드로 보낼 때 이 요청은 내부 메시(Mesh) 간 통신이므로 mTLS로 암호화해야 한다’는 것을 식별하기 위함입니다.

Envoy Proxy는 Host 헤더가 내부 KubeDNS(서비스명)와 일치할 때만 해당 서비스에 맞는 인증서와 SNI를 로드하여 mTLS 핸드쉐이크를 시도합니다. Host가 외부 도메인(devopschan.com)인 상태 그대로 전송되면, Gateway는 이를 내부 트래픽으로 인식하지 못해 평문(Plaintext)으로 전송하게 되고, 암호화된 트래픽만 허용하는 수신 측 Sidecar에 의해 연결이 거부됩니다.

따라서 URLRewrite를 통해 Host를 내부 서비스명으로 변경하거나, ServiceEntry로 외부 도메인을 메시에 등록하는 절차가 필수적입니다.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: coffee-route
  namespace: application
spec:
  parentRefs:
  - name: edge-gateway
  hostnames:
  - "devopschan.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    filters:
    - type: URLRewrite
      urlRewrite: 
        hostname: coffee-svc.application.svc.cluster.local # hostname을 coffe service의 kubeDNS 도메인으로 변경합니다.
    backendRefs:
    - name: coffee-svc # 해당 서비스로 Rewrite합니다.
      port: 80

해당 구성을 추가한 뒤 구성을 저장합니다.

먼저 구성 전 Ingress Traffic이 잘 전달되는지 확인합니다.

정상적으로 devopschan.com 도메인으로 접속되는 것을 확인할 수 있습니다.

Kubernetes Pods안에서 coffee Service의 ClusterIP로 요청을 전송합니다.

curl용 Pods를 생성합니다.(sidecar는 제거한 후 요청을 전송합니다.)

kubectl run curl --image=curlimages/curl -n application --annotations="sidecar.istio.io/inject=false" -it --rm -- sh

요청이 되는 것을 확인할 수 있습니다.

4. Istio Sidecar mTLS 구성

Istio는 기본적으로 PERMISSIVE 모드로 동작합니다.

예를 들어 사이드카(Envoy)가 있는 A, B 파드 간 통신은 자동으로 mTLS 암호화가 적용되지만, 수신 측(B)은 암호화되지 않은 평문(Plain Text) 요청도 허용합니다.

해당 포스트에서는 STRICT 모드를 사용하여 정책을 변경하여 mTLS 통신만 허용하도록 강제합니다.

PeerAuthentication : Envoy Proxy의 mTLS 정책을 구성합니다.

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: specific-app-mtls
  namespace: application 
spec:
  selector:
    matchLabels:
      app: coffee # application Pods 만 해당 정책을 활성화합니다.
  mtls:
    mode: STRICT # mTLS를 강제합니다.

해당 구성을 추가한 후 curl을 통해 Pods에서 요청합니다.

Sidecar끼리 통신하는 것이 아니기 때문에 요청이 거절되는 것을 확인할 수 있습니다.

Istio Sidecar가 붙은 NGINX Gateway Fabric으로 접속 시 정상적인 응답을 하는 것을 확인할 수 있습니다.

Istio Monitoring 시스템인 Kiali에서도 mTLS가 구성된 것을 확인할 수 있습니다.

(Kiali 배포 포스트)

5. 결론

이번 실습을 통해 NGINX Gateway Fabric과 Istio를 연동함으로써 외부 요청부터 내부 애플리케이션에 도달하기까지의 전 구간에 강력한 보안 정책을 성공적으로 적용해 보았습니다. PeerAuthentication 정책을 STRICT 모드로 설정하여 사이드카를 통하지 않은 비인가 평문(Plaintext) 트래픽이 효과적으로 차단됨을 확인하였으며, Gateway 단에서의 적절한 Host 헤더 재작성(URLRewrite)을 통해 서비스 메시 내부의 mTLS 핸드쉐이크가 끊김 없이 수행됨을 검증할 수 있었습니다.

결과적으로 Gateway API의 표준화된 인터페이스와 Istio의 강력한 보안 기능을 결합하여, 운영의 복잡성을 최소화하면서도 엔터프라이즈급의 제로 트러스트 환경을 구축할 수 있었습니다.

F5 Distributed Cloud를 통해 JWT의 클레임 기반 접근 제어를 포함한 다양한 애플리케이션 보호 기능을 경험해 보고 싶으시다면 NGINX STORE를 통해 문의하세요.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required