본문으로 건너뛰기
Ingress-NGINX YAML 분석

Ingress-NGINX YAML 분석

Ingress-NGINX 컨트롤러 설치에 사용되는 YAML 파일을 분석합니다.

전체 구성

Ingress-NGINX 구성 리소스:
1. Namespace                 - 전용 네임스페이스
2. ServiceAccount (x2)       - Pod 의 신원
3. Role (x2)                 - 네임스페이스 권한
4. ClusterRole (x2)          - 클러스터 권한
5. RoleBinding (x2)          - 네임스페이스 권한 바인딩
6. ClusterRoleBinding (x2)   - 클러스터 권한 바인딩
7. ConfigMap                 - 컨트롤러 설정
8. Service (x2)              - 네트워크 엔드포인트
9. Deployment                - 컨트롤러 배포
10. Job (x2)                 - Webhook 인증서 생성/패치
11. IngressClass             - Ingress 클래스 정의
12. ValidatingWebhook        - Ingress 검증

1. Namespace

apiVersion: v1
kind: Namespace
metadata:
  labels:
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
  name: ingress-nginx

설명

필드값설명
nameingress-nginxIngress-NGINX 전용 네임스페이스
labelsapp.kubernetes.io/*Kubernetes 권장 라벨 표준

역할

  • Ingress-NGINX 관련 리소스 격리
  • 시스템 네임스페이스와 분리

2. ServiceAccount (x2)

2-1. 컨트롤러용

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/version: 1.11.3
  name: ingress-nginx
  namespace: ingress-nginx
automountServiceAccountToken: true

2-2. Webhook 인증서 생성용

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/component: admission-webhook
    app.kubernetes.io/version: 1.11.3
  name: ingress-nginx-admission
  namespace: ingress-nginx
automountServiceAccountToken: true

automountServiceAccountToken

automountServiceAccountToken: true
  • Pod 에서 ServiceAccount 토큰 자동 마운트
  • Kubernetes API 접근에 필요

3. Role (x2)

3-1. 컨트롤러용 Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
rules:
# 네임스페이스 조회
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get"]

# 기본 리소스 조회
- apiGroups: [""]
  resources: ["configmaps", "pods", "secrets", "endpoints"]
  verbs: ["get", "list", "watch"]

# 서비스 조회
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list", "watch"]

# Ingress 리소스 관리
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get", "list", "watch"]

# Ingress 상태 업데이트
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses/status"]
  verbs: ["update"]

# IngressClass 조회
- apiGroups: ["networking.k8s.io"]
  resources: ["ingressclasses"]
  verbs: ["get", "list", "watch"]

# 리더 선출 (Leader Election)
- apiGroups: ["coordination.k8s.io"]
  resourceNames: ["ingress-nginx-leader"]
  resources: ["leases"]
  verbs: ["get", "update"]
- apiGroups: ["coordination.k8s.io"]
  resources: ["leases"]
  verbs: ["create"]

# 이벤트 생성
- apiGroups: [""]
  resources: ["events"]
  verbs: ["create", "patch"]

# 엔드포인트슬라이스 조회
- apiGroups: ["discovery.k8s.io"]
  resources: ["endpointslices"]
  verbs: ["list", "watch", "get"]

권한 요약

리소스권한용도
namespacesget네임스페이스 정보 조회
configmaps, pods, secrets, endpointsget, list, watch기본 리소스 조회
servicesget, list, watch서비스 조회
ingressesget, list, watchIngress 리소스 모니터링
ingresses/statusupdateIngress 상태 업데이트
ingressclassesget, list, watchIngress 클래스 조회
leasesget, update, create리더 선출 (고가용성)
eventscreate, patch이벤트 기록
endpointsliceslist, watch, get엔드포인트 조회

3-2. Webhook 용 Role

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ingress-nginx-admission
  namespace: ingress-nginx
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "create"]

역할

  • Webhook 인증서 시크릿 생성 및 조회

4. ClusterRole (x2)

4-1. 컨트롤러용 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: ingress-nginx
rules:
# 클러스터 전체 리소스 조회
- apiGroups: [""]
  resources: ["configmaps", "endpoints", "nodes", "pods", "secrets", "namespaces"]
  verbs: ["list", "watch"]

# 노드 조회
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get"]

# 서비스 조회
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list", "watch"]

# Ingress 리소스 관리
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get", "list", "watch"]

# 이벤트 생성
- apiGroups: [""]
  resources: ["events"]
  verbs: ["create", "patch"]

# Ingress 상태 업데이트
- apiGroups: ["networking.k8s.io"]
  resources: ["ingresses/status"]
  verbs: ["update"]

# IngressClass 조회
- apiGroups: ["networking.k8s.io"]
  resources: ["ingressclasses"]
  verbs: ["get", "list", "watch"]

# 엔드포인트슬라이스 조회
- apiGroups: ["discovery.k8s.io"]
  resources: ["endpointslices"]
  verbs: ["list", "watch", "get"]

# 리스 조회
- apiGroups: ["coordination.k8s.io"]
  resources: ["leases"]
  verbs: ["list", "watch"]

ClusterRole vs Role 차이

범위RoleClusterRole
적용 범위네임스페이스 내클러스터 전체
사용 목적네임스페이스 리소스노드, 네임스페이스 등 클러스터 리소스

4-2. Webhook 용 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: ingress-nginx-admission
rules:
- apiGroups: ["admissionregistration.k8s.io"]
  resources: ["validatingwebhookconfigurations"]
  verbs: ["get", "update"]

역할

  • ValidatingWebhookConfiguration 업데이트

5. RoleBinding & ClusterRoleBinding

5-1. RoleBinding (x2)

# 컨트롤러용
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
roleRef:
  kind: Role
  name: ingress-nginx
subjects:
- kind: ServiceAccount
  name: ingress-nginx
  namespace: ingress-nginx

# Webhook 용
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ingress-nginx-admission
  namespace: ingress-nginx
roleRef:
  kind: Role
  name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
  name: ingress-nginx-admission
  namespace: ingress-nginx

5-2. ClusterRoleBinding (x2)

# 컨트롤러용
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ingress-nginx
roleRef:
  kind: ClusterRole
  name: ingress-nginx
subjects:
- kind: ServiceAccount
  name: ingress-nginx
  namespace: ingress-nginx

# Webhook 용
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ingress-nginx-admission
roleRef:
  kind: ClusterRole
  name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
  name: ingress-nginx-admission
  namespace: ingress-nginx

6. ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
data:
  allow-snippet-annotations: "false"

설정 설명

설정값설명
allow-snippet-annotations“false”스니펫 주석 허용 안 함 (보안)

보안 고려사항

# CVE-2021-25742 대응
# allow-snippet-annotations: "true" 일 경우
# 악의적인 nginx 설정 주입 가능

# 예시 (악의적 주석):
# nginx.ingress.kubernetes.io/configuration-snippet: |
#   set $secret $http_authorization;
#   proxy_set_header X-Secret $secret;

기타 주요 설정 옵션

data:
  # SSL/TLS 설정
  ssl-protocols: "TLSv1.2 TLSv1.3"
  ssl-ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:..."
  
  # 타임아웃 설정
  proxy-connect-timeout: "10"
  proxy-read-timeout: "60"
  proxy-send-timeout: "60"
  
  # 리소스 제한
  max-worker-connections: "1024"
  
  # 로깅 설정
  access-log-path: "/var/log/nginx/access.log"
  error-log-path: "/var/log/nginx/error.log"
  
  # 기타
  use-forwarded-headers: "true"
  compute-full-forwarded-for: "true"

7. Service (x2)

7-1. 컨트롤러 Service (LoadBalancer)

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - appProtocol: http
    name: http
    port: 80
    protocol: TCP
    targetPort: http
  - appProtocol: https
    name: https
    port: 443
    protocol: TCP
    targetPort: https
  selector:
    app.kubernetes.io/component: controller
    app.kubernetes.io/name: ingress-nginx

중요 설정 설명

externalTrafficPolicy: Local

externalTrafficPolicy: Local
값설명장단점
Cluster모든 Pod 로 트래픽 분산IP 보존 안됨, 균등 분산
Local로컬 Pod 로만 트래픽IP 보존됨, 불균형 가능
Cluster 모드:
Client → Node1 → Pod(Node3)  # 소스 IP 변경

Local 모드:
Client → Node1 → Pod(Node1)  # 소스 IP 보존

ipFamilyPolicy

ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
정책설명
SingleStack단일 IP 스택 (IPv4 또는 IPv6)
PreferDualStack듀얼스택 선호
RequireDualStack듀얼스택 필수

appProtocol

appProtocol: http   # HTTP 프로토콜
appProtocol: https  # HTTPS 프로토콜
  • Kubernetes 1.20+ 에서 사용
  • 서비스 메쉬 (Istio 등) 와 호환

7-2. Webhook Service (ClusterIP)

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller-admission
  namespace: ingress-nginx
spec:
  type: ClusterIP
  ports:
  - appProtocol: https
    name: https-webhook
    port: 443
    targetPort: webhook
  selector:
    app.kubernetes.io/component: controller

역할

  • Validating Webhook 엔드포인트 제공
  • 내부 클러스터 통신용

8. Deployment - 컨트롤러

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  minReadySeconds: 0
  revisionHistoryLimit: 10
  strategy:
    rollingUpdate:
      maxUnavailable: 1
    type: RollingUpdate
  template:
    spec:
      containers:
      - args:
        - /nginx-ingress-controller
        - --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
        - --election-id=ingress-nginx-leader
        - --controller-class=k8s.io/ingress-nginx
        - --ingress-class=nginx
        - --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
        - --validating-webhook=:8443
        - --validating-webhook-certificate=/usr/local/certificates/cert
        - --validating-webhook-key=/usr/local/certificates/key
        - --enable-metrics=false
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: LD_PRELOAD
          value: /usr/local/lib/libmimalloc.so
        image: registry.k8s.io/ingress-nginx/controller:v1.11.3@sha256:d56f135b6462cfc476447cfe564b83a45e8bb7da2774963b00d12161112270b7
        imagePullPolicy: IfNotPresent
        lifecycle:
          preStop:
            exec:
              command:
              - /wait-shutdown
        livenessProbe:
          failureThreshold: 5
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
            port: 10254
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 10
        name: controller
        ports:
        - containerPort: 80
          name: http
        - containerPort: 443
          name: https
        - containerPort: 8443
          name: webhook
        resources:
          requests:
            cpu: 100m
            memory: 90Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - ALL
          readOnlyRootFilesystem: false
          runAsNonRoot: true
          runAsUser: 101
        volumeMounts:
        - mountPath: /usr/local/certificates/
          name: webhook-cert
          readOnly: true
      serviceAccountName: ingress-nginx
      terminationGracePeriodSeconds: 300
      volumes:
      - name: webhook-cert
        secret:
          secretName: ingress-nginx-admission

컨테이너 인수 (args)

인수설명
/nginx-ingress-controller실행 바이너리
--publish-serviceLoadBalancer Service 참조 (외부 IP 광고)
--election-id리더 선출용 ID
--controller-class컨트롤러 클래스 식별자
--ingress-class=nginx기본 Ingress 클래스
--configmap설정 ConfigMap 참조
--validating-webhook=:8443Webhook 포트
--validating-webhook-certificateWebhook 인증서 경로
--validating-webhook-keyWebhook 키 경로
--enable-metrics=false메트릭스 비활성화

환경 변수

env:
- POD_NAME         # Pod 이름 (필드 참조)
- POD_NAMESPACE    # 네임스페이스 (필드 참조)
- LD_PRELOAD       # 메모리 할당자 (성능 최적화)

Lifecycle Hook

lifecycle:
  preStop:
    exec:
      command:
      - /wait-shutdown
  • Pod 종료 시 연결 드레이닝 대기
  • 우아한 종료 (Graceful Shutdown)

프로브

livenessProbe:
  httpGet:
    path: /healthz      # 생존 체크
    port: 10254
  failureThreshold: 5   # 5 회 실패 시 재시작
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /healthz      # 준비 상태 체크
    port: 10254
  failureThreshold: 3   # 3 회 실패 시 트래픽 제거

보안 컨텍스트

securityContext:
  allowPrivilegeEscalation: false    # 권한 상승 불가
  capabilities:
    add:
    - NET_BIND_SERVICE               # 1024 미만 포트 바인딩 허용
    drop:
    - ALL                            # 기타 모든 capability 제거
  runAsNonRoot: true                 # 루트 사용자 불가
  runAsUser: 101                     # nginx 사용자
  seccompProfile:
    type: RuntimeDefault             # 기본 seccomp 프로파일

리소스 요청

resources:
  requests:
    cpu: 100m      # 0.1 코어 보장
    memory: 90Mi   # 90MB 보장

배포 전략

strategy:
  rollingUpdate:
    maxUnavailable: 1  # 최대 1 개 Pod 만 사용 불가
  type: RollingUpdate

종료 대기 시간

terminationGracePeriodSeconds: 300  # 5 분
  • 긴 대기 시간: 기존 연결 처리 완료

9. Job (x2) - Webhook 인증서 생성

9-1. 인증서 생성 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: ingress-nginx-admission-create
  namespace: ingress-nginx
spec:
  template:
    spec:
      containers:
      - args:
        - create
        - --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
        - --namespace=$(POD_NAMESPACE)
        - --secret-name=ingress-nginx-admission
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.4
        name: create
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 65532
      restartPolicy: OnFailure
      serviceAccountName: ingress-nginx-admission

역할

  • Webhook 인증서 자동 생성
  • Self-signed 인증서 생성

생성되는 시크릿

# ingress-nginx-admission 시크릿
apiVersion: v1
kind: Secret
metadata:
  name: ingress-nginx-admission
data:
  ca.crt: <CA 인증서>
  tls.crt: <서버 인증서>
  tls.key: <서버 키>

9-2. Webhook 패치 Job

apiVersion: batch/v1
kind: Job
metadata:
  name: ingress-nginx-admission-patch
  namespace: ingress-nginx
spec:
  template:
    spec:
      containers:
      - args:
        - patch
        - --webhook-name=ingress-nginx-admission
        - --namespace=$(POD_NAMESPACE)
        - --patch-mutating=false
        - --secret-name=ingress-nginx-admission
        - --patch-failure-policy=Fail
        image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.4.4
        name: patch
      restartPolicy: OnFailure
      serviceAccountName: ingress-nginx-admission

역할

  • ValidatingWebhookConfiguration 업데이트
  • 생성된 인증서로 CA 번들 패치

패치 내용

# WebhookConfiguration 의 CABundle 업데이트
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: ingress-nginx-admission
webhooks:
- clientConfig:
    caBundle: <생성된 CA 인증서>

10. IngressClass

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx

설명

필드값설명
namenginxIngress 클래스 이름
controllerk8s.io/ingress-nginx컨트롤러 식별자

역할

  • Ingress 리소스와 컨트롤러 연결
  • 여러 Ingress 컨트롤러 공존 가능

사용 예시

# Ingress 리소스에서 참조
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
spec:
  ingressClassName: nginx  # ← 이 클래스 사용
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app
            port:
              number: 80

11. ValidatingWebhookConfiguration

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: ingress-nginx-admission
webhooks:
- admissionReviewVersions:
  - v1
  clientConfig:
    service:
      name: ingress-nginx-controller-admission
      namespace: ingress-nginx
      path: /networking/v1/ingresses
      port: 443
  failurePolicy: Fail
  matchPolicy: Equivalent
  name: validate.nginx.ingress.kubernetes.io
  rules:
  - apiGroups: ["networking.k8s.io"]
    apiVersions: ["v1"]
    operations: ["CREATE", "UPDATE"]
    resources: ["ingresses"]
  sideEffects: None

설정 설명

필드값설명
admissionReviewVersionsv1AdmissionReview 버전
failurePolicyFail검증 실패 시 요청 거부
matchPolicyEquivalent동등한 리소스도 매칭
sideEffectsNone사이드 이펙트 없음

검증 항목

  • Ingress 규칙 유효성 검사
  • 주석 (annotation) 검증
  • 경로 충돌 검사
  • TLS 설정 검증

리소스 관계도

Ingress-NGINX를 구성하는 주요 리소스들과 그 관계입니다.

    graph TD
    NS[Namespace: ingress-nginx] --> RBAC[RBAC: SA / Roles / Bindings]
    NS --> IC[IngressClass: nginx]
    
    subgraph Controller_Logic
    RBAC --> DEP[Deployment: ingress-nginx-controller]
    DEP --> SVC_LB[Service: LoadBalancer / Port 80, 443]
    DEP --> CM[ConfigMap: ingress-nginx-controller]
    end
    
    subgraph Admission_Webhook
    J1[Job: admission-create] --> S_ADM[Secret: ingress-nginx-admission]
    J2[Job: admission-patch] --> S_ADM
    S_ADM --> WH[ValidatingWebhookConfiguration]
    DEP --> SVC_ADM[Service: ClusterIP / Port 443]
    SVC_ADM --> WH
    end
  
구성 요소주요 역할
ControllerIngress 리소스를 감시하고 NGINX 설정을 자동으로 생성/갱신
IngressClass클러스터 내 여러 Ingress 컨트롤러 중 nginx를 지정하기 위한 식별자
Admission WebhookIngress 리소스 생성/수정 시 문법적 오류가 없는지 사전 검증
RBAC컨트롤러가 클러스터 내 리소스(Ingress, Secret 등)를 읽을 수 있는 권한 부여

설치 확인

# Ingress-NGINX 설치
kubectl apply -f ingress-nginx.yaml

# Pod 상태 확인
kubectl get pods -n ingress-nginx
# NAME                                        READY   STATUS    RESTARTS   AGE
# ingress-nginx-controller-xxxxxxxxxx-xxxxx   1/1     Running   0          2m
# ingress-nginx-admission-create-xxxxx        0/1     Completed 0          2m
# ingress-nginx-admission-patch-xxxxx         0/1     Completed 0          2m

# Service 확인
kubectl get svc -n ingress-nginx
# NAME                                 TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)
# ingress-nginx-controller             LoadBalancer   10.96.xxx.xxx  192.168.x.x   80:3xxxx/TCP,443:3xxxx/TCP
# ingress-nginx-controller-admission   ClusterIP      10.96.xxx.xxx  <none>        443/TCP

# IngressClass 확인
kubectl get ingressclass
# NAME    CONTROLLER                       AGE
# nginx   k8s.io/ingress-nginx             2m

# 테스트 Ingress 생성
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: test.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: test-service
            port:
              number: 80
EOF

# Ingress 확인
kubectl get ingress
# NAME            CLASS   HOSTS             ADDRESS        PORTS   AGE
# test-ingress    nginx   test.example.com  192.168.x.x    80      1m

요약

카테고리리소스개수
Namespaceingress-nginx1
ServiceAccountcontroller, admission2
Rolecontroller, admission2
ClusterRolecontroller, admission2
RoleBindingcontroller, admission2
ClusterRoleBindingcontroller, admission2
ConfigMapcontroller 설정1
Servicecontroller, admission2
Deploymentcontroller1
Jobcreate, patch2
IngressClassnginx1
ValidatingWebhookadmission1
총계19

Ingress-NGINX 는 Kubernetes Ingress 리소스를 구현하는 가장 널리 사용되는 컨트롤러입니다.