Network - Ingress

2026. 1. 5. 22:11·CKA

이번 강의는 “Ingress를 왜 쓰는가?”를 서비스(Service)부터 역순으로 쌓아 올리며 설명합니다. 결론부터 말하면:

  • Service는 “클러스터 내부에서 Pod 집합을 안정적으로 노출(가상 VIP + L4 로드밸런싱)”하는 기본 단위이고
  • Ingress는 “HTTP(S) 트래픽을 URL/Host 기반으로 여러 Service로 라우팅하고, TLS(SSL)까지 한 곳에서 처리”하는 L7 진입점입니다.

1) 서비스부터 다시: Pod를 외부에 노출하려면?

회사에 온라인 스토어 my-online-store.com를 운영한다고 해봅시다.

1.1 내부 의존성: DB는 ClusterIP로

앱은 MySQL이 필요합니다.

  • MySQL Pod(Deployment/StatefulSet 등)
  • MySQL Service(ClusterIP) → 클러스터 내부에서만 접근
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  type: ClusterIP
  selector:
    app: mysql
  ports:
  - port: 3306
    targetPort: 3306

앱 Pod는 mysql-service라는 이름(DNS)으로 DB에 붙습니다.

1.2 외부 노출: NodePort로 시작하면?

웹앱을 외부에 열기 위해 Service를 NodePort로 만들면:

  • 노드의 고정 포트 범위(보통 30000~32767) 중 하나(예: 30080)가 열립니다.
  • 사용자는 http://<노드IP>:30080로 접속합니다.
apiVersion: v1
kind: Service
metadata:
  name: web-nodeport
spec:
  type: NodePort
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080

이 구성은 동작은 합니다. 트래픽이 늘면 Deployment replica를 늘리고, Service가 Pod로 분산합니다.


2) 운영을 생각하면 NodePort/LoadBalancer만으로는 “관리 포인트”가 폭증한다

2.1 “IP를 치게 할 순 없으니” DNS를 붙임

사용자가 IP 대신 my-online-store.com으로 들어오게 DNS를 구성합니다.

하지만 여전히 포트가 남습니다:

  • my-online-store.com:30080

2.2 “포트도 숨기자” → 앞단 프록시/로드밸런서가 필요

NodePort는 일반적으로 80/443 같은 “표준 포트”를 직접 쓰기 어렵습니다(고포트만 할당).

그래서 보통:

  • 외부 80 → 내부 노드의 30080으로 프록시하는 별도 프록시/로드밸런서가 필요해집니다.
  • 온프레미스라면 HAProxy/Nginx/하드웨어 LB 같은 걸 앞단에 둡니다.

2.3 클라우드라면? Service type=LoadBalancer

GCP 같은 환경에서는 type: LoadBalancer를 쓰면:

  • Kubernetes가 기본적으로 NodePort와 비슷한 구성(노드 포트 오픈)을 하고
  • 클라우드에 외부 LB 프로비저닝 요청을 보내서
  • 외부 IP를 가진 로드밸런서를 자동으로 만들어 줍니다.

그러면 사용자는:

  • my-online-store.com → LB 외부 IP → Service → Pod

여기까지는 “단일 웹앱”이면 괜찮습니다.


3) 문제가 커지는 지점: 서비스가 늘어날수록 외부 LB/프록시가 계속 늘어난다

회사가 성장해서 /watch 같은 영상 서비스가 추가됐다고 해봅시다.

  • web 앱(기존)
  • video 앱(신규)

각각을 type: LoadBalancer로 노출하면:

  • LB가 2개가 되고
  • 서비스가 늘수록 LB가 계속 늘고(=비용 증가)
  • “URL 경로에 따라 다른 백엔드로 보내기” 같은 라우팅은 LB를 매번 재설정해야 합니다.

여기에 TLS(HTTPS)까지 붙이면 더 복잡해집니다.

  • 앱마다 TLS를 구현하게 하면 팀별 방식이 달라지고 유지보수 지옥
  • LB/프록시 레벨에서 TLS termination을 하려면 설정이 계속 커짐

“이런 L7 라우팅/SSL/규칙 관리를 쿠버네티스 안에서, YAML로, 일관되게 관리할 수 없을까?”
그게 Ingress의 출발점입니다.


4) Ingress의 정체: “클러스터 내부에 두는 L7 진입점” + 규칙 리소스

Ingress는 크게 2개로 나뉩니다.

4.1 Ingress Controller (구현체)

