1. Cluster IP
개요
- 클러스터 내부 접근 전용: ClusterIP는 클러스터 내부에서만 접근 가능하며, 도메인(DNS) 기반으로도 접근할 수 있습니다.
- DNAT 기반 통신: 클라이언트가 ClusterIP로 접근 시 해당 노드의 iptables 규칙에 따라 DNAT 처리가 되어, 백엔드 Pod로 트래픽이 분산됩니다.
- iptables 규칙 자동 생성: ClusterIP 서비스 생성 시
kube-proxy가 각 노드의iptables에 관련 규칙을 자동으로 설정하여, 모든 노드에서 동일한 방식으로 트래픽이 처리됩니다.

실습 환경 구성
ClusterIP 통신 원리를 이해하기 위해, 실습 리소스를 배포합니다.
- 클라이언트 파드 :
net-pod - 목적지 파드 :
webpod1,2,3
목적지(backend) 파드(Pod) 생성 : 3 pod.yaml
cat <<EOT> 3pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: webpod1
labels:
app: webpod
spec:
nodeName: myk8s-worker
containers:
- name: container
image: traefik/whoami
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
name: webpod2
labels:
app: webpod
spec:
nodeName: myk8s-worker2
containers:
- name: container
image: traefik/whoami
terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Pod
metadata:
name: webpod3
labels:
app: webpod
spec:
nodeName: myk8s-worker3
containers:
- name: container
image: traefik/whoami
terminationGracePeriodSeconds: 0
EOT
클라이언트(TestPod) 생성 : netpod.yaml
cat <<EOT> netpod.yaml
apiVersion: v1
kind: Pod
metadata:
name: net-pod
spec:
nodeName: myk8s-control-plane
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOT
서비스(ClusterIP) 생성 : svc-clusterip.yaml
cat <<EOT> svc-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: svc-clusterip
spec:
ports:
- name: svc-webport
port: 9000 # 서비스 IP 에 접속 시 사용하는 포트 port 를 의미
targetPort: 80 # 타킷 targetPort 는 서비스를 통해서 목적지 파드로 접속 시 해당 파드로 접속하는 포트를 의미
selector:
app: webpod # 셀렉터 아래 app:webpod 레이블이 설정되어 있는 파드들은 해당 서비스에 연동됨
type: ClusterIP # 서비스 타입
EOT
리소스 생성 및 확인
#생성
kubectl apply -f 3pod.yaml,netpod.yaml,svc-clusterip.yaml
# 파드와 서비스 사용 네트워크 대역 정보 확인
# 파드와 서비스 사용 네트워크 대역 정보 확인
kubectl cluster-info dump | grep -m 2 -E "cluster-cidr|service-cluster-ip-range"
"--service-cluster-ip-range=10.200.1.0/24",
"--cluster-cidr=10.10.0.0/16",
# 파드 확인
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
net-pod 1/1 Running 0 30m 10.10.0.8 myk8s-control-plane <none> <none>
webpod1 1/1 Running 0 30m 10.10.2.3 myk8s-worker <none> <none>
webpod2 1/1 Running 0 30m 10.10.1.4 myk8s-worker2 <none> <none>
webpod3 1/1 Running 0 30m 10.10.3.3 myk8s-worker3 <none> <none>
# 서비스 확인
kubectl get svc svc-clusterip
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc-clusterip ClusterIP 10.200.1.221 <none> 9000/TCP 25m
서비스(ClusterIP) 접속 확인
변수정의
용이한 실습을 위해 파드와 서비스 IP를 변수로 지정합니다.
# webpod 파드의 IP를 변수에 지정
WEBPOD1=$(kubectl get pod webpod1 -o jsonpath={.status.podIP})
WEBPOD2=$(kubectl get pod webpod2 -o jsonpath={.status.podIP})
WEBPOD3=$(kubectl get pod webpod3 -o jsonpath={.status.podIP})
echo $WEBPOD1 $WEBPOD2 $WEBPOD3
# 서비스 IP 변수 지정 : svc-clusterip 의 ClusterIP주소
SVC1=$(kubectl get svc svc-clusterip -o jsonpath={.spec.clusterIP})
echo $SVC1
net-pod -> web-pod IP로 직접 통신
반복문을 통해 webpod1,2,3 파드의 IP로 직접 통신합니다.
for pod in $WEBPOD1 $WEBPOD2 $WEBPOD3; do kubectl exec -it net-pod -- curl -s $pod; done
for pod in $WEBPOD1 $WEBPOD2 $WEBPOD3; do kubectl exec -it net-pod -- curl -s $pod | grep Hostname; done
for pod in $WEBPOD1 $WEBPOD2 $WEBPOD3; do kubectl exec -it net-pod -- curl -s $pod | grep Host; done
for pod in $WEBPOD1 $WEBPOD2 $WEBPOD3; do kubectl exec -it net-pod -- curl -s $pod | egrep 'Host|RemoteAddr'; done
목적지 파드(web-pod)의 IP로 직접 접속 시, 응답헤더의 RemoteAddr는 출발지 파드(net-pod)의 IP가 출력됨을 확인할 수 있습니다.

