본문 바로가기
Cloud Native/Kubernetes

4. Ingress - Nginx

by jys275 2026. 1. 29.

이전까지 서비스(Service)를 통해 클러스터 내부 통신을 정복했다면, 이번엔 클러스터의 '정문'을 만드는 인그레스(Ingress)를 파헤쳐 볼 시간이다.

 

인그레스는 단순히 외부 노출을 넘어 L7 스위치처럼 경로를 제어하고 보안을 책임지는 아주 똑똑한 녀석이다.


 

 

1. 인그레스의 필요성과 사용 목적

기존에는 외부 접근을 위해 각 서비스마다 IP나 포트를 할당해야 했지만, 인그레스는 하나의 진입점(도메인)에서 여러 서비스를 관리하게 해준다.

  • 서비스 로드 밸런싱: 쇼핑몰처럼 쇼핑(/), 고객센터(/customer), 주문(/order) 등 경로(Path)별로 서로 다른 파드(+서비스)에 연결준다. 이는 고가의 L4/L7 하드웨어 스위치 역할을 소프트웨어로 대체하는 것과 같다.
  • 카나리 업그레이드 (Canary Upgrade): 새 버전(v2)을 배포할 때, 전체 트래픽 중 일부(예: 10%)만 v2로 보내어 안정성을 테스트할 수 있다.

 

2. 인그레스 컨트롤러 (구현체)

인그레스 오브젝트만 만든다고 트래픽이 흐르지는 않는다. 인그레스는 '규칙(Rule)'일 뿐이고, 이를 실행할 '구현체'가 필요한데 이를 인그레스 컨트롤러라고 한다.

  • 종류: 대표적으로 Nginx, Kong 등이 있다.
  • 작동 원리: Nginx 컨트롤러를 설치하면 전용 네임스페이스와 함께 엔진엑스 파드가 생성된다. 이 파드가 인그레스 규칙을 실시간으로 읽어 인식이 되서 트래픽을 배달한다.
  • 외부 연결: 사용자 트래픽이 엔진엑스 파드를 거쳐야 하므로, 이 파드에 NodePortLoadBalancer 서비스를 연결해 외부 통로를 열어줘야 한다.

이제 인그레스의 핵심 기능을 알아보자


 

 

 

1. 상세 서비스 로드 밸런싱 (Path-based Routing)

하나의 호스트 IP와 포트로 들어온 요청을 경로에 따라 분기한다.

  • 설정 예시: 사용자가 192.168.0.30:30431로 접속 시 (사전에 Nginx Controller = Ingress Controller가 설치되어 있는 것)
    • / 접속 → 쇼핑 서비스 파드 연결
    • /order 접속 → 주문 관리 서비스 파드 연결
  • 도메인 기반: 서로 다른 도메인 이름(Host)을 각각 다른 서비스에 연결하는 것도 가능하다.

 

 

2. 카나리 업그레이드 및 트래픽 조정

  • 어노테이션(Annotation)을 활용해 트래픽의 흐름을 정교하게 제어한다.
  • 무게 중심(Weight): 특정 인그레스에 weight: 10% 어노테이션을 주면 해당 도메인 트래픽의 10%만 신규 버전 파드로 보낼 수 있다.
  • 헤더 기반(Header): 접속자의 언어 설정이 KR일 때만 신규 버전으로 연결하는 등 특정 조건부 트래픽 제어가 가능하다.

 

 

3. HTTPS 인증서 관리 (SSL/TLS Termination)

파드마다 인증서를 심기 번거로울 때, 인그레스가 인증서 관리를 대행한다.

  • Nginx 파드로 HTTPS를 사용하려면 443 포트로 연결해야한다.
  • 준비물: 인증서(ca.crt)와 키(ca.key)를 담은 시크릿(Secret) 오브젝트.
  • 설정: 인그레스 정의서의 tls 옵션에 해당 시크릿 이름을 연결한다.
  • 결과: 사용자가 https://로만 접속 가능하도록 강제하며, 복잡한 암호화 통신 처리는 인그레스가 도맡아 파드의 부담을 줄여준다.

 

 

 