Ingress는 “개념/규격”이고, 실제 트래픽을 처리하는 제품이 필요합니다.

  • NGINX Ingress, GCE Ingress, HAProxy, Traefik, Contour, Istio Gateway 등

중요 포인트:

  • 쿠버네티스는 Ingress Controller를 기본으로 설치해주지 않습니다.
  • Ingress 리소스(YAML)만 만들어서는 아무 일도 안 일어납니다.
  • 먼저 “컨트롤러”를 클러스터에 배포해야 합니다.

4.2 Ingress Resource (규칙)

Ingress 리소스는 “이 Host/Path로 들어오면 어떤 Service로 보낼지”를 정의하는 규칙 모음입니다.


5) NGINX Ingress Controller를 예로: 뭐가 필요하나?

강의 흐름(최소 구성)은 아래 4종 세트입니다.

  1. Deployment: nginx ingress controller Pod
  2. Service: 외부에서 ingress controller로 들어올 진입점(NodePort 또는 LoadBalancer)
  3. ConfigMap: nginx 동작 옵션(빈 ConfigMap이라도 미리 만들어두면 확장 쉬움)
  4. ServiceAccount + RBAC(Role/ClusterRole, Binding): Ingress 리소스/Service/Endpoint 등을 watch할 권한

실무에서는 Helm으로 설치하는 경우가 많지만, 개념상 위 구성요소가 핵심입니다.

컨트롤러가 하는 일은 단순 “nginx 띄우기”가 아닙니다.

  • Kubernetes API를 watch
  • Ingress 리소스가 추가/변경되면 nginx 설정을 자동으로 생성/리로드
  • TLS 시크릿, 서비스 엔드포인트 변화를 반영

6) Ingress Resource 기본 형태 (networking.k8s.io/v1)

6.1 단일 백엔드(모든 트래픽 → 한 서비스)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-web
spec:
  ingressClassName: nginx
  defaultBackend:
    service:
      name: web-service
      port:
        number: 80
  • rules 없이 defaultBackend만 있으면 “모든 요청이 web-service로” 갑니다.

6.2 경로 기반 라우팅: /는 web, /watch는 video

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-store
spec:
  ingressClassName: nginx
  rules:
  - host: my-online-store.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /watch
        pathType: Prefix
        backend:
          service:
            name: video-service
            port:
              number: 80
  • rules(Host) → 그 아래 paths(Path)
    즉, Host 단위로 큰 갈래를 나누고 그 안에서 Path로 세부 분기합니다.

6.3 호스트 기반 라우팅: wear. vs watch.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-host-split
spec:
  ingressClassName: nginx
  rules:
  - host: wear.my-online-store.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: wear-service
            port:
              number: 80
  - host: watch.my-online-store.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: video-service
            port:
              number: 80
  • DNS는 여러 레코드를 같은 Ingress 진입점(LB IP)으로 가리키게 만들 수 있습니다.
  • Ingress는 Host 헤더로 어떤 rule을 적용할지 결정합니다.

7) “Default Backend(404)”는 왜 보이나?

kubectl describe ingress를 보면 종종 default backend 이야기가 나옵니다.

  • Ingress rules/path에 매칭이 안 되면 어디로 보낼지 필요합니다.
  • 보통은 “404 페이지 서비스”를 하나 두고 그쪽으로 보내도록 구성합니다.

컨트롤러 설치 시 기본 404 백엔드가 함께 배포되는 경우도 있고, 직접 만들기도 합니다.


8) Kubernetes 버전 변화 포인트: kubectl로 Ingress를 imperative하게 만들 수 있다(1.20+)

강의에 나온 형식처럼, (환경에 따라) 아래처럼 만들 수 있습니다.

kubectl create ingress ingress-test \
  --class=nginx \
  --rule="wear.my-online-store.com/wear*=wear-service:80"

핵심은:

  • “Ingress도 결국 Kubernetes 리소스라서”
  • kubectl로 선언적(YAML) / 명령형(Imperative) 모두 가능하다는 점입니다.

9) NGINX Ingress에서 자주 만나는 함정: rewrite-target

문제 상황:

  • 사용자가 Ingress로 http://<ingress>/watch로 접속
  • Ingress가 backend인 watch-service로 보냄

