Kubernetes 네트워킹: CNI, Cilium(eBPF 및 네트워크 정책 포함)
Kubernetes는 뛰어난 방식으로 네트워크를 추상화합니다. 각 Pod는 라우팅 가능한 IP 주소를 얻습니다. 동일한 Pod 내의 컨테이너는 네트워크 네임스페이스를 공유하며 Pod는 다음을 수행할 수 있습니다. NAT 없이 어떤 노드에서든 서로 통신할 수 있습니다. 하지만 겉으로 보이는 단순함은 숨겨져 있습니다. 정말 복잡합니다. 이 모델은 실제로 어떻게 작동하나요? 누가 거래하는가 IP 할당, 노드 간 트래픽 라우팅, 네트워크 정책 구현?
대답은 컨테이너 네트워크 인터페이스(CNI), 표준은 네트워킹 플러그인이 Kubernetes와 통합되는 방법을 정의합니다. 이 기사에서는 Kubernetes 네트워킹 모델을 내부에서 살펴보겠습니다. kube-proxy 작동 방식, 이유 eBPF가 포함된 섬모 기존 솔루션을 대체하는가? 네트워크 정책을 구현하여 프로덕션 클러스터에서 워크로드를 격리합니다.
무엇을 배울 것인가
- Kubernetes 네트워크 모델: 포드당 IP, 플랫 네트워크, NAT 없음
- CNI(컨테이너 네트워크 인터페이스) 작동 방식 및 주요 플러그인
- kube-proxy(iptables/IPVS)와 eBPF를 사용하는 Cilium의 차이점
- eBPF는 iptables에 비해 -30% 지연 시간과 +60% 처리량을 제공하기 때문입니다.
- CNI로 Cilium을 설치하고 구성하는 방법
- 네트워크 정책: 구문, 실제 예, 기본 거부 및 네임스페이스 격리
- 레이어 7 규칙(HTTP, gRPC, Kafka)에 대한 CiliumNetworkPolicy
쿠버네티스 네트워크 모델
Kubernetes는 네 가지 기본 요구 사항을 갖춘 네트워킹 모델을 부과합니다. CNI 구현은 다음을 준수해야 합니다.
- 모든 포드는 NAT 없이 다른 모든 포드와 통신할 수 있습니다.
- 모든 노드는 NAT 없이 모든 포드와 통신할 수 있습니다.
- 포드가 자신의 것으로 간주하는 IP와 다른 사람이 포드에 도달하는 데 사용하는 동일한 IP
- Pod 내의 컨테이너는 네트워크 네임스페이스와 IP를 공유합니다.
이 "평면 네트워크 모델"은 애플리케이션 추론을 크게 단순화합니다. 마이크로서비스는 호출하는 서비스가 동일한 노드에 있는지 아니면 다른 노드에 있는지 알 필요가 없습니다. 원격. 복잡성은 클러스터 네트워크 계층으로 이동됩니다.
Pod 간 통신 작동 방식
Pod A가 다른 노드에 있는 Pod B와 통신하려고 할 때 일반적인 흐름은 다음과 같습니다. 오버레이 네트워크(예: VXLAN) 기반 솔루션을 따르십시오.
- 패키지는 인터페이스를 통해 Pod A의 컨테이너를 종료합니다.
eth0 - 다음을 통해 노드 네임스페이스를 입력합니다.
veth pair - CNI 플러그인은 이를 가로채서 VXLAN(또는 GRE, Geneve...)에 캡슐화합니다.
- 패킷은 물리적 네트워크를 통과하여 Pod B 노드로 이동합니다.
- 대상 노드의 CNI는 패킷을 캡슐화 해제합니다.
- 패킷은 veth 쌍을 통해 Pod B에 도착합니다.
BGP 또는 기본 라우팅(예: 기본 라우팅 모드의 Cilium) 기반 솔루션을 사용하면 캡슐화가 필요하지 않으며 성능이 크게 향상됩니다.
컨테이너 네트워크 인터페이스(CNI)
CNI는 컨테이너 런타임이 호출되는 방식을 정의하는 CNCF 사양입니다. 네트워크 플러그인. Kubernetes는 CNI를 사용하여 네트워크 관리를 플러그인에 위임합니다. kubelet이 포드를 생성할 때 구성된 CNI 플러그인을 호출하여 주소를 할당합니다. IP를 설정하고 네트워크 인터페이스를 구성합니다.
주요 CNI 플러그인
| 플러그인 | 기술 | 네트워크 정책 | L7 정책 | 사용 사례 |
|---|---|---|---|---|
| 플란넬 | VXLAN 오버레이 | 아니요(기본) | No | 개발, 단순 클러스터 |
| 옥양목 | BGP/오버레이 | Si | No | 온프레미스, 성능 |
| 섬모 | eBPF | Si | 예(HTTP, gRPC) | 생산, 서비스 메시 |
| AWS VPC CNI | ENI 네이티브 | 예(SG) | No | EKS |
| 애저 CNI | 네이티브 VNet | 예(NSG) | No | AKS |
kube-proxy: 기존 접근 방식
kube-proxy는 서비스 구현을 담당하는 Kubernetes 구성 요소입니다. 클라이언트가 서비스를 호출하면 kube-proxy는 트래픽이 다음 중 하나에 도착하는지 확인합니다. 포드 백엔드. 전통적으로 사용 iptables 이 목적을 위해.
iptables의 문제점은 규칙 수에 따라 복잡성이 선형적으로 증가한다는 것입니다. 10,000개의 서비스와 100,000개의 엔드포인트가 있는 클러스터에서 iptables는 수백만 개의 규칙을 관리합니다. 모든 패킷은 상당한 영향을 미치면서 이 규칙 체인을 통과해야 합니다. 노드의 대기 시간과 CPU에 관한 것입니다.
트리 내 대안 e IPVS (IP 가상 서버), 해시 테이블을 사용합니다. iptables 선형 스캔 대신 O(1) 조회를 위해. 그러나 IPVS에는 다음과 같은 제한 사항도 있습니다. 고급 정책을 지원하지 않으며 여전히 추가 iptables 규칙 관리가 필요합니다.
iptables 확장 문제
10,000개의 서비스를 통해 iptables가 포함된 kube-proxy는 서비스에만 약 40,000개의 규칙을 생성합니다. 이러한 규칙의 업데이트 시간은 밀리초에서 분으로 늘어납니다. 클러스터링됨 규모가 크면 이벤트 조정 및 배포 업데이트 중에 지연 시간이 길어집니다. 이것이 Cilium이 kube-proxy를 대체하는 주요 이유 중 하나입니다.
Cilium 및 eBPF: Kubernetes 네트워킹의 미래
eBPF (확장 버클리 패킷 필터)는 Linux 커널 기술입니다. 이를 통해 샌드박스 프로그램을 수정하지 않고도 커널에서 직접 실행할 수 있습니다. 커널 모듈 없이. Cilium은 eBPF를 사용하여 네트워크 트래픽을 가로채고 처리합니다. 커널 수준에서 iptables와 kube-proxy를 완전히 우회합니다.
eBPF를 사용한 Cilium의 이점
- 성능: iptables에 비해 지연 시간 최대 30% 감소, 처리량 60% 증가
- 확장성: O(1) iptables 선형 스캔 대신 BPF 맵으로 조회
- 관찰 가능성: 허블은 L3/L4/L7 트래픽에 대한 실시간 가시성을 제공합니다.
- 레이어 7 정책: HTTP 경로, 메소드, 헤더, gRPC 메소드, Kafka 주제 기반 정책
- 사이드카가 없는 서비스 메시: 커널에 mTLS 및 로드 밸런싱 구현, 사이드카 오버헤드 없음
- Kube 프록시 교체: Cilium은 kube-proxy를 완전히 대체할 수 있습니다.
실륨 설치
Helm을 사용하여 Kubernetes 클러스터에 Cilium을 설치하고 이를 대체하도록 구성합니다. kube-proxy를 사용하고 관찰 가능성을 위해 Hubble을 활성화합니다.
# Aggiungi il repo Helm di Cilium
helm repo add cilium https://helm.cilium.io/
helm repo update
# Installa Cilium con kube-proxy replacement e Hubble abilitati
helm install cilium cilium/cilium \
--version 1.16.0 \
--namespace kube-system \
--set kubeProxyReplacement=true \
--set k8sServiceHost=API_SERVER_HOST \
--set k8sServicePort=API_SERVER_PORT \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set ipam.mode=kubernetes
# Verifica installazione
cilium status --wait
# Verifica connettivita
cilium connectivity test
생산 중인 Cilium: 고급 구성
프로덕션 클러스터의 경우 다음을 포함한 전체 Helm 값 구성이 있습니다. 성능을 극대화하기 위한 기본 라우팅(VXLAN 캡슐화 없음):
# cilium-values-production.yaml
kubeProxyReplacement: true
k8sServiceHost: "10.0.0.1" # indirizzo API server
k8sServicePort: "6443"
# Native routing mode (senza overlay VXLAN)
# Richiede che la rete sottostante supporti il routing dei pod CIDR
tunnel: disabled
autoDirectNodeRoutes: true
ipv4NativeRoutingCIDR: "10.244.0.0/16"
# IPAM
ipam:
mode: kubernetes
# BGP per annunciare i pod CIDR ai router
bgp:
enabled: true
announce:
podCIDR: true
lbIP: true
# Hubble - osservabilita Layer 7
hubble:
enabled: true
metrics:
enabled:
- dns:query;ignoreAAAA
- drop
- tcp
- flow
- icmp
- http
relay:
enabled: true
replicas: 2
ui:
enabled: true
# Monitoring con Prometheus
prometheus:
enabled: true
serviceMonitor:
enabled: true
# Encryption (WireGuard)
encryption:
enabled: true
type: wireguard
# Load Balancing con DSR (Direct Server Return)
loadBalancer:
mode: dsr # elimina un hop di rete nel path di ritorno
# Limita connessioni per Pod
bpf:
mapDynamicSizeRatio: 0.0025
Kubernetes의 네트워크 정책
기본적으로 Kubernetes 클러스터의 모든 Pod는 서로 자유롭게 통신할 수 있습니다. 이는 개발에는 편리하지만 프로덕션에서는 보안 문제가 있습니다. 그만큼 네트워크 정책 Pod에 대한 진입 및 송신 규칙을 정의할 수 있습니다.
주의: CNI 플러그인 필요
NetworkPolicy는 Kubernetes 리소스이지만 구현은 다음에 따라 다릅니다. CNI 플러그인. Flannel은 기본적으로 NetworkPolicy를 지원하지 않습니다. 그것을 사용하려면 Cilium이 필요합니다. Calico 또는 이를 구현하는 다른 CNI입니다. 리소스가 서버 API에 의해 승인되었습니다. 하지만 CNI가 지원하지 않으면 무시됩니다.
기본 거부: 기본 모범 사례
워크로드를 격리하고 정책을 적용하는 첫 번째 단계 기본 거부 각 네임스페이스에. 이는 명시적으로 승인되지 않은 모든 트래픽을 거부합니다.
# default-deny-all.yaml
# Nega tutto il traffico ingress e egress nel namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # seleziona TUTTI i pod nel namespace
policyTypes:
- Ingress
- Egress
---
# Permetti il traffico DNS (necessario per la risoluzione dei nomi)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
일반적인 애플리케이션을 위한 NetworkPolicy
프런트엔드, 백엔드, 데이터베이스라는 3계층 애플리케이션을 분리하는 방법을 살펴보겠습니다. 프런트엔드만 외부로부터의 트래픽을 허용하고 백엔드만 DB에 도달할 수 있습니다.
# network-policies-app.yaml
# Frontend: accetta traffico dall'ingress controller
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
podSelector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 8000
- ports:
- protocol: UDP
port: 53
---
# Backend: accetta solo dal frontend, puo raggiungere DB
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8000
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- ports:
- protocol: UDP
port: 53
---
# Database: accetta solo dal backend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
CiliumNetworkPolicy: 정책 계층 7
표준 Kubernetes NetworkPolicy는 레이어 3/4(IP 및 포트)에서 작동합니다. 섬모가 확장됩니다. 이것으로 CiliumNetworkPolicy, 컨텐츠 기반 정책을 허용합니다. 통신: HTTP 경로, gRPC 방법, Kafka 주제, DNS 쿼리.
Cilium을 사용한 HTTP 정책
프런트엔드가 특정 백엔드 엔드포인트만 호출하도록 허용합니다.
# cilium-http-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: frontend-to-backend-l7
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8000"
protocol: TCP
rules:
http:
- method: "GET"
path: "/api/v1/products.*"
- method: "POST"
path: "/api/v1/orders"
- method: "GET"
path: "/health"
Cilium을 사용한 DNS 정책
포드가 확인할 수 있는 DNS 도메인을 제한합니다(데이터 유출 방지에 유용함).
# cilium-dns-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: restrict-dns-egress
namespace: production
spec:
endpointSelector:
matchLabels:
app: backend
egress:
# Permetti solo DNS verso il cluster DNS
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s:k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: ANY
rules:
dns:
- matchPattern: "*.internal.company.com"
- matchPattern: "*.svc.cluster.local"
- matchPattern: "api.stripe.com"
허블: 네트워크 관측성
허블과 Cilium 관측 레이어. 실시간 가시성을 제공합니다. 모든 클러스터 네트워크 트래픽(통신 ID 기반) IP 주소 대신 Kubernetes 라벨을 지정합니다.
# Installa il CLI di Hubble
export HUBBLE_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/hubble/master/stable.txt)
curl -L --fail --remote-name-all \
https://github.com/cilium/hubble/releases/download/$HUBBLE_VERSION/hubble-linux-amd64.tar.gz
tar xzvf hubble-linux-amd64.tar.gz
sudo mv hubble /usr/local/bin
# Port-forward al relay Hubble
cilium hubble port-forward &
# Osserva il traffico in tempo reale
hubble observe --namespace production --follow
# Filtra per Pod specifici
hubble observe \
--namespace production \
--from-pod frontend-7d9d6b8f-abc12 \
--to-pod backend-5c4f8d9-xyz99 \
--follow
# Mostra solo i drop (traffico bloccato dalle policy)
hubble observe \
--namespace production \
--verdict DROPPED \
--follow
# Statistiche per service
hubble observe \
--namespace production \
--output json | jq '.flow.destination.namespace'
네트워크 정책 디버깅 및 문제 해결
NetworkPolicy 디버깅은 Kubernetes에서 가장 일반적인 과제 중 하나입니다. 여기에 한 가지 접근 방식이 있습니다. 체계적:
# 1. Verifica quali NetworkPolicy si applicano a un Pod
kubectl get networkpolicies -n production -o wide
# 2. Test di connettivita con un Pod temporaneo
kubectl run test-pod \
--image=nicolaka/netshoot \
--rm \
-it \
--restart=Never \
-n production \
-- bash
# All'interno del Pod:
# Test TCP
nc -zv backend-service 8000
# Test DNS
nslookup backend-service.production.svc.cluster.local
# Test HTTP
curl -v http://backend-service:8000/health
# 3. Con Cilium, usa il tool di policy verification
cilium policy get # mostra tutte le policy caricate
# 4. Testa la connettivita specifica
kubectl exec -n production frontend-pod -- \
curl -v http://backend-service:8000/api/v1/products
# 5. Con Hubble, vedi perche un pacchetto viene droppato
hubble observe \
--namespace production \
--verdict DROPPED \
--from-pod frontend-7d9d6b8f \
--follow
다중 네임스페이스 격리
다중 테넌트 클러스터에서는 네임스페이스를 격리하는 것이 중요합니다. 기본적으로 NetworkPolicy는 네임스페이스 간 트래픽을 차단하지 않습니다. 완전한 격리를 구현하는 방법은 다음과 같습니다.
# Isola completamente un namespace da tutti gli altri
# (ma permette il traffico interno al namespace)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: namespace-isolation
namespace: tenant-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
# Permetti solo traffico dallo stesso namespace
- from:
- podSelector: {}
# Permetti da monitoring namespace
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
egress:
# Permetti solo traffico verso lo stesso namespace
- to:
- podSelector: {}
# Permetti DNS
- ports:
- protocol: UDP
port: 53
# Permetti verso monitoring namespace
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
성능 벤치마크: Cilium 대 kube-proxy
벤치마크는 eBPF를 사용하는 Cilium과 iptables를 사용하는 kube-proxy 사이에 상당한 차이를 보여줍니다. 서비스 수가 많은 클러스터:
| 미터법 | kube-proxy iptables | 섬모 eBPF | 개선 |
|---|---|---|---|
| P50 대기 시간(10K 서비스) | 450μs | 130μs | -71% |
| P99 대기 시간(10K 서비스) | 2.1ms | 320μs | -85% |
| 처리량(Gbps) | 22Gbps | 36Gbps | +64% |
| CPU 업데이트 규칙(10K svc) | 180초 | 2초 | -99% |
| 연결/초 | 220K | 380K | +73% |
Kubernetes 네트워킹 모범 사례
생산 네트워킹 체크리스트
- 지금 올바른 CNI를 선택하세요. 프로덕션 및 컴플렉스의 Migare CNI. 고급 네트워크 정책이나 서비스 메시를 계획하고 있다면 Cilium을 고려해 보세요.
- 모든 네임스페이스에서 기본 거부: 항상 모든 것을 거부하는 정책으로 시작한 다음 예외를 추가하세요.
- 포드의 일관된 라벨: NetworkPolicy는 라벨에 따라 다릅니다. 명확한 규칙(앱, 계층, 버전)을 사용하세요.
- 배포하기 전에 정책을 테스트하세요. 미국
cilium connectivity test또는 테스트 포드를 통해 확인하세요. - 허블 활성화: 프로덕션에서는 디버깅 및 규정 준수를 위해 트래픽 가시성이 중요합니다.
- 트랙 드롭: 예기치 않게 삭제된 트래픽에 대해 Prometheus에서 경고 구성
- DNS를 차단하지 마세요: 송신 정책에서 UDP/TCP 53을 kube-dns에 허용하는 것을 항상 기억하세요.
- 문서 정책: Kubernetes 주석을 사용하여 각 NetworkPolicy의 목적 설명
피해야 할 안티패턴
NetworkPolicy의 일반적인 오류
- 너무 느슨한 정책: 사용
namespaceSelector: {}matchLabels가 없으면 손상된 네임스페이스를 포함하여 모든 네임스페이스의 트래픽이 허용됩니다. - DNS를 잊어버리는 중: 모든 송신을 차단하고 포트 53을 잊어버린 경우 포드는 더 이상 호스트 이름을 확인하지 않습니다.
- 업데이트되지 않은 라벨: 올바른 라벨 없이 새 포드를 추가하면 NetworkPolicy가 이를 보호하지 않습니다.
- 개발 중인 테스트만 해당: NetworkPolicy는 프로덕션에서 예기치 않은 트래픽을 차단할 수 있습니다. 항상 현실적인 트래픽이 있는 스테이징에서 테스트하세요.
- 선택기 대신 IP를 사용하십시오. 포드 IP가 변경됩니다. 항상 podSelector 및 네임스페이스Selector를 사용하고, 내부 트래픽에는 ipBlock을 사용하지 마세요.
결론 및 다음 단계
플랫한 포드당 IP 접근 방식을 갖춘 Kubernetes 네트워킹 모델은 디자인이 우아합니다. 단순하면서도 구현이 정교합니다. CNI 플러그인을 선택하는 것은 다음 중 하나입니다. 생산 클러스터에 대한 가장 중요한 아키텍처 결정: 성능, 보안 및 관찰 가능성 기능을 사용할 수 있습니다.
eBPF가 포함된 Cilium은 현재 사용 가능한 가장 발전된 CNI입니다. kube-proxy를 다음으로 대체하세요. 뛰어난 성능, 레이어 7 정책 제공, Hubble과 관측 가능성 통합 및 mTLS용 기존 서비스 메시를 대체할 수 있습니다. 프로덕션 중인 새 클러스터의 경우 CNCF 커뮤니티와 Google, Amazon, 관리형 Kubernetes 서비스에서 이를 사용하는 Microsoft.
기본 거부 접근 방식으로 올바르게 구현된 네트워크 정책은 포드가 손상되면 공격 표면이 대폭 줄어듭니다. 나는 아니다 생산 시 선택 사항: 이는 기본적인 안전 요구 사항입니다.
Kubernetes at Scale 시리즈의 향후 기사
관련 시리즈
- 프로덕션에서의 MLOps 및 기계 학습 — Kubernetes의 GPU 워크로드
- 플랫폼 엔지니어링 — K8s의 내부 개발자 플랫폼
- 관찰 가능성 및 OpenTelemetry — 클러스터 모니터링







