안녕하세요. 오늘은 쿠버네티스 사용시, 클러스터가 외부에 노출이 필요할 경우 고려하게 되는 Ingress 객체 중 Nginx-Ingress Controller의 튜닝에 관해 알아보는 시간을 갖도록 하겠습니다.
들어가며 ..
오늘 포스팅에서는 Nginx-Ingress Controller의 자세한 동작원리는 담고 있지 않습니다.
그리고 Nginx-Ingress 튜닝 방법을 모색하던 중, 신규 프로젝트가 관리형 쿠버네티스 서비스인 EKS에서 실행 될 예정이기에 ,
실제 환경에서는 Nginx Ingress Controller 대신 ALB Ingress Controller를 사용했습니다.
하지만 튜닝 방법을 기록해두고 공유하는 것이 좋을 것 같아 글로 작성하게 되었습니다.
왜 튜닝이 필요한가?
우선, Helm 으로 쿠버네티스 클러스터 내에 Ingress-nginx Chart를 쉽게 설치함으로써, 구성에 용이함은 있었습니다.
그러나, 해당 차트로 설치된 Nginx의 기본 설정으로는 메신저 서비스의 특성상 응답 지연이 쉽게 발생하곤 했습니다.
응답 지연이 발생한 원인은 다음과 같습니다.
- 서비스 요청시, HTTP 클라이언트가 대상 서버에 새로운 TCP 연결을 생성하고 요청을 작성후 응답을 받습니다.
- 그런 다음 서버는 해당 리소스를 해제하기 위해 TCP 연결을 닫게됩니다.

- 이러한 과정은 메시지마다 하나씩 TCP 연결을 만들고 닫는 작업을 반복하게 됩니다.
- 쉽게 예로 들면, 전화 통화에서 상대방이 말을 끝낸 후 전화를 끊고 다시 걸기를 반복하는것과 비슷하죠.
이에 따라, Keep Alive 설정으로 업스트림 서버로의 Keep Alive연결을 활성화하여, Nginx 각 워커 프로세스의 캐시에 유지되는 최대 유휴 Keep Alive 연결 수를 정의 했습니다.
실제로 Keep Alive가 없으면 CPU 오버헤드가 더 많이 발생하며 서버의 리소스가 효율적으로 사용되지 않습니다.
- Nginx는 워커 노드의 스레드 풀로 관리 되기에 CPU 오버헤드는 심각할 정도로 발생하진 않긴 합니다 ..
간단한 예시를 들긴 했지만,이 외에도 nginx 성능 튜닝이 필요한 여러가지 이유가 있었습니다.
본론으로 들어가서,
실제 Ingress-nginx의 Helm 차트 구조는 간단하게 다음과 같습니다.
└── ingress-nginx
├── changelog
├── ci
├── templates
│ └── admission-webhooks
│ └── job-patch
└── tests
실제로 templates 디렉토리엔 Ingress-Nginx Controller를 정의하기 위한 yaml파일이 수십개가 있습니다.

이 중 , controller-configmapd의 구성을 간단하게 살펴보도록 하겠습니다.
apiVersion: v1
kind: ConfigMap
metadata:
labels:
{{- include "ingress-nginx.labels" . | nindent 4 }}
app.kubernetes.io/component: controller
{{- with .Values.controller.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if .Values.controller.configAnnotations }}
annotations: {{ toYaml .Values.controller.configAnnotations | nindent 4 }}
{{- end }}
name: {{ include "ingress-nginx.controller.fullname" . }}
namespace: {{ include "ingress-nginx.namespace" . }}
data:
allow-snippet-annotations: "{{ .Values.controller.allowSnippetAnnotations }}"
{{- if .Values.controller.addHeaders }}
add-headers: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.fullname" . }}-custom-add-headers
{{- end }}
{{- if .Values.controller.proxySetHeaders }}
proxy-set-headers: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.fullname" . }}-custom-proxy-headers
{{- end }}
{{- if .Values.dhParam }}
ssl-dh-param: {{ include "ingress-nginx.namespace" . }}/{{ include "ingress-nginx.controller.fullname" . }}
{{- end }}
{{- range $key, $value := .Values.controller.config }}
{{- $key | nindent 2 }}: {{ $value | quote }}
{{- end }}
- 해당 내용을 잘 살펴보면 data 블록에 nginx config 옵션들이 지정되어 있는 것을 볼 수 있습니다.
- 해당 옵션들의 상세 값은 상위 경로의 values.yaml로 관리되고 있습니다.
- 또한, 위에서 보이는 바와 같이 templates 디렉토리 내의 모든 yaml 객체들의 설정 값들은 하드코딩 되어있지 않습니다.
- 한 가지 더 특이한 점은, 상단의 templates 디렉토리 사진에서 확인할 수 있듯이, Nginx의 옵션 별로 별도의 ConfigMap이 관리되고 있음을 알 수 있습니다.
- 만약 , 제가 적용하려는 Keep Alive 옵션 같은 경우에도 별도의 ConfigMap을 사용할 수도 있겠죠.
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
namespace: nginx-ingress
data:
proxy-connect-timeout: "10s"
proxy-read-timeout: "10s"
keepalive: "10s"
이런식으로 여러 개의 ConfigMap 객체를 용도별로 관리한다면, 관리적인 측면과 조금씩 설정을 다르게 해야하는 경우에도 유용하게 사용할 수 있을 것으로 생각이 됩니다.
그렇다면, templates/controller-deployment.yaml 파일에서 실제로 ConfigMap이 어떻게 사용되고 있는지 확인해볼까요 ?
~~~
# controller-deployment.yaml 일부분
spec:
template:
spec:
volumes:
{{- if .Values.controller.customTemplate.configMapName }}
- name: nginx-template-volume
configMap:
name: {{ .Values.controller.customTemplate.configMapName }}
items:
- key: {{ .Values.controller.customTemplate.configMapKey }}
path: nginx.tmpl
- 보시는 바와 같이 위에서 생성했던 ConfigMap을 볼륨 형태로 사용중이며, 해당 ConfigMap의 이름또한 상위경로의 values.yaml에서 관리됩니다.
- 해당 deployment를 apply 하게 된다면 의존성 순서는 다음과 같습니다.
- values.yaml -> *-.configmap.yaml -> *-.deployment.yaml
- 각 yaml에서 특정 ConfigMap을 지정할 수도 있겠죠.
끝으로
Nginx-Ingress Controller를 도입하려 알아보던 와중, 비록 EKS 내에서는 ALB Ingress Controller가 더 적합하다는 판단을 내렸지만, 여러 설정을 커스텀하게 조작할 필요가 있다면 Nginx-Ingress Controller의 도입 또한 좋은 선택지가 될 것 같습니다.
참고
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
ConfigMap - Ingress-Nginx Controller
ConfigMaps ConfigMaps allow you to decouple configuration artifacts from image content to keep containerized applications portable. The ConfigMap API resource stores configuration data as key-value pairs. The data provides the configurations for system com
kubernetes.github.io
https://helm.sh/ko/docs/topics/charts/
차트
차트 형식을 설명하고, 헬름으로 차트를 빌드하기 위한 기본지침을 제공한다.
helm.sh
https://github.com/kubernetes/ingress-nginx/blob/main/charts/ingress-nginx/values.yaml
ingress-nginx/charts/ingress-nginx/values.yaml at main · kubernetes/ingress-nginx
Ingress-NGINX Controller for Kubernetes. Contribute to kubernetes/ingress-nginx development by creating an account on GitHub.
github.com