본문 바로가기
DevOps/Kubernetes

[k8s] 외부 접속은 왜 Ingress일까? 쿠버네티스 인/아웃바운드 트래픽 총정리

by couque 2026. 3. 15.
반응형

쿠버네티스 환경에서 애플리케이션을 운영하다 보면, 외부 사용자가 애플리케이션에 접속하게 하거나, 애플리케이션이 외부의 다른 서비스(데이터베이스, 외부 API 등)와 통신해야 하는 상황이 필연적으로 발생합니다. 이처럼 클러스터 내부와 외부 사이의 네트워크 트래픽 흐름을 제어하는 핵심적인 개념이 바로 Ingress와 Egress입니다.

오늘은 이 두 가지 개념에 대해 깊이 있게 알아보고, 실제 구성 예시와 테스트 결과를 통해 어떻게 활용할 수 있는지 명확하게 정리해보는 시간을 갖겠습니다.

 

이전에 학습한 [k8s] 외부 서비스 접근을 위한 Service(ClusterIP, NodePort, LoadBalancer) 알아보기

 

1. 왜 Ingress와 Egress가 필요할까요?

쿠버네티스 클러스터 내부의 파드(Pod)들은 기본적으로 클러스터 내부의 IP 주소를 할당받아 서로 통신합니다. 이 내부 IP 주소는 외부에서는 접근할 수 없으며, 파드가 재시작되면 IP 주소가 변경될 수도 있습니다.

  • Ingress가 필요한 이유: 외부 사용자나 서비스가 클러스터 내부의 서비스에 안정적으로 접속하기 위해서는 고정된 진입점이 필요합니다. 단순히 Service를 NodePort나 LoadBalancer 타입으로 노출하는 것만으로는 HTTP/HTTPS 기반의 정교한 라우팅, SSL/TLS 인증서 관리 등을 효율적으로 처리하기 어렵습니다. Ingress는 이러한 요구사항을 충족하기 위해 등장한 개념입니다.
  • Egress가 필요한 이유: 클러스터 내부의 파드가 외부 세계로 데이터를 전송하거나 외부 서비스를 호출해야 하는 경우, 어떤 경로를 통해 나가는지 제어하고 보안 정책을 적용할 필요가 있습니다. 특정 파드만 외부 통신을 허용하거나, 특정 목적지로의 통신만 허용하는 등 세밀한 제어가 필요할 때 Egress 설정을 사용합니다.

2. 쿠버네티스 Ingress: 외부에서 내부로의 통로

Ingress는 클러스터 외부에서 클러스터 내부 서비스로의 HTTP 및 HTTPS 경로를 노출하는 API 객체입니다. 단순히 외부 접속을 허용하는 것 이상의 기능을 제공합니다.

Ingress의 주요 기능:

  • L7 로드 밸런싱: HTTP 요청의 호스트 헤더(Host: example.com)나 경로(path: /api)를 기반으로 트래픽을 서로 다른 백엔드 서비스로 전달할 수 있습니다.
  • SSL/TLS 종료 (SSL Termination): Ingress 컨트롤러에서 SSL 인증서를 관리하고 복호화 처리를 수행하여 백엔드 서비스의 부담을 줄여줍니다.
  • 이름 기반 가상 호스팅: 하나의 IP 주소로 여러 도메인 이름을 처리할 수 있습니다.

Ingress 아키텍처 예시

Ingress 개념을 직관적으로 이해하기 위해, 사용자의 요청이 어떻게 내부 서비스까지 전달되는지 나타내는 아키텍처 입니다.

이미지 1: Kubernetes Ingress 아키텍처 구성도

 

이미지 1: Kubernetes Ingress 아키텍처 구성도

