쿠버네티스 서비스 타입

xgro·2022년 7월 4일
0

Kubernetes

목록 보기
2/3
post-thumbnail

[C182] 서비스의 타입은 ClusterIP, NodePort, LoadBalancer, ExternalName 네 가지가 있습니다. 이들은 어떻게 다른가요?

📌 Publishing Services (ServiceTypes)

애플리케이션 중 일부(예: 프론트엔드)는 서비스를 클러스터 밖에 위치한 외부 IP 주소에 노출하고 싶은 경우가 있을 것이다.

쿠버네티스 ServiceTypes는 원하는 서비스 종류를 지정할 수 있도록 해준다. 기본 값은 ClusterIP이다.

📌 Type 값과 그 동작은 다음과 같다.

  • ClusterIP:
    (Default)service type 서비스를 클러스터-내부 IP에 노출시킨다.
    이 값을 선택하면 클러스터 내에서만 서비스에 도달할 수 있다.
    이것은 ServiceTypes의 기본 값이다

  • NodePort:
    고정 포트 (NodePort)로 각 노드의 IP에 서비스를 노출시킨다.
    NodePort 서비스가 라우팅되는 ClusterIP 서비스가 자동으로 생성된다. 
    <NodeIP>:<NodePort>를 요청하여, 클러스터 외부에서 NodePort 서비스에 접속할 수 있다.

  • LoadBalancer:
    클라우드 공급자의 로드 밸런서를 사용하여 서비스를 외부에 노출시킨다.
    외부 로드 밸런서가 라우팅되는 NodePort와 ClusterIP 서비스가 자동으로 생성된다.
  • ExternalName:
    값과 함께 CNAME 레코드를 리턴하여, 서비스를 externalName 필드의 콘텐츠 (예:foo.bar.example.com)에 매핑한다. 어떤 종류의 프록시도 설정되어 있지 않다.

참고: 
ExternalName 유형을 사용하려면 kube-dns 버전 1.7 또는 CoreDNS 버전 1.7 이상이 필요하다.

인그레스를 사용하여 서비스를 노출시킬 수도 있다.

인그레스는 서비스 유형이 아니지만, 클러스터의 진입점 역할을 한다.

동일한 IP 주소로 여러 서비스를 노출시킬 수 있기 때문에 라우팅 규칙을 단일 리소스로 통합할 수 있다.

👉 ClusterIP

(Default)service type

서비스를 클러스터-내부 IP에 노출시킨다.

이 값을 선택하면 클러스터 내에서만 서비스에 도달할 수 있다.

이것은 ServiceTypes의 기본 값이다.

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

👉 NodePort

type 필드를 NodePort로 설정하면, 쿠버네티스 컨트롤 플레인은 --service-node-port-range 플래그로 지정된 범위에서 포트를 할당한다 (기본값 : 30000-32767).

각 노드는 해당 포트 (모든 노드에서 동일한 포트 번호)를 서비스로 프록시한다.

서비스는 할당된 포트를 .spec.ports[*].nodePort 필드에 나타낸다.

포트를 프록시하기 위해 특정 IP를 지정하려면, kube-proxy에 대한 --nodeport-addresses 플래그 또는 kube-proxy 구성 파일의 동등한 nodePortAddresses 필드를 특정 IP 블록으로 설정할 수 있다.

이 플래그는 쉼표로 구분된 IP 블록 목록(예: 10.0.0.0/8192.0.2.0/25)을 사용하여 kube-proxy가 로컬 노드로 고려해야 하는 IP 주소 범위를 지정한다.

예를 들어, --nodeport-addresses=127.0.0.0/8 플래그로 kube-proxy를 시작하면, kube-proxy는 NodePort 서비스에 대하여 루프백(loopback) 인터페이스만 선택한다. 

--nodeport-addresses의 기본 값은 비어있는 목록이다.

이것은 kube-proxy가 NodePort에 대해 사용 가능한 모든 네트워크 인터페이스를 고려해야 한다는 것을 의미한다. (이는 이전 쿠버네티스 릴리스와도 호환된다).

특정 포트 번호를 원한다면, nodePort 필드에 값을 지정할 수 있다.

컨트롤 플레인은 해당 포트를 할당하거나 API 트랜잭션이 실패했다고 보고한다.

이는 사용자 스스로 포트 충돌의 가능성을 고려해야 한다는 의미이다. 또한 NodePort 사용을 위해 구성된 범위 내에 있는, 유효한 포트 번호를 사용해야 한다.

NodePort를 사용하면 자유롭게 자체 로드 밸런싱 솔루션을 설정하거나, 쿠버네티스가 완벽하게 지원하지 않는 환경을 구성하거나, 하나 이상의 노드 IP를 직접 노출시킬 수 있다.