net-pod -> 서비스(svc-clusterip)로 통신
생성한 svc-clusterip 서비스의 ClusterIP로 접속합니다.
# TCP 80,9000 포트별 접속 확인 : 출력 정보 의미 확인
root@myk8s-control-plane:/# curl -s --connect-timeout 1 $SVC1
root@myk8s-control-plane:/# curl -s --connect-timeout 1 $SVC1:9000
마찬가지로, 정상적으로 통신됨을 확인할 수 있습니다.

서비스(ClusterIP) 부하분산 확인
반복해서 서비스로 요청을 날려보면, 서비스에 연결된 엔드포인트로 랜덤하게 요청이 가는 것을 확인할 수 있습니다.

100번 접속을 시도 후 결과를 확인하면 대략 33% 정도로 부하분산 접속됨을 확인할 수 있습니다.

서비스(ClusterIP) 통신 흐름 분석
어떻게 서비스(ClusterIP)로 통신되는 가능한 것일까요? 각 노드의 TCP Listen 정보를 보면 서비스로 요청한 9000번 포트도 존재하지 않습니다.

각 워커 노드에서 패킷 덤프 확인(tcpdump)
각 노드에서 패킷을 캡처하여 네트워크를 분석합니다.
pcap파일을 만들어, wireshark 툴을 이용하여 확인.
tcpdump -i eth0 tcp port 80 -nnq
tcpdump -i eth0 tcp port 80 -w /root/svc1-1.pcap
tcpdump -i eth0 tcp port 9000 -nnq
ngrep -tW byline -d eth0 '' 'tcp port 80'
# tcpdump/ngrep : vethX
VETH1=<각자 자신의 veth 이름>
tcpdump -i $VETH1 tcp port 80 -nn
tcpdump -i $VETH1 tcp port 80 -w /root/svc1-2.pcap
tcpdump -i $VETH1 tcp port 9000 -nn
TCP 계층에서는 9000번 포트는 트래픽이 없는 것을 확인할 수 있습니다. 이것은 Iptables이 사용하는 Netfilter의 동작원리를 살펴 보아야합니다.
결론적으로, kube-proxy를 통해 IP와 포트가 리다이렉션 되고 iptables 룰에 의해 트래픽을 제어하기 때문에 노드레벨에서 캡처되는 패킷애는 보이지 않습니다.


서비스(ClusterIP) Iptables 분석
그렇다면 iptables에는 ClusterIP가 어떻게 룰이 적용되어 통신 할 수 있는지 살펴봅니다.
서비스(ClusterIP) - iptables 통신흐름

쿠버네티스 ClusterIP 서비스의 트래픽이 클러스터 내에서 어떻게 라우팅되는지 자세하게 살펴봅니다.
- PREROUTING
PREROUTING체인은 모든 들어오는 패킷이 라우팅되기 전에 가장 먼저 실행되는 체인입니다.- 목적지가 0.0.0.0/0인 모든 트래픽에 대해
KUBE-SERVICES체인으로 전달됩니다.
- 목적지가 0.0.0.0/0인 모든 트래픽에 대해
- KUBE-SERVICES
KUBE-SERVICES체인은ClusterIP및NodePort와 같은 서비스 관련 트래픽을 처리합니다.ClusterIP가9000포트로 들어오는 패킷이KUBE-SVC-KBDBEBILI6IU6WL7RF라는 서비스 관련 체인으로 전달됩니다.
- KUBE-SVC-YYY
이 체인은 개별 서비스에 대해KUBE-SERVICES에서 라우팅된 트래픽을 처리합니다. 각 서비스에 대한 고유한 엔드포인트 목록과 라운드로빈, 확률 기반의 로드밸런싱을 처리할 수 있습니다.KUBE-SVC-YYY체인은 세 개의 백엔드 Pod 또는 Node를 나타내는KUBE-SEP-...체인으로 트래픽을 분산하고 있습니다.- 로드밸런싱은
statistic mode random probability방식으로 처리되고 있으며, 각KUBE-SEP-규칙의 확률이 달라질 수 있습니다.
- KUBE-SEP-ZZ1 ~
KUBE-SEP체인은 서비스의 개별 백엔드 엔드포인트로 트래픽을 전달합니다. 이 체인은 실제로 Pod IP와 포트로 트래픽을 전달하며, DNAT를 사용하여 최종적으로 목적지와 IP 포트를 변경합니다.KUBE-SEP-T7YVH2JOMUTQFUDU체인은 목적지 IP와 포트를10.10.1.4:80으로 변경하는DNAT규칙을 사용합니다.- 이 체인을 통해
KUBE-SVC-YYY체인에서 전달된 트래픽이 최종 백엔드 엔드포인트로 라우팅됩니다.