위 구성도를 보시면 외부 클라이언트의 요청이 어떻게 클러스터 내부로 들어오는지 명확히 알 수 있습니다.

  1. 외부 클라이언트: 사용자가 브라우저나 앱을 통해 서비스에 접속을 시도합니다.
  2. 클라우드 로드 밸런서: 클라우드 환경이라면 Public IP를 가진 로드 밸런서가 요청을 먼저 받습니다.
  3. Ingress 컨트롤러: 로드 밸런서에서 전달된 트래픽을 Ingress 컨트롤러(예: Nginx, Traefik, HAProxy 등)가 받습니다. Ingress 컨트롤러는 실제 트래픽을 처리하는 프록시 서버 역할을 합니다.
  4. Ingress 규칙 적용: Ingress 컨트롤러는 생성된 Ingress 객체의 정의(설정 파일)를 읽어 들여, 요청된 호스트(example.com)나 경로(/api)에 따라 적절한 서비스로 트래픽을 라우팅합니다.
  5. 백엔드 서비스: 최종적으로 트래픽은 실제 애플리케이션이 실행 중인 파드들로 구성된 서비스로 전달됩니다.

중요한 점: Ingress는 규칙(설정)일 뿐이며, 이를 실제로 수행하는 것은 Ingress 컨트롤러입니다. 따라서 Ingress를 사용하기 위해서는 먼저 클러스터에 Ingress 컨트롤러가 설치되어 있어야 합니다.

Ingress 실습: Nginx Ingress 컨트롤러 설치 및 활용

가장 대중적으로 사용되는 Nginx Ingress 컨트롤러를 사용하여 Ingress를 구성해보겠습니다.

1. Nginx Ingress 컨트롤러 설치:

Helm을 사용하여 간편하게 설치할 수 있습니다.

Bash
helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace

2. 샘플 애플리케이션 배포:

테스트를 위해 간단한 http-echo 애플리케이션을 두 개의 서로 다른 서비스로 배포합니다.

YAML
# apple-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: apple-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: apple
  template:
    metadata:
      labels:
        app: apple
    spec:
      containers:
      - name: apple-app
        image: hashicorp/http-echo
        args:
        - "-text=apple"
---
apiVersion: v1
kind: Service
metadata:
  name: apple-service
spec:
  selector:
    app: apple
  ports:
    - protocol: TCP
      port: 5678
      targetPort: 5678
YAML
 
# banana-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: banana-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: banana
  template:
    metadata:
      labels:
        app: banana
    spec:
      containers:
      - name: banana-app
        image: hashicorp/http-echo
        args:
        - "-text=banana"
---
apiVersion: v1
kind: Service
metadata:
  name: banana-service
spec:
  selector:
    app: banana
  ports:
    - protocol: TCP
      port: 5678
      targetPort: 5678

위 두 YAML 파일을 적용합니다:

Bash
 
kubectl apply -f apple-app.yaml
kubectl apply -f banana-app.yaml

 

3. Ingress 리소스 생성 (라우팅 설정):

이제 Ingress 객체를 생성하여, 경로(path)에 따라 요청을 다른 서비스로 전달하도록 설정합니다.

YAML
# simple-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx # 설치한 Ingress 컨트롤러의 클래스 지정
  rules:
  - host: my-k8s-app.com # 사용할 가상 호스트 이름
    http:
      paths:
      - path: /apple
        pathType: Prefix
        backend:
          service:
            name: apple-service
            port:
              number: 5678
      - path: /banana
        pathType: Prefix
        backend:
          service:
            name: banana-service
            port:
              number: 5678

위 Ingress 리소스를 적용합니다:

Bash
kubectl apply -f simple-ingress.yaml

 

4. 테스트 및 결과 확인:

이제 외부에서 접속하는 것처럼 테스트해보겠습니다. 실제 도메인을 구매하지 않았으므로, /etc/hosts 파일을 수정하거나 curl의 --resolve 옵션을 사용하여 가상 호스트 이름(my-k8s-app.com)이 Ingress 컨트롤러의 외부 IP를 가리키도록 설정해야 합니다.

먼저 Ingress 컨트롤러의 외부 IP를 확인합니다.

Bash
kubectl get svc -n ingress-nginx

