NGINX Ingress Controller Annotation rewrite, response header 설정

이 포스트는 NGINX Ingress Controller Annotation 설정을 통해 보다 심화된 기능인 request rewrite 기능과 추가 response header를 삽입하는 방법에 대해 설명합니다.

목차

1. NGINX Ingress Controller Annotation이란?
2. Deployment, service 사전 구성
3. NGINX Ingress Controller Annotation rewrite 설정
4. NGINX Ingress Controller Annotation 추가 response header 설정

1. NGINX Ingress Controller Annotation이란?

NGINX Ingress Controller Annotation

NGINX Ingress Controller의 annotation 설정은 Ingress 리소스의 고급 설정을 사용할 수 있게 합니다.
Ingress 리소스는 NGINX의 기본적인 기능인 host/path 기반 라우팅, TLS termination만을 지원하고, request rewrite나 추가 response header 삽입과 같은 고급 설정은 지원하지 않습니다.
하지만 NGINX Ingress Controller의 Ingress 리소스에 annotation을 추가하면 connection timeout 값을 추가하는 등의 고급 설정을 사용할 수 있습니다.
이러한 설정들은 ConfigMap을 통해서도 지원하지만, annotation 설정이 우선됩니다.

Annotation 설정에 대해 보다 자세한 내용을 여기를 참조하세요.

2. Deployment, service 사전 구성

NGINX Ingress Controller Annotation 설정에 앞서 NGINX Ingress Controller를 통해서 라우팅 될 backend1, backend2의 deployment, 서비스를 다음과 같이 구성하였습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend1
  template:
    metadata:
      labels:
        app: backend1
    spec:
      containers:
      - name: backend1
        image: nginxdemos/nginx-hello:plain-text
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: backend1-svc
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: backend1
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend2
  template:
    metadata:
      labels:
        app: backend2
    spec:
      containers:
      - name: backend2
        image: nginxdemos/nginx-hello:plain-text
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: backend2-svc
  labels:
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: backend2

컨테이너의 서버는 200 코드와 함께 서버 주소, 서버 이름, 요청 시간, 요청 URI, 요청 ID를 반환합니다.

server {
    listen 8080;
    listen [::]:8080;

    location / {
        default_type text/plain;
        expires -1;
        return 200 'Server address: $server_addr:$server_port\nServer name: $hostname\nDate: $time_local\nURI: $request_uri\nRequest ID: $request_id\n';
    }
}

생성된 pod와 서비스는 다음과 같습니다.

# kubectl get pod,service


NAME                            READY   STATUS    RESTARTS   AGE
pod/backend1-584b5f78fb-bcc4f   1/1     Running   0          29s
pod/backend1-584b5f78fb-zrdtl   1/1     Running   0          29s
pod/backend2-7464c479f8-rpg62   1/1     Running   0          29s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/backend1-svc   ClusterIP   10.102.194.233    <none>        80/TCP    29s
service/backend2-svc   ClusterIP   10.107.124.18     <none>        80/TCP    29s

Kubernetes 클러스터 외부에서 Ingress Controller를 통해 클러스터 내부의 서비스에 접근하기 위해 NodePort 서비스를 배포합니다.

# kubectl apply -f nodeport.yaml


배포 중인 Ingress controller의 NodePort 서비스를 확인합니다.

# kubectl get svc -n nginx-ingress

NAME            TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
nginx-ingress   NodePort   10.102.97.200   <none>        80:30348/TCP,443:32253/TCP   15m

30348 포트로 http 요청을 수신함을 확인할 수 있습니다.

2. NGINX Ingress Controller Annotation rewrite 설정

Ingress 파일의 annotations를 통해 rewrite 설정을 구성합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.org/rewrites: "serviceName=backend1-svc rewrite=/;serviceName=backend2-svc rewrite=/test/"
  name: ingress-rewrite
