본문 바로가기
Container/Kubernetes

[k8s] 쿠버네티스 애플리케이션 접근 구성하기: NodePort, Ingress, Istio

by wrynn 2022. 5. 21.

 쿠버네티스 클러스터를 구축할 때, 애플리케이션을 외부 사용자가 접근 가능하도록 구성하는 방법에는 여러가지가 있습니다. 이번 시간에는 NodePort, Ingress, Istio 각각의 방법을 하나씩 차례로 살펴보겠습니다.

  • NodePort 및 LoadBalancer (쿠버네티스 Service)
  • Ingress
  • Istio

NodePort

 NodePort 타입의 Service를 생성하면 쿠버네티스는 클러스터의 모든 노드에 포트를 하나 할당합니다.(기본값: 30000-32767) 그리고 해당 포트로 들어오는 요청을 특정 애플리케이션으로 전달합니다. 

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: MyApp
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30000

 예를 들어 쿠버네티스 워커 노드 중 하나의 IP가 10.2.3.45이고, 위 예제처럼 30000번 포트를 사용하는 NodePort Service가 생성되었다면 외부 사용자는 10.2.3.45:30000으로 접속하여 애플리케이션 컨테이너의 80포트에 접근할 수 있습니다.

NodePort의 문제점

 NodePort를 사용하여 애플리케이션에 접근하도록 구성할 경우 몇가지 단점이 존재합니다.

  • 우선 외부 사용자가 10.2.3.45:30000으로 접속해야 한다는 것이 문제입니다. 30000은 웹 서비스를 위한 표준 포트 번호가 아닙니다. 또한 포트별로 다른 애플리케이션을 제공하는 것이 사용자들에게는 혼란스러울 수 있습니다.
  • 각 서비스당 하나의 포트를 사용합니다. 서비스의 숫자가 작을 때에는 문제가 되지 않지만 그 수가 늘어날수록 포트는 부족하게 됩니다.

 

Ingress

 NodePort와는 달리 Ingress를 사용하면 노드에 포트를 하나만 사용할 수 있습니다. 쿠버네티스에서 Ingress는 클러스터 내의 서비스에 대한 외부 접근을 관리하는 오브젝트입니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-ingress
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: bar.foo.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service2
            port:
              number: 80

 Ingress는 단지 트래픽을 어떤 서비스에 보낼 지에 대한 규칙을 정의합니다. 실제로 노드의 특정 포트로 유입되는 트래픽을 수신하는 컴포넌트는 Pod 형태로 실행되는 Ingress controller이며, 이 Ingress controller가 Ingress에 명시된 라우팅 규칙을 참조하여 주어진 트래픽을 어떤 서비스로 전달할지 결정합니다.

 따라서 Ingress를 사용하려면 클러스터에는 반드시 Ingress controller가 실행 중이어야 합니다. 하지만 Ingress controller는 컨트롤 플레인에 의해 자동으로 실행되지 않으므로, Ingress를 사용하기 위해서는 별도로 Ingress controller를 실행시켜 주어야 합니다. 쿠버네티스에서 사용 가능한 Ingress controller 목록은 여기를 참고해주세요.

Ingress의 장점

 운영 환경에서는 노드를 하나만 사용하는 것이 아니므로 로드밸런서를 노드 그룹 앞에 위치시키는 것이 일반적입니다. 로드밸런서와 함께 Ingress를 사용하도록 구성하면 단일 로드밸런서를 진입점으로 하면서, Ingress의 Host 및 Path 기반 라우팅을 통해 다수의 서비스를 제공할 수 있습니다. 

Ingress 구성요소

 Ingress가 동작하기 위해서는 3가지 구성 요소가 필요합니다.

  1. 라우팅 규칙을 명시한 Ingress
  2. 실제로 트래픽 라우팅을 담당하는 Ingress controller
  3. Ingress에 일치하는 라우팅 규칙이 없는 경우를 처리하는 Default back-end Pod (HTTP 404 Not Found)

Ingress의 한계 

 Ingress를 사용하는 것이 좋은 방법이긴 합니다만, 더 많은 부가 기능을 요구하는 사용자들에게는 적합하지 않을 수도 있습니다. 다음은 Ingess를 사용하는 경우 나타날 수 있는 한계점을 보여줍니다.

  • 클러스터의 Observability를 확보하기 어렵습니다.
    Nginx Plus와 같은 구독형 서비스를 사용하면 모니터링과 관련된 확장 기능을 제공하지만 추가 비용이 발생합니다.
  • 트래픽 제어 기능이 부족합니다.
    Canary(새 버전으로 유입되는 트래픽의 비율을 서서히 늘리는 방법), Dark launch(운영 환경에 일부 사용자 대상으로만 새 버전 공개)와 같은 배포 전략을 구현하는 데 제약사항이 있습니다.
  • 서비스의 회복탄력성 관련 기능이 없습니다. 
    요청이 실패한 경우 재시도하는 Retry, 서비스가 불가능한 Pod로 보내는 트래픽을 일시적으로 차단하는 Circuit Breaker 등

 

