Kubernetes NGINX Ingress Controller의 성능 테스트

Kubernetes는 컨테이너형 애플리케이션을 관리하기 위한 사실상의 표준이 되었으며, 많은 기업이 Production 환경에서 이를 채택하고 있습니다. 이 포스트에서는 Kubernetes NGINX Ingress Controller 를 통해 달성할 수 있는 성능 종류를 설명하고 초당 SSL/TLS 트랜잭션 및 처리량의 세 가지 Metric에 대한 성능 테스트 결과를 자세히 설명합니다. 또한 우리가 사용한 전체 NGINX 및 Kubernetes 구성도 포함합니다.

성능 수치 및 구성을 사용하여 필요한 성능 및 규모 수준에서 자체 애플리케이션을 제공하기 위한 올바른 토폴로지(Topology), 사양 및 Kubernetes 구성을 결정하는 데 도움을 받을 수 있습니다.

목차

1. 토폴로지(Topology)
2. 사용된 하드웨어
3. 사용된 소프트웨어
4. Metric 수집
5. Testing Methodology(테스트 방법론)
5-1. RPS 테스트
5-2. TPS 테스트
5-3. HTTP Throughput(처리량) 테스트
6. 성능 분석
6-1. HTTP 요청에 대한 RPS

6-2. HTTPS 요청에 대한 RPS
6-3. TPS
6-4. Throughput(처리량)
7. 테스트의 기술적 세부 사항
7-1. Kubernetes NGINX Ingress Controller 배포를 위한 Kubernetes 구성
7-2. NGINX Ingress Controller Expose을 위한 Kubernetes 서비스 구성
7-3. Kubernetes
NGINX Ingress Controller 용 Kubernetes ConfigMap
7-4. Backend에 대한 Kubernetes DaemonSet
7-4-1. 네트워킹 최적화

7-4-2. Backend DaemonSet 배포
7-4-3. Kubernetes Ingress 리소스
8. 결론

1. 토폴로지(Topology)

모든 테스트에서 클라이언트 시스템에서 실행되는 wrk 유틸리티는 트래픽을 생성하고 40Gigabit 이더넷 링크를 통해 10Gigabit 링크로 연결된 두 노드(Primary 노드 와 Secondary 노드)의 Kubernetes 클러스터로 트래픽을 전송했습니다.

NGINX Ingress Controller는 SSL Termination 및 Layer 7 라우팅을 수행하기 위해 기본 노드에 Kubernetes Pod로 배포되었습니다. Secondary 노드에서 실행되는 Upstream Pod는 다양한 크기의 정적 콘텐츠를 제공하는 NGINX 웹 서버였습니다.

2. 사용된 하드웨어

테스트에 사용된 하드웨어는 다음과 같습니다.

MachineCPUNetworkMemory
Client2x Intel(R) Xeon(R) CPU E5‑2699 v4 @ 2.20GHz, 44 real (or 88 HT) cores1x Intel XL710 40GbE QSFP+128 GB
기본 노드
(Primary Node)
2x Intel(R) Xeon(R) Platinum 8168 CPU @ 2.70GHz, 48 real (or 96 HT) cores1x Intel XL710 40GbE QSFP+192 GB
보조 노드
(Secondary Node)
2x Intel(R) Xeon(R) CPU E5‑2699 v4 @ 2.20GHz, 44 real (or 88 HT) cores1x Intel 10‑Gigabit X540‑AT2128 GB

3. 사용된 소프트웨어

테스트를 위해 다음 소프트웨어를 사용했습니다.

4. Metric 수집