spec:
  rules:
  - host: example.com
    http:
      paths:
        - path: /backend1/
          pathType: Prefix
          backend:
            service:
              name: backend1-svc
              port:
                number: 80
        - path: /backend2/
          pathType: Prefix
          backend:
            service:
              name: backend2-svc
              port:
                number: 80
  • annotations 항목에 nginx.org/rewrites 설정을 추가합니다
  • “serviceName=<서비스명> rewrite=<rewrite 내용>” 형식으로 rewrite 설정을 작성합니다.

위와 같이 설정 시 다음과 같이 적용됩니다.

  • /backend1/ 요청의 URI를 /로 rewrite합니다
  • /bakcend2/ 요청의 URI를 /test/로 rewrite합니다
  • /backend1 요청은 /backend1/ 요청으로 redirect됩니다
  • /backend2 요청은 /backend2/ 요청으로 redirect됩니다

작성한 Ingress 파일을 배포하고 확인합니다.

# kubectl apply -f rewrite.yaml

# kubectl get ingress

NAME              CLASS    HOSTS         ADDRESS   PORTS   AGE
ingress-rewrite   <none>   example.com             80      3m14s

example.com/backend1과 example.com/backend2로 요청을 보내 rewrite 설정을 확인합니다.

# curl example.com:30348/backend1/hello

Server address: 10.244.1.34:8080
Server name: backend1-584b5f78fb-zrdtl
Date: 09/Apr/2024:07:36:39 +0000
URI: /hello
Request ID: 4e358f781161955642bda8e17705e8ec


# curl example.com:30348/backend2/hello

Server address: 10.244.1.33:8080
Server name: backend2-7464c479f8-rpg62
Date: 09/Apr/2024:07:37:01 +0000
URI: /test/hello
Request ID: ada22f6e0d67c59e8ab64e4a4f74ef52

example.com/backend1/hello 요청에 대해 URI가 /hello로 rewrite되고,
example.com/backend2/hello 요청에 대해 URI가 /test/hello로 rewrite됨을 확인할 수 있습니다.

3. NGINX Ingress Controller Annotation response header 설정

response header를 추가하기 위해서는 annotations에 snippets 설정이 필요합니다.
기본적으로 NGINX Ingress Controller 설정에서 snippets는 비활성화되어 있기 때문에, deployment 파일의 설정을 통해 활성화해야 합니다.

# vi ingress-snippets.yaml


apiVersion: apps/v1
kind: Deployment

......

spec:
  template:
    spec:
      args:
        - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
        - -enable-snippets                                   # snippets 활성화 구문 추가

수정된 deployment 파일을 통해 snippets 설정이 활성화된 NGINX Ingress Controller를 재배포합니다.

# kubectl apply -f ingress-snippets.yaml

Ingress 파일의 annotation항목에 location-snippets를 설정하여 response header을 추가합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.org/location-snippets: |
      add_header Custom-Header my-header;

  name: ingress-header
spec:
  rules:
  - host: example.com
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: backend1-svc
              port:
                number: 80
  • annotations 항목에 nginx.org/location-snippets 설정을 추가합니다.
  • add_header <헤더 이름> <헤더 내용> 형식으로 작성합니다.

example.com으로 요청을 전송할 때, 헤더에 Custom-Header 헤더 이름의 my-header 헤더 내용으로 헤더가 추가되도록 설정했습니다.

배포한 Ingress 파일을 확인합니다.

# kubectl get ingress ingress-header


NAME             CLASS    HOSTS         ADDRESS   PORTS   AGE
ingress-header   <none>   example.com             80      24m

설정한 서비스에 요청 시, 설정한 request header을 반환하는 것을 확인할 수 있습니다.

# curl -I example.com:30348

HTTP/1.1 200 OK
Server: nginx/1.25.3
Date: Tue, 09 Apr 2024 06:56:50 GMT
Content-Type: text/plain
Content-Length: 157
Connection: keep-alive
Expires: Tue, 09 Apr 2024 06:56:49 GMT
Cache-Control: no-cache
Custom-Header: my-header               # 설정한 header가 반환됨

아래 폼을 통해 NGINX Plus Ingress Controller Trial 라이선스를 신청해보세요!

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

* indicates required