쿠버네티스 - 서비스(ClusterIP, NodePort, LoadBalancer)와 인그레스

Hoonkii·2022년 1월 9일
1
post-custom-banner

오늘은 쿠버네티스의 서비스에 대해서 정리해보겠다. 입사 초반에 도커파일의 빌드 시간 단축 태스크를 진행하였는데, 도커파일 빌드를 로컬 컴퓨터에서 이리 저리 시도하기에는 너무 느려서 클라우드 컴퓨팅 환경에서 테스트 해보고 싶었다.
마침 사내에서 다른 동료 개발자들이 스테이징에 코드를 올리기 전, 클라우드 환경에서 미리 테스트를 하고 싶은 needs가 있었기 때문에 인프라 공부 겸 dev환경을 구축하기로 마음먹었었다.

우리 서비스는 쿠버네티스를 통해 머신러닝 서버와 웹 백엔드 서버들의 클러스터를 관리하고 있었는데 이를 최소한의 컴퓨팅 자원으로 dev환경을 구축하고자 하였다.

당시 쿠버네티스를 처음 공부하고 다루면서 이해하기 어려웠던 부분이 서비스와 인그레스여서 관련된 내용을 정리해보고자 한다.

서비스란?

서비스는 pod 집합에서 실행 중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법이다.

즉 특정 pod들의 집합을 클러스터 내 다른 pod들 혹은 외부 서비스에 어떻게 노출할 것인지를 정의한 추상화 방법이라고 생각하면 된다.

쿠버네티스에서의 pod은 영구적이지 않다. 종종 소멸되거나 복구되며, pod들은 고유한 IP 주소를 가지긴 하지만 이는 동적으로 변경된다. 이런 환경 속에서 다른 서비스가 이 pod 집합들과 통신하려면 일반적으로는 서비스 디스커버리 메커니즘이 필요하다. 그러나 서비스 디스커버리 메커니즘을 사용하려면 애플리케이션을 수정해야 하는 경우가 있는데, 쿠버네티스에서는 서비스라는 개념을 통해 팟에게 고유한 IP 주소와 집합에 대한 단일 DNS 명을 부여하고 레플리카들에게 알아서 로드밸런싱을 수행해준다. (굉장하다.)

예를 들어보자. 클러스터 내 프론트앤드와 백엔드 서버가 있다고 가정하자. 백엔드는 고 가용성을 위해 여러 개의 레플리카들로 관리된다. 만약에 프론트엔드가 백엔드와 통신하려고 하면 “서비스”라는 개념 없이는 실제 IP 주소를 추적해야 한다. 그러나 쿠버네티스에서 제공하는 서비스라는 추상화 개념을 이용하면, 백엔드 파트의 실제 IP 주소를 추적할 필요 없이 등록된 내부 DNS 주소를 통해 통신이 가능하다.

서비스 종류

서비스의 종류에는 3가지가 존재한다.

  • Cluster IP

Cluster IP는 클러스터 안에 있는 다른 Pod들이 접근할 수 있도록 IP를 할당한다. 내부 IP만을 할당하기 때문에 클러스터 외부에서는 접근이 불가능하다.

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

Cluster IP에 대한 그림을 보면 이해가 쉽다 아래 그림을 보자.

Pod들은 K8s 클러스터 내 존재하고 Cluster IP Service는 해당 Pod들에게 트래픽을 로드밸런싱 한다. Cluster IP는 클러스터 내부에서만 유효하며, 클러스터 외부와의 통신을 위해서는 NodePort나 LoadBalancer 서비스가 필요하다.

  • NodePort

NodePort는 고정 포트로 Pod이 배포된 노드들의 IP에 서비스를 노출시킨다. NodePort 서비스는 ClusterIP 서비스를 자동으로 생성한다. NodeIP:NodePort를 요청하여 클러스터 외부에서 NodePort 서비스에 접근할 수 있다. 다음 그림을 보자.

실제 VM 노드의 특정 Port를 뚫어놓는다. VM의 IP주소와 개방된 Port를 통해 Pod에 접근할 수 있다.

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

여기서 port, targetPort, nodePort 세 가지 개념이 나오는데 nodePort는 실제 VM 노드에 접근할 때 사용되는 port, port 서비스의 포트, 마지막으로 targetPort는 Pod에 접근할 때 사용하는 포트이다. 트래픽이 오게되면 흐름상 nodePort -> port -> targetPort로 전달된다.

NodePort는 노드의 개방된 Port로 네트워크 접근을 허용할 수 있지만, 실제 분산 노드 애플리케이션을 구현한다고 가정했을 때 auto scaling의 이유로 노드들의 네트워크 환경이 동적으로 변경된다면, 서비스 디스커버리와 같은 방법으로 클라이언트 단에서 노드들의 네트워크 엔드포인트들을 관리해야한다는 문제가 생긴다.

이를 해결할 수 있는 것이 로드밸런서이다.

  • LoadBalancer

로드 밸런서는 서비스를 외부에 노출시키는 표준 방법이다. 로드밸런서는 따로 물리 장비(컴퓨터)가 필요한데, 클라우드 컴퓨팅 환경에서는 벤더사가 제공하는 로드밸런서를 사용하면 된다.


위 그림에서는 NodePort개념이 그려져있지는 않지만, 실제로는 LoadBalancer가 분산 Node들에 정의된 NodePort를 통해 로드밸런싱을 한 후 서비스가 Pod들 사이에서 로드밸런싱을 수행한다.


Ingress

만약에 다양한 서비스들이 존재하는 마이크로서비스 환경에서(여기서 서비스는 쿠버네티스 서비스를 의미하는 것이 아니다.)는 서비스마다 로드밸런서를 정의해야할까? 로드밸런서가 여러 개면 비용이 많이 들기 때문에, 하나의 로드밸런서를 통해 특정 url을 기반으로 다른 성격의 서비스들을 라우팅하고 싶으면 어떻게 할까? 이럴 때 사용하는 것이 K8s의 Ingress이다.
Ingress는 쿠버네티스의 서비스 종류 중 하나가 아닌, 서비스들을 묶는 하나의 스마트 라우터 역할을 수행한다. 즉 하나의 LoadBalancer에서 여러 서비스를 노출할 수 없는 한계를 해결하는 것이 Ingress이다.


잡담..

쿠버네티스에 대해 공부하면서 구글에서 정말 대단한걸 만들었구나 라는 생각이 든다. 구글에서 몇년간 프로덕션 워크로드를 운영하면서 불편했던 점들을 해결하는 툴을 만들고 그걸 오픈소스화 해서 다른 개발자들이 유용하게 사용할 수 있게 한 것은 정말 대단한 것 같다.. (오픈소스 정말 감사합니다...돈 받고 팔았어도 샀을건데..!!!)

쿠버네티스에 대해 좀 더 공부하여 효율적이고 안정적인 시스템을 구축하는 방법을 더 모색해보고 싶다.

참고자료

profile
개발 공부 내용 정리
post-custom-banner

0개의 댓글