테스트를 실행하여 다음과 같은 세 가지 성능 Metric 수집했습니다.

  • Requests per second (RPS) – 고정된 시간 동안 평균적으로 NGINX Ingress Controller가 초당 처리할 수 있는 요청 수입니다. 클라이언트는 각 요청을 시작하고 NGINX Ingress Controller로 전달했습니다. NGINX Ingress Controller는 클라이언트가 요청한 정적 콘텐츠를 가져오기 위해 요청을 Upstream Pod로 Proxy 처리했습니다. 정적 콘텐츠는 대략 1KB 파일로, 작은 CSS나 JavaScript 파일 이거나 매우 작은 이미지입니다.
  • SSL/TLS transactions per second (TPS) – 고정된 시간 동안 NGINX Ingress Controller가 설정하고 서비스를 제공할 수 있는 새로운 HTTPS 연결 수입니다. 클라이언트는 각각 새로운 연결을 통해 일련의 HTTPS 요청을 전송했습니다. 클라이언트와 NGINX Ingress Controller는 TLS Handshake를 수행하여 보안 연결을 설정한 다음 NGINX Ingress Controller가 요청을 구문 분석하고 0KB 응답을 다시 전송했습니다. 요청이 완전히 충족된 후 연결이 종료되었습니다.
  • Throughput(처리량) – 고정된 시간 동안 정적 콘텐츠에 대한 HTTP 요청을 처리하는 동안 NGINX가 유지할 수 있는 데이터 전송 속도입니다. 더 큰 파일을 요청하면 시스템의 전체 처리량을 증가시키므로 때문에 정적 콘텐츠는 1MB 파일이었습니다.

5. Testing Methodology(테스트 방법론)

다음 작업 옵션을 사용하여 클라이언트 트래픽을 생성했습니다.

  • -c 옵션: 생성할 TCP 연결 수를 지정합니다. 테스트를 위해 1000개의 연결로 설정했니다.
  • -d 옵션: 트래픽을 생성하는 기간을 지정합니다. 각각 180초(3분) 동안 테스트를 실행했습니다.
  • -t 옵션: 만들 스레드 수를 지정합니다. 여기서는 44개의 스레드를 지정했습니다.

각 CPU를 완전히 실행하기 위해 단일 작업 프로세스를 CPU에 고정할 수 있는 작업 세트를 사용했습니다. 이 방법은 wrk 스레드 수를 증가시키는 것보다 더 일관된 결과를 산출합니다.

HTTPS 성능을 테스트할 때 2048비트 키 크기와 Perfect Forward Secrecy의 RSA를 사용했습니다. SSL 암호는 ECDHE-RSA-AES256-GCM-SHA384였습니다.

5-1. RPS 테스트

RPS를 측정하기 위해 클라이언트 시스템에서 다음 스크립트를 실행했습니다.

taskset -c 0-21,44-65 wrk -t 44 -c 1000 -d 180s https://host.example.com:443/1kb.bin

이 스크립트는 44개 CPU 각각에 하나의 wrk 스레드를 생성합니다. 각 스레드는 1000개의 TCP 연결을 생성하고 3분 동안 각 연결을 통해 1KB 파일을 지속적으로 요청합니다.

5-2. TPS 테스트

TPS를 측정하기 위해 다음 스크립트를 실행했습니다.

taskset -c 0-21,44-65 wrk -t 44 -c 1000 -d 180s -H ‘Connection: Close’ https://host.example.com:443

이 테스트는 RPS 테스트와 동일한 wrk 옵션을 사용하지만 SSL/TLS 연결 처리에 중점을 두기 때문에 두 가지 중요한 차이점이 있습니다.

  • 클라이언트는 각 요청에 대한 연결을 열고 닫습니다(-H 옵션은 HTTP Connection: close 헤더를 설정함).
  • 요청한 파일의 크기는 1KB가 아니라 0KB입니다.

5-3. HTTP Throughput(처리량) 테스트

처리량을 측정하기 위해 다음 스크립트를 실행했습니다.

taskset -c 0-21,44-65 wrk -t 44 -c 1000 -d 180s https://host.example.com:443/1mb.bin

이 테스트는 요청한 파일의 크기가 1KB가 아닌 1MB라는 점을 제외하고 wrk 옵션을 RPS 테스트로 사용합니다.

6. 성능 분석

6-1. HTTP 요청에 대한 RPS