클러스터에서 외부로 나가는 트래픽 처리
KUBE-POSTROUTING 체인은 외부로 나가는 트래픽을 처리하며, SNAT을 통해 클러스터 외부에서 트래픽 출발지 IP주소가 올바르게 보이도록 설정합니다.
이러한 설정이 없으면, 클러스터 외부의 다른 네트워크가 클러스터 내의 출발지 IP주소를 모르게 되어 응답이 실패할 수 있습니다.
KUBE-POSTROUTING 에서 0x4000 마킹에 따라 SNAT 여부를 결정하고 패킷의 트래픽을 처리합니다.
0x4000마크가 없는 경우,- 패킷에
0x4000마크가 없는 경우, 더 이상KUBE-POSTROUTING체인을 처리하지 않고 다음 규칙으로 전달 (RETURN).
- 패킷에
0x4000마크가 있는 경우,KUBE-POSTROUTING체인 내에서 모든 패킷에0x4000마크를 설정MASQUERADE규칙을 통해 쿠버네티스 서비스 트래픽의 출발지 IP를 변경하여 올바른 SNAT 처리를 적용.
iptables -t nat -S | grep KUBE-POSTROUTING
-A KUBE-POSTROUTING -m mark ! --mark 0x4000/0x4000 -j RETURN
-A KUBE-POSTROUTING -j MARK --set-xmark 0x4000/0x0
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully
모든 노드에서 iptables 규칙 확인
서비스를 생성하면 kube-proxy에 의해서 iptables 규칙이 모든 노드에 추가됨을 확인할 수 있습니다.

ClusterIP의 부족한 점
- 외부에서 접근 불가능: ClusterIP는 클러스터 내부에서만 접근할 수 있어, 외부 클라이언트가 직접 접속할 수 없습니다. ⇒ NodePort 또는 LoadBalancer 서비스로 외부 접근 가능하도록 설정해야 합니다.
- Pod 상태에 따른 트래픽 제어 불가:
iptables를 사용하는 경우 헬스체크가 없어, 문제가 있는 Pod에도 트래픽이 전달될 수 있습니다. ⇒ Readiness Probe 설정으로 Pod 비정상 시 엔드포인트에서 제거 필요합니다. - 단순한 로드밸런싱: 기본적으로 랜덤 또는 세션 어피니티 분산 방식만 지원되어, 복잡한 로드밸런싱 정책 적용이 어렵습니다.
⇒IPVS를 사용하면 라운드 로빈, 최소 연결 등 다양한 알고리즘 지원 가능합니다. - Node 간 비효율적 라우팅: 목적지 Pod가 같은 노드에 위치해도 트래픽이 다른 노드로 전달될 수 있어 네트워크 성능 저하 가능합니다.
2. NodePort
개요
- 외부 접근 가능: 외부 클라이언트가 노드의 IP와 NodePort를 통해 서비스에 접근할 수 있으며, 이후 트래픽 처리는 ClusterIP와 동일하게 내부 Pod로 전달됩니다.
- SNAT/DNAT 처리: 외부 트래픽은 해당 노드의
iptables규칙에 의해 SNAT/DNAT 처리되어 목적지 Pod와 통신 후, 리턴 트래픽은 최초로 접근한 노드를 경유해 외부로 나갑니다. - 모든 노드에 규칙 설정: 모든 노드(마스터 포함)에 NodePort 관련
iptables규칙이 설정되어, 어느 노드로 접근해도 분산 접속 가능합니다. - NodePort 포트 범위 고정: 기본적으로 30000-32767 범위를 사용하며, 필요 시 설정 변경 가능합니다.

