🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Ingress로 외부 라우팅 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 11. 29. · 20 Views

Ingress로 외부 라우팅 완벽 가이드

Kubernetes 클러스터 외부에서 들어오는 트래픽을 내부 서비스로 연결하는 Ingress의 개념부터 실전 설정까지, 초급 개발자도 쉽게 이해할 수 있도록 단계별로 설명합니다.


목차

  1. Ingress_개념과_필요성
  2. Ingress_Controller_설치
  3. Ingress_리소스_작성
  4. 경로_기반_라우팅
  5. 호스트_기반_라우팅
  6. TLS_HTTPS_설정

1. Ingress 개념과 필요성

어느 날 김개발 씨는 Kubernetes 클러스터에 배포한 웹 애플리케이션을 외부에서 접속하려고 했습니다. NodePort로 열어봤지만 포트 번호가 30000번대라 URL이 지저분했고, LoadBalancer를 쓰자니 서비스마다 비용이 발생했습니다.

"분명 더 좋은 방법이 있을 텐데..." 김개발 씨는 고민에 빠졌습니다.

Ingress는 클러스터 외부에서 들어오는 HTTP/HTTPS 요청을 내부 서비스로 라우팅해주는 API 객체입니다. 마치 건물 입구의 안내 데스크처럼, 방문자가 어느 층 어느 부서를 찾는지에 따라 적절한 곳으로 안내해주는 역할을 합니다.

하나의 진입점으로 여러 서비스를 관리할 수 있어 비용과 복잡성을 크게 줄일 수 있습니다.

다음 코드를 살펴봅시다.

# 기본적인 Ingress 리소스 예시
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

김개발 씨는 입사 6개월 차 DevOps 엔지니어입니다. 최근 회사에서 마이크로서비스 아키텍처로 전환하면서 Kubernetes를 도입했는데, 서비스가 늘어날수록 외부 접속 관리가 골칫거리가 되었습니다.

처음에는 각 서비스마다 LoadBalancer 타입의 Service를 만들었습니다. 문제는 클라우드 환경에서 LoadBalancer 하나당 비용이 발생한다는 것이었습니다.

서비스가 10개가 되니 비용도 10배가 되었습니다. 그때 선배 개발자 박시니어 씨가 다가왔습니다.

"Ingress를 써보는 게 어때요? 하나의 LoadBalancer로 모든 서비스를 관리할 수 있어요." 그렇다면 Ingress란 정확히 무엇일까요?

쉽게 비유하자면, Ingress는 마치 대형 쇼핑몰의 종합 안내 데스크와 같습니다. 방문객이 "화장품 매장이요"라고 하면 3층으로, "식당가요"라고 하면 지하 1층으로 안내해줍니다.

모든 방문객은 한 곳의 입구로 들어오지만, 각자 원하는 목적지로 정확하게 안내받을 수 있습니다. Ingress가 없던 시절에는 어땠을까요?

개발자들은 NodePort를 사용해 30000번대의 포트로 서비스를 노출했습니다. myapp.com:32145 같은 URL은 사용자에게 불편했고, 보안상으로도 좋지 않았습니다.

또 다른 선택지인 LoadBalancer는 서비스마다 외부 IP를 할당받아야 해서 비용이 급증했습니다. 바로 이런 문제를 해결하기 위해 Ingress가 등장했습니다.

Ingress를 사용하면 하나의 외부 IP로 여러 서비스에 접근할 수 있습니다. URL 경로나 호스트 이름에 따라 트래픽을 적절한 서비스로 분배합니다.

api.myapp.com은 API 서버로, www.myapp.com은 웹 서버로 자동 연결되는 것입니다. 위의 코드를 살펴보면, spec.rules 아래에 라우팅 규칙이 정의되어 있습니다.

host 필드에 도메인을 지정하고, paths 아래에 경로별로 연결할 서비스를 지정합니다. 이 설정 하나로 외부 트래픽이 자동으로 my-service로 전달됩니다.

실제 현업에서는 어떻게 활용할까요? 예를 들어 이커머스 서비스를 운영한다고 가정해봅시다.

shop.example.com은 쇼핑몰 프론트엔드로, api.example.com은 백엔드 API로, admin.example.com은 관리자 페이지로 연결해야 합니다. Ingress 하나로 이 모든 라우팅을 깔끔하게 관리할 수 있습니다.

하지만 주의할 점도 있습니다. Ingress 리소스만 만든다고 바로 작동하지 않습니다.

