본문 바로가기

k8s

7. Services - ClusterIP | NodePort | LoadBalancer

728x90

1. ClusterIP

- Pod의 IP는 휘발성이기 때문에, 영구적인 Service의 IP를 통해서 연결

- ClusterIP 타입은 Cluster 타입 내에서만 접근이 가능

- Service는 여러 Pod에 연결이 가능하며, 각 Pod에 Random으로 트래픽은 보내줌

 

"Pod 들이 직접 서로를 찾지 말고, Service의 고정 IP로 통신해라"

[Client Pod]
      |
      |  svc-1:9000
      v
+-------------------+
| Service (ClusterIP)
| name: svc-1
| ClusterIP: 10.x.x.x
| Port: 9000
+-------------------+
      |
      | forwarding
      v
+-------------------+
| Pod pod-1
| IP: 10.244.x.x
| containerPort:8080
+-------------------+

 

kubernetes의 통신 방식은 Pod ↔ Service 방식으로 통신한다고 생각하면 된다.

 

왜 Service를 쓰는가??

1. Pod의 IP는 가변적이나, Service(ClusterIP)는 고정적이다.

2. Kubernetes 내부 DNS가 자동 생성되어, 이름 기반 DNS도 제공된다.

 

port : Service가 받는 포트

targetPort : 실제 Pod 컨테이너 포트

Service:9000 → Pod:8080

 

ClusterIP는 외부 접근이 가능한가?

- 기본적으로는 불가능

- ClusterIP는 클러스터 내부 전용 IP

- Pod -> Service 접근 가능

- Node 내부 접근 가능

- 외부 PC에서는 접근 불가

 

그렇가면 외부접근은 어떻게 해야 하는데?

- NodePort

- LoadBalancer

- Ingress

 

서비스가 어떤 Pod와 연결되어 있는지 확인하는 방법

kubectl get endpoints

 

e.g)

[root@k8s-master ~]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS      AGE     IP              NODE          NOMINATED NODE   READINESS GATES
pod-1   1/1     Running   7 (45m ago)   2d17h   20.100.194.84   k8s-worker1   <none>           <none>
pod-2   1/1     Running   6 (46m ago)   2d16h   20.110.126.14   k8s-worker2   <none>           <none>

[root@k8s-master ~]# kubectl get endpoints
NAME         ENDPOINTS                               AGE
kubernetes   192.168.56.30:6443                      4d23h
svc-1        20.100.194.84:8080,20.110.126.14:8080   2d17h
svc-2        20.100.194.84:8080,20.110.126.14:8080   2d17h
svc-3        20.100.194.84:8080,20.110.126.14:8080   2d16h
svc-4        20.100.194.84:8080,20.110.126.14:8080   2d16h

pod-1과 pod-2는 svc-1, svc-2, svc-3, svc-4 전부에 물려 있다는 것을 확인.

 

 

2. NodePort -> Cluster 외부에서 Node IP 와 Port를 통하여 Pod에 접근하는 기술

- NodePort 타입은 ClusterIP 타입의 기능을 포함하며, 워커노드의 IP를 통해 Cluster 외부에서 연결이 가능

- Node는 사내 내부망이라면, 내부망에 있는 시스템이 임시적인 테스트 목적으로 사용

- NodePort의 할당 범위 : 30000 ~ 32767

- nodePort 속성을 넣지 않으면, Port 할당 범위 내에서 자동부여

 

Service

apiVersion: v1
kind: Service
metadata:
  name: svc-2
spec:
  selector:
    app: pod
  ports:
  - port: 9000
    targetPort: 8080
    nodePort: 30001
  type: NodePort

 

Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
     app: pod
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-worker2
  containers:
  - name: container
    image: kubetm/app
    ports:
    - containerPort: 8080

 

 

 

pod -> 요청이 분산되는지 확인

apiVersion: v1
kind: Pod
metadata:
  name: pod-2
  labels:
     app: pod
spec:
  nodeSelector:
    kubernetes.io/hostname: k8s-worker2
  containers:
  - name: container
    image: kubetm/app
    ports:
    - containerPort: 8080

 

Appendix) Service를 추가하여 externalTrafficPolicy 기능 확인

apiVersion: v1
kind: Service
metadata:
  name: svc-3
spec:
  selector:
    app: pod
  ports:
  - port: 9000
    targetPort: 8080
    nodePort: 30002
  type: NodePort
  externalTrafficPolicy: Local

 

※ externalTrafficPolicy 기본 값 : Cluster

Cluster 모드의 특징

Cluster 모드 동작

예를 들어:

NodePod 존재 여부
worker1 O
worker2 X
위와 같은 상황에서 외부 사용자가:

worker2:30002

로 접속해도 Kubernetes는:

