클러스터 내부에서 가상 IP를 할당받고, 각 노드에 파드로 떠있는 kube-proxy 를 통해서 파드와 통신하는 내부용 로드 밸런서이다.
쿠버네티스 API 에 접속 가능하게 하기 위해 클러스터 생성시 기본적으로 기동되는 Kubernetes 서비스도 ClusterIP 이다.
kube-proxy 는 각 노드에 파드로 떠있으며, kube-system 네임스페이스에서 조회 가능하다.
$ kubectl get pods -o wide -n kube-system | grep proxy
kube-proxy-6pn2g 1/1 Running 1 (45d ago) 119d 172.18.0.4 desktop-worker <none> <none>
kube-proxy-c8r4l 1/1 Running 1 (45d ago) 119d 172.18.0.3 desktop-worker2 <none> <none>
kube-proxy-l52jn 1/1 Running 0 119d 172.18.0.3 desktop-control-plane <none> <none>
1. ClusterIP 생성
아래와 같은 매니페스트로 생성한다.
apiVersion: v1
kind: Service
metadata:
name: sample-clusterip
spec:
type: ClusterIP
ports:
- name: "http-port"
protocol: "TCP"
port: 8080
targetPort: 80
selector:
app: sample-app
spec.ports[].port 는 ClusterIP 에서 수신하는 포트를 지정하고, spec.ports[].targetPort 는 목적지 파드의 포트번호를 지정한다.
이제 클러스터 내부 파드에서 방금 생성한 서비스명인 sample-clusterip 를 도메인명으로 호출하면, 서비스가 바라보고 있는 파드들(app=sample-app 라벨을 가지고 있는 파드들)로 로드밸런싱 된다.
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- curl -s http://sample-clusterip:8080
Host=sample-clusterip Path=/ From=sample-deployment-75c768d5fb-9qdjm ClientIP=10.244.1.158 XFF=
pod "testpod" deleted
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- curl -s http://sample-clusterip:8080
Host=sample-clusterip Path=/ From=sample-deployment-75c768d5fb-g5vkv ClientIP=10.244.1.159 XFF=
pod "testpod" deleted
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- curl -s http://sample-clusterip:8080
Host=sample-clusterip Path=/ From=sample-deployment-75c768d5fb-2lkwp ClientIP=10.244.1.163 XFF=
pod "testpod" deleted
2. ClusterIP 의 서비스 디스커버리
한가지 의문이 생긴다. 파드에서 sample-clusterip 도메인으로 호출했을 뿐인데 어떻게 도메인을 해석하고 목적지 파드까지 도달하게 되는 걸까? 아래와 같은 순서로 해석된다.
1) 파드 내에서 질의
파드 내에서 http://sample-clusterip:8080 질의
2) 파드 내 DNS 레코드 해석
파드 내 /etc/resolv.conf DNS 레코드에 따라 suffix 를 붙여 kube-dns 로 질의한다.
/etc/resolv.conf 는 아래 커맨드로 조회할 수 있다.
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
options ndots:5
이에 따라 10.96.0.10 DNS(kube-dns) 에서 해석이 가능 할 때까지 search 에 지정된 suffix 를 붙여 아래 순서대로 질의한다.
sample-clusterip.default.svc.cluster.local
sample-clusterip.svc.cluster.local
sample-clusterip.cluster.local
sample-clusterip
3) kube-dns 의 블록 매칭
kube-dns 에서는 coredns configMap 의 설정에 따라 kubernetes cluster.local 블록에 매칭되어 쿠버네티스 API 서버인 kube-apiserver 에 질의한다.
해당 설정은 아래 커맨드로 조회 할 수 있다.
$ kubectl get configmaps coredns -n kube-system -o yaml
...
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
...
4) kube-apiserver 에서 네임스페이스와 서비스 명칭으로 서비스 IP 를 조회
쿠버네티스가 자동 생성하는 서비스의 DNS 이름 규칙에 따라 해당하는 서비스의 IP 를 조회한다.
규칙은 아래와 같다.
{서비스명}.{네임스페이스명}.svc.cluster.local
5) kube-dns 에서 이를 A 레코드로 응답하여 해석됨
실제로 dig 명령어를 통해 10.96.0.10 DNS 에서 도메인을 어떻게 해석하는지 질의 가능하다.
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- dig @10.96.0.10 sample-clusterip.default.svc.cluster.local
;; ANSWER SECTION:
sample-clusterip.default.svc.cluster.local. 30 IN A 10.96.82.60
10.96.82.60 서비스가 응답함을 의미한다.
6) 해당 서비스를 호출하여 각 파드로 로드밸런싱 됨
해석된 서비스 IP 인 10.96.82.60:8080 으로 호출한다.
3. ClusterIP 의 가상 IP 직접 지정
일반적으로 ClusterIP 를 생성할 때 IP 를 지정하지 않기 때문에 할당 가능한 대역 내에서 자동 할당된다. 하지만, 직접 IP 로 서비스를 참조하고자 하는 상황이 있을 수 있다.
- DNS 캐시나 방화벽 정책을 고정 IP로 관리할 때(IP 기반 ACL)
- 테스트 환경에서 동일한 IP 를 사용해야 할 때
직접 IP 를 지정하기 위해서는 spec.clusterIP 에 지정할 IP 를 설정한다.
apiVersion: v1
kind: Service
metadata:
name: clusterip-vip
spec:
type: ClusterIP
clusterIP: 10.96.82.70
ports:
- name: "http-port"
protocol: "TCP"
port: 8080
targetPort: 80
selector:
app: sample-app
아래 커맨드로 직접 지정한 IP 가 설정되었는지 확인 가능하다.
$ kubectl get services clusterip-vip
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
clusterip-vip ClusterIP 10.96.82.70 <none> 8080/TCP 13m
다만, 지정하는 IP 는 아래와 같은 조건이 있으므로 주의하여 사용한다.
| Service CIDR 대역 내 IP 로 지정해야 함 | 예: 10.96.0.0/12 범위 안이어야 함(kube-apiserver의 --service-cluster-ip-range 옵션으로 설정되는 범위) |
| 이미 다른 Service 가 사용중이지 않아야 함 | IP 충돌 발생 시 생성 실패 (The Service "X" is invalid: spec.clusterIP: Invalid value: "10.96.100.50": provided IP is already allocated) |
| 한번 IP 를 지정하여 생성하면 변경할 수 없음(immutable) | IP 를 변경하려면 삭제 후 재생성 해야 함 |
'Kubernetes' 카테고리의 다른 글
| [Kubernetes] ClusterIP - externalIPs 서비스 이해 (0) | 2025.10.19 |
|---|---|
| [Kubernetes] 서비스에 할당 가능한 IP 대역 조회 (0) | 2025.10.19 |
| [Kubernetes] 서비스 디스커버리와 DNS 설정 (1) | 2025.10.14 |
| [Kubernetes] Multi Port ClusterIP, 포트 이름을 사용한 참조 (0) | 2025.10.12 |
| [Kubernetes] 클러스터 네트워크 개괄 (0) | 2025.10.12 |