반드시 Ingress Controller가 클러스터에 설치되어 있어야 합니다. 이것은 다음 장에서 자세히 다루겠습니다.

다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 눈이 반짝였습니다.

"하나의 진입점으로 모든 서비스를 관리할 수 있다니, 정말 효율적이네요!" Ingress의 개념을 이해했다면, 이제 실제로 구현하기 위한 첫 번째 단계인 Ingress Controller 설치로 넘어가 봅시다.

실전 팁

💡 - Ingress는 L7(애플리케이션 계층) 로드밸런싱을 제공하므로 HTTP/HTTPS 트래픽에 최적화되어 있습니다

  • TCP/UDP 트래픽은 Ingress가 아닌 Service의 LoadBalancer나 NodePort를 사용해야 합니다

2. Ingress Controller 설치

김개발 씨는 신나게 Ingress 리소스를 작성하고 kubectl apply를 실행했습니다. 그런데 아무리 기다려도 외부에서 접속이 되지 않았습니다.

kubectl get ingress를 해보니 ADDRESS 컬럼이 비어 있었습니다. "뭐가 문제지?" 한참을 삽질하던 김개발 씨에게 박시니어 씨가 물었습니다.

"혹시 Ingress Controller 설치했어요?"

Ingress Controller는 Ingress 리소스를 실제로 구현하는 컴포넌트입니다. Ingress 리소스가 라우팅 규칙을 정의하는 설계도라면, Ingress Controller는 그 설계도를 보고 실제 건물을 짓는 건설 회사와 같습니다.

가장 많이 사용되는 것은 NGINX Ingress Controller이며, Helm이나 매니페스트 파일로 쉽게 설치할 수 있습니다.

다음 코드를 살펴봅시다.

# NGINX Ingress Controller 설치 (Helm 사용)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# 기본 설치
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace

# 설치 확인
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

# Ingress Controller의 외부 IP 확인
kubectl get svc ingress-nginx-controller -n ingress-nginx

김개발 씨는 멍한 표정으로 물었습니다. "Ingress Controller요?

Ingress만 만들면 되는 거 아니었나요?" 박시니어 씨가 웃으며 설명했습니다. "Kubernetes의 Ingress는 조금 특별해요.

리소스와 컨트롤러가 분리되어 있거든요." 이게 무슨 말일까요? 쉽게 비유하자면, Ingress 리소스는 마치 건축 설계도와 같습니다.

"1층은 카페, 2층은 사무실로 해주세요"라고 적힌 도면입니다. 하지만 설계도만 있다고 건물이 지어지진 않습니다.

실제로 벽돌을 쌓고 배관을 설치하는 건설 회사가 필요합니다. Ingress Controller가 바로 그 건설 회사 역할을 합니다.

Kubernetes는 왜 이렇게 설계했을까요? 이런 분리 구조 덕분에 다양한 구현체 중에서 선택할 수 있습니다.

NGINX, Traefik, HAProxy, AWS ALB, Google Cloud Load Balancer 등 각각의 특성에 맞는 Controller를 사용할 수 있습니다. 마치 같은 설계도로 여러 건설 회사 중 하나를 선택할 수 있는 것처럼요.

가장 널리 사용되는 것은 NGINX Ingress Controller입니다. NGINX는 이미 웹 서버와 리버스 프록시로 수십 년간 검증된 기술입니다.

안정성이 뛰어나고 문서도 풍부합니다. 대부분의 운영 환경에서 무난하게 사용할 수 있습니다.

위의 코드를 보면, Helm을 사용해 설치하는 과정이 나와 있습니다. 먼저 ingress-nginx 레포지토리를 추가하고, helm install 명령으로 설치합니다.

--create-namespace 옵션은 ingress-nginx 네임스페이스가 없으면 자동으로 생성해줍니다. 설치가 완료되면 kubectl get svc 명령으로 외부 IP를 확인할 수 있습니다.

클라우드 환경이라면 LoadBalancer 타입의 Service가 생성되고, 외부 IP가 자동 할당됩니다. 이 IP가 바로 모든 Ingress 트래픽이 들어오는 단일 진입점입니다.

온프레미스 환경이라면 어떻게 할까요? 클라우드 LoadBalancer를 사용할 수 없는 환경에서는 MetalLBNodePort 방식을 사용합니다.

MetalLB는 베어메탈 환경에서 LoadBalancer 기능을 제공하는 솔루션입니다. 김개발 씨가 고개를 끄덕였습니다.