worker2
  ↓
cluster 내부 forwarding
  ↓
worker1 의 Pod

 

어떤 Node로 들어와도 Pod만 있으면 내부적으로 찾아간다.

 

externalTrafficPolicy 값을 Local로 두는 경우,

현재 Node에 Pod가 있을 때만 요청을 처리한다.

예시

NodePod 존재 여부
worker1 O
worker2 X
요청 1
worker1:30002

→ 성공

왜냐면 worker1에 Pod 있음.

요청 2
worker2:30002

→ 실패

왜냐면 worker2에는 Pod 없음.

Kubernetes가 다른 Node로 forwarding 안 함.

 

옵션으로 Local 을 주는 이유는

 

  • 접근 제어
  • IP 기반 인증
  • Rate Limit
  • WAF
  • GeoIP
  • Apache access log
  • X-Forwarded-For 분석

단점

트래픽 불균형 가능

예:

NodePod 수
worker1 3
worker2 0
worker3 1

이면:

  • worker2로 온 요청은 실패
  • worker1에 요청 몰림 가능

따라서

  • AWS NLB
  • MetalLB
  • External LB
  • Ingress Controller

등과 같이 사용.

LB가 Pod 있는 Node로만 보내도록 구성함.

 

요약 

Cluster

외부 요청
   ↓
아무 Node 가능
   ↓
다른 Node Pod로 forwarding 가능
 

Local

외부 요청
   ↓
현재 Node에 Pod 있으면 처리
없으면 DROP

 

 

3. LoadBalancer

- LoadBalancer 타입의 Service는 클라우드 서비스에서 사용 가능

- LoadBalancer 타입으로 Service 생성시 NodePort 타입의 기능을 포함

- LoadBalancer가 생성해주는 IP를 통해 내부의 IP 대역은 노출시키지 않고, 외부 시스템에 연결 가능

- LoadBalancer는 NodePort를 통해 트래픽을 전달

 

service)

apiVersion: v1
kind: Service
metadata:
  name: svc-4
spec:
  selector:
    app: pod
  ports:
  - port: 9000
    targetPort: 8080
  # 외부에서 접근 가능한 로드밸런서를 생성해라
  type: LoadBalancer
  

LoadBalancer는 내부적으로 이렇게 동작

외부 사용자
      ↓
Cloud Load Balancer
      ↓
NodePort
      ↓
Service
      ↓
Pod

1. LoadBalancer 생성 -> 2. 자동으로 NodePort 생성 -> 3. 각 Node로 트래픽 전달 -> 4. Pod로 분산

 

 

[root@k8s-master ~]# kubectl get svc
NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP      10.96.0.1        <none>        443/TCP          5d4h
svc-1        ClusterIP      10.102.93.200    <none>        9000/TCP         2d22h
svc-2        NodePort       10.107.115.131   <none>        9000:30001/TCP   3h43m
svc-3        NodePort       10.97.23.13      <none>        9000:30002/TCP   3h16m
svc-4        LoadBalancer   10.97.102.222    <pending>     9000:30618/TCP   40m

 

※ 여기서 LoadBalancer의 상태는 왜 pending 상태인가?

  • kubeadm
  • VirtualBox
  • Rocky Linux
  • 직접 구성한 Kubernetes Cluster

이 환경에는:

외부 LoadBalancer를 생성해줄 시스템이 없음
 

그래서 Kubernetes가 계속:

"LoadBalancer 만들어주세요..."

라고 요청만 하고 기다리는 상태가 <pending>.

Kubernetes는 내부적으로:

1. ClusterIP 생성
2. NodePort 생성
3. 외부 LB 생성 요청
 

 

현재 상황은 마지막 단계에서 실패 중.

 

예를 들어 AWS에서는:

Kubernetes
   ↓
AWS API 호출
   ↓
ELB/NLB 자동 생성
   ↓
Public IP 할당
 
이렇게 짜여진 상황에서는
kubectl get svc
 

하면:

EXTERNAL-IP   52.x.x.x
 

같이 실제 공인 IP가 나옴.

그런데 왜 PORT는 생겼을까?

잘 보면:

9000:30618/TCP
 

이렇게 되어있다.

이건 Kubernetes가:

LoadBalancer 생성 실패
↓
그래도 NodePort는 만들어둠
 

상태라는 뜻.

즉 아래와 같이

NodeIP:30618
 

로 접근 가능함.

'k8s' 카테고리의 다른 글

8. Volume - emptyDir | hostPath | PV/PVC  (0) 2026.05.12
6. kubectl [create | apply | get | describe | delete | exec]  (0) 2026.05.08
5. Node Schedule  (0) 2026.05.07
4. Service  (0) 2026.05.07
3. labels  (0) 2026.05.07