Home (K8S) 인그레스와 인그레스 컨트롤러
Post
Cancel

(K8S) 인그레스와 인그레스 컨트롤러

이 글은 Mumshad Mannambeth가 강의한 Udemy의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의 커리큘럼을 토대로 공부한 내용을 정리하였음을 밝힙니다.


인그레스의 간단한 개념

인그레스(ingress)라는 단어는 외부에서 내부로 향하는 것을 의미한다. 예를 들어, 인그레스 트래픽은 외부에서 서버 내부로 들어오는 트래픽을 의미한다.

쿠버네티스에서 인그레스란, 클러스터 외부에서 내부로 접근하는 요청들을 어떻게 처리할 것인지 정의해둔 규칙들의 모음이다. 인그레스는 아래와 같은 기능들을 제공한다.

  • 트래픽 로드밸런싱
  • 서비스에 외부 URL을 제공함 (외부 요청을 라우팅)
    • /apple, /apple/red 등과 같이 특정 경로로 들어온 요청을 어떠한 서비스로 전달할지 정의하는 라우팅 규칙을 설정할 수 있음
  • SSL 인증서 처리
    • 여러 개의 서비스로 요청을 라우팅할 때, 보안 연결을 위한 인증서를 쉽게 적용할 수 있음
  • 도메인 기반 가상 호스팅을 제공함
    • 같은 IP에 대해 다른 도메인 이름으로 요청이 왔을 때, 어떻게 처리할 것인지 정의할 수 있음

인그레스 오브젝트 자체는 위와 같은 기능들에 대해 규칙들을 정의해둔 리소스이고, 실제로 동작하기 위해서는 인그레스 컨트롤러라는 특별한 서버가 필요하다. 즉, 실제로 외부 요청을 받아들이는 인그레스 컨트롤러 서버가 인그레스 오브젝트에 정의된 규칙들을 로드해서 사용하는 것이다.

인그레스 컨트롤러는 Nginx 웹 서버 인그레스 컨트롤러, GKE의 인그레스 컨트롤러, Contour, Istio, HAPROXY, Kong 등 매우 다양하게 존재한다. 이들 중 쿠버네티스 커뮤니티에서 활발히 사용되고 있는 Nginx의 인그레스 컨트롤러가 대표적이다. 인그레스 컨트롤러는 쿠버네티스에서 default로 배포하지 않기 때문에 직접 설치를 위한 YAML 파일을 내려받아 설치하여 디플로이먼트를 통해 배포하든 해야 한다.


인그레스를 왜 사용할까?

NodePort 또는 LoadBalancer 타입의 서비스를 사용해도 위의 기능들을 얼추 구현할 수는 있다. 그럼에도 인그레스를 사용해야 하는 이유가 있을까?

fig01

위 그림과 같이 애플리케이션이 3개의 디플로이먼트로 생성되어 있다고 예를 들어보자. 인그레스를 사용하지 않고서 NodePort 또는 LoadBalancer 타입의 서비스를 이용하여 클러스터 외부에서 파드에 접근할 수 있도록 하였다.

그럴싸하게 작동할 수 있어 보이지만, 서비스마다 세부적인 설정을 할 때마다 복잡성이 증가하게 된다. 예를 들어, SSL/TLS 보안 연결, 접근 도메인에 따른 라우팅 등을 구현하기 위해서는 각 서비스와 디플로이먼트에 대해서 개별적으로 설정을 해야 한다. 이와 같은 방법으로는 애플리케이션의 스케일이 커질수록 복잡성은 매우 커질 것이다.

fig02

한편, 인그레스 오브젝트를 사용하면 서비스의 URL마다 따로따로 접근할 필요 없이, 하나의 인그레스 URL 엔드포인트를 사용하여 복잡성을 줄일 수 있다. 즉, 클라이언트는 인그레스의 URL로만 접근하게 되고, 요청에 따라 인그레스에 정의된 라우팅 규칙에 맞게 처리되어 적절한 디플로이먼트의 파드로 요청이 전달될 수 있는 것이다. 보안 연결 등과 같은 세부 설정 또한 서비스와 디플로이먼트가 아닌 인그레스에서 처리되기 때문에, 각 서비스와 디플로이먼트에 일일이 설정을 적용할 필요 없이 복잡한 설정들을 한번에 관리할 수 있다.


인그레스 사용 방법

