Skip to content

KR_K8s_Network

somaz edited this page Mar 30, 2026 · 1 revision

쿠버네티스 네트워크 심화 (Q11-Q21)

네트워크 심화 (11~20번)


Q11. 같은 노드 내 Pod 통신에서 ARP Proxy의 동작 원리는?

  • Pod의 veth pair는 호스트의 caliXXX 인터페이스와 연결되는데, caliXXX는 IP 없이 MAC 주소만 가진다.
  • Pod가 목적지 Pod의 MAC 주소를 알기 위해 ARP 요청을 보내면, 호스트 커널의 ARP Proxy가 자신의 MAC 주소로 응답한다.
  • Pod는 호스트 MAC으로 패킷을 보내고, 호스트의 라우팅 테이블이 목적지 Pod의 veth 인터페이스로 패킷을 전달한다. 이를 통해 L2 브리지 없이도 효율적인 Pod 간 통신이 가능하다.

Q12. Overlay Network의 VXLAN 캡슐화 과정과 성능 영향은?

VXLAN은 L2 over L3 터널링으로 동작한다.

  • ① Pod의 원본 패킷(Inner Ethernet + IP) →
  • ② VXLAN 헤더 추가(VNID 포함) →
  • ③ 외부 UDP 헤더(포트 4789) 추가 →
  • ④ 외부 IP 헤더(노드 IP) 추가 →
  • ⑤ 외부 Ethernet 헤더.

MTU는 1500에서 50바이트 감소하여 1450이 되며, CPU 오버헤드(캡슐화/역캡슐화)와 대역폭 오버헤드(약 3%)가 발생한다. AWS VPC CNI는 이를 해결하기 위해 Pod가 VPC IP를 직접 사용한다.


Q13. iptables vs IPVS 모드의 성능 차이와 선택 기준은?

  • iptables는 순차 검색으로 O(n) 복잡도를 가지며, 1000개 이상 Service에서 성능 저하가 발생한다. Rule 업데이트 시 전체 재작성이 필요하다.
  • IPVS는 해시 테이블로 O(1) 복잡도를 가지며, 대규모 클러스터에 적합하다. rr(라운드 로빈), lc(최소 연결), sh(소스 해싱) 등 다양한 로드밸런싱 알고리즘을 지원한다.
  • 100개 이하 Service는 iptables, 그 이상은 IPVS를 권장한다. IPVS는 ipvsadm으로 실시간 연결 상태를 확인할 수 있다.

Q14. kube-proxy의 iptables 체인 구조와 DNAT/SNAT 과정은?

Service 생성 시 kube-proxy가 iptables 규칙을 생성한다.

  • PREROUTING → KUBE-SERVICES → KUBE-SVC-XXX → KUBE-SEP-XXX (각 Pod Endpoint). ClusterIP 트래픽: DNAT로 Pod IP로 변환.
  • NodePort 트래픽: KUBE-MARK-MASQ로 마킹 후 SNAT로 노드 IP로 변환(externalTrafficPolicy: Cluster), Local 설정 시 SNAT 생략.
  • conntrack으로 연결 추적하여 응답 패킷도 올바르게 라우팅한다. iptables-save로 전체 규칙을 확인하고, KUBE-SERVICES 체인부터 추적한다.

Q15. CoreDNS의 캐싱 전략과 ndots 설정의 영향은?

  • CoreDNS는 /etc/resolv.conf 의 ndots(기본값 5) 설정에 따라 DNS 쿼리를 처리한다.
  • FQDN이 아닌 경우 search 도메인을 순차적으로 붙여 조회하므로, my-service 조회 시 최대 6번의 쿼리가 발생할 수 있다.
  • ndots를 낮추거나 FQDN(my-service.namespace.svc.cluster.local)을 사용하여 쿼리 수를 줄인다.
  • CoreDNS는 cache plugin으로 TTL 기반 캐싱을 하며, 응답 시간을 ms 단위로 단축한다. autopath plugin은 search 순서를 최적화한다.

