본문 바로가기
Cloud/Kubernates

Service

by 민휘 2023. 10. 29.

서비스

 

서비스

외부와 접하는 단일 엔드포인트 뒤에 있는 클러스터에서 실행되는 애플리케이션을 노출시키며, 이는 워크로드가 여러 백엔드로 나뉘어 있는 경우에도 가능하다.

kubernetes.io

 

서비스 소개

🌱 서비스란?

  • 디플로이먼트의 파드를 연결하고 포트를 외부에 노출하는 오브젝트
  • 파드의 논리적 집합과 그것들에 접근할 수 있는 정책을 정의하는 추상적 개념
  • 서비스 추상화의 Decoupling : 백엔드 세트를 구성하는 파드가 프론트엔드 세트를 구성하는 파드에 기능을 제공하는 상황을 가정해보자. 백엔드 세트를 구성하는 실제 파드는 변경될 수 있지만, 프론트엔드 클라이언트는 이를 인식할 필요 없이 의존성을 유지할 수 있다. (이거 의존성주입 아녀~)

 

🌱 서비스의 기능

  • 여러개의 파드에 쉽게 접근할 수 있도록 고유한 도메인 부여
  • 여러 파드에 접근할 때, 요청을 분산하는 로드 밸런서 기능 수행
  • 클라우드 플랫폼의 로드 밸런서, 클러스터 노드 등을 통해 파드를 외부로 노출

 

🌱 서비스의 종류

  • 서비스의 종류에 따라 파드에 접근할 수 있는 방법이 달라짐
  • ClusterIp : 쿠버네티스 내부에서만 파드들에 접근할 때 사용
  • NodePort : 포트를 클러스터의 모든 노드에 개방하여 외부에서 파드에 접근 가능
  • LoadBalancer : 클라우드 플랫폼이 제공하는 로드 밸런서를 동적으로 프로비저닝해 파드에 연결하여 외부 개방, 실제 운영 환경에서 사용

 

ClusterIP : 내부 파드 연결

 

🌱 yaml 파일

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-clusterip
spec:
  ports:
    - name: web-port
      port: 8080
      targetPort: 80
  selector:
    app: webserver
  type: ClusterIP
  • spec.selector : 이 서비스를 통해 접근 가능한 파드를 선택
  • spec.ports.port : 서비스가 받는 내부 IP로 개방할 포트
  • spec.ports.targetPort : 연결된 파드가 내부적으로 사용하는 포트

 

🌱 서비스 생성하고 내부 접속 테스트

  • 서비스 생성 : kubectl apply -f hostname-svc-clusterip.yaml
  • 서비스 목록 확인 : kubectl get services
NAME                     TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
**hostname-svc-clusterip   ClusterIP   10.8.5.213   <none>        8080/TCP   12s**
kubernetes               ClusterIP   10.8.0.1     <none>        443/TCP    36h

 

  • 임시 파드 생성 : kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
    • 서비스 IP와 포트로 파드에 요청 전송 : curl 10.8.5.213:8080 --silent | grep Hello
    • 서비스 이름으로 요청 전송(일반적) : curl hostname-svc-clusterip:8080 --silent | grep Hello
    • 서비스와 연결된 여러 파드에 자동으로 요청이 분산된다

클러스터 내부에서 파드끼리 요청과 응답을 주고 받을 때는 ClusterIP 타입의 서비스가 이들을 중개한다. 같은 클러스터 안의 어떤 파드가 다른 파드를 연결하는 서비스의 내부 IP와 개방 포트로 요청을 보내면, 내부적으로 로드 밸런싱을 수행해서 응답을 처리한다.

 

NodePort

모든 노드의 동일한 포트를 개방한다. 외부에서는 노드 IP와 포트로 요청을 보낸다.

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-nodeport
spec:
  ports:
    - name: web-port
      port: 8080
      targetPort: 80
  selector:
    app: webserver
  type: NodePort
  • spec.ports.port : 서비스가 받는 내부 IP로 개방할 포트
  • 노드의 포트는 랜덤으로 선택된다

 

🌱 노드의 포트 개방

NodePort 타입 서비스를 만들면 모든 노드에서 동일하게 접근할 수 있는 포트를 개방한다. 이때 포트는 랜덤하게 선택되었는데, 확인해보니 30144번이 개방되었다. 따라서 모든 노드에 대해 내부 IP 혹은 외부 IP의 30144번을 통해 파드에 접근할 수 있다.

  • 임시 파드 생성 : kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
  • 요청 : curl 10.128.0.4:**30144** --slient | grep Hello
  • GKE 방화별 설정 추가 : gcloud compute firewall-rules create temp-nodeport-svc --allow=tcp:32765

 

🌱 ClusterIP도 포함

NodePort 타입 서비스는 ClusterIP의 기능을 포함하고 있어서, NodePort로 만들면 서비스 내부 네트워크와 외부 네트워크 양쪽에서 접근할 수 있다.

 

LoadBalancer

서비스 생성과 함께 로드밸런서를 생성하여 파드와 연결한다. 모든 노드의 동일한 포트를 개방한다.

외부에서는 로드밸런서의 IP로 요청을 보낸다.

apiVersion: v1
kind: Service
metadata:
  name: hostname-svc-nodeport
spec:
  ports:
    - name: web-port
      port: 80
      targetPort: 80
  selector:
    app: webserver
  type: LoadBalancer
  • spec.port : 로드 밸런서에 접근하기 위한 포트

 