"아, 그래서 Ingress 리소스만 만들었을 때 아무 일도 안 일어났던 거군요!" 맞습니다. Ingress Controller가 설치되어 있어야 Ingress 리소스를 감시하고, 변경사항을 감지해 라우팅 규칙을 적용합니다.

Controller 없이는 Ingress는 그저 클러스터에 저장된 YAML 문서에 불과합니다. 이제 Controller도 설치했으니, 본격적으로 Ingress 리소스를 작성하는 방법을 알아봅시다.

실전 팁

💡 - 클러스터당 여러 개의 Ingress Controller를 운영할 수 있으며, ingressClassName으로 구분합니다

  • Controller 설치 후 외부 IP가 할당되기까지 몇 분 정도 걸릴 수 있으니 조금 기다려보세요

3. Ingress 리소스 작성

Ingress Controller 설치를 마친 김개발 씨는 이제 본격적으로 Ingress 리소스를 작성하려고 합니다. 하지만 YAML 파일을 열어보니 생소한 필드들이 가득했습니다.

spec, rules, paths, backend... "이게 다 뭐지?" 걱정 마세요.

하나씩 차근차근 알아보겠습니다.

Ingress 리소스는 외부 요청을 내부 서비스로 연결하는 규칙을 정의하는 Kubernetes 객체입니다. 마치 우편물 분류 센터의 분류 규칙표와 같습니다.

"서울시 강남구로 가는 우편물은 A 트럭에, 서초구로 가는 건 B 트럭에" 같은 규칙을 정의하면, 시스템이 자동으로 분류해줍니다. 핵심 필드는 rules, paths, backend입니다.

다음 코드를 살펴봅시다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp-ingress
  namespace: production
  annotations:
    # NGINX 특화 설정
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"
spec:
  ingressClassName: nginx  # 사용할 Ingress Controller 지정
  rules:
  - host: webapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: webapp-service
            port:
              number: 8080

박시니어 씨가 화이트보드에 그림을 그리며 설명하기 시작했습니다. "Ingress 리소스는 크게 세 부분으로 나눌 수 있어요.

metadata, spec, 그리고 spec 안의 rules입니다." 먼저 metadata 부분을 봅시다. name은 이 Ingress의 이름입니다.

namespace는 어느 네임스페이스에 생성할지 지정합니다. 그리고 annotations가 있는데, 이게 매우 중요합니다.

annotations는 Ingress Controller에게 전달하는 추가 설정입니다. 예를 들어 nginx.ingress.kubernetes.io/proxy-body-size: "10m"은 요청 본문 크기를 10MB까지 허용하라는 의미입니다.

파일 업로드 기능이 있다면 이 값을 늘려야 합니다. 기본값은 보통 1MB 정도로 작습니다.

다음으로 spec 부분입니다. ingressClassName은 어떤 Ingress Controller를 사용할지 지정합니다.

클러스터에 여러 Controller가 있을 때 유용합니다. 지정하지 않으면 기본 Controller가 사용됩니다.

핵심은 rules 배열입니다. 각 rule은 hosthttp.paths로 구성됩니다.

host는 도메인 이름입니다. webapp.example.com으로 들어온 요청만 이 규칙을 적용받습니다.

host를 생략하면 모든 호스트에 적용됩니다. paths 배열 안에는 경로별 라우팅 규칙이 들어갑니다.

path는 URL 경로입니다. "/"는 루트 경로, "/api"는 /api로 시작하는 경로를 의미합니다.

pathType은 경로 매칭 방식을 지정합니다. Prefix는 해당 경로로 시작하는 모든 요청을, Exact는 정확히 일치하는 요청만 매칭합니다.

마지막으로 backend입니다. backend.service.name은 트래픽을 전달할 Service의 이름입니다.

port.number는 해당 Service의 포트 번호입니다. 이 Service가 실제 Pod들로 트래픽을 분배합니다.

김개발 씨가 질문했습니다. "그러면 Service가 먼저 있어야 하겠네요?" 박시니어 씨가 고개를 끄덕였습니다.

"맞아요. Ingress는 Service로 트래픽을 전달하고, Service가 Pod로 전달합니다.

Ingress -> Service -> Pod 순서입니다." 실제로 kubectl apply -f ingress.yaml 명령을 실행하면, Ingress Controller가 이 리소스를 감지합니다. 그리고 정의된 규칙에 따라 내부 라우팅 설정을 업데이트합니다.