💡 꼬리 질문

Q: 만약 인그레스 컨트롤러(Nginx Pod)가 죽어버린다면, 인그레스 룰이 설정된 서비스들은 외부에서 접근이 가능할까? 이를 방지하기 위해 실무에서는 어떤 조치를 취할까?

 

 

결론: 인그레스 컨트롤러가 죽으면 모든 외부 통로가 차단된다. 따라서 고가용성(HA) 확보가 필수적이다.

  1. 위험성: 인그레스는 클러스터의 단일 진입점이므로, 구현체인 파드에 장애가 생기면 모든 서비스가 먹통이 된다.
  2. 대응 방법
    • Replicas 확장: 인그레스 컨트롤러의 파드 개수를 2개 이상으로 늘려 하나가 죽어도 서비스가 유지되게 한다.
    • 안티 어피니티(Anti-Affinity): 컨트롤러 파드들이 서로 다른 물리 노드에 배치되도록 설정하여 노드 장애 시에도 살아남도록 설계한다.

 

 


 

 

 

 

0. Nginx 인그레스 컨트롤러 설치

쿠버네티스에서 인그레스 규칙은 단순한 명세일 뿐, 이를 실제로 수행할 구현체(인그레스 컨트롤러)가 없으면 아무 일도 일어나지 않는다.

kubectl apply -f https://raw.githubusercontent.com/k8s-1pro/install/refs/heads/main/ground/k8s-1.27/nginx-1.8.2/nginx-controller.yaml
  • 설정 방식: 제공된 배포 파일을 통해 Deployment, ReplicaSet, 그리고 실제 엔진엑스 파드를 생성한다.
  • 서비스 연결: 엔진엑스 파드로 트래픽을 보내기 위해 NodePort 서비스를 연결한다. 본 실습 예제에서는 포트 번호를 3043130798로 미리 설정해 두었다.
    • * Service(NodePort) 와 Port(30431, 30798) 설정은 위 배포 파일에 포함되어 있다.
  • 핵심 역할: 엔진엑스는 쿠버네티스 내부에 새로운 인그레스 규칙이 생성되면 이를 실시간으로 읽어 트래픽 분배 로직에 반영한다.

 

 

 

1. 서비스 로드 밸런싱 (Path-based Routing)

인프런_대세는 쿠버네티스

하나의 진입점에서 URL 경로에 따라 서로 다른 업무 파드로 트래픽을 보낸다.

apiVersion: v1
kind: Pod                 # 로드 밸런싱 대상 서비스 -> 파드
metadata:
  name: pod-shopping
  labels:
    category: shopping
spec:
  containers:
  - name: container
    image: kubetm/shopping
---
apiVersion: v1
kind: Service          # 로드 밸런싱 대상 서비스
metadata:
  name: svc-shopping
spec:
  selector:
    category: shopping
  ports:
  - port: 8080        # 로드 밸런싱 대상 서비스의 port 번호: 8080
  • 리소스 구성: 쇼핑(svc-shopping), 고객센터(svc-customer), 주문(svc-order) 세 종류의 파드와 서비스를 각각 생성한다.

 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: service-loadbalancing
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-shopping
            port:
              number: 8080       # 이전에 생성해놓은 로드 밸런싱 대상 서비스의 포트
      - path: /customer
        pathType: Prefix
        backend:
          service:
            name: svc-customer
            port:
              number: 8080       # 이전에 생성해놓은 로드 밸런싱 대상 서비스의 포트
      - path: /order
        pathType: Prefix
        backend:
          service:
            name: svc-order
            port:
              number: 8080       # 이전에 생성해놓은 로드 밸런싱 대상 서비스의 포트
  • 인그레스 규칙 설정
    • / (루트 패스) → svc-shopping 서비스 연결
    • /customer → svc-customer 서비스 연결
    • /order → svc-order 서비스 연결
  • 검증: curl 192.168.56.30:30431/order와 같이 경로를 붙여 호출하면, 별도의 장비 없이도 인그레스가 정확한 파드로 트래픽을 전달하는 것을 확인할 수 있다.

 

 

 

