NGINX Ingress 설치 가이드
1. 개요
본 문서는 gitops 저장소의 /ingress-nginx 디렉터리 구조를 기반으로 NGINX Ingress Controller를 Kubernetes에 설치하는 전체 과정을 안내합니다. NGINX Ingress Controller는 Kubernetes 클러스터의 Ingress 리소스를 처리하여 외부 트래픽을 내부 서비스로 라우팅합니다. Kustomize, Helm, Makefile을 활용한 배포 자동화, 환경별 설정, 주요 커스텀 옵션, 운영 팁을 포함합니다.
2. 사전 요구사항
- Kubernetes 클러스터: v1.19 이상
- 로컬 도구
kubectl: Kubernetes 클러스터 제어kustomize: v4.x 이상helm: v3.x 이상
- 인증서:
cert-manager를 통한 TLS 인증서 발급 준비 (선택) - DNS 등록: 필요 시 Ingress 호스트 설정
3. 디렉터리 구조 및 역할
ingress-nginx/
├── Makefile # 배포 자동화 스크립트
├── kustomize/
│ ├── base/ # 공통 리소스(Helm 차트, CRD 등)
│ └── overlays/
│ ├── dev-public/ # Public IngressController 환경 설정
│ | ├── kustomization.yaml # Kustomize 구성
│ | └── helm/
│ | ├── values.yaml # NGINX Ingress 설정
│ | └── helm-chart.yaml # HelmChartInflationGenerator
│ └── dev-internal/ # Internal IngressController 환경 설정
│ ├── kustomization.yaml # Kustomize 구성
│ └── helm/
│ ├── values.yaml # NGINX Ingress 설정
│ └── helm-chart.yaml # HelmChartInflationGenerator
- Makefile:
apply,delete,preview등 배포 자동화 명령어 - kustomize/base/: 모든 환경에 공통 적용될 리소스(Helm 차트, CRD 등)
- kustomize/overlays/dev-public/: dev-public 환경 특화 설정
- kustomize/overlays/dev-internal/: dev-internal 환경 특화 설정
- helm/values.yaml: NGINX Ingress Helm Chart 커스터마이징 설정
4. 설치 단계
4.1. values.yaml 커스터마이징
Public Ingress Controller 설정을 먼저 진행하고, Internal 환경의 설정은 이후 섹션(4.1.6)에서 다룹니다.
kustomize/overlays/dev-public/helm/values.yaml 파일을 열어 주요 설정을 수정합니다.
4.1.1. 기본 컨트롤러 설정
controller:
replicaCount: 1
config:
allow-snippet-annotations: "true"
metrics:
enabled: true
serviceMonitor:
enabled: true
additionalLabels:
prometheus: main
resources:
requests:
cpu: 100m
memory: 90Mi
4.1.2. Ingress Class 설정
controller:
ingressClass: nginx
ingressClassResource:
name: nginx
enabled: true
default: true
4.1.3. 배포 노드 선정
특정 노드에 배포해야 하는 경우, 다음과 같이 hostPort, nodeSelector, tolerations 등을 설정합니다.
다음은 Kind ControlPlane에 Ingress Controller를 배포하기 위한 설정입니다.
controller:
hostPort:
enabled: true
nodeSelector:
ingress-ready: "true"
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
4.1.4. 서비스 설정
이 설정은 AWS LoadBalancer를 internet-facing으로 설정하고, target-type을 ip로 하여 pod IP를 직접 라우팅합니다.
controller:
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-target-type: ip
4.1.5. Admission Webhooks
controller:
admissionWebhooks:
enabled: true
certManager:
enabled: true
clusterIssuer: "selfsigned-cluster-issuer"
Admission Webhooks을 위한 인증서를 cert-manager의 selfsigned-cluster-issuer를 사용하여 생성합니다. 이 인증서의 유효 기간은 1년이며, 만기 전에 자동 갱신됩니다. prometheusrules.yaml에 인증서 만료 전 alert(CertExpiry)를 구성하여 만기 시 자동 갱신 실패를 방지합니다. 기존 patch 방식을 사용하는 경우 1년마다 수동 업데이트가 필요합니다.
4.1.6 Internal Ingress Controller 설정
kustomize/overlays/dev-internal/helm/values.yaml 파일을 열어 주요 설정을 수정합니다.
Internal 환경은 public과 다르게 설정해야 합니다. admissionWebhooks를 비활성화하여 webhook 충돌을 방지하고, IngressClass를 ’nginx-internal’로 지정하여 별도의 Ingress Controller로 운영합니다. 이렇게 하면 같은 클러스터에서 Public과 Internal Ingress를 분리하여 관리할 수 있습니다.
controller:
admissionWebhooks:
enabled: false
ingressClass: nginx-internal
ingressClassResource:
name: nginx-internal
enabled: true
default: false
controllerValue: k8s.io/ingress-nginx-internal
4.2. Kustomize 구성
4.2.1. kustomization.yaml 구성
kustomize/overlays/dev-public/kustomization.yaml에서 namespace, generators 지정
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: ingress-nginx
generators:
- ./helm/helm-chart.yaml
4.2.2. HelmChartInflationGenerator 설정
helm/helm-chart.yaml에서 Helm 차트 경로와 values 파일 지정
apiVersion: builtin
kind: HelmChartInflationGenerator
metadata:
name: nginx-ingress
name: ingress-nginx
chartHome: ../../base/helm
chart: ingress-nginx
releaseName: nginx-ingress
valuesFile: ./helm/values.yaml
includeCRDs: true
namespace: ingress-nginx
4.3. 배포 프로세스 (Makefile 활용)
이 가이드는 dev-public 환경을 기준으로 작성되었습니다.
dev-internal 환경의 경우, DEPLOY_ENV=dev-internal로 변경하세요.
Step 1: Namespace 생성
make namespace DEPLOY_ENV=dev-public
Step 2: 배포 미리보기
make preview DEPLOY_ENV=dev-public
Step 3: 배포 실행
make apply DEPLOY_ENV=dev-public
Step 4: 배포 상태 확인
kubectl get pods -n ingress-nginx -w
5. 설치 후 검증
5.1. 리소스 상태 확인
kubectl get pods,svc,ingress -n ingress-nginx
확인 사항:
- Controller Pod이
Running상태 - Service 생성 확인 (LoadBalancer 타입 시 External IP 확인)
5.2. Ingress 기능 테스트
샘플 Ingress 리소스를 생성하여 기능 검증
kubectl create deploy nginx --image nginx
kubectl expose deploy nginx --port 80
kubectl apply -f -<<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
namespace: default
spec:
ingressClassName: nginx
rules:
- host: nginx.cnapcloud.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
EOF
새로 배포된 ingress 정보를 확인하고 curl을 사용하여 접속하여 정상적으로 응답이 오는지 확인합니다.
# dev-internal의 ingress-nginx-internal-controller 서비스 cluster-ip를 확인
kubectl get svc -n ingress-nginx
# 예시: cluster-ip가 10.96.82.209인 경우
kubectl exec -it curl-pod -- sh
curl -v --resolve nginx.cnapcloud.com:80:10.96.82.209 http://nginx.cnapcloud.com
Internal 환경에서는 ingressClassName: nginx-internal로 변경하세요.
6. Admission Webhooks 설정 가이드
6.1. Public/Internal 환경에서 Webhook 충돌 방지
같은 클러스터에 public과 internal ingress-nginx를 설치할 경우, ValidatingWebhook이 모든 ingress 리소스를 검사하여 충돌이 발생할 수 있습니다. 특히, ingressClassName: nginx (public)인 ingress를 생성할 때 internal ingress-nginx의 webhook이 활성화되어 있으면 다음과 같은 TLS certificate 오류가 발생합니다:
Error from server (InternalError): error when creating "STDIN": Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://ingress-nginx-internal-controller-admission.ingress-nginx-internal.svc:443/networking/v1/ingresses?timeout=10s": tls: failed to verify certificate: x509: certificate is valid for ingress-nginx-internal-controller-admission, ingress-nginx-internal-controller-admission.ingress-nginx, ingress-nginx-internal-controller-admission.ingress-nginx.svc, not ingress-nginx-internal-controller-admission.ingress-nginx-internal.svc
이 오류는 certificate의 SAN(Subject Alternative Name)이 webhook 서비스 주소와 일치하지 않아 발생합니다.
문제점
- NGINX Ingress의 ValidatingWebhook은 기본적으로
resources: ["ingresses"],scope: "*"로 모든 ingress를 검증합니다. - IngressClass는 controller 처리 시에만 구분되며, webhook 검증 단계에서는 무시됩니다.
해결 방법
한쪽 Webhook 비활성화 (권장):
- Public ingress-nginx:
admissionWebhooks.enabled: false(외부 접근용, 검증 생략). - Internal ingress-nginx:
admissionWebhooks.enabled: true(내부 검증 필요).
- Public ingress-nginx:
Namespace/Label 기반 필터링 (고급):
- Webhook에
namespaceSelector또는objectSelector를 추가하여 특정 ingress만 검증. - Ingress 리소스에 대응 label을 부여.
- Webhook에
운영 권장 패턴
- Internal: Webhook 비활성화
- Public: Webhook 활성화(보안 검증)
7. 운영 및 Troubleshooting
7.1. Pod가 Running 상태가 아닌 경우
kubectl get pods -n ingress-nginx
kubectl describe pod <pod명> -n ingress-nginx
kubectl logs <pod명> -n ingress-nginx
7.2. Service External IP 미할당
LoadBalancer 타입 시 클라우드 프로바이더 확인
7.3. 설정 변경 후 Ingress 재배포
NGINX Ingress Controller 신규 배포 또는 설정 변경(예: annotation 허용, 리소스 제한 등) 후 기존 Ingress 리소스가 정상적으로 작동하지 않을 수 있습니다. 이 경우, 관련 Ingress에 IngressClassName이 설정하거나 재배포하세요.
kubectl rollout restart deployment <ingress-controller-deployment> -n ingress-nginx # Controller 재시작 (선택)
kubectl delete ingress <ingress-name> -n <namespace> # 기존 Ingress 삭제
kubectl apply -f <ingress-yaml> # 재배포
8. 배포 제거
8.1. NGINX Ingress 삭제
make delete DEPLOY_ENV=dev-public
8.2. Namespace 삭제 (선택사항)
kubectl delete namespace ingress-nginx
9. 부록: 최종 체크리스트
설치 전:
- Kubernetes 클러스터 준비 (v1.19+)
- kubectl, kustomize, helm 설치
- 네임스페이스 생성
설치:
- values.yaml 커스터마이징 완료
- kustomization.yaml 구성 완료
- make namespace 실행
- make preview 실행 및 확인
- make apply 실행
검증:
- Controller Pod이 Running 상태
- Service 생성 확인
- 샘플 Ingress로 라우팅 테스트
운영:
- 모니터링 설정
/home/ubuntu/devel/github/gitops/nginx/install_guide.md