표와 그래프는 Kubernetes NGINX Ingress Controller 가 다양한 수의 CPU에서 초당 처리한 1KB 파일에 대한 HTTP 요청 수를 보여줍니다.

성능은 CPU 수에 거의 정비례하여 최대 16개 CPU까지 증가합니다. 우리는 16개에 비해 24개 CPU를 사용할 경우 성능 면에서 거의 또는 전혀 이점이 없다는 사실을 발견했습니다. 이는 리소스 경합이 결국 더 많은 수의 CPU에서 기대되는 성능 향상을 능가하기 때문입니다.

CPUsRPS
136,647
274,192
4148,936
8300,625
16342,651
24342,785

6-2. HTTPS 요청에 대한 RPS

HTTPS 요청에 필요한 암호화 및 암호 해독은 암호화되지 않은 HTTP 요청에 비해 컴퓨팅 비용을 증가시킵니다.

최대 8개의 CPU를 사용하는 테스트의 경우 결과는 예상대로입니다. RPS는 HTTP에 비해 HTTPS의 경우 약 20% 더 낮습니다.

16개 또는 24개의 CPU를 사용하는 테스트의 경우 리소스 경합으로 인해 HTTPS와 HTTP 사이에 기본적으로 차이가 없습니다.

CPUsRPS
128,640
258,041
4117,255
8236,703
16341,232
24342,785

6-3. TPS

표와 그래프는 Intel® Hyper‑Threading Technology(HT)을 사용하거나 사용하지 않는 다양한 수의 CPU에서 NGINX Ingress Controller의 TPS 성능을 보여줍니다.

TLS Handshake는 CPU 바인딩되어 있고 암호화 작업은 병렬화가 가능하기 때문에 HT는 이 Metric의 성능을 크게 향상시킬 수 있습니다. 최대 16개 CPU에서 성능이 50~65% 향상되었습니다.

CPUsSSL TPS (HT Disabled)SSL TPS (HT Enabled)
14,4337,325
28,70714,254
417,43326,950
831,48547,638
1654,87756,715
2458,12658,811
Kubernetes NGINX Ingress Controller

6-4. Throughput(처리량)

표와 그래프는 NGINX가 서로 다른 수의 CPU에서 3분 동안 유지할 수 있는 HTTP 요청의 처리량(Gbps)을 보여줍니다.

처리량은 클라이언트가 발행한 요청의 크기에 비례합니다. 성능은 예상대로 10Gbps 미만으로 정점을 찍었습니다. Kubernetes 클러스터의 보조 노드에는 Intel 10Gigabit X540-AT2 네트워크 인터페이스 카드가 장착되어 있습니다.

CPUsThroughput (Gbps)
11.91
24.78
48.72
88.64
168.80
248.80
Kubernetes NGINX Ingress Controller

7. 테스트의 기술적 세부 사항

7-1. Kubernetes NGINX Ingress Controller 배포를 위한 Kubernetes 구성

다음 Kubernetes 구성 파일을 사용하여 Kubernetes NGINX Ingress Controller를 배포했습니다. DockerHub Repository에서 nginx/nginx-ingress:edge 컨테이너 이미지 전용 Pod 사본 하나를 실행하는 Kubernetes DaemonSet를 정의합니다. nodeSelector 필드에 기본 노드의 레이블(npq3)을 지정하여 Pod를 기본 노드에 할당합니다.

클러스터 노드에 연결된 레이블을 나열하려면 다음 명령을 실행합니다.

$ kubectl get nodes --show-labels

