우리는 지난 글에서 minikube에 대해 살펴봤습니다.

minikube를 왜 써야 하는지, minikube를 사용하기 전 유의해야 할 점, 그리고 minikube를 직접 설치하는 것까지 같이 해봤는데요.

minikube를 설치만 하고 끝내기는 너무 아쉽죠? 그래서 이번엔 minikube로 생성한 Kubernetes 클러스터 위에서 Ingress를 활용한 Nginx 앱 배포 및 노출 실습을 진행해보려 합니다.

이번 가이드를 통해 Kubernetes의 핵심 기능이자 요즘 널리 쓰이고 있는 Ingress를 로컬 minikube 클러스터 위에서 직접 사용해보며 작동 방식까지 익히실 수 있으실 겁니다.

어렵지 않게 따라하실 수 있도록 최대한 직관적인 구성으로 준비한 가이드이니, 꼭 확인해보세요!

🔀minikube에서 Ingress를 활용한 Nginx 앱 배포 가이드

(출처: https://kubernetes.io/docs/concepts/services-networking/ingress/)

먼저 minikube 클러스터 위에서 기본적이지만 필수로 알아야 할 Ingress 실습을 진행해보겠습니다.

“Ingress에 대해 많이는 들어봤지만 아직 왜 쓰이고 언제 써야 하는지 모르겠어요…”

그렇다면 더욱 좋습니다! 제가 minikube 클러스터 위에서 배포한 간단한 앱을 Ingress로 노출하면서 Ingress가 어떨 때 쓰이는지도 컴팩트하게 설명드릴게요.

Ingress는 외부에서 들어오는 HTTP 또는 HTTPS 요청을 수신한 다음, 미리 정의된 라우팅 규칙을 기반으로 적절한 클러스터 내부 서비스(Pod)에 해당 요청을 전달하는 역할을 수행합니다.

특히 Ingress를 사용하면 단일 IP 주소와 포트를 사용하면서도 URL의 경로에 따라 서로 다른 애플리케이션으로 트래픽을 분산할 수 있는데요.

각 서비스는 고유한 URL 경로를 할당받아 구분되기 때문에, 리소스 사용을 최적화하고 외부 접근 지점 관리를 단순화할 수 있는 것입니다.

minikube로 쉽게 예를 들면, minikube 클러스터 IP의 80 포트로 들어오는 HTTP 요청 중 아래와 같은 요청은 미리 정의된 규칙에 따라 각각 적절한 서비스로 전달되는 것입니다.

  • /app1 클러스터 내 서비스 A
  • /app2 클러스터 내 서비스 B

사실 Kubernetes의 Ingress 리소스 자체는 외부 요청을 어떻게 내부 서비스로 연결할지에 대한 ‘라우팅 규칙 설명서’에 가깝습니다.

특정 URL 경로로 요청이 올 경우 어떤 서비스로 전달할지를 Ingress YAML 파일에 선언적으로 명시하거든요.

그럼 Ingress 리소스에 정의된 규칙을 참고해서 실제 트래픽을 전달은 누가 하냐고요?

바로, Ingress Controller입니다.

그래서 Kubernetes 클러스터에서 Ingress 기능을 사용하려면 Ingress Contoller를 별도로 설치하고, Ingress 리소스를 정의해야 합니다.

우리가 사용 중인 minikube에서는 다양한 부가 기능을 애드온 형태로 제공하는데요. Ingress Controller도 애드온 형태로 쉽게 설치 가능합니다.

Ingress 실습을 위해 minikube에 Ingress 애드온을 먼저 설치해볼게요.

1️⃣minikube에서 Ingress 애드온 설치하기

지난 글에서 생성했던 minikube 클러스터를 minikube start 명령어로 작동시킨 뒤, minikube addons {minikube 클러스터 이름} list 명령어로 현재 minikube에 설치된 애드온과 사용 가능한 애드온 목록을 확인해봅니다.

이미지에 표시된 것처럼, 현재 minikube 클러스터에는 Ingress 애드온이 아직 비활성화(disabled) 상태인데요. 아래 명령어로 Ingress 애드온을 활성화해보겠습니다.

minikube addons -p {minikube 클러스터 이름} enable ingress

명령어를 실행하면 아래처럼 Ingress 애드온 설치가 진행됩니다. (설치하는 데에 시간이 약간 소요될 수 있습니다.)

설치가 끝나고 minikube addons {minikube 클러스터 이름} list 명령어를 다시 실행하면…

Ingress가 활성화(enabled✅)되었다고 뜨네요!

그럼 이제 Ingress로 트래픽을 라우팅할 서비스를 Kubernetes의 Deployment와 Service 리소스로 생성하고, 트래픽 라우팅 규칙을 명시하는 Ingress 리소스도 생성해보겠습니다.

2️⃣Deployment, Service, Ingress 리소스 작성하기

직관적인 실습을 위해, 트래픽을 받을 각 서비스를 Nginx 서버로 구성해보겠습니다.

우리가 이번 실습에서 배포할 테스트용 서비스는 아래 2가지입니다.

  • user-nginx: /user로 끝나는 트래픽을 받는 Nginx 서버
  • product-nginx: /product로 끝나는 트래픽을 받는 Nginx 서버

각 Deployment에서 유의해서 볼 점은, user 서비스가 사용하는 Nginx 이미지 버전(1.23)과 product 서비스에서 사용하는 Nginx 이미지 버전(1.25)이 서로 다르다는 것입니다.

이건 모든 배포가 끝나고 테스트할 때 트래픽이 예상대로 전달되는지 보기 위함입니다.

그럼 user-nginx 서비스를 배포하기 위한 Kubernetes 리소스 명세서를 먼저 작성해보겠습니다.

user-nginx.yaml
# 1. user-nginx 배포를 위한 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: user-nginx
  template:
    metadata:
      labels:
        app: user-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.23 # Ingress 테스트 시 구분을 위해 product 서비스와 다른 버전 사용
        ports:
        - containerPort: 80
 
---
# 2. user-nginx 배포를 위한 Service
apiVersion: v1
kind: Service
metadata:
  name: user-nginx-service
spec:
  selector:
    app: user-nginx
  ports:
  - protocol: TCP
    port: 80 # Service가 노출할 포트
    targetPort: 80 # Pod의 컨테이너 포트
 
# Ingress가 외부 트래픽을 minikube 클러스터 내부 Service로 전달하므로, Service의 Type은 ClusterIP로 지정합니다.
# Kubernetes Service의 기본 Type이 ClusterIP이기 때문에 명세서에 Type을 따로 지정하지 않습니다.

다음은 product-nginx 서비스 배포를 위한 Kuberentes 리소스 명세서입니다.

product-nginx.yaml
# 1. product-nginx 배포를 위한 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: product-nginx
  template:
    metadata:
      labels:
        app: product-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25 # Ingress 테스트 시 구분을 위해 user 서비스와 다른 버전 사용
        ports:
        - containerPort: 80
 
---
# 2. product-nginx 배포를 위한 Service
apiVersion: v1
kind: Service
metadata:
  name: product-nginx-service
spec:
  selector:
    app: product-nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

마지막으로 트래픽을 라우팅할 Ingress 리소스입니다.

example-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  # 사용할 Ingress의 Class명 (minikube의 Ingress 애드온 사용 시 'nginx'로 지정)
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /user # 라우팅 규칙이 적용될 경로
        pathType: Prefix # URI가 path 값으로 시작(Prefix)하면 라우팅하도록 설정
        backend:
          service:
            name: user-nginx-service # user-nginx의 Service 이름
            port:
              number: 80 # 해당 Service가 노출 중인 포트 번호
      - path: /product
        pathType: Prefix
        backend:
          service:
            name: product-nginx-service # product-nginx의 Service 이름
            port:
              number: 80

저는 아래와 같이 임의의 폴더(ingress-test)를 새로 만든 다음 각 명세서(Manifest)를 생성했습니다.

Manifest를 모두 작성했다면, 이제 minikube 클러스터에 배포해볼 차례입니다.

3️⃣minikube 클러스터에 작성한 Kubernetes 리소스 배포하기

Kubernetes 클러스터에 리소스를 배포할 때 kubectl을 사용하죠. minikube 클러스터도 마찬가지입니다.

특히 kubectl apply -f {파일명 또는 폴더명} 명령어를 사용하면, 여러 Manifest도 한 번에 배포 가능한데요. 제 경우엔 아래와 같이 Manifest가 포함된 폴더를 지정하는 명령어로 실습에 필요한 모든 리소스를 클러스터에 배포할 수 있습니다.

kubectl apply -f ingress-test

실제 터미널에서 ingress-test 폴더가 있는 경로로 이동한 다음, 해당 명령어를 실행하면 아래와 같이 Manifest에서 정의한 모든 Kubernetes 리소스가 배포됩니다.

우리가 작성한 Manifest에서 Namespace를 따로 지정하지 않았기 때문에, default Namespace에 위 리소스가 모두 배포되었습니다. 그래서 배포된 리소스들은 kubectl get all 명령어로 확인 가능합니다.

Ingress 실습에 필요한 리소스가 모두 배포되었으니, 이제 실제로 트래픽 라우팅이 잘 되는지 테스트해보겠습니다.

4️⃣Ingress로 트래픽 라우팅 동작 테스트하기

우리는 지금까지 Ingress Controller 애드온을 활성화했고, Ingress 리소스를 비롯해 테스트에 필요한 모든 Kubernetes 리소스를 클러스터에 배포했습니다.

Ingress는 클러스터로 접근하는 외부 트래픽의 라우팅을 담당한다고 했었죠. 여기서 이야기하는 외부 트래픽은 minikube 클러스터의 IP를 통해 클러스터로 접근하는 HTTP/HTTPS 요청을 의미합니다.

그래서 우리가 실습 중인 minikube 클러스터의 IP를 알아야 Ingress 테스트도 할 수 있습니다. minikube 클러스터의 IP를 확인하는 명령어는 아래와 같습니다.

minikube -p {minikube 클러스터 이름} ip

터미널에 해당 명령어를 실행하면 아래처럼 우리가 사용 중인 minikube 클러스터의 IP를 알 수 있습니다.

간단하죠? 그럼 이제 터미널에서 minikube 클러스터 IP와 우리가 Ingress 리소스에서 정의한 path를 합친 URL에 접근해보겠습니다.

curl 명령어를 사용하면 특정 URL에 접근하는 테스트가 가능한데요. 우리는 두 가지 서비스에 트래픽을 보내서 테스트하기 때문에 아래 명령어를 각각 입력해보겠습니다.

  • curl http://{minikube_ip}/user
  • curl http://{minikube_ip}/product

우리가 주목해야 할 것은 404 Not Found 에러 아래의 각 Nginx의 버전입니다.

아래처럼 각 Deployment에서 다르게 명시한 Nginx 버전이 표시되고 있죠?

  • user 서비스의 Nginx 이미지 버전: 1.23
  • product 서비스의 Nginx 이미지 버전: 1.25

위와 같은 메시지가 표시되었다면, 본 실습의 의도대로 Ingress Controller가 URI에 따라 외부 트래픽을 규칙에 맞는 Service로 전달하여 각 Nginx 서버가 해당 요청을 받은 것입니다.

우리가 각 Deployment에 사용한 기본 Nginx 서버 내에는 각각 /user 경로와 /product 경로에 대한 페이지가 없기 때문에 404 Not Found 에러가 표시된 것인데, 컴팩트하면서도 Ingress의 트래픽 라우팅 기능을 직관적으로 보여주는 실습을 위해 각 페이지는 만들지 않았거든요.


🔭마무리

이번 실습으로 우리는 minikube 클러스터 상에서 Ingress를 통해 외부 트래픽을 라우팅해봤는데요.

실습을 진행하면서 여러분들도 자연스레 Ingress를 사용하는 이유와 Kubernetes 클러스터 상에서 Ingress로 트래픽을 라우팅하는 방법을 익히셨을 겁니다.

이렇게 minikube를 활용하면 로컬 환경에서도 손쉽게 Kubernetes 기능을 테스트하고 실습할 수 있답니다.

다음 글에서는 minikube 클러스터 상에서 클라우드 네이티브 툴을 사용하는 실습을 진행해보겠습니다.

수많은 클라우드 네이티브 툴이 있지만, 그 중에서도 Kubernetes 리소스를 체계적이고 편리하게 관리할 수 있는 Kustomize를 minikube 클러스터 위에서 사용해볼 예정인데요.

그러니 다음 글도 기대해 주세요!