Kubernetes 네트워크 - Service : 개념, 종류 그리고 간단 실습

이숭늉·2025년 5월 28일
0

DevOps

목록 보기
11/19
post-thumbnail

🌐 Kubernetes Service - 개념과 종류, 간단 실습

저번 글에서 어떤 오브젝트가 있는지 간단히 살펴보았다. 이번 글에서는 그 중에서도 Service(서비스) 에 대해 중점적으로 다뤄보고, 각 서비스의 유형에 따라 간단한 실습도 함께 진행해볼 예정이다.

쿠버네티스 서비스란?

서비스(Service) 는 클러스터 내부 또는 외부의 클라이언트와 파드 간의 연결을 안정적으로 제공하는 추상적 리소스이다.
Kubernetes에서 파드는 일시적인 존재로, 동적으로 생성되거나 종료된다. 이 때문에 파드의 IP는 고정되어 있지 않으며, 클라이언트가 특정 파드에 직접 요청을 보내기란 어렵다. 이를 해결하기 위해 서비스가 사용된다.

  • 서비스는 논리적인 파드 셋을 정의하고, 해당 파드 집합에 접근할 수 있는 정책과 접근 지점을 제공한다.
  • selector를 통해 특정 라벨을 가진 파드들을 자동으로 찾아 엔드포인트 목록으로 관리한다.
  • 클러스터 내부에서 CoreDNS를 통해 서비스 이름이 자동으로 DNS 이름으로 등록된다. 즉, 클라이언트가 http://my-service와 같이 서비스 이름으로 요청을 보내면, CoreDNS가 해당 요청을 서비스의 ClusterIP로 변환해준다. (-> 서비스 디스커버리 Service Discovery)
  • 이를 통해 클라이언트는 파드의 변화와 무관하게 항상 동일한 방식으로 접근할 수 있다.

종류

쿠버네티스 서비스는 타입에 따라 트래픽 유입 방식이 달라진다. 대표적으로 ClusterIP, NodePort, LoadBalancer, ExternalName의 네 가지 유형이 존재한다.

1️⃣ ClusterIP

ClusterIP는 쿠버네티스 서비스의 기본 설정값으로 클러스터 내에서만 파드에 접근될 수 있도록 하는 유형이다. 클러스터 내부에서만 접근 가능한 IP를 할당하며, 외부에서는 접근할 수 없다.

실습

먼저 ClusterIP 유형의 서비스와 해당 서비스에 매핑될 디플로이먼트를 yaml로 정의 후 생성한다.

# service-clusterip.yaml
apiVersion: v1	
kind: Service	
metadata:	
  name: web-service	
spec:	
  selector:	
    app.kubernetes.io/name: web-deploy # 서비스가 연결할 pod 정의
  type: ClusterIP
  ports:	
  - protocol: TCP	
    port: 80 # 클라이언트가 서비스에 요청할 때 사용할 포트


# deployment.yaml  
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-service-01
spec:	
  replicas: 3		
  selector:	
    matchLabels:	
      app.kubernetes.io/name: web-deploy
  template:	
    metadata:	
      labels:	
        app.kubernetes.io/name: web-deploy
    spec:
      containers:
      - name: nginx	
        image: nginx:latest
        
kubectl apply -f service-clusterip.yaml
kubectl apply -f deployment.yaml

kubectl get all

이후 클러스터 내부의 다른 파드에서 해당 서비스의 ClusterIP로 curl 명령어를 통해 요청을 보내면 접속이 잘 되는 것을 확인할 수 있다.

2️⃣ NodePort

각 노드의 특정 포트를 통해 외부 접근을 제공하는 유형이다. NAT를 사용하는 클러스터 내에서 각 노드들의 지정된 포트(30000~32767)를 외부에 노출시켜 준다.

실습

먼저 NodePort 유형의 서비스와 해당 서비스에 매핑될 디플로이먼트를 yaml로 정의 후 생성한다.