컨테이너 이미지는 수신 및 발신 HTTP 및 HTTPS 연결을 위해 각각 포트 80 및 443에서 Expose됩니다. args 필드에 다음과 같은 두 가지 인수가 포함됩니다.

  • -nginx-configmaps: 이 인수를 사용하면 ConfigMap을 사용하여 NGINX Ingress Controller Pod에 구성 변경 사항을 적용할 수 있습니다.
  • -default-server-tls-secret: Ingress 리소스에 지정된 TLS 경로 기반 규칙과 일치하지 않는 NGINX Ingress Controller Entry Point에 도달하는 TLS 요청에 사용되는 기본 암을 설정합니다.
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  selector:
    matchLabels:
      app: nginx-ingress
  template:
    metadata:
      labels:
        app: nginx-ingress
    spec:
      serviceAccountName: nginx-ingress
      nodeSelector:
        kubernetes.io/hostname: npq3
      hostNetwork: true
      containers:
      - image: nginx/nginx-ingress:edge
        imagePullPolicy: IfNotPresent
        name: nginx-ingress
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        - name: https
          containerPort: 443
          hostPort: 443
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        args:
          - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
          - -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret

7-2. NGINX Ingress Controller Expose을 위한 Kubernetes 서비스 구성

아래 구성은 Kubernetes NGINX Ingress Controller Pod를 정적 포트(80 및 443)의 호스트 IP 주소에 Expose하는 Kubernetes 서비스를 생성합니다. 테스트 환경에서는 externalIPs 필드에 외부 IP 주소(10.10.16.10)를 할당하여 NGINX Ingress Controller Pod를 클라이언트 시스템에 Expose합니다. 주소는 기본 노드의 40GbE 네트워크 인터페이스에 할당된 주소여야 합니다.

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress
  namespace: nginx-ingress
spec:
  externalTrafficPolicy: Local
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  - port: 443
    targetPort: 443
    protocol: TCP
    name: https
  externalIPs:
  - 10.10.16.10
  selector:
    app: nginx-ingress

7-3. Kubernetes NGINX Ingress Controller 용 Kubernetes ConfigMap

ConfigMap을 사용하면 NGINX 구성을 보다 세밀하게 제어할 수 있으므로 고급 NGINX 기능을 사용하고 NGINX 동작을 사용자 지정할 수 있습니다. 데이터 항목 아래에서 사용 가능한 ConfigMap 키 목록에 값을 할당하여 NGINX 지시문을 설정할 수 있습니다.

일부 NGINX 모듈 및 매개변수는 일반 ConfigMap 및 주석을 통해 직접 설정할 수 없습니다. 그러나 기본 템플릿 ConfigMap 키를 사용하면 사용자 지정 NGINX 구성 템플릿을 Load하여 Kubernetes 환경에서 NGINX 구성을 완벽하게 제어할 수 있습니다.

예를 들어 이 구성에서는 기본 nginx 템플릿을 수정하고 다음 지시문을 설정하여 성능을 더욱 향상시킵니다.

그런 다음 아래와 같이 수정된 템플릿을 기본 템플릿 ConfigMap 키 값에 붙여넣습니다. 가장 관련성이 높은 지시문을 강조 표시하기 위해 http{} 컨텍스트(Context)의 구성을 요약했으며 수정된 지시문은 주황색으로 표시됩니다.

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
  namespace: nginx-ingress
data:
  worker-processes: "24"
  worker-connections: "100000"
  worker-rlimit-nofile: "102400"
  worker-cpu-affinity: "auto 111111111111111111111111"
  keepalive: "200"
  main-template: | 
   user nginx;
   worker_processes  {{.WorkerProcesses}};
   {{- if .WorkerRlimitNofile}}
   worker_rlimit_nofile {{.WorkerRlimitNofile}};{{end}}
   {{- if .WorkerCPUAffinity}}
   worker_cpu_affinity {{.WorkerCPUAffinity}};{{end}}
   {{- if .WorkerShutdownTimeout}}
   worker_shutdown_timeout {{.WorkerShutdownTimeout}};{{end}}
   daemon off;

   error_log  /var/log/nginx/error.log {{.ErrorLogLevel}};
   pid        /var/run/nginx.pid;

   {{- if .MainSnippets}}
   {{range $value := .MainSnippets}}
   {{$value}}{{end}}
   {{- end}}

   events {
       worker_connections  {{.WorkerConnections}};
   }

   http {
       include       /etc/nginx/mime.types;
       default_type  application/octet-stream;
       
       ...
      

       sendfile        on;
       access_log  off;
       tcp_nopush  on;
       tcp_nodelay on;

       keepalive_timeout  315;
       keepalive_requests 10000000;

       #gzip  on;   
        ...
   }

