본문 바로가기

엔지니어링(TA, AA, SA)/DevOps

[k8s] Kubernetes NodePort vs LoadBalancer vs Ingress?

https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0

 

Kubernetes NodePort vs LoadBalancer vs Ingress? When should I use what?

Recently, someone asked me what the difference between NodePorts, LoadBalancers, and Ingress were. They are all different ways to get…

medium.com

 

NodePorts, LoadBalancers, Ingress 는 모두 외부 트래픽을 클러스터로 가져오는 방법이지만, 각각 다른 방식으로 이를 수행한다. 각 방법이 어떻게 작동하는지, 언제 사용해야 하는지 살펴보겠다.

 

참고: 여기서 설명하는 모든 내용은 Google Kubernetes Engine에 적용된다. 다른 클라우드, 온프레미스, minikube 또는 다른 환경에서 실행 중인 경우, 약간의 차이가 있을 수 있다. 깊이 있는 기술적 세부사항은 다루지 않는다.


ClusterIP

ClusterIP 서비스는 기본 Kubernetes 서비스입니다. 클러스터 내에서 다른 앱이 접근할 수 있는 서비스를 제공한다. 외부 접근은 불가능하다.

 

ClusterIP 서비스의 YAML은 다음과 같다:

apiVersion: v1
kind: Service
metadata:
  name: my-internal-service
spec:
  selector:
    app: my-app
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP

 

ClusterIP 서비스를 인터넷에서 접근할 수 없는데 왜 다루는걸까? Kubernetes 프록시를 사용하면 접근할 수 있기 때문이다.

kubernetes proxy 시작:

$ kubectl proxy --port=8080

 

이제 다음 스킴을 사용하여 Kubernetes API를 통해 이 서비스에 접근할 수 있다:

http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/

 

따라서 위에서 정의한 서비스에 접근하려면 다음 주소를 사용할 수 있다:

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

 

언제 사용할까? Kubernetes 프록시를 사용하여 서비스를 접근할 몇가지 시나리오가 있다.

- 서비스를 디버깅하거나, 어떤 이유로 직접 노트북에서 연결할때

- 내부 트래픽을 허용하거나, 내부 대시보드를 표시할 때 등

- 이 방법은 인증된 사용자로 kubectl을 실행해야 하므로, 이 방법을 사용하여 서비스를 인터넷에 노출하거나 프로덕션 서비스에 사용해서는 안된다.


NodePort

NodePort 서비스는 외부 트래픽을 서비스로 직접 가져오는 가장 원시적인 방법이다. 이름에서 알 수 있듯이, NodePort는 모든 노드(VM)에서 특정 포트를 열고, 이 포트로 전송된 모든 트래픽은 서비스로 전달된다.

이것은 기술적으로 가장 정확한 다이어그램은 아니지만, NodePort가 어떻게 작동하는지 잘 설명한다고 생각한다.

 

NodePort 서비스의 YAML은 다음과 같다:

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  selector:
    app: my-app
  type: NodePort
  ports:
  - name: http
    port: 80
    targetPort: 80
    nodePort: 30036
    protocol: TCP

 

기본적으로 NodePort 서비스는 일반 "ClusterIP" 서비스와 두가지 차이점이 있다. 첫째, type이 "NodePort"이다. 또한, 노드에서 열 포트를 지정하는 추가 포트인 nodePort가 있다. 이 포트를 지정하지 않으면 임의의 포트를 선택한다. 대부분의 경우 kubernetes가 포트를 선택하도록 해야 한다. thockin이 말했듯이, 사용할 수 있는 포트에는 많은 주의사항이 있다.

 

언제 사용해야 할까? 이 방법에는 많은 단점이 있다:

- 포트당 하나의 서비스만 가질 수 있다.

- 30000-32767 포트만 사용할 수 있다.

- 노드/VM IP 주소가 변경되면 이를 처리해야 한다.

 

이러한 이유로, 프로덕션에서 이 방법을 사용하여 서비스를 직접 노출하는 것을 권장하지 않는다. 항상 사용 가능할 필요가 없는 서비스를 실행하거나 비용에 민감한 경우 이 방법이 적합하다. 예로는 데모앱이나 임시 애플리케이션이 있다.


LoadBalancer

LoadBalancer 서비스는 인터넷에 서비스를 노출하는 표준 방법이다. GKE에서는 네트워크 로드 밸런서를 생성하여 모든 트래픽을 서비스로 전달하는 단일 IP 주소를 제공한다.

actual traffic chain: traffic -> Load Balancer -> Node+Port -> Service cluster ip -> IPVS -> Pod

 

서비스를 직접 노출하려고할때의 기본 방법이다. 지정한 포트의 모든 트래픽이 서비스로 전달된다. 필터링, 라우팅 등이 없고, HTTP, TCP, UDP, Websockets, gRPC 등 거의 모든 종류의 트래픽을 보낼 수 있다.

 

큰 단점은 LoadBalancer로 노출된 각 서비스가 자체 IP 주소를 갖게 되며, 노출된 서비스당 LoadBalancer 비용을 지불해야 하므로 비용이 많이 들수 있다는 것이다.


Ingress

위의 모든 예와 달리, Ingress는 실제로 서비스 유형이 아니다. 대신 여러 서비스 앞에 위치하여 클러스터로 들어가는 "스마트 라우터" 또는 진입점 역할을 한다.

 

Ingress로 다양한 작업을 수행할 수 있으며, 다양한 기능을 가진 여러 유형의 Ingress 컨트롤러가 있다.

 

기본 GKE Ingress 컨트롤러는 HTTP(S) 로드 밸런서를 생성한다. 이를 통해 백엔드 서비스로의 경로 기반 및 서브도메인 기반 라우팅을 수행할 수 있다. 예를 들어, foo.yourdomain.com 의 모든 트래픽을 foo 서비스로 보내고, yourdomain.com/bar/ 경로 아래의 모든 트래픽을 bar 서비스로 보낼 수 있다.

 

L7 HTTP 로드밸런서를 사용하는 GKE의 Ingress 객체 YAML은 다음과 같다:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: other
    servicePort: 8080
  rules:
  - host: foo.mydomain.com
    http:
      paths:
      - backend:
          serviceName: foo
          servicePort: 8080
  - host: mydomain.
    http:
      paths:
      - path: /bar/*
        backend:
          serviceName: bar
          servicePort: 8080

 

Ingress는 아마도 서비스를 노출하는 가장 강력한 방법이지만, 가장 복잡할 수도 있다. Google Cloud Load Balancer, Nginx, Contour, Istio 등 다양한 유형의 Ingress 컨트롤러가 있다. 또한, cert-manager와 같은 Ingress 컨트롤러 플러그인이 있어 서비스에 대한 SSL 인증서를 자동으로 발급할 수 있다.

 

Ingress는 동일한 IP 주소 아래 여러 서비스를 노출하려는 경우 가장 유용하며, 이들 서비스가 모두 동일한 L7 프로토콜(일반적으로 HTTP)을 사용하는 경우에 유용하다. 네이티브 GCP 통합을 사용하는 경우 하나의 로드 밸런서에 대해서만 비용을 지불하며, Ingress가 "스마트"하기 때문에 많은 기능(SSL, 인증, 라우팅 등)을 기본으로 제공한다.