이 서비스는 <NodeIP>:spec.ports[*].nodePort와 .spec.clusterIP:spec.ports[*].port로 표기된다. kube-proxy에 대한 --nodeport-addresses 플래그 또는 kube-proxy 구성 파일의 동등한 필드가 설정된 경우, <NodeIP> 는 노드 IP를 필터링한다.

예를 들면

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: NodePort
  selector:
    app: MyApp
  ports:
      *# 기본적으로 그리고 편의상 `targetPort` 는 `port` 필드와 동일한 값으로 설정된다.*
    - port: 80
      targetPort: 80
      *# 선택적 필드
			# 기본적으로 그리고 편의상 쿠버네티스 컨트롤 플레인은 포트 범위에서 할당한다
			# (기본값: 30000-32767)*
			nodePort: 30007

👉 Loadbalancer

외부 로드 밸런서를 지원하는 클라우드 공급자 상에서, type 필드를 LoadBalancer로 설정하면 서비스에 대한 로드 밸런서를 프로비저닝한다.

로드 밸런서의 실제 생성은 비동기적으로 수행되고, 프로비저닝된 밸런서에 대한 정보는 서비스의 .status.loadBalancer 필드에 발행된다.

예를 들면

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  clusterIP: 10.0.171.239
  type: LoadBalancer
status:
  loadBalancer:
    ingress:
    - ip: 192.0.2.127

외부 로드 밸런서의 트래픽은 백엔드 파드로 전달된다.

클라우드 공급자는 로드 밸런싱 방식을 결정한다.

일부 클라우드 공급자는 loadBalancerIP를 지정할 수 있도록 허용한다.

이 경우, 로드 밸런서는 사용자 지정 loadBalancerIP로 생성된다. 

loadBalancerIP 필드가 지정되지 않으면, 임시 IP 주소로 loadBalancer가 설정된다. 

loadBalancerIP를 지정했지만 클라우드 공급자가 이 기능을 지원하지 않는 경우, 설정한 loadbalancerIP 필드는 무시된다.

👉 ExternalName

ExternalName 유형의 서비스는 my-service 또는 cassandra와 같은 일반적인 셀렉터에 대한 서비스가 아닌, DNS 이름에 대한 서비스에 매핑한다. spec.externalName 파라미터를 사용하여 이러한 서비스를 지정한다.

예를 들면, 이 서비스 정의는 prod 네임 스페이스의 my-service 서비스를 my.database.example.com에 매핑한다.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

참고: 
ExternalName은 IPv4 주소 문자열을 허용하지만, IP 주소가 아닌 숫자로 구성된 DNS 이름을 허용한다. IPv4 주소와 유사한 ExternalName은 CoreDNS 또는 ingress-nginx에 의해 확인되지 않는데, ExternalName은 정식(canonical) DNS 이름을 지정하기 때문이다. IP 주소를 하드 코딩하려면, 헤드리스(headless) 서비스 사용을 고려한다.

my-service.prod.svc.cluster.local 호스트를 검색하면, 클러스터 DNS 서비스는 my.database.example.com 값의 CNAME 레코드를 반환한다. my-service에 접근하는 것은 다른 서비스와 같은 방식으로 작동하지만, 리다이렉션은 프록시 또는 포워딩을 통하지 않고 DNS 수준에서 발생한다는 중요한 차이점이 있다. 나중에 데이터베이스를 클러스터로 이동하기로 결정한 경우, 해당 파드를 시작하고 적절한 셀렉터 또는 엔드포인트를 추가하고, 서비스의 유형(type)을 변경할 수 있다.

👉 External IP

하나 이상의 클러스터 노드로 라우팅되는 외부 IP가 있는 경우, 쿠버네티스 서비스는 이러한 externalIPs에 노출될 수 있다. 서비스 포트에서 외부 IP (목적지 IP)를 사용하여 클러스터로 들어오는 트래픽은 서비스 엔드포인트 중 하나로 라우팅된다. externalIPs는 쿠버네티스에 의해 관리되지 않으며 클러스터 관리자에게 책임이 있다.

서비스 명세에서, externalIPs는 모든 ServiceTypes와 함께 지정할 수 있다. 아래 예에서, 클라이언트는 "80.11.12.10:80"(외부 IP:포트)로 "my-service"에 접근할 수 있다.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9376
  externalIPs:
    - 80.11.12.10

✅ 참조 레퍼런스

https://kubernetes.io/docs/concepts/services-networking/service/#externalname

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

profile
안녕하세요! DevOps 엔지니어 이재찬입니다. 블로그에 대한 피드백은 언제나 환영합니다! 기술, 개발, 운영에 관한 다양한 주제로 함께 나누며, 더 나은 협업과 효율적인 개발 환경을 만드는 과정에 대해 인사이트를 나누고 싶습니다. 함께 여행하는 기분으로, 즐겁게 읽어주시면 감사하겠습니다! 🚀

0개의 댓글