Service & Networking
모든 Pod는 고유 IP를 가진다 — K8s 네트워킹의 핵심 원칙
1. K8s 네트워킹 모델
1.1 세 가지 규칙
- 모든 Pod는 고유한 IP를 가짐 (NAT 없이 직접 통신)
- 모든 노드의 Pod끼리 NAT 없이 통신 가능
- Pod가 보는 자신의 IP = 다른 Pod가 보는 그 Pod의 IP
이 규칙을 구현하는 것이 CNI(Container Network Interface) 플러그인의 역할.
1.2 네트워크 계층
flowchart TB
subgraph External["외부 트래픽"]
Client["클라이언트"]
end
subgraph L7["L7 — Ingress"]
Ingress_NW["Ingress Controller<br/>(Nginx/Traefik)"]
end
subgraph L4["L4 — Service"]
SVC["Service<br/>(ClusterIP/NodePort/LB)"]
end
subgraph L3["L3 — Pod Network"]
Pod_NW["Pod ↔ Pod<br/>(CNI 관리)"]
end
Client --> Ingress_NW --> SVC --> Pod_NW
2. Service
Pod는 죽으면 IP가 바뀜. Service는 Pod 그룹에 안정적인 IP와 DNS 이름을 부여함.
2.1 Service 유형
| 유형 | 접근 범위 | 사용 |
|---|---|---|
| ClusterIP (기본) | 클러스터 내부만 | 내부 서비스 간 통신 |
| NodePort | 노드IP:포트로 외부 접근 | 개발/테스트 |
| LoadBalancer | 클라우드 LB 자동 생성 | ✅ 프로덕션 (클라우드) |
| ExternalName | 외부 DNS로 매핑 | 외부 서비스 참조 |
flowchart LR
subgraph ClusterIP_SVC["ClusterIP"]
CIP["10.96.0.100:80"] --> Pod1_C["Pod 1"] & Pod2_C["Pod 2"]
end
subgraph NodePort_SVC["NodePort"]
NP["NodeIP:30080"] --> CIP2["ClusterIP"] --> Pod1_N["Pod 1"] & Pod2_N["Pod 2"]
end
subgraph LB_SVC["LoadBalancer"]
LB_NW["외부 LB IP:80"] --> NP2["NodePort"] --> CIP3["ClusterIP"] --> Pod1_L["Pod 1"] & Pod2_L["Pod 2"]
end
2.2 Service 동작 원리
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web # 이 레이블을 가진 Pod에 트래픽 분산
ports:
- port: 80 # Service 포트
targetPort: 8080 # Pod 포트
type: ClusterIP
kube-proxy가 각 노드에 iptables/IPVS 규칙을 생성하여, Service IP로 들어오는 트래픽을 실제 Pod IP로 분산함.
2.3 Session Affinity
spec:
sessionAffinity: ClientIP # 같은 클라이언트 → 같은 Pod
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
3. DNS — CoreDNS
3.1 서비스 DNS
<service>.<namespace>.svc.cluster.local
예: web.default.svc.cluster.local
db.production.svc.cluster.local
같은 네임스페이스에서는 서비스 이름만으로 접근 가능: curl http://web
3.2 Pod DNS
<pod-ip-dashed>.<namespace>.pod.cluster.local
예: 10-244-1-5.default.pod.cluster.local
4. Ingress
4.1 왜 Ingress인가
Service(NodePort/LB)만으로는:
- 서비스마다 별도 포트/LB 필요
- TLS 종단을 각 서비스에서 처리
- 경로/도메인 기반 라우팅 불가
Ingress는 L7 라우팅 + TLS 종단 + 호스트/경로 기반 분배를 한 곳에서 처리.
4.2 Ingress Controller
Ingress 오브젝트를 감시하고 실제 라우팅을 수행하는 컴포넌트. 별도 설치 필요.
| Controller | 특징 |
|---|---|
| Nginx Ingress | ✅ 가장 많이 사용. 안정적 |
| Traefik | 동적 설정, Let's Encrypt 자동화 |
| HAProxy | 고성능, TCP/UDP 지원 |
| Istio Gateway | Service Mesh와 통합 |
| AWS ALB Ingress | AWS ALB 자동 프로비저닝 |
4.3 Ingress 설정 예시
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
4.4 Gateway API (Ingress 후속)
Ingress의 한계(L4 미지원, 복잡한 라우팅 어려움)를 해결하기 위해 Gateway API가 등장. K8s 공식 후속 표준.
| Ingress | Gateway API | |
|---|---|---|
| L4 | ❌ | ✅ TCP/UDP |
| L7 | ✅ | ✅ |
| 역할 분리 | 없음 | 인프라(GatewayClass) / 클러스터(Gateway) / 앱(HTTPRoute) |
| 상태 | 안정적, 레거시 | GA, 점진적 전환 |
5. NetworkPolicy
5.1 Pod 간 트래픽 제어
기본적으로 K8s에서 모든 Pod는 모든 Pod와 통신 가능. NetworkPolicy로 이를 제한.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-policy
namespace: production
spec:
podSelector:
matchLabels:
app: db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api # api Pod에서만 DB 접근 허용
ports:
- port: 5432
5.2 CNI별 NetworkPolicy 지원
| CNI | NetworkPolicy | 비고 |
|---|---|---|
| Calico | ✅ | 가장 많이 사용되는 CNI |
| Cilium | ✅ (L7까지) | eBPF 기반, 관찰성 우수 |
| Flannel | ❌ | 가장 단순하지만 NetworkPolicy 미지원 |
| Weave | ✅ |
6. CNI 비교
| CNI | 기술 | NetworkPolicy | 특징 | 추천 |
|---|---|---|---|---|
| Flannel | VXLAN | ❌ | 가장 단순, 소규모/학습용 | 학습 |
| Calico | BGP/VXLAN | ✅ | ✅ 가장 많이 사용, 유연한 정책 | 프로덕션 |
| Cilium | eBPF | ✅ (L7) | 고성능, 관찰성, Service Mesh 통합 | ✅ 차세대 |
| Weave | VXLAN | ✅ | 멀티클라우드 친화 |
💡 Calico가 현재 표준, Cilium이 차세대. Cilium은 eBPF를 사용하여 kube-proxy를 대체할 수 있고, L7 정책, 네이티브 관찰성까지 제공함. 새로 구축한다면 Cilium을 검토할 가치가 있음.
다음 글
→ #5 Storage — PV, PVC, StorageClass, CSI