실습 구성
NodePort의 통신 원리를 이해하기 위해 실습을 위한 리소스를 생성합니다.
목적지(backend) 디플로이먼트(Pod) 파일 생성 : echo-deploy.yaml
cat <<EOT> echo-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-echo
spec:
replicas: 3
selector:
matchLabels:
app: deploy-websrv
template:
metadata:
labels:
app: deploy-websrv
spec:
terminationGracePeriodSeconds: 0
containers:
- name: kans-websrv
image: mendhak/http-https-echo
ports:
- containerPort: 8080
EOT
서비스(NodePort) 파일 생성 : svc-nodeport.yaml
cat <<EOT> svc-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: svc-nodeport
spec:
ports:
- name: svc-webport
port: 9000 # 서비스 ClusterIP 에 접속 시 사용하는 포트 port 를 의미
targetPort: 8080 # 타킷 targetPort 는 서비스를 통해서 목적지 파드로 접속 시 해당 파드로 접속하는 포트를 의미
selector:
app: deploy-websrv
type: NodePort
EOT
외부 클라이언트(mypc) 컨테이너 생성 : NodePort 통신 확인을 위해 노드와 같은 네트워크 대역의 컨테이너 생성
docker run -d --rm --name mypc --network kind --ip <노드_CIDR> nicolaka/netshoot sleep infinity
docker run -d --rm --name mypc --network kind --ip 172.18.0.100 nicolaka/netshoot sleep infinity
생성 및 확인
# 생성
kubectl apply -f echo-deploy.yaml,svc-nodeport.yaml
# pod 확인
kubectl get deploy,pod -o wide
# 서비스(NodePort) 확인
kubectl get svc svc-nodeport
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc-nodeport NodePort 10.200.1.78 <none> 9000:32364/TCP 3m14s
kubectl get endpoints svc-nodeport
NAME ENDPOINTS AGE
svc-nodeport 10.10.1.4:8080,10.10.2.3:8080,10.10.3.3:8080 48s
kubectl describe svc svc-nodeport
# mypc(외부클라이언트) 확인
docker ps | grep mypc
3960affdcfb4 nicolaka/netshoot "sleep infinity" 2 days ago Up 2 day
서비스(NodePort) 접속 확인
변수정의
용이한 실습을 위해노드와 서비스 포트를 변수로 지정합니다.
CNODE=172.17.0.2
NODE1=172.17.0.3
NODE2=172.17.0.4
NODE3=172.17.0.5
NPORT=$(kubectl get service svc-nodeport -o jsonpath='{.spec.ports[0].nodePort}')
echo $NPOR
CIP=$(kubectl get service svc-nodeport -o jsonpath="{.spec.clusterIP}")
CIPPORT=$(kubectl get service svc-nodeport -o jsonpath="{.spec.ports[0].port}")
외부 클라이언트(mypc 컨테이너)에서 접속 시도NodePort는 ClusterIP를 포함하기 때문에 두 개의 서비스 타입 모두 통신이 잘되는 것을 확인할 수 있습니다.
# ClusterIP 접속 확인
docker exec -it mypc curl -s $CIP:$CIPPORT
{
"path": "/",
"headers": {
"host": "10.200.1.78:9000",
"user-agent": "curl/7.88.1",
"accept": "*/*"
},
"method": "GET",
"body": "",
"fresh": false,
"hostname": "10.200.1.78",
"ip": "::ffff:172.17.0.2",
"ips": [],
"protocol": "http",
"query": {},
"subdomains": [],
"xhr": false,
"os": {
"hostname": "deploy-echo-5c689d5454-g5dcf"
},
"connection": {}
}
# NodePort 접속 확인
docker exec -it myk8s-control-plane curl -s $CNODE:$NPORT | jq
{
"path": "/",
"headers": {
"host": "172.17.0.2:32364",
"user-agent": "curl/7.88.1",
"accept": "*/*"
},
"method": "GET",
"body": "",
"fresh": false,
"hostname": "172.17.0.2",
"ip": "::ffff:172.17.0.2",
"ips": [],
"protocol": "http",
"query": {},
"subdomains": [],
"xhr": false,
"os": {
"hostname": "deploy-echo-5c689d5454-g5dcf"
},
"connection": {}
}
서비스(NodePort) 부하분산 접속 확인
NodePort도 부하분산 룰이 동일하게 적용되는 것을 확인할 수 있습니다.