# service-nodeport.yaml
apiVersion: v1	
kind: Service	
metadata:
  name: web-service-nodeport
spec:	
  selector:	
    app.kubernetes.io/name: web-deploy	
  type: NodePort
  ports:	
  - protocol: TCP
    nodePort: 31001 
    port: 80 
    targetPort: 80 
    
# nodePort : 노드의 네트워크 인터페이스에서 열려 있는 포트, 외부 트래픽을 받아 ClusterIP로 전달하는 진입점 역할
# port : 서비스가 클러스터 내부에서 사용하는, ClusterIP에서 동작하는 포트 (client → service)
# targetPort : pod의 어플리케이션 쪽에서 서비스를 향해 열려 있는 포트 (service → pod)
kubectl apply -f service-nodeport.yaml
kubectl apply -f deployment.yaml

가상 머신에서 쿠버네티스를 실행 중이라고 하면 포트포워딩 설정이 필요하다.

31051 호스트 포트로 접속하면 이를 10.0.2.7 노드의 NodePort 31001로 포트포워딩하고, 31052 호스트 포트로 접속하면 이를 10.0.2.8 노드의 NodePort 31001로 포트포워딩한다.

요청 흐름

  1. 클라이언트가 브라우저에서 127.0.0.1:31051 로 요청.
  2. 포트포워딩 설정에 따라 10.0.2.7(워커노드):31001로 포트포워딩.
  3. 요청이 NodePort로 들어오면 해당 노드의 kube-proxy가 요청 수신. kube-proxy31001 포트로 들어온 요청을 가로채서 매핑된 서비스의 ClusterIP:Port(80)로 전달.
  4. 서비스가 selector을 기준으로 연결된 pod들 중 하나로 트래픽 분배.
  5. 서비스가 연결된 pod의 targetPort(80)로 요청 전달하고, pod의 컨테이너에서 80 포트로 실제 어플리케이션이 응답한다.

3️⃣ LoadBalancer

클라우드 환경(AWS, Azure, GCP)에서 사용되는 서비스 유형으로, 클러스터 외부에서 접근할 수 있도록 퍼블릭 IP와 로드밸런서를 자동으로 생성해준다.

서비스 정의 시 type: LoadBalancer로 설정하면, Kubernetes는 클라우드 벤더의 API를 호출해 로드밸런서를 생성하고, 퍼블릭 IP를 할당한다.
외부 사용자는 이 퍼블릭 IP를 통해 서비스에 직접 접근할 수 있으며, 요청은 로드밸런서를 거쳐 클러스터 내부적으로는 NodePort + ClusterIP 구조를 그대로 따른다.

하지만, 로컬 환경에서는 클라우드처럼 로드밸런서를 자동 생성할 벤더 API가 없다. 따라서, LoadBalancer 타입 서비스를 생성해도 아무 IP도 할당되지 않는다. 이때 클러스터 내부에서 가짜 클라우드 벤더 역할을 할 수 있는 것이 바로 MetalLB이다.

🪄 MetalLb

MetalLB는 베어메탈이나 로컬 환경에서도 LoadBalancer 서비스를 사용할 수 있게 해주는 컨트롤러이다.
클러스터 내부에서 클라우드 벤더 역할을 흉내 내어, 사용자가 정의한 IP 풀에서 가상의 외부 IP를 할당한다. 로드밸런서 리소스를 생성하는 것이 아니라, 트래픽을 특정 노드로 전달할 수 있는 방식(ARP or BGP)을 통해 로드밸런서처럼 행동하는 방식이다.

ARP (L2 모드 : Address Resolution Protocol)

  • 로컬 네트워크(같은 서브넷 안)에서, '이 IP를 가진 장비가 어디에 있어?'라고 물어볼 때 사용.
  • 동작 방식
    1. 사용자의 노트북은 "192.168.0.100은 누가 갖고 있지?"라고 브로드캐스트(ARP 요청)
    2. MetalLB는 클러스터 내부의 특정 노드가 이 IP를 갖고 있는 것처럼 ARP 응답을 보냄
    3. 노트북은 이제 해당 노드의 MAC 주소를 알게 되고, 이후 패킷을 직접 그 노드에 보낸다.