그런데 rewrite를 안 하면 보통 요청 URI가 그대로 전달됩니다.

  • /watch → 백엔드에도 /watch로 전달됨
    (즉 http://watch-service/watch)

하지만 watch 앱은 루트(/)만 제공하고 /watch 라우트가 없다면:

  • 404 Not Found

9.1 해결: nginx.ingress.kubernetes.io/rewrite-target

Ingress에서 /watch로 들어온 요청을 백엔드에 /로 바꿔서 보내고 싶다면:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-rewrite
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: my-online-store.com
    http:
      paths:
      - path: /watch
        pathType: Prefix
        backend:
          service:
            name: watch-service
            port:
              number: 80
      - path: /wear
        pathType: Prefix
        backend:
          service:
            name: wear-service
            port:
              number: 80

이렇게 하면 의도는:

  • http://<ingress>/watch → http://watch-service/
  • http://<ingress>/wear → http://wear-service/

즉, “Ingress에서 라우팅에만 쓰는 prefix(/watch, /wear)를 백엔드로 전달하지 않도록” 하는 옵션입니다.

9.2 정규식 기반 예시(개념)

강의 후반의 replace("/something(/|$)(.*)", "/$2") 같은 형태는 “캡처 그룹으로 뒤쪽 경로를 살려서 전달”하려는 패턴입니다.

예:

  • /something/abc → /abc

컨트롤러/버전에 따라 “정규식 path 지원 여부”나 “annotation 옵션”이 달라질 수 있으니, 실습에서는 해당 컨트롤러 문서 기준으로 확인하는 습관이 좋습니다.


10) Ingress를 써도 “외부로 노출”은 한 번은 해야 한다

Ingress를 쓰면 모든 것이 해결되는 것처럼 보이지만, 외부 트래픽이 Ingress Controller까지 들어와야 합니다.

그래서 보통:

  • Ingress Controller Service를 NodePort 또는 LoadBalancer로 1회 노출
  • 그 이후 “새 서비스 추가/라우팅 변경/TLS 추가”는 Ingress 리소스(YAML)만 바꿔서 해결

즉, 핵심 가치는:

  • 외부 LB/프록시를 서비스마다 늘리는 대신
  • Ingress Controller 하나에 규칙을 모아 관리하는 것입니다.

11) 정리: Service vs Ingress, 언제 뭘 쓰나?

Service

  • Pod 집합을 안정적으로 노출(ClusterIP/NodePort/LoadBalancer)
  • L4 중심(TCP/UDP) 관점
  • “클러스터 내부/외부”를 연결하는 기본 빌딩 블록

Ingress

  • HTTP(S) 트래픽을 Host/Path 기반으로 여러 Service로 라우팅
  • TLS(HTTPS) termination을 중앙집중식으로 처리 가능
  • 규칙이 Kubernetes 리소스로 관리되므로 배포/형상관리(YAML) 친화적
  • 단, Ingress Controller 설치가 선행되어야 함

실습에서 바로 보는 커맨드

# ingress 리소스 보기
kubectl get ingress -A
kubectl describe ingress <name>

# ingress controller(예: nginx) 배포 여부 확인(환경마다 라벨/이름 다름)
kubectl -n ingress-nginx get all
kubectl -n kube-system get pods | grep -i ingress

# rewrite나 라우팅 문제 확인용
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller

 

 

Practice Test URL: https://uklabs.kodekloud.com/topic/practice-test-cka-ingress-networking-1-2/

Practice Test URL: https://uklabs.kodekloud.com/topic/practice-test-cka-ingress-networking-2-2/

'CKA' 카테고리의 다른 글

Network - 정리(2)  (0) 2026.01.05
Network - Gateway API  (0) 2026.01.05
Network - Service Networking  (0) 2026.01.05
Network - IPAM(IP Address Management)  (0) 2026.01.05
Network - Pod Networking & CNI  (1) 2026.01.05
'CKA' 카테고리의 다른 글
  • Network - 정리(2)
  • Network - Gateway API
  • Network - Service Networking
  • Network - IPAM(IP Address Management)
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      스레드
      JPQL
      자바
      양방향 맵핑
      Target
      jpq
      @discriminatorvalue
      빈 후처리기
      reentarantlock
      log trace
      @discriminatorcolumn
      hibernate5module
      Thread
      @args
      requset scope
      프록시 팩토리
      고급
      조회 성능 최적화
      페치 조인
      프록시
      버퍼
      gesingleresult
      WAS
      typequery
      김영한
      락
      jdk 동적 프록시
      @within
      단방향 맵핑
      cglib
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Network - Ingress
    상단으로

    티스토리툴바