노드 TCP 포트 확인
과거 쿠버네티스 버전은 각 노드에 노드포트가 Listen 되지만, 현재 쿠버네티스 버전에는 iptables rules 처리되어 포트가 노출되지 않습니다.

서비스(NodePort) Iptables 분석
쿠버네티스 NodePort 서비스의 트래픽이 클러스터 내에서 어떻게 라우팅되는지 자세하게 살펴봅니다.
- PREROUTING
모든 외부에서 들어오는 패킷은 먼저PREROUTING체인에서 처리됩니다.- 모든 외부 트래픽(
PREROUTING)은KUBE-SERVICES체인으로 전달됩니다.KUBE-SERVICES는 모든 서비스 관련 트래픽을 처리하는 체인입니다.
- 모든 외부 트래픽(
- KUBE-SERVICES
KUBE-SERVICES체인은 서비스(ClusterIP 또는 NodePort) 관련 트래픽을 처리합니다. NodePort는 ClusterIP를 포함합니다.ClusterIP가9000포트로 들어오는 패킷이KUBE-SVC-VTR7MTHHNMFZ3OFSF라는 서비스 관련 체인으로 전달됩니다.NodePort서비스와 관련된 트래픽은 마지막에KUBE-NODEPORTS체인으로 전달됩니다.
- KUBE-NODEPORTS
KUBE-NODEPORTS체인은NodePort서비스와 관련된 트래픽을 처리합니다. 이 체인에서NodePort서비스에 대한 규칙이 존재하고, 트래픽이 올바른 서비스로 전달되도록 설정합니다.NodePort서비스는 외부 포트32364로 연결되며,KUBE-EXT-VTR7MTHHNMFZ3OFS체인으로 전달됩니다.- 이 체인은
NodePort서비스를 처리하기 위한 추가적인 NAT 및 라우팅 규칙을 포함하고 있습니다.
- KUBE-EXT-XXX
KUBE-EXT체인은 외부에서 들어오는NodePort트래픽을 처리하고, 백엔드 Pod로 전달되기 전에 마스커레이딩 (MASQUERADE)을 수행합니다. (EXT는 External에 약자.)- 외부에서
NodePort로 들어오는 트래픽은MASQUERADE를 통해 출발지 IP가 변경됩니다 (KUBE-MARK-MASQ). - 이후
KUBE-SVC-VTR7MTHHNMFZ3OFS체인으로 전달되어, 서비스의 백엔드로 트래픽이 분배됩니다
- 외부에서
- KUBE-SVC-XXX
KUBE-SVC체인은 서비스의 백엔드 Pod로 트래픽을 분배하는 역할을 합니다.- 로드밸런싱 알고리즘(
statistic --mode random --probability)을 사용하여, 특정 백엔드 Pod로 트래픽을 분배합니다. - 예를 들어,
10.10.1.5:8080,10.10.2.4:8080,10.10.3.4:8080의 백엔드 Pod로 확률 기반의 분산 로드밸런싱을 수행합니다.
- 로드밸런싱 알고리즘(
- KUBE-SEP-XXX
KUBE-SEP체인은 서비스의 최종 백엔드 Pod로 트래픽을 전달합니다.- 각
KUBE-SEP체인은 특정 백엔드 Pod로의DNAT(Destination NAT)를 수행하여 최종적으로 패킷의 목적지 IP를 해당 Pod IP로 변경합니다. - 이 예시에서는
10.10.1.5,10.10.2.4,10.10.3.4의 Pod로 패킷이 전달됩니다.
- 각
- POSTROUTING
POSTROUTING체인은 패킷이 클러스터에서 나가기 전에 출발지 IP를 마스커레이딩하여 외부 네트워크에서도 올바르게 패킷을 처리할 수 있도록 합니다.0x4000마크가 없는 경우,- 패킷에
0x4000마크가 없는 경우, 더 이상KUBE-POSTROUTING체인을 처리하지 않고 다음 규칙으로 전달(RETURN)
- 패킷에
0x4000마크가 있는 경우,KUBE-POSTROUTING체인 내에서 모든 패킷에0x4000마크를 설정MASQUERADE규칙을 통해 쿠버네티스 서비스 트래픽의 출발지 IP를 변경하여 올바른 SNAT 처리를 적용.

externalTrafficPolicy
목적지 파드의 로그를 확인해보면 ClusterIP 와 다르게, 출발지 IP가 파드가 아닌, 노드의 IP가 출력됩니다.
즉, NodePort에서는 기본적으로 노드의 IP로 SNAT 되어서 웹서버에서 클라이언트의 IP를 수집할 수 없습니다.

하지만, 중요 서비스를 처리하는 경우 법적인 보안 요구사항으로, 최초 접속자(외부 클라이언트)의 IP를 수집해야 합니다.
이러한 문제를 해결할 수 있는 방법이 바로 externalTrafficPolicy 입니다.
externalTrafficPolicy: Local은 NodePort 통신 시에, 해당 노드에 배치된 파드로만 전달이 되며, 다른 노드에 배포된 파드로는 전달이 되지 않습니다.
실습 : externalTrafficPolicy: Local
svc-nodeport의 externalTrafficPolicy을 변경합니다 Cluster -> Local
# externalTrafficPolicy: local 설정 변경
kubectl patch svc svc-nodeport -p '{"spec":{"externalTrafficPolicy": "Local"}}'
kubectl get svc svc-nodeport -o json | grep 'TrafficPolicy"'
"externalTrafficPolicy": "Local",
"internalTrafficPolicy": "Cluster",
외부 클라이언트에서 다시 접속을 시도하고 로그를 확인합니다.
# 파드 로그 실시간 확인 (웹 파드에 접속자의 IP가 출력)
kubectl logs -f -l app=deploy-websrv
외부 클라이언트(mypc)에서 접속 시도
docker exec -it mypc curl $NODE1:$NPORT | jq
응답헤더의 ip를 살펴보면 노드 IP가 아닌, 외부 클라이언트(mypc)의 IP가 출력됨을 확인할 수 있습니다.

파드 3개를 2개로 줄이고, 각 노드로부터 NodePort 통신을 시도해 보면 컨트롤플레인과 노드2는 파드가 배치되지 않았기 때문에 접속되지 않습니다.
kubectl scale deployment deploy-echo --replicas=2
docker exec -it mypc curl $CODE:$NPORT | jq
docker exec -it mypc curl $NODE1:$NPORT | jq
docker exec -it mypc curl $NODE2:$NPORT | jq
docker exec -it mypc curl $NODE3:$NPORT | jq

서비스(NodePort) 부족한 점
- 보안 취약성: NodePort 서비스는 외부에서 노드의 IP와 포트를 통해 직접 접근해야 하므로 내부망이 노출되어 보안에 취약합니다.
- 클라이언트 IP 손실 :
externalTrafficPolicy: Local을 설정하면 클라이언트 IP를 보존할 수 있습니다. 하지만 이 경우, 해당 NodePort로 연결된 노드에 요청을 수신할 수 있는 파드가 존재하지 않으면 트래픽이 실패하게 됩니다. - 유연성 문제: 고정된 포트 범위(30000-32767)로 인해 포트 충돌 및 관리 어렵습니다.
결론
ClusterIP와 NodePort 서비스가 이렇게 복잡하게 동작하는 이유는, 초기 쿠버네티스 설계에서 개발자가 직접 서버를 관리하면서도 손쉽게 부하 분산과 서비스 연결을 설정할 수 있도록 하기 위함이었습니다.
하지만 이러한 구조는 각 노드에 iptables 규칙을 생성하고, 트래픽을 여러 노드 간 분산시키는 과정에서 비효율성을 초래하기도 합니다. 즉, 개발자 편의성을 위해 설계되었지만, 결과적으로 관리와 성능 측면에서 복잡하고 최적화되지 않은 동작 방식이 된 것입니다.
다음 포스팅에서는, 이러한 문제를 해결하기 위해 도입된 LoadBalancer 등 다양한 서비스에 대해 알아봅니다.
'Kubernetes > Network' 카테고리의 다른 글
| kube-proxy IPVS 모드의 동작 원리 이해 - KANS 5주차 2 (2) | 2024.10.06 |
|---|---|
| MetalLB를 활용한 LoadBalancer 서비스의 동작 원리 이해 - KANS 5주차 1 (2) | 2024.10.06 |
| Calico CNI 기본 네트워크 이해 & 네트워크 모드 - KANS 3주차 (5) | 2024.09.22 |
| Pause 컨테이너 & Flannel CNI - KANS 2주차 (3) | 2024.09.08 |
| 컨테이너 격리 & 네트워크 및 보안 - KANS 1주차 (0) | 2024.08.27 |