이 모든 과정이 자동으로 이루어집니다. 이제 기본적인 Ingress 작성법을 익혔으니, 더 정교한 라우팅 방법을 알아봅시다.

실전 팁

💡 - pathType은 Prefix, Exact, ImplementationSpecific 세 가지가 있으며, 대부분 Prefix를 사용합니다

  • annotations는 Controller마다 다르므로, 사용하는 Controller의 문서를 참고하세요

4. 경로 기반 라우팅

김개발 씨의 회사에서 새로운 요구사항이 생겼습니다. 프론트엔드와 백엔드 API를 같은 도메인에서 서비스해야 합니다.

myapp.com으로 접속하면 웹 페이지가, myapp.com/api로 접속하면 API 서버가 응답해야 합니다. "하나의 도메인에서 어떻게 두 개의 서비스를 분리하지?" 바로 경로 기반 라우팅이 해답입니다.

경로 기반 라우팅은 URL 경로에 따라 서로 다른 서비스로 트래픽을 분배하는 방식입니다. 마치 백화점 층별 안내와 같습니다.

1층 화장품, 2층 여성복, 3층 남성복처럼, /로 오면 프론트엔드로, /api로 오면 백엔드로, /admin으로 오면 관리자 서비스로 연결됩니다. 하나의 도메인으로 여러 마이크로서비스를 통합할 수 있습니다.