출력 결과에서 ingress-nginx-controller 서비스의 EXTERNAL-IP를 확인합니다. (예: 35.243.123.456)

이제 curl을 사용하여 테스트합니다.

Bash
 
# Ingress 컨트롤러의 IP를 <INGRESS_CONTROLLER_IP> 자리에 넣습니다.
curl -H "Host: my-k8s-app.com" http://<INGRESS_CONTROLLER_IP>/apple
# 출력: apple

curl -H "Host: my-k8s-app.com" http://<INGRESS_CONTROLLER_IP>/banana
# 출력: banana

결과 분석: 하나의 IP 주소와 포트(80)를 통해 접속했지만, 요청 경로( /apple, /banana)에 따라 Ingress 컨트롤러가 서로 다른 백엔드 서비스(apple-service, banana-service)로 트래픽을 정확히 라우팅하여 다른 결과가 출력되는 것을 확인할 수 있습니다.

3. 쿠버네티스 Egress: 내부에서 외부로의 통로

Egress는 클러스터 내부의 파드가 클러스터 외부의 서비스로 나가는 트래픽을 제어하는 개념입니다. Ingress처럼 단일 API 객체로 정의되기보다는, 네트워크 정책(NetworkPolicy)을 통해 구현되거나 클라우드 공급자의 NAT 게이트웨이 등을 활용하여 구성됩니다.

Egress의 주요 기능 및 활용:

  • 보안: 특정 파드만 외부 통신을 허용하거나, 특정 목적지 IP 대역으로의 통신만 허용하여 보안을 강화할 수 있습니다.
  • 컴플라이언스: 데이터 유출 방지(DLP) 등을 위해 외부로 나가는 트래픽을 감시하고 제어할 수 있습니다.
  • 고정 IP 확보: 클러스터 내부 파드의 IP는 유동적이므로, 외부 서비스에서 특정 클러스터 파드의 요청을 허용하려면 고정된 Egress IP(예: NAT 게이트웨이 IP)를 사용해야 할 수 있습니다.

Egress 아키텍처 예시 (NAT 게이트웨이 활용)

파드가 외부 인터넷으로 나갈 때 고정된 IP를 갖게 하는 일반적인 아키텍처를 살펴보겠습니다.

이미지 2: Kubernetes Egress 아키텍처 구성도 (NAT Gateway 활용)

 

이미지 2: Kubernetes Egress 아키텍처 구성도 (NAT Gateway 활용)

위 구성도는 파드가 외부 인터넷 서비스로 통신하는 과정을 보여줍니다.

  1. 클러스터 내부 파드: 애플리케이션 파드가 외부 API 호스트 이름으로 요청을 보냅니다.
  2. CNI 및 네트워크 정책: 요청은 먼저 클러스터 네트워킹 레이어(CNI 플러그인)를 통과합니다. 이때 **네트워크 정책(NetworkPolicy)**이 설정되어 있다면, 해당 파드가 외부로 통신할 권한이 있는지 확인하고 트래픽을 허용하거나 차단합니다.
  3. Egress 게이트웨이 (NAT Gateway): 허용된 트래픽은 클러스터 외부로 나가기 위해 Egress 게이트웨이(예: 클라우드 공급자의 NAT Gateway, 또는 별도로 구성한 Egress Gateway 파드)를 거칩니다.
  4. 소스 IP 변환 (SNAT): Egress 게이트웨이는 파드의 내부 IP를 자신의 고정된 Public IP로 변환(Source NAT)하여 외부로 전송합니다.
  5. 외부 서비스: 외부 서비스는 Egress 게이트웨이의 고정 IP로부터 요청을 받게 되며, 이를 바탕으로 방화벽 허용 목록(Whitelist)을 관리할 수 있습니다.

Egress 실습: NetworkPolicy를 이용한 외부 통신 제한

이번에는 쿠버네티스 자체 기능인 NetworkPolicy를 사용하여 특정 파드의 외부 통신(Egress)을 제어하는 실습을 진행해보겠습니다.

 