🌱 로드밸런서의 IP와 포트로 파드 접근

  • 서비스 생성과 동시에 로드 밸런서를 새롭게 생성해 파드와 연결한다.
  • IP 확인 : kubectl get services → 34.171.151.96:80
NAME                     TYPE           CLUSTER-IP   EXTERNAL-IP     PORT(S)        AGE
hostname-svc-nodeport    LoadBalancer   10.8.13.76   **34.171.151.96**   80:30144/TCP   19m
  • 로드밸런서에 요청 보내기 : curl 34.171.151.96:80 --silent | grep Hello
minhwi@minhwiui-MacBookPro  ~/kubernetes/chap6  curl 34.171.151.96:80 --silent | grep Hello
<p>Hello,  hostname-deployment-**9664ffd7f-9958g**</p>	</blockquote>
 minhwi@minhwiui-MacBookPro  ~/kubernetes/chap6  curl 34.171.151.96:80 --silent | grep Hello
<p>Hello,  hostname-deployment-**9664ffd7f-plskp**</p>	</blockquote>
 minhwi@minhwiui-MacBookPro  ~/kubernetes/chap6  curl 34.171.151.96:80 --silent | grep Hello
<p>Hello,  hostname-deployment-9664ffd7f-9958g</p>	</blockquote>


🌱 NodePort의 간접적인 사용

로드밸런서를 연결하더라도 모든 노드에 대해 동일한 포트가 연결되기 때문에 NodePort 기능을 사용할 수 있다. 위의 출력 결과에서 본 대로 30144번 포트로 접근할 수 있다.

  • 임시 파드 생성 : kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
  • 요청 : curl 10.128.0.4:30144 --slient | grep Hello

 

LoadBalancer : externalTrafficPolicy 옵션

로드 밸런서 타입 서비스를 사용할 때 externalTrafficPolicy 옵션을 선택할 수 있다. externalTrafficPolicy는 어떤 노드의 포트를 개방할지 결정한다. 위에서 사용한 예제는 디폴트 옵션인 Cluster을 사용하여 모든 노드의 랜덤 포트를 개방한다.

🌱 externalTrafficPolicy 옵션

  • Cluster : 모든 워커 노드의 동일한 랜덤 포트를 개방
  • Local : 파드가 위치한 노드만 랜덤 포트 개방
kind: Service
# ..
spec:
  externalTrafficPolicy: Local # Cluster(기본값)

🌱 Cluster 설정의 한계

외부 트래픽은 노드 중 하나로 보내지고, 그 노드에서 다시 파드 중 하나로 전달된다. 모든 노드의 랜덤 포트를 개방하면 노드에서 파드를 선택하는 과정에서 자신 파드가 아닌 다른 노드의 파드에 전달할 수도 있다. 이렇게 되면 불필요한 네트워크 hop이 발생하고, 클라이언트의 IP 주소가 보존되지 않는다.

 

🌱 Local 설정의 문제 해결

Local로 설정하면 파드가 위치한 노드만 랜덤한 포트를 개방한다. 로드밸런서는 파드가 위치한 노드로만 요청을 전달하고, 해당 노드 안에서만 요청이 분산된다. 따라서 네트워크 홉이 한 단계 적으며, 클라이언트 IP를 보존할 수 있다.

 

🌱 Local 설정의 한계

하지만 각 노드에 파드가 고르지 않게 스케줄링되는 경우, 요청이 고르게 분산되지 않는 문제가 있다. 즉 자원 활용률 측면에서 바람직하지 않다.

 

🌱 Cluster와 Local 중 무엇을 선택해야할까?

불필요한 네트워크 홉으로 인한 Latency나 클라이언트 IP 보존이 중요하다 → Local

그런것보다는 균등한 트래픽 분배가 더 중요하다 → Cluster

 

 

서비스 타입의 비교

 

🌱 참고 : ClusterIP, NodePort, LoadBalancer, Ingress의 비교

 

[발번역] Kubernetes NodePort vs LoadBalancer vs Ingress?? 언제 무엇을 써야 할까??

본 글은 아래 글을 발번역 한 내용입니다. 누락되거나 잘못 옮겨진 내용이 있을(아니 많을;;) 수 있습니다. 어색하거나 잘못된 표현은 알려주세요. 원글: Kubernetes NodePort vs LoadBalancer vs Ingress? When s

blog.leocat.kr

 

 

 

 

 

 

ExternalName

쿠버네티스를 외부 시스템과 연동해야할 때 ExternalName 타입의 서비스를 사용한다.

서비스가 외부 도메인을 가리키도록 설정한다. 서비스에 이름을 부여하고, 파드들이 이 이름으로 요청을 보낼 경우, 서비스가 이 트래픽을 외부 도메인으로 포워딩한다.

apiVersion: v1
kind: Service
metadata:
  name: externalname-svc # 서비스 이름
spec:
  type: **ExternalName**
  externalName: my.database.com # 포워딩할 외부 서비스

쿠버네티스 내부의 파드가 externalname-svc에게 요청을 보내면, 이 요청을 서비스가 받아서 my.database.com으로 포워딩한다.

'Cloud > Kubernates' 카테고리의 다른 글

설정값 전달 : ConfigMap, Secret  (1) 2023.10.29
NameSpace 관리  (1) 2023.10.29
ReplicaSet, Deployment  (0) 2023.10.29
Pod, NameSpace  (1) 2023.10.29
쿠버네티스 시작하기 : 내부 구조  (0) 2023.10.29