Q16. Calico의 BGP 라우팅과 Route Reflector의 역할은?

  • Calico는 BGP로 Pod CIDR 정보를 노드 간 광고한다.
  • Full-mesh 모드는 모든 노드가 서로 피어링하여 N(N-1)/2 개의 연결이 생성되므로, 100개 이상 노드에서는 확장성 문제가 발생한다.
  • Route Reflector 모드는 중앙 RR 노드가 라우팅 정보를 집중 관리하여 N개의 연결만 필요하다.
  • RR은 SPOF 방지를 위해 다중화하며, Kubernetes Node를 RR로 설정하거나 전용 RR을 구성한다. calicoctl node status로 BGP 피어 상태를 확인한다.

Q17. Service Mesh 없이 Pod 간 mTLS 구현 방법은?

  • ① Cert-Manager로 CA 인증서 생성 →
  • ② 각 Pod에 TLS Secret 마운트 →
  • ③ 애플리케이션에서 TLS 핸드셰이크 구현.

NetworkPolicy로 특정 Label Pod만 통신 허용하고, PSP(Pod Security Policy) 또는 PSA(Pod Security Admission)로 권한 제한한다.

Linkerd/Istio 같은 Service Mesh는 이를 자동화하여 애플리케이션 코드 수정 없이 mTLS를 제공하며, 트래픽 암호화, 인증, 인가, Observability를 통합 관리한다.