Note: 테스트 당시 템플릿을 사용하여 access_log, keepalive_timeout 및 keepalive_requests 지시문을 설정해야 했습니다. NGINX Ingress Controller의 후속 Commit에서 추가 ConfigMap 키가 추가되어 이러한 지시문을 구성하기 위해 템플릿을 사용할 필요가 없어졌습니다. 또한 http-snippets 키를 사용하여 템플릿을 처리하는 대신 다른 지시문(예: tcp_nodelay 및 tcp_nopush)을 구성할 수 있습니다.

7-4. Backend에 대한 Kubernetes DaemonSet

이 섹션에서는 테스트에서 NGINX Ingress Controller와 Upstream Pod 사이의 네트워크 성능 최적화에 대해 설명합니다. 최적화에는 웹 서버 Upstream을 위한 Flannel 네트워킹 스택 및 DaemonSet가 포함됩니다.

7-4-1. 네트워킹 최적화

Flannel은 Kubernetes 환경에서 Layer 3 네트워크 Fabric을 구성하기 위한 도구입니다. 클러스터의 노드가 동일한 서브넷에 있지 않고 Layer 2 연결로 연결할 수 없는 경우 Flannel의 VXLAN Backend 옵션을 사용하는 것이 좋습니다. 호스트 간 컨테이너 통신이 다른 서브넷에서 수행되어야 하는 경우 각 노드의 Flannel 장치는 TCP 패킷을 UDP 패킷으로 캡슐화하여 원격 VXLAN 장치로 보내는 VXLAN 장치입니다. 그러나 VXLAN Backend 옵션은 모든 요청이 올바른 Pod 대상에 도달하기 위해 Flannel 장치를 통과해야 하기 때문에 최적의 성능이 아닙니다.

테스트 환경의 클러스터 노드는 동일한 서브넷에 있었고 Layer 2 연결이 있었습니다. 따라서 호스트 간 컨테이너 통신에 VXLAN 장치가 필요하지 않았습니다. 동일한 LAN 내에서 원격 시스템 IP 주소에 대한 Direct Kernel IP 경로를 만들 수 있었습니다.

따라서 NGINX Ingress Controller가 웹 서버 Pod에 연결을 Proxy할 때마다 UDP 패킷을 원격 호스트로 캡슐화하는 flannel daemon 대신 패킷을 대상 호스트로 전달하고 flannel 장치를 우회했습니다. 이렇게 하면 성능이 향상되고 종속성 수가 줄어듭니다. 이 옵션을 설정하는 가장 쉬운 방법은 Flannel 네트워크를 배포하기 전에 Flannel ConfigMap의 Backend 옵션을 “Type”: “host-gw”로 변경하는 것입니다. 또는 Kernel 경로 테이블을 수동으로 변경할 수 있습니다.

7-4-2. Backend DaemonSet 배포

Backend Pod에 사용되는 NGINX 구성은 app-conf 및 main-conf ConfigMap에 의해 정의됩니다. Binary ConfigMap은 RPS 테스트에서 클라이언트에 반환되는 1KB 파일을 생성합니다.

apiVersion: v1
data:
  app.conf: "server {\n listen 80;\nlocation / {\n root /usr/share/nginx/bin;
    \n  }\n}\n"
kind: ConfigMap
metadata:
  name: app-conf
  namespace: default

---