2. 카나리 업그레이드 (Canary Upgrade)

인프런_대세는 쿠버네티스

기존 버전(v1)을 운영하면서 신규 버전(v2)에 트래픽의 일부만 흘려보내 테스트하는 기법이다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-v1
  labels:
    app: v1
spec:
  containers:
  - name: container
    image: kubetm/app:v1
---
apiVersion: v1
kind: Service
metadata:
  name: svc-v1
spec:
  selector:
    app: v1
  ports:
  - port: 8080
apiVersion: v1
kind: Pod
metadata:
  name: pod-v2
  labels:
    app: v2
spec:
  containers:
  - name: container
    image: kubetm/app:v2
---
apiVersion: v1
kind: Service
metadata:
  name: svc-v2
spec:
  selector:
    app: v2
  ports:
  - port: 8080

ㅡㅡㅡㅡ

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app
spec:
  ingressClassName: nginx
  rules:
  - host: 
http://www.app.com
    http:
      paths:
      - path: /               # 실습 목적에 맞게 path가 한개이다.
        pathType: Prefix
        backend:
          service:
            name: svc-v1
            port:
              number: 8080
  • 도메인 기반 접근: www.app.com이라는 호스트 이름을 사용하여 접근하도록 설정한다.

 

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-v2
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  rules:
  - host: 
http://www.app.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-v2
            port:
              number: 8080
  • 가중치(Weight) 제어: nginx.ingress.kubernetes.io/canary-weight: "10" 어노테이션을 통해 트래픽의 10%만 v2 파드로 가도록 설정한다.

 

# 위(이전) Ingress 삭제 후 아래 Ingress 생성해서 실습 바꿔보자.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-kr
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Accept-Language"
    nginx.ingress.kubernetes.io/canary-by-header-value: "kr"
spec:
  ingressClassName: nginx
  rules:
  - host: 
http://www.app.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-v2
            port:
              number: 8080
  • 헤더(Header) 제어: 특정 헤더 값(Accept-Language: kr)을 가진 요청만 100% v2로 보내 특정 타겟 그룹에 대해서만 신규 기능을 테스트할 수도 있다.
curl -H "Accept-Language: kr" www.app.com:30431/version

 

 

 

 

3. HTTPS 보안 설정 (SSL/TLS Termination)

인프런_대세는 쿠버네티스

파드 자체에서 구현하기 힘든 인증서 관리 기능을 인그레스 레벨에서 대행한다.

  • 인증서 준비: openssl 명령어로 사설 인증서(tls.key, tls.crt)를 생성한 뒤, 이를 쿠버네티스 Secret(secret-https) 오브젝트로 저장한다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https
spec:
  ingressClassName: nginx
  tls: 
  - hosts:
    - http://www.https.com
    secretNamesecret-https
  rules:
  - host: http://www.https.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: svc-https
            port:
              number: 8080
  • TLS 설정: 인그레스 정의서의 tls 필드에 도메인(www.https.com)과 시크릿 이름을 매핑한다.
  • 검증: 윈도우 호스트 파일에 도메인을 등록한 후 브라우저에서 https://로 접속하여 보안 연결이 활성화되는지 확인한다.

 

 

 

 

💡실무 트러블슈팅 가이드

  • 도메인 확인: 실습 시, www.app.com 같은 도메인으로 호출할 때 연결이 안 된다면, 반드시 /etc/hosts 파일에 마스터 IP와 도메인이 등록되어 있는지 체크해라.
  • 애노테이션 주의: 카나리 배포 시 canary: "true" 옵션을 빼먹으면 가중치 설정이 무시되므로 주의가 필요하다.
  • 포트 매핑: 엔진엑스 서비스를 통해 트래픽이 들어와야 하므로, 외부에서는 반드시 엔진엑스 서비스의 NodePort로 접속해야 함을 잊지 마라.

 

 

 

위 학습용 정리 내용 및 사진 자료는 "인프런_대세는 쿠버네티스(https://inf.run/Lv5RV)" 강의를 소스로 작성하였습니다