Q18. Ingress Controller의 동작 원리와 NGINX vs Traefik vs Istio Gateway 비교는?

  • Ingress Controller는 Ingress 리소스를 감시하여 리버스 프록시 설정을 자동 생성한다. NGINX Ingress: 가장 성숙하고 안정적, annotation 기반 설정, ConfigMap으로 글로벌 설정.
  • Traefik: 동적 설정, 자동 SSL(Let's Encrypt), 미들웨어 체인, Kubernetes CRD 지원.
  • Istio Gateway: Service Mesh 통합, L7 라우팅, 트래픽 분할(Canary), mTLS, Observability 내장.
  • 단순한 L7 라우팅은 NGINX, 동적 환경은 Traefik, 마이크로서비스 고급 기능은 Istio를 선택한다.

Q19. AWS LoadBalancer Controller vs Legacy Cloud Provider의 차이는?

Legacy(in-tree)는 K8s 코어에 포함되어 업데이트가 느리고, Classic LB만 지원한다.

AWS LoadBalancer Controller(out-of-tree)는 ALB/NLB를 네이티브 지원하고, IP 모드, TargetGroupBinding, WAF 통합, Subnet Discovery(태그 기반), NLB의 Client IP 보존을 제공한다.

Ingress로 ALB 생성 시 annotation으로 세밀한 제어가 가능하며, Service로 NLB 생성 시 Instance/IP 타입을 선택할 수 있다. IP 타입은 Pod IP를 직접 등록하여 노드 홉을 제거한다.


Q20. 외부 클라이언트 Source IP 확인 방법과 X-Forwarded-For vs Proxy Protocol 차이는?

  • AWS: externalTrafficPolicy: Local + NLB(Proxy Protocol v2)로 클라이언트 IP 유지. ALB는 X-Forwarded-For 헤더 사용.
  • On-Premise: externalTrafficPolicy: Local + MetalLB(Layer2/BGP 모드).
  • X-Forwarded-For: HTTP 헤더, L7에서만 동작, 애플리케이션 파싱 필요, 여러 프록시 거칠 때 체인 형성.
  • Proxy Protocol: TCP 연결 시작 시 바이너리 헤더 전송, L4에서 동작, NGINX/HAProxy 지원, 성능 우수. externalTrafficPolicy: Local 은 불균형 문제가 있으므로 Pod가 모든 노드에 고르게 분산되도록 Anti-Affinity 설정이 필요하다.

💡 용어 설명:

  • 네트워크 심화 질문들(Q11-Q20)에서 사용된 용어들(ARP Proxy, Overlay Network, VXLAN, IPIP, iptables, IPVS, CNI, Calico, BGP, CoreDNS, Ingress Controller, X-Forwarded-For, Proxy Protocol 등)에 대한
  • 상세한 설명은 문서 상단의 주요 용어 통합 정리 > 네트워킹 섹션을 참고하세요.

Q21. 외부에서 Pod까지 전체 패킷 흐름을 단계별로 설명하세요.

  • External Traffic → Ingress Controller/LoadBalancer(AWS ELB, NLB, ALB) 진입 →
  • Service ClusterIP(Virtual IP, Endpoints 관리) →
  • kube-proxy(iptables KUBE-SERVICES 체인, DNAT로 Pod IP 변환, IPVS 모드는 해시 테이블 사용) →
  • CNI Network(Calico/Flannel이 라우팅, 같은 노드는 veth pair + ARP Proxy) →
  • Overlay Network(다른 노드는 VXLAN/IPIP 캡슐화, 터널링 인터페이스) →
  • Pod Container Port 도착. 디버깅: kubectl logs, tcpdump, iptables-save, Endpoints 확인, NetworkPolicy 검증.

💡 용어 설명:

  • 위 답변에 사용된 네트워크 관련 용어들(ClusterIP, Endpoints, DNAT, IPVS, CNI, veth pair, ARP Proxy, Overlay Network, VXLAN, IPIP, 캡슐화, NetworkPolicy 등)에 대한
  • 상세한 설명은 문서 상단의 주요 용어 통합 정리 > 네트워킹 섹션을 참고하세요.

Q21-1. CNI Plugin이 Pod 네트워크를 설정하는 전체 과정과 IPAM의 역할은?

CNI(Container Network Interface)는 kubelet과 네트워크 플러그인 간의 표준 인터페이스다.

Pod 네트워크 설정 흐름:

  • ① kubelet이 CRI(Container Runtime Interface)를 통해 컨테이너 생성 요청 →
  • ② CRI가 네트워크 네임스페이스 생성 →
  • ③ kubelet이 CNI Plugin 호출(ADD 커맨드) →
  • IPAM(IP Address Management) Plugin이 사용 가능한 IP 주소 할당 →
  • ⑤ CNI Plugin이 veth pair 생성(한쪽은 Pod 네임스페이스, 다른쪽은 호스트) →
  • ⑥ Pod쪽 인터페이스에 IP 설정 및 기본 라우트 추가 →
  • ⑦ 호스트쪽 인터페이스를 브리지 또는 라우팅 테이블에 연결 →
  • ⑧ CNI가 결과(IP, Gateway, DNS)를 kubelet에 반환.

IPAM 역할:

  • host-local: 로컬 파일에 IP 할당 정보 저장, 간단하지만 노드 간 동기화 없음.
  • Calico IPAM: etcd 기반 분산 IP 관리, IP Pool 개념으로 효율적 할당.
  • Whereabouts: etcd/Kubernetes API로 멀티 네트워크 IP 관리.

디버깅:

  • CNI 로그: /var/log/pods/ 또는 /opt/cni/bin/ 실행 로그
  • IP 할당 상태: Calico의 경우 calicoctl ipam show
  • 네트워크 네임스페이스: ip netns list, nsenter 명령으로 접근

Q21-2. Service Mesh에서 Sidecar Proxy가 트래픽을 가로채는 iptables 규칙 원리는?

Istio/Linkerd 같은 Service Mesh는 Envoy/Linkerd-proxy를 sidecar로 주입하여 모든 트래픽을 가로챈다.

Sidecar Injection 과정:

  • ① Mutating Admission Webhook이 Pod Spec 수정 →
  • ② Init Container(istio-init)가 iptables 규칙 설정 →
  • ③ Sidecar Proxy 컨테이너 추가 →
  • ④ 애플리케이션 컨테이너와 함께 실행.

iptables 규칙 구조:

# Outbound 트래픽 가로채기
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001

# Inbound 트래픽 가로채기
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A ISTIO_INBOUND -p tcp --dport 80 -j REDIRECT --to-ports 15006

동작 원리:

  • Outbound: 애플리케이션이 외부로 보내는 트래픽을 Envoy의 15001 포트로 리다이렉트
  • Inbound: Pod로 들어오는 트래픽을 Envoy의 15006 포트로 리다이렉트
  • Envoy가 mTLS, 라우팅, 로드밸런싱, Retry, Circuit Breaker 적용 후 실제 목적지로 전달

예외 처리:

  • Envoy 자신의 트래픽은 무한 루프 방지를 위해 제외
  • Prometheus 메트릭 수집 포트(15090) 제외
  • traffic.sidecar.istio.io/excludeOutboundPorts annotation으로 특정 포트 제외

Q21-3. Kubernetes에서 MTU 불일치로 인한 패킷 단편화 문제와 해결 방법은?

MTU(Maximum Transmission Unit)는 한 번에 전송 가능한 최대 패킷 크기다.

문제 상황:

  • 일반 Ethernet MTU: 1500 bytes
  • VXLAN Overlay 오버헤드: 50 bytes (VXLAN header 8 + Outer IP 20 + Outer UDP 8 + Outer Ethernet 14)
  • Pod의 실제 사용 가능 MTU: 1450 bytes
  • 애플리케이션이 1500 byte 패킷 전송 시 단편화(fragmentation) 발생

증상:

  • 대용량 데이터 전송 시 성능 저하
  • TCP 연결이 중간에 끊김
  • PMTUD (Path MTU Discovery) 실패 시 통신 불가

해결 방법:

1. Pod MTU 자동 설정:

# Calico CNI 설정
apiVersion: projectcalico.org/v3
kind: FelixConfiguration
metadata:
  name: default
spec:
  mtuIfacePattern: "^((en|wl|ww|sl|ib)[opsx].*|(eth|wlan|wwan).*)"
  vxlanMTU: 1450  # VXLAN 사용 시

2. CNI에서 자동 감지:

  • Calico: FELIX_IPINIPMTU, FELIX_VXLANMTU 환경변수
  • Cilium: tunnel-protocol 설정에 따라 자동 계산
  • AWS VPC CNI: ENI MTU 기반 자동 설정 (Jumbo Frame 지원 시 9001)

3. TCP MSS Clamping:

# iptables로 MSS 조정
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

4. 물리 인터페이스 Jumbo Frame 활성화:

# 호스트 네트워크에서 MTU 증가
ip link set dev eth0 mtu 9000

확인 방법:

# Pod 내부 MTU 확인
kubectl exec -it <pod> -- ip link show eth0

# PMTUD 테스트 (Don't Fragment 플래그로 ping)
ping -M do -s 1472 <destination>  # 성공하면 MTU 1500 OK
ping -M do -s 1422 <destination>  # VXLAN 환경에서 테스트

Q21-4. NodePort Service의 SNAT 동작과 Session Affinity 문제를 설명하세요.

NodePort Service는 모든 노드의 특정 포트로 외부 접근을 허용한다.

기본 동작 (externalTrafficPolicy: Cluster):

  • ① 외부 클라이언트가 Node1:30080으로 요청 →
  • ② Node1의 kube-proxy가 랜덤하게 Node2의 Pod B 선택 →
  • SNAT(Source NAT) 발생: 클라이언트 IP → Node1 IP로 변경 →
  • ④ Pod B는 Node1을 클라이언트로 인식 (원본 IP 손실) →
  • ⑤ 응답 패킷도 Node1을 거쳐 돌아감 (추가 홉)

SNAT 발생 이유:

  • Node2의 Pod B가 클라이언트 IP로 직접 응답하면, 클라이언트는 Node1으로 요청했는데 Node2에서 응답이 와서 연결이 끊김 (비대칭 라우팅)
  • SNAT로 Node1 IP를 유지하여 응답 경로 보장

Session Affinity 문제:

apiVersion: v1
kind: Service
spec:
  sessionAffinity: ClientIP  # 같은 클라이언트 IP는 같은 Pod로
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800  # 3시간

문제점:

  • SNAT로 인해 모든 요청이 Node IP에서 오는 것처럼 보임
  • 여러 클라이언트가 같은 Node를 통하면 모두 같은 Pod로 라우팅 (불균형)

해결 방법:

1. externalTrafficPolicy: Local 사용:

spec:
  type: NodePort
  externalTrafficPolicy: Local  # SNAT 제거, 원본 IP 유지
  • 장점: 클라이언트 IP 유지, Session Affinity 정상 동작, 홉 감소
  • 단점: Pod 없는 노드로 요청 시 실패, 불균형 가능성

2. LoadBalancer + Proxy Protocol:

service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"

3. Ingress Controller 사용:

  • L7에서 X-Forwarded-For 헤더로 원본 IP 전달
  • Ingress가 Session Affinity 관리 (Cookie 기반)

디버깅:

# conntrack 테이블 확인
conntrack -L | grep <service-ip>

# iptables SNAT 규칙 확인
iptables -t nat -L KUBE-POSTROUTING -n -v

# Session Affinity 동작 확인
kubectl get endpoints <service> --watch

Q21-5. Dual-Stack (IPv4/IPv6) Kubernetes 클러스터 구성과 고려사항은?

Dual-Stack은 IPv4와 IPv6를 동시에 지원하는 네트워크 구성이다 (K8s 1.23+ GA).

클러스터 설정:

# kube-apiserver 플래그
--service-cluster-ip-range=10.96.0.0/12,fd00:1234::/112
--feature-gates=IPv6DualStack=true

# kube-controller-manager 플래그
--cluster-cidr=10.244.0.0/16,fd00:5678::/104
--service-cluster-ip-range=10.96.0.0/12,fd00:1234::/112
--node-cidr-mask-size-ipv4=24
--node-cidr-mask-size-ipv6=120

Pod 네트워크:

apiVersion: v1
kind: Pod
metadata:
  name: dual-stack-pod
spec:
  containers:
  - name: app
    image: nginx
status:
  podIPs:
  - ip: 10.244.1.5      # IPv4
  - ip: fd00:5678::5    # IPv6

Service 구성:

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ipFamilyPolicy: PreferDualStack  # SingleStack | PreferDualStack | RequireDualStack
  ipFamilies:
  - IPv4
  - IPv6
  clusterIPs:
  - 10.96.100.200      # Primary (IPv4)
  - fd00:1234::200     # Secondary (IPv6)

CNI 지원:

  • Calico: Dual-Stack 완전 지원, IPv6 BGP 피어링
  • Cilium: Native IPv6 지원, eBPF 기반 고성능
  • Flannel: 제한적 지원 (VXLAN 모드만)

고려사항:

1. DNS 해석:

# CoreDNS가 AAAA 레코드 자동 생성
my-service.default.svc.cluster.local.  # A + AAAA 반환

2. 애플리케이션 호환성:

  • 0.0.0.0:8080::/0:8080 또는 [::]:8080 (IPv6 바인딩)
  • Go: net.Listen("tcp", ":8080") 자동 Dual-Stack
  • Python: socket.AF_INET6 + IPV6_V6ONLY=0

3. NetworkPolicy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
spec:
  ingress:
  - from:
    - ipBlock:
        cidr: 10.0.0.0/8      # IPv4
    - ipBlock:
        cidr: fd00::/8        # IPv6

4. Cloud Provider 제약:

  • AWS: VPC IPv6 CIDR 필요, ELB는 Dual-Stack NLB만 지원
  • GCP: Dual-Stack GKE 베타, 추가 설정 필요
  • Azure: AKS Dual-Stack 프리뷰

마이그레이션 전략:

  • ① IPv4 Single-Stack 클러스터 구성
  • ipFamilyPolicy: PreferDualStack으로 점진적 IPv6 추가
  • ③ 애플리케이션별 IPv6 호환성 검증
  • ipFamilyPolicy: RequireDualStack으로 강제
  • ⑤ Primary IP Family를 IPv6로 전환 (ipFamilies 순서 변경)

디버깅:

# Pod IPv6 주소 확인
kubectl get pod <pod> -o jsonpath='{.status.podIPs}'

# IPv6 연결 테스트
kubectl exec -it <pod> -- curl -6 http://[fd00:1234::200]:80

# CNI IPv6 라우팅 확인
ip -6 route show

Clone this wiki locally