다음 코드를 살펴봅시다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: path-based-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      # /api/* 요청은 backend-api 서비스로
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: backend-api
            port:
              number: 3000
      # /admin/* 요청은 admin-panel 서비스로
      - path: /admin(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: admin-panel
            port:
              number: 8080
      # 나머지 모든 요청은 frontend 서비스로
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend
            port:
              number: 80

박시니어 씨가 화이트보드에 그림을 그리기 시작했습니다. 하나의 도메인에서 세 개의 화살표가 각각 다른 서비스로 뻗어나가는 그림이었습니다.

"경로 기반 라우팅은 마이크로서비스 아키텍처에서 정말 많이 쓰여요." 왜 경로 기반 라우팅이 필요할까요? 과거에는 프론트엔드와 백엔드가 하나의 서버에서 동작했습니다.

하지만 마이크로서비스 시대에는 각각 독립된 서비스로 분리됩니다. 문제는 사용자 입장에서는 여전히 하나의 도메인으로 접속하고 싶다는 것입니다.

CORS 문제도 있습니다. 프론트엔드가 frontend.example.com이고 API가 api.example.com이라면, 브라우저의 동일 출처 정책 때문에 복잡한 CORS 설정이 필요합니다.

하지만 같은 도메인의 다른 경로라면 이 문제가 깔끔하게 해결됩니다. 위의 코드를 자세히 살펴봅시다.

paths 배열에 세 개의 규칙이 정의되어 있습니다. 순서가 중요합니다.

Ingress Controller는 위에서 아래로 규칙을 평가하며, 먼저 매칭되는 규칙이 적용됩니다. /api로 시작하는 요청은 backend-api 서비스로 전달됩니다.

/admin으로 시작하는 요청은 admin-panel 서비스로 갑니다. 그 외 모든 요청은 마지막 규칙에 따라 frontend 서비스로 전달됩니다.

여기서 rewrite-target 어노테이션에 주목하세요. /api/users로 요청이 들어오면, backend-api 서비스에는 /users로 전달됩니다.

/api 접두사가 제거되는 것입니다. 이것이 rewrite-target의 역할입니다.

백엔드 서비스는 자신이 /api 하위에서 동작하는지 몰라도 됩니다. 정규표현식 패턴 /api(/|$)(.*)를 분석해봅시다.

(/|$)는 슬래시가 있거나 문자열 끝을 의미합니다. (.*)는 그 뒤의 모든 문자를 캡처합니다.

$2는 두 번째 캡처 그룹, 즉 (.*)에 해당하는 부분입니다. 따라서 /api/users/123은 /users/123으로 변환됩니다.

김개발 씨가 감탄했습니다. "이렇게 하면 프론트엔드 코드에서 /api/users만 호출하면 되겠네요.

환경별로 URL을 바꿀 필요가 없어요!" 맞습니다. 개발, 스테이징, 프로덕션 환경 모두 같은 경로 구조를 사용할 수 있어 개발이 훨씬 편해집니다.

실전 팁

💡 - paths 규칙의 순서가 중요합니다. 더 구체적인 경로를 먼저 정의하세요

  • rewrite-target을 사용할 때는 정규표현식과 캡처 그룹을 정확히 이해해야 합니다

5. 호스트 기반 라우팅

프로젝트가 성장하면서 김개발 씨의 회사는 여러 서비스를 운영하게 되었습니다. 메인 사이트 외에도 API 문서 사이트, 관리자 포털, 모바일 전용 API가 필요했습니다.

"다 같은 서버에 올리기엔 부담스럽고, 서비스별로 도메인을 분리하면 좋겠는데..." 호스트 기반 라우팅이 바로 그 해답입니다.

호스트 기반 라우팅은 요청의 도메인(호스트) 이름에 따라 서로 다른 서비스로 트래픽을 분배합니다. 마치 같은 건물에 여러 회사가 입주해 있는 것과 같습니다.

A 회사를 찾으면 3층으로, B 회사를 찾으면 5층으로 안내합니다. 하나의 IP 주소(Ingress Controller)로 여러 도메인의 서비스를 운영할 수 있어 비용 효율적입니다.

다음 코드를 살펴봅시다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
spec:
  ingressClassName: nginx
  rules:
  # 메인 웹사이트
  - host: www.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: main-website
            port:
              number: 80
  # API 서버
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-server
            port:
              number: 8080
  # 문서 사이트
  - host: docs.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: docs-site
            port:
              number: 3000

박시니어 씨가 칠판에 하나의 건물 그림을 그렸습니다. 그리고 건물 입구에서 세 갈래로 뻗어나가는 화살표를 그렸습니다.

"호스트 기반 라우팅은 가상 호스팅이라고도 불려요. 웹 서버가 오래전부터 사용해온 기술이죠." HTTP 요청에는 Host 헤더가 포함됩니다.

브라우저에서 www.example.com을 입력하면, DNS를 통해 IP 주소를 얻습니다. 그리고 해당 IP로 HTTP 요청을 보내는데, 이때 Host: www.example.com이라는 헤더가 함께 전송됩니다.

서버는 이 헤더를 보고 어떤 사이트에 대한 요청인지 판단합니다. Ingress도 동일한 원리를 사용합니다.

위의 코드를 보면 rules 배열에 세 개의 규칙이 있습니다. 각각 다른 host 값을 가지고 있습니다.

www.example.com으로 들어온 요청은 main-website 서비스로, api.example.com은 api-server로, docs.example.com은 docs-site로 전달됩니다. DNS 설정은 어떻게 해야 할까요?

모든 도메인이 같은 IP 주소를 가리키도록 설정합니다. 그 IP는 Ingress Controller의 외부 IP입니다.

Ingress Controller가 Host 헤더를 보고 적절한 서비스로 라우팅해줍니다. 김개발 씨가 질문했습니다.

"와일드카드 도메인도 가능한가요? *.example.com처럼요." 박시니어 씨가 고개를 끄덕였습니다.

"네, 가능해요. host: '*.example.com'으로 설정하면 됩니다.

단, 정확히 일치하는 규칙이 우선 적용됩니다." 실무에서 흔히 보는 패턴이 있습니다. 서브도메인으로 환경을 구분하는 것입니다.

dev.example.com은 개발 환경, staging.example.com은 스테이징 환경, www.example.com은 프로덕션 환경으로 설정합니다. 하나의 클러스터에서 여러 환경을 운영할 때 유용합니다.

호스트 기반과 경로 기반을 조합할 수도 있습니다. api.example.com/v1은 v1 API 서비스로, api.example.com/v2는 v2 API 서비스로 연결하는 식입니다.

이렇게 하면 API 버전 관리가 깔끔해집니다. 김개발 씨가 정리했습니다.

"그러면 경로 기반은 하나의 도메인 안에서 분기할 때, 호스트 기반은 도메인 자체를 분리할 때 사용하면 되겠네요!" 정확합니다. 두 방식을 상황에 맞게 조합하면 복잡한 마이크로서비스 구조도 깔끔하게 관리할 수 있습니다.

실전 팁

💡 - 모든 서브도메인의 DNS를 Ingress Controller IP로 설정하면, 새 서비스 추가 시 DNS 변경 없이 Ingress만 수정하면 됩니다

  • 와일드카드 호스트를 사용할 때는 보안에 주의하세요. 의도치 않은 서브도메인 접근이 가능할 수 있습니다

6. TLS HTTPS 설정

서비스 오픈이 얼마 남지 않았습니다. 그런데 보안팀에서 연락이 왔습니다.

"HTTPS 적용 안 하면 출시 불가입니다." 김개발 씨는 당황했습니다. 인증서는 어디서 받아야 하고, 어떻게 적용해야 하지?

다행히 Ingress에서는 TLS 설정이 생각보다 간단합니다.

**TLS(Transport Layer Security)**는 클라이언트와 서버 간 통신을 암호화하는 프로토콜입니다. HTTPS가 바로 HTTP에 TLS를 적용한 것입니다.

Ingress에서 TLS를 설정하면, 외부 트래픽은 암호화되어 들어오고 내부 서비스로는 일반 HTTP로 전달됩니다. 이를 **TLS 종료(TLS Termination)**라고 합니다.

인증서는 Kubernetes Secret에 저장하여 관리합니다.

다음 코드를 살펴봅시다.

# 1. TLS 인증서를 Secret으로 생성
kubectl create secret tls example-tls \
  --cert=tls.crt \
  --key=tls.key \
  -n production

# 2. IngressTLS 설정 추가
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: secure-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - secure.example.com
    - api.example.com
    secretName: example-tls
  rules:
  - host: secure.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: secure-app
            port:
              number: 8080

박시니어 씨가 진지한 표정으로 말했습니다. "요즘 HTTPS는 선택이 아니라 필수예요.

브라우저에서도 HTTP 사이트는 '안전하지 않음'이라고 경고하잖아요." TLS 종료가 뭔가요? 쉽게 비유하자면, 보안 검색대와 같습니다.

공항에서 보안 검색을 통과하면 내부에서는 자유롭게 이동할 수 있습니다. 마찬가지로 Ingress에서 TLS 암호화를 해제하면, 내부 Pod들은 일반 HTTP로 통신합니다.

이것이 TLS 종료입니다. 왜 Ingress에서 TLS를 처리할까요?

각 서비스마다 인증서를 관리하면 복잡해집니다. 인증서 갱신 시 모든 서비스를 수정해야 합니다.

Ingress에서 중앙 집중식으로 관리하면 훨씬 효율적입니다. 인증서 하나만 갱신하면 모든 서비스에 적용됩니다.

먼저 인증서를 준비해야 합니다. 인증서 파일(.crt)과 개인 키 파일(.key)이 필요합니다.

상용 인증 기관(CA)에서 구매하거나, Let's Encrypt를 통해 무료로 발급받을 수 있습니다. 테스트 환경에서는 자체 서명 인증서를 사용할 수도 있습니다.

위의 코드에서 첫 번째 명령을 봅시다. kubectl create secret tls 명령으로 인증서를 Secret 객체로 저장합니다.

tls.crt는 인증서 파일, tls.key는 개인 키 파일입니다. Secret 이름은 example-tls입니다.

다음으로 Ingress 설정입니다. tls 섹션이 추가되었습니다.

hosts에는 이 인증서를 적용할 도메인 목록을 작성합니다. secretName은 앞서 만든 Secret의 이름입니다.

하나의 인증서로 여러 도메인을 커버하려면 SAN(Subject Alternative Name) 인증서가 필요합니다. ssl-redirect 어노테이션도 중요합니다.

이 설정을 true로 하면, HTTP로 들어온 요청을 자동으로 HTTPS로 리다이렉트합니다. 사용자가 http://secure.example.com을 입력해도 https://로 자동 전환됩니다.

김개발 씨가 물었습니다. "인증서 갱신은 어떻게 하나요?

만료되면 수동으로 교체해야 하나요?" 박시니어 씨가 미소 지었습니다. "cert-manager를 사용하면 자동화할 수 있어요.

Let's Encrypt 인증서를 자동으로 발급받고 갱신해줍니다. 실무에서는 거의 필수로 사용해요." cert-manager를 설치하면, Ingress에 어노테이션만 추가하면 됩니다.

cert-manager.io/cluster-issuer: "letsencrypt-prod"처럼요. 그러면 자동으로 인증서가 발급되고, 만료 전에 갱신됩니다.

"이제 HTTPS도 적용했으니, 보안팀 검수도 통과하겠네요!" 김개발 씨의 얼굴에 안도감이 번졌습니다.

실전 팁

💡 - cert-manager와 Let's Encrypt를 조합하면 무료로 자동 인증서 관리가 가능합니다

  • 와일드카드 인증서(*.example.com)를 사용하면 서브도메인마다 인증서를 발급받지 않아도 됩니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Kubernetes#Ingress#IngressController#Routing#TLS#Kubernetes,Ingress,Network

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.