apiVersion: v1
data:
  nginx.conf: |+
    user  nginx;
    worker_processes  44;
    worker_rlimit_nofile 102400;
    worker_cpu_affinity auto 0000000000000000000000111111111111111111111100000000000000000000001111111111111111111111;

    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;

    events {
        worker_connections  100000;
    }

    http {

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        sendfile        on;
        tcp_nopush     on;
        tcp_nodelay on;

        access_log off;

        include /etc/nginx/conf.d/*.conf;
    }

---

apiVersion: v1
data:
  1kb.bin: "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
kind: ConfigMap
metadata:
  name: binary
  namespace: default

이제 정적 파일을 반환하는 보조 노드(web-server-payload) 전용 NGINX Backend Pod 1개로 구성된 Kubernetes DaemonSet를 생성합니다. ConfigMap(app-conf, main-conf 및 Binary)은 nginx 이미지에 볼륨으로 마운트됩니다. nodeSelector 필드에 보조 노드의 레이블(nbdw34)을 지정하여 Pod를 보조 노드에 할당합니다. 지정한 레이블이 보조 노드에 연결되어 있는지 확인하십시오.

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: web-server-payload
spec:
  selector:
    matchLabels:
      app: web-server-payload
  template:
    metadata:
      labels:
        app: web-server-payload
    spec:
      hostNetwork: true
      containers:
      - name: web-server-payload
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:
        - name: app-config-volume
          mountPath: /etc/nginx/conf.d
        - name: main-config-volume
          mountPath: /etc/nginx
        - name: binary-payload
          mountPath: /usr/share/nginx/bin
      volumes: 
      - name: app-config-volume
        configMap:
          name: app-conf
      - name: main-config-volume
        configMap:
          name: main-conf
      - name: binary-payload
        configMap:
          name: binary 
      nodeSelector: 
        kubernetes.io/hostname: nbdw34

네트워킹 성능을 더욱 극대화하기 위해 hostNetwork 필드를 true로 설정하여 web-server-payload Pod를 호스트 네트워크 Namespace로 설정했습니다. 이는 web-server-payload Pod를 컨테이너 네트워킹 Namespace(cni0)에 Expose하는 대신 포트 80에서 호스트(보조 노드) 네트워크 드라이버에 직접 Expose합니다. 이는 기본 동작입니다. hostNetwork를 true로 설정하면 RPS가 평균 10~15% 증가할 것으로 예상할 수 있습니다.

마지막으로 web-server-svc 서비스를 생성하여 web-server-payload Pod를 Kubernetes NGINX Ingress Controller 에 Expose합니다.

apiVersion: v1
kind: Service
metadata:
  name: web-server-svc
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: web-server-payload

7-4-3. Kubernetes Ingress 리소스

Ingress 리소스를 사용하면 SSL 종료 및 Layer 7 경로 기반 라우팅과 같은 기본 NGINX 기능을 설정할 수 있습니다. SSL Termination를 위해 Kubernetes Secret을 사용하고 host.example.com 호스트 헤더가 있는 모든 요청 URI가 포트 80을 통해 web-server-svc 서비스에 Proxy된다는 규칙을 설정합니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-ingress
spec:
  tls:
  - hosts:
    - host.example.com
    secretName: example-secret
  rules:
  - host: host.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web-server-svc
          servicePort: 80

8. 결론

Kubernetes 환경에서 NGINX Ingress Controller 로 최적의 성능 테스트 결과를 생성하는 데 사용되는 구성 및 배포 세부 정보를 제공했습니다. 16개 CPU를 초과하여 확장한 결과 RPS 결과는 최대 약 340,000개로 수렴되었습니다. 16개의 CPU만 있는 시스템은 24개의 CPU가 있는 시스템과 동일한 RPS를 제공할 수 있습니다. 이 정보를 사용하여 Kubernetes에서 Production Workload를 배포할 때 성능 및 확장 요구 사항을 충족하는 경제적인 솔루션을 프로비저닝하(P)는 방법에 대해 설명합니다.

솔루션 개요를 확인하고 NGINX Plus Ingress Controller 성능을 직접 테스트 및 사용해 보려면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 최신 소식을 빠르게 전달받고 싶으시면 아래 뉴스레터를 구독하세요.