1. 테스트용 네임스페이스 및 파드 생성:

Bash
kubectl create namespace egress-test
kubectl run app-pod --image=radial/busyboxplus:curl -n egress-test --command -- sleep 3600

app-pod라는 파드를 생성하고, 외부 인터넷 통신이 가능한지 먼저 확인합니다.

Bash
# 파드 내부에서 google.com으로 curl 요청
kubectl exec -it app-pod -n egress-test -- curl -I google.com
# 출력: HTTP/1.1 200 OK ... (정상 통신)

 

2. Egress 제한 NetworkPolicy 적용:

이제 app-pod가 외부 인터넷(클러스터 외부 IP 대역)으로 나가는 모든 트래픽을 차단하는 NetworkPolicy를 생성합니다. 단, 클러스터 내부 통신(DNS 조회 등)을 위해 내부 IP 대역은 허용해야 합니다.

YAML
 
# deny-egress-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-egress-to-internet
  namespace: egress-test
spec:
  podSelector:
    matchLabels:
      run: app-pod # 대상 파드 지정
  policyTypes:
  - Egress
  egress:
  - to:
    - ipBlock:
        cidr: 0.0.0.0/0
        except: # 클러스터 내부 IP 대역은 제외 (예시 대역이며, 실제 환경에 맞게 조정 필요)
        - 10.0.0.0/8
        - 172.16.0.0/12
        - 192.168.0.0/16

위 NetworkPolicy를 적용합니다:

Bash
kubectl apply -f deny-egress-policy.yaml

 

3. 테스트 및 결과 확인:

다시 app-pod에서 외부 인터넷 통신을 시도합니다.

Bash
# 파드 내부에서 google.com으로 curl 요청
kubectl exec -it app-pod -n egress-test -- curl -I google.com --connect-timeout 5
# 출력: curl: (28) Connection timed out after 5001 milliseconds
# (타임아웃 발생 - 차단됨)

결과 분석: NetworkPolicy가 적용된 후, app-pod에서 외부 인터넷(google.com)으로의 통신이 차단되어 타임아웃이 발생하는 것을 확인할 수 있습니다. 이는 Egress 정책이 정상적으로 작동하여 내부에서 외부로의 트래픽을 제어하고 있음을 보여줍니다.

4. 인사이트 및 마무리

오늘은 쿠버네티스 네트워크의 중요한 두 축인 Ingress와 Egress에 대해 알아보았습니다. 핵심 내용을 정리하며 인사이트를 공유합니다.

  • Ingress는 단순한 문이 아니라 '관리되는 입구'입니다: 외부 요청을 내부 서비스로 단순히 전달하는 것을 넘어, L7 로드 밸런싱, SSL 종료, 호스트 기반 라우팅 등 풍부한 기능을 제공하여 애플리케이션의 외부 노출을 통합 관리할 수 있게 해줍니다. 적절한 Ingress 컨트롤러 선택과 효율적인 규칙 설계가 중요합니다.
  • Egress는 '안전한 출구'입니다: 클러스터 내부의 파드가 외부 세계와 무분별하게 통신하는 것을 방지하고, 보안 정책을 적용하여 외부 서비스를 안전하게 호출할 수 있는 경로를 제공합니다. NetworkPolicy와 NAT 게이트웨이를 결합하여 강력하고 유연한 Egress 제어를 구현해야 합니다.
  • 보안의 핵심 요소: Ingress와 Egress는 쿠버네티스 보안의 가장 앞단과 뒷단을 담당합니다. Ingress를 통한 외부 공격 방어(WAF 연동 등)와 Egress를 통한 내부 데이터 유출 방지 및 외부 서비스와의 신뢰 관계 형성(고정 IP 활용)은 현대적인 클라우드 네이티브 애플리케이션 운영의 필수 조건입니다.

Ingress와 Egress를 명확히 이해하고 활용한다면, 쿠버네티스 클러스터의 네트워크를 더욱 안전하고 유연하게 관리할 수 있을 것입니다.

반응형

댓글