Istio

 Istio는 Ingress의 동작방식과 유사하지만 더 확장된 기능을 제공합니다. 풍부한 트래픽 제어 기능과 회복 탄력성 관련 기능을 모두 가지고 있으며 각각의 마이크로서비스로 향하는 트래픽 흐름을 쉽게 관찰할 수 있도록 여러가지 메트릭을 제공하여 Ingress의 한계에서 나열한 문제점들을 모두 해결합니다. 어떻게 이러한 기능이 가능한걸까요? 그것을 알아 보기 전에 먼저 Ingress와 Istio의 구성요소를 공통점과 차이점 위주로 비교해보겠습니다.

 Ingress 구성에서 대표적으로 Nginx가 Ingress controller 역할을 수행한 것과 마찬가지로 Istio에서는 istio-ingressgateway라고 불리우는 Pod 내부에 포함된 고성능 프록시 컨테이너 Envoy가 쿠버네티스 클러스터 내부로 유입되는 트래픽을 가장 먼저 수신하고 각각의 서비스로 라우팅합니다. 

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-ingress
spec:
  selector:
    app: my-ingressgateway
  servers:
  - port:
      number: 80
      name: http2
      protocol: HTTP2
    hosts:
    - "*"

 Istio에서 Ingress controller에 대응하는 것이 istio-ingressgateway라면, 규칙을 정의하는 Ingress에 대응하는 것은 Gateway와 Virtual Service라는 쿠버네티스 커스텀 리소스입니다. istio-ingressgateway Pod 내부의 Envoy는 Gateway와 Virtual Service에 명시된 규칙대로 트래픽을 라우팅합니다.

 여기까지만 보면 Ingress 구성요소의 이름만 바꿔놓은 것처럼 보입니다. 하지만 Istio와 Ingress의 가장 큰 차이점은 Back-end Pod에 있습니다. Istio는 Back-end Pod에 Envoy 프록시 컨테이너를 하나 더 주입합니다.(!!!) 이렇게 함으로써 Istio는 Back-end로 유입되는 트래픽을 항상 Envoy 프록시 컨테이너를 통해서만 전달합니다. 그렇기 때문에 약간의 오버헤드를 희생하여 풍부한 트래픽 관리 기능을 지원할 수 있습니다. istio에서 사용하는 모든 프록시 컨테이너들의 집합을 Data Plane이라고 부릅니다. 

Istio 구성요소

 Istio가 동작하기 위한 3가지 구성 요소가 있습니다. (Destination Rule 등 세부 설정은 여기서는 다루지 않겠습니다.)

  1. 수신할 포트, 호스트명, 프로토콜, 인증서 등을 정의하는 Gateway 
  2. Gateway에서 수신한 트래픽의 라우팅 규칙을 지정하는 Virtual Service (Ingress와 유사하나 더 풍부한 기능 제공)
  3. Envoy 컨테이너로 구성되어 실제 트래픽 라우팅을 수행하는 Ingressgateway (Ingress controller와 유사)

 트래픽을 주고 받는데에는 위 3가지 구성 요소면 충분하지만, 실제로는 각각의 Envoy 프록시 컨테이너를 관리하는 컴포넌트가 추가로 필요합니다. 이 컴포넌트를 istiod라고 부르고 이들 집합을 Control Plane이라고 합니다. istiod는 라우팅 규칙과 Data Plane의 변경 사항을 감지하고 각각의 Envoy 프록시가 이를 반영하도록 도와줍니다.

Istio의 장점

  • L7 트래픽을 다룰 수 있습니다. Nginx도 마찬가지이지만, Envoy는 더 많은 기능을 제공합니다.
    (비율 기반 트래픽 라우팅, Circuit Breaker, Pod로 향하는 트래픽의 로드밸런싱 설정 등)
  • Gateway, Virtual Service 등의 설정값이 바뀌더라도 Envoy를 다시 시작할 필요가 없습니다. Envoy는 Hot reload 기능을 포함하고 있어 동적으로 변경된 설정값을 반영합니다. 컨테이너를 다시 시작할 필요가 없으므로 트래픽이 유실되거나 성능이 일시적으로 저하되는 상황을 미리 방지합니다.
  • Egress gateway를 사용할 수 있습니다. Inbound 트래픽 뿐만 아니라 Outbound 트래픽에 대한 제어도 가능합니다.

Istio의 단점

  • 각각의 Envoy Proxy를 관리하기 위한 Control Plane 컴포넌트(Pilot)가 별도로 필요합니다.
  • Istio는 클러스터 내부 통신에 사용되는 트래픽 관리(east-west traffic)를 위한 것이므로 외부와의 통신에 사용되는 트래픽(north-south traffic)을 관리하기 위해서는 istio의 Service Entry를 사용하거나, 별도의 노력이 필요합니다.

 


참고자료

[1] https://www.mirantis.com/blog/your-app-deserves-more-than-kubernetes-ingress-kubernetes-ingress-vs-istio-gateway-webinar/

[2] https://kubernetes.io/docs/concepts/services-networking/ingress/

 

Ingress

FEATURE STATE: Kubernetes v1.19 [stable] An API object that manages external access to the services in a cluster, typically HTTP. Ingress may provide load balancing, SSL termination and name-based virtual hosting. Terminology For clarity, this guide define

kubernetes.io

 

댓글