인그레스를 사용하기 위해서는 다음의 순서를 따라야 한다.

  • 인그레스 컨트롤러를 생성한다.
    • 예를 들어, 공식 깃허브에서 제공되는 Nginx 인그레스 컨트롤러의 YAML 파일을 이용할 수 있다.
  • 인그레스 컨트롤러를 외부로 노출하기 위해 인그레스의 서비스를 생성한다.
    • kubectl apply -f {인그레스 컨트롤러 YAML 파일을 제공하는 경로}.yaml 명령으로 인그레스 컨트롤러를 실행한다 하더라도, 인그레스 컨트롤러 서버(e.g., Nginx)의 디플로이먼트만 생성되었을 뿐, 해당 (Nginx)서버의 파드에 접근할 수 있는 서비스가 생성된 것은 아니므로, 직접 생성해야 한다.
  • 요청 처리 규칙을 정의하는 인그레스 오브젝트를 생성한다.
    • 인그레스 오브젝트를 생성하면, 인그레스 컨트롤러는 항상 인그레스 리소스를 지켜보고 있다가 자동으로 로드해서 인그레스 컨트롤러 웹 서버(e.g., Nginx)에 적용한다. 기본적으로 모든 네임스페이스의 인그레스 리소스를 다룬다.
  • 인그레스 컨트롤러 서버로 들어온 요청은 인그레스 규칙에 따라 적절한 서비스로 전달된다.

인그레스 컨트롤러 생성의 예

예를 들어, ingress-nginx를 생성하고자 한다면, https://kubernetes.github.io/ingress-nginx/deploy/ 사이트에서 아래 명령어를 참고하여 kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml 명령어로 생성할 수 있다.

이후, 다음과 같이 ingress-nginx 네임스페이스의 디플로이먼트와 파드를 확인해보면 Nginx 웹 서버가 생성되어 있을 것이다.

1
2
3
4
5
6
7
8
9
$ kubectl get deployment -n ingress-nginx
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
ingress-nginx-controller   1/1     1            1           6m41s

$ kubectl get pods -n ingress-nginx
NAME                                       READY   STATUS      RESTARTS   AGE
ingress-nginx-admission-create-sln9j       0/1     Completed   0          6m48s
ingress-nginx-admission-patch-r7p5j        0/1     Completed   1          6m48s
ingress-nginx-controller-b4fcbcc8f-sm4qm   1/1     Running     0          6m48s

하지만 이처럼 YAML 파일을 통해 Nginx 인그레스 컨트롤러를 설치했다 하더라도, Nginx 디플로이먼트만 생성됐을 뿐, Nginx 웹 서버를 클러스터 외부로 노출하기 위한 서비스가 생성되지는 않았다. 따라서 다음 과정인 서비스를 환경에 맞게 생성해야 한다.

인그레스 컨트롤러를 노출하기 위한 서비스 생성의 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ingress-service-example.yaml

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx # ingress-nginx-controller 디플로이먼트가 위치한 ingress-nginx 네임스페이스에 서비스를 생성함
spec:
  type: NodePort # AWS, GKE 등 LoadBalancer 타입의 서비스를 사용할 수 있다면 LoadBalancer를 사용함
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
  - name: https
    port: 443
    targetPort: 443
    protocol: TCP

인그레스 컨트롤러를 노출하기 위한 서비스는 ingress-nginx-controller 디플로이먼트가 위치한 ingress-nginx 네임스페이스에 생성한다. 이 예제에서는 간단한 테스트를 위해서 NodPort 타입의 서비스를 만들었으나, LoadBalancer 타입의 서비스를 활용할 수 있는 AWS 등의 환경에서는 LoadBalancer 타입으로 서비스를 생성하여 사용한다.

이후, kubectl apply -f ingress-service-example.yaml 명령으로 서비스를 실행한다.

인그레스 오브젝트 생성의 예

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ingress-example.yaml

apiVersion: networking.k8s.io.v1beta1
kind: Ingress # 인그레스 오브젝트를 생성하므로
metadata:
  name: ingress-example

spec:
  rules:
  - host: simon.example.com # 해당 도메인 이름으로 접근하는 요청에 대해서 처리 규칙을 적용함
    http:
      paths:
      - path: /subpath # 해당 경로에 들어온 요청을 backend에 정의된 서비스로 전달함
        backend:
          serviceName: hostname-service # '/subpath' 경로로 들어온 요청을 hostname-service라는 Servce에 전달함
          servicePort: 80 # serviceName에 설정한 서비스의 포트

kubectl apply -f ingress-example.yaml 명령어를 통해, 요청을 처리하는 규칙을 정의하는 인그레스 오브젝트를 생성할 수 있다. 이후, 인그레스 컨트롤러가 인그레스 오브젝트를 발견하여 규칙을 적용한다.

참고로 위 예제에서는 simon.example.com/subpath라는 요청이 있을 때, ‘hostname-service’라는 이름의 서비스로 요청을 전달한다. kubectl apply -f hostname-deployment.yamlkubectl apply -f hostname-service.yaml 명령으로 미리 파드와 서비스를 생성해두어야 한다. (이 과정은 생략)


참고 문헌

[1] Mumshad Mannambeth의 강의 : Certified Kubernetes Administrator (CKA) with Practice Tests
[2] 시작하세요! 도커/쿠버네티스 (용찬호 지음) : 시작하세요! 도커/쿠버네티스
[3] 따배쿠 강의 : 8-1 Kubernetes Ingress 개념과 Ingress Controller 설치!

This post is licensed under CC BY 4.0 by the author.