=> 같은 네트워크 안에서만 작동하므로, 로컬 테스트에 적합.

BGP (L3 모드 : Border Gateway Protocol)

  • 외부 라우터와 MetalLB가 직접 라우팅 정보를 교환하여 정식 경로 광고를 한다.
  • 동작 방식
    1. MetalLB는 라우터와 BGP 세션을 맺는다
    2. "203.0.113.50으로의 트래픽은 쿠버네티스 클러스터의 특정 노드로 보내"라고 광고한다.
    3. 이후 외부 라우터는 이 정보를 기반으로 올바른 노드로 패킷을 전달한다.

=> BGP 라우터가 필요하므로, 보통 기업 데이터 센터에서 사용

동작 흐름

  1. 사용자가 LoadBalancer 타입의 서비스를 생성
  2. Kubernetes는 API 요청을 받고 로드밸런서 상태를 pending으로 표시
  3. MetalLB 컨트롤러가 이를 감지하고,
  4. 사용자가 정의한 IP 주소풀(IPAddressPool)에서 하나의 IP를 할당
  5. 이 IP를 서비스의 externalIP로 설정
  6. 외부 요청은 해당 IP로 들어오며, MetalLB는 해당 노드에 트래픽을 전달

실습 #1 : MetalLb 환경

# metallb-config.yaml
apiVersion: metallb.io/v1beta1 
kind: IPAddressPool
metadata:
  name: metallb-config
  namespace: metallb-system
spec:
  addresses:
  - 10.0.2.20-10.0.2.40 # 10.0.2.20-10.0.2.40 범위 중에서 할당
  autoAssign: true
--- 
apiVersion: metallb.io/v1beta1 
kind: L2Advertisement 
metadata:
  name: metallb-config
  namespace: metallb-system
spec:
  ipAddressPools:
    - metallb-config

IPAddressPool을 설정하고, 퍼블릭 IP가 자동 할당되도록 한다.

# service-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
  name: web-service-loadbalancer
spec:
  selector:
    app.kubernetes.io/name: web-deploy
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

위와 같이 정의하면 MetalLB가 감지해서 IP 풀에서 IP를 하나 골라 자동으로 외부 IP를 서비스에 붙여준다.

실습 #2 : 클라우드 환경

클라우드 환경용 LoadBalancer 서비스를 정의하는 YAML은 다음과 같다.
externalIPsnodePort를 수동으로 지정할 필요 없이, 클라우드 벤더가 퍼블릭 IP 및 로드밸런서를 자동으로 생성해준다.

# service-loadbalancer.yaml
apiVersion: v1	
kind: Service	
metadata:
  name: web-service-loadbalancer
spec:	
  selector:
    app.kubernetes.io/name: web-deploy	
  type: LoadBalancer	
  ports:
  - protocol: TCP
    port: 80	
    targetPort: 80

4️⃣ External Name

내부의 서비스가 외부의 도메인을 가리키도록 하는 유형이다.

# service-externalname.yaml
apiVersion: v1	
kind: Service	
metadata: 
  name: web-service-externalname
spec: 	
  type: ExternalName
  externalName: www.google.com
kubectl exec -it [pod-name] -- /bin/bash

curl "web-service-externalname"

CoreDNS가 요청을 www.google.com으로 리다이렉트한다.


이번 글에서는 쿠버네티스에서 서비스가 어떻게 외부와 통신하며, 클러스터 내부에서는 어떤 방식으로 트래픽이 전달되는지 서비스 유형별로 정리해보았다. 다음 글에서는 Ingress를 중심으로 외부 트래픽 제어 방식을 살펴 보며 쿠버네티스 네트워크에 대해 더 깊이 이해해보도록 하겠다.

profile
부지런히 살자

0개의 댓글