Kubernetes 클러스터에 Ingress Nginx Controller를 설치하고 설정하는 방법을 설명합니다.
Ingress Controller는 클러스터 외부에서 내부 서비스로의 HTTP/HTTPS 라우팅을 제공합니다.
Ingress 리소스: Kubernetes 리소스로, 라우팅 규칙을 정의합니다. Ingress Controller: 실제로 Ingress 규칙을 구현하는 컨트롤러 (nginx, traefik, haproxy 등)
[!WARNING] Kubernetes Ingress Nginx는 2026년 3월에 공식 유지보수가 종료됩니다. 이후에는 보안 패치가 제공되지 않으므로, 프로덕션 환경에서는 대안 중 하나를 고려해야 합니다:
- Gateway API (Kubernetes 공식 차세대 라우팅 API)
- Traefik
- Contour
- Istio Ingress Gateway
curl -fLO https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
다운로드한 deploy.yaml 파일을 편집하여 다음 설정을 추가합니다.
Control Plane 노드에 Ingress Controller를 배포하도록 설정:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
# 이 부분 추가
nodeSelector:
app: ingress-controller
containers:
- name: controller
# ... 기존 설정
HTTPS 트래픽을 백엔드로 직접 전달하려면:
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
template:
spec:
containers:
- name: controller
args:
- /nginx-ingress-controller
# 이 라인 추가
- --enable-ssl-passthrough
kubectl apply -f deploy.yaml
# Pod 상태 확인
kubectl get pods -n ingress-nginx
# 출력 예시:
# NAME READY STATUS RESTARTS AGE
# ingress-nginx-admission-create-xxxxx 0/1 Completed 0 2m
# ingress-nginx-admission-patch-xxxxx 0/1 Completed 0 2m
# ingress-nginx-controller-5c9b7d6f7b-xxxxx 1/1 Running 0 2m34s
# 배포 완료 대기
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=90s
Kind 환경에서 Ingress Nginx Service는 NodePort 타입으로 동작합니다:
kubectl get svc -n ingress-nginx
예상 출력:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.96.xxx.xxx <none> 80:xxxxx/TCP,443:xxxxx/TCP 2m
ingress-nginx-controller-admission ClusterIP 10.96.xxx.xxx <none> 443/TCP 2m
간단한 테스트 Deployment를 생성하여 Ingress가 작동하는지 확인:
# 테스트 Deployment 생성
kubectl create deployment hello-world --image=gcr.io/google-samples/hello-app:1.0
kubectl expose deployment hello-world --port=8080
# 테스트 Ingress 생성
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-world-ingress
spec:
ingressClassName: nginx
rules:
- host: hello.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: hello-world
port:
number: 8080
EOF
# /etc/hosts 에 추가
sudo sh -c 'echo "127.0.0.1 hello.local" >> /etc/hosts'
# 테스트
curl http://hello.local
# 정리
kubectl delete ingress hello-world-ingress
kubectl delete svc hello-world
kubectl delete deployment hello-world
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
kubernetes.io/ingress.class: nginx
spec:
ingressClassName: nginx
rules:
- host: myapp.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-ingress
namespace: argocd
annotations:
kubernetes.io/ingress.class: nginx
spec:
ingressClassName: nginx
tls:
- hosts:
- argocd.cicd.com
secretName: argocd-tls # TLS Secret 이름
rules:
- host: argocd.cicd.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 80
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: cicd-jenkins
annotations:
kubernetes.io/ingress.class: nginx
# Jenkins는 세션 유지를 위해 session affinity 필요
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "jenkins-route"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
spec:
ingressClassName: nginx
tls:
- hosts:
- jenkins.cicd.com
secretName: jenkins-tls
rules:
- host: jenkins.cicd.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: jenkins
port:
number: 8080
Ingress Nginx는 다양한 annotations를 통해 동작을 커스터마이징할 수 있습니다:
annotations:
# IngressClass 지정 (레거시 방식)
kubernetes.io/ingress.class: nginx
# 리다이렉트 (HTTP → HTTPS)
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# 리라이트 제한
nginx.ingress.kubernetes.io/limit-rps: "10"
# 업로드 크기 제한
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
# 타임아웃 설정
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization"
# htpasswd 파일 생성
htpasswd -c auth myuser
# Secret 생성
kubectl create secret generic basic-auth --from-file=auth -n default
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
annotations:
# URL 재작성
nginx.ingress.kubernetes.io/rewrite-target: /$2
# 예: /api/v1/users -> /users
사용 예:
spec:
rules:
- host: api.example.com
http:
paths:
- path: /api/v1(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 8080
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/8,172.16.0.0/12"
Ingress에서 HTTPS를 사용하려면 TLS Secret이 필요합니다.
자세한 내용은 TLS 인증서 관리 문서를 참조하세요.
간단한 예시:
# Self-signed 인증서 생성 (테스트용)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=myapp.local/O=myapp"
# Secret 생성
kubectl create secret tls myapp-tls \
--cert=tls.crt \
--key=tls.key \
-n default
/etc/hosts 파일에 도메인 추가:
sudo vi /etc/hosts
다음 라인 추가:
127.0.0.1 argocd.cicd.com
127.0.0.1 jenkins.cicd.com
127.0.0.1 myapp.local
# HTTP 테스트
curl http://myapp.local
# HTTPS 테스트 (self-signed 인증서)
curl -k https://argocd.cicd.com
# 헤더 확인
curl -I http://myapp.local
https://argocd.cicd.comhttps://jenkins.cicd.com[!NOTE] Self-signed 인증서를 사용하는 경우, 브라우저에서 보안 경고가 표시됩니다. “고급” → “계속 진행”을 클릭하여 접속하세요.
kubectl get ingress --all-namespaces
kubectl describe ingress <ingress-name> -n <namespace>
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller
kubectl get configmap -n ingress-nginx
kubectl describe configmap ingress-nginx-controller -n ingress-nginx
## ⚙️ ConfigMap 커스터마이징
Ingress Nginx의 전역 설정은 `ingress-nginx-controller` ConfigMap을 통해 변경할 수 있습니다:
```bash
# ConfigMap 편집
kubectl edit configmap ingress-nginx-controller -n ingress-nginx
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
data:
# 로그 레벨 설정
error-log-level: "info" # debug, info, notice, warn, error
# 클라이언트 body 크기 제한
proxy-body-size: "100m"
# 버퍼 크기
proxy-buffer-size: "16k"
# Keep-alive 타임아웃
keep-alive: "75"
# Upstream keep-alive 연결 수
upstream-keepalive-connections: "100"
# SSL 프로토콜
ssl-protocols: "TLSv1.2 TLSv1.3"
# SSL Ciphers
ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"
# HSTS 활성화
hsts: "true"
hsts-max-age: "31536000"
hsts-include-subdomains: "true"
# 사용자 정의 헤더
add-headers: "ingress-nginx/custom-headers"
# Rate limiting
limit-req-status-code: "429"
# 로그 포맷
log-format-upstream: '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"'
# Custom headers ConfigMap 생성
kubectl create configmap custom-headers -n ingress-nginx \
--from-literal=X-Frame-Options=DENY \
--from-literal=X-Content-Type-Options=nosniff \
--from-literal=X-XSS-Protection="1; mode=block"
# Ingress Controller Pod 재시작 (설정 적용)
kubectl rollout restart deployment ingress-nginx-controller -n ingress-nginx
# 상태 확인
kubectl rollout status deployment ingress-nginx-controller -n ingress-nginx
# 로그 확인
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
kubectl get svc <service-name> -n <namespace>
kubectl get pods -n <namespace> --show-labels
/etc/hosts에 도메인이 등록되어 있는지 확인kubectl describe ingress <ingress-name> -n <namespace>
Ingress Nginx 설치 후: