204. Networking - Introduction
- Linux 네트워킹 기초 (Switching, Routing, DNS, Namespace)
- Docker 네트워킹
- CNI (Container Network Interface)
- Cluster Networking / Pod Networking
- Service Networking
- DNS in Kubernetes / CoreDNS
- Ingress
- Gateway API (2025)
205. Prerequisite - Switching, Routing, Gateways
Switching (L2)
# 네트워크 인터페이스 확인
ip link
ip addr
# IP 주소 할당
ip addr add 192.168.1.10/24 dev eth0
# 같은 스위치에 연결된 호스트끼리 통신
# Host A (192.168.1.10) ↔ Host B (192.168.1.11) → 직접 통신 가능Routing (L3)
# 라우팅 테이블 확인
route
ip route
# 라우트 추가
ip route add 192.168.2.0/24 via 192.168.1.1
# 기본 게이트웨이 설정
ip route add default via 192.168.1.1
# 또는
ip route add 0.0.0.0/0 via 192.168.1.1네트워크 토폴로지
- Network 192.168.1.0/24 — Switch ↔ Host A (192.168.1.10), Host B (192.168.1.11)
- Network 192.168.2.0/24 — Switch ↔ Host C (192.168.2.10), Host D (192.168.2.11)
- 두 네트워크는 Router/Gateway (192.168.1.1 / 192.168.2.1)로 연결
Linux 라우터 설정
# IP 포워딩 활성화 (기본 비활성)
cat /proc/sys/net/ipv4/ip_forward # 0이면 비활성
echo 1 > /proc/sys/net/ipv4/ip_forward
# 영구 설정
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p206. Prerequisite - DNS
/etc/hosts (로컬 호스트 파일)
# /etc/hosts
192.168.1.11 db
192.168.1.10 web
# 이름으로 접근 가능
ping db
ssh webDNS 서버
# DNS 서버 지정
# /etc/resolv.conf
nameserver 192.168.1.100
search mycompany.com # 도메인 자동 붙이기
# 조회 순서: /etc/nsswitch.conf
# hosts: files dns → /etc/hosts 먼저, 없으면 DNS 서버DNS 레코드 타입
| 레코드 | 설명 | 예시 |
|---|---|---|
A | 호스트명 → IPv4 | web.mycompany.com → 192.168.1.10 |
AAAA | 호스트명 → IPv6 | |
CNAME | 이름 → 이름 (별칭) | food.mycompany.com → eat.mycompany.com |
# DNS 조회 도구
nslookup www.google.com # DNS 서버에만 질의 (/etc/hosts 무시)
dig www.google.com # 상세 DNS 응답 확인207. Prerequisite - CoreDNS
CoreDNS란?
“플러그인 체인으로 동작하는 유연한 DNS 서버 — Kubernetes 내부 DNS의 표준”
왜 CoreDNS인가? (과거 kube-dns 대체)
- 단일 바이너리 (kube-dns는 dnsmasq + kubedns + sidecar 3개 컨테이너였음)
- 플러그인 방식 — Corefile에 필요한 플러그인만 조합
- 메모리 효율, 설정 단순, 확장성 우수
# CoreDNS 실행 (바이너리)
./coredns
# Corefile 설정 예시
cat /etc/coredns/Corefile
# . {
# forward . 8.8.8.8
# log
# errors
# }Corefile 플러그인 핵심
Corefile은 플러그인 체인 형태. 요청이 위에서 아래로 플러그인을 통과하며 처리됨.
| 플러그인 | 역할 |
|---|---|
kubernetes | Service/Pod → IP 변환 (K8s DNS 핵심) |
forward | 해결 못한 쿼리를 상위 DNS로 전달 (8.8.8.8 등) |
cache | DNS 응답 캐싱 (TTL 기반) |
loop | DNS 무한 루프 감지 |
reload | Corefile 변경 시 자동 재로드 |
errors | 에러를 로그로 출력 |
health | /health 엔드포인트 (liveness probe용) |
ready | /ready 엔드포인트 (readiness probe용) |
prometheus | 메트릭 노출 (:9153) |
loadbalance | A/AAAA 레코드 무작위 섞기 |
Kubernetes는 Go로 작성된 유연한 DNS 서버 클러스터 내부 DNS로 사용 (kube-dns 대체)
208. Prerequisite - Network Namespaces
네트워크 네임스페이스 개념
- Host Network Namespace: eth0 (192.168.1.10), Routing Table, ARP Table
- Namespace
red: veth0 + 자체 Routing Table - Namespace
blue: veth0 + 자체 Routing Table red의 veth0 ↔blue의 veth0 = veth pair (가상 케이블)
# 네트워크 네임스페이스 생성/조회
ip netns add red
ip netns add blue
ip netns list
# 네임스페이스 내에서 명령 실행
ip netns exec red ip link
ip -n red link
# veth pair 생성 (가상 케이블)
ip link add veth-red type veth peer name veth-blue
# 각 네임스페이스에 인터페이스 배정
ip link set veth-red netns red
ip link set veth-blue netns blue
# IP 할당 및 활성화
ip -n red addr add 192.168.15.1/24 dev veth-red
ip -n blue addr add 192.168.15.2/24 dev veth-blue
ip -n red link set veth-red up
ip -n blue link set veth-blue up
# 네임스페이스 간 통신 확인
ip netns exec red ping 192.168.15.2Linux Bridge (가상 스위치)
# Bridge 생성
ip link add v-net-0 type bridge
ip link set v-net-0 up
# 각 네임스페이스를 Bridge에 연결
ip link add veth-red type veth peer name veth-red-br
ip link set veth-red netns red
ip link set veth-red-br master v-net-0
ip -n red addr add 192.168.15.1/24 dev veth-red
ip -n red link set veth-red up
ip link set veth-red-br up
# Bridge에 호스트 IP 할당 (호스트-네임스페이스 간 통신)
ip addr add 192.168.15.5/24 dev v-net-0
# 외부 네트워크 접근 (NAT)
iptables -t nat -A POSTROUTING -s 192.168.15.0/24 -j MASQUERADE
ip -n blue route add default via 192.168.15.5210. Prerequisite - Docker Networking
Docker 네트워크 모드
| 모드 | 명령 | 설명 |
|---|---|---|
none | --network none | 네트워크 완전 격리 |
host | --network host | 호스트 네트워크 직접 사용 |
bridge | 기본값 | 가상 내부 네트워크 (172.17.0.0/16) |
# Docker 브리지 확인
docker network ls
ip link # docker0 인터페이스 확인
ip addr # docker0 IP 확인 (172.17.0.1)
# 컨테이너 실행 시 Docker가 자동으로:
# 1. 컨테이너용 네트워크 네임스페이스 생성
# 2. veth pair 생성 후 연결
# 3. IP 주소 할당 (172.17.0.x)Port Publishing
# 호스트 8080 → 컨테이너 80 포트 포워딩
docker run -p 8080:80 nginx
# 내부적으로 iptables NAT 규칙 생성
iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.3:80211. Prerequisite - CNI
CNI란?
“컨테이너에 네트워크를 붙여주는 플러그인 표준”
왜 표준이 필요한가?
- 컨테이너 런타임(containerd)과 네트워크 구현체(Calico/Flannel 등)가 각자 다른 API로 붙이면 조합 수만큼 어댑터 필요
- CNI라는 통일된 인터페이스를 만들어서 → 런타임은 한 번만 구현하면 모든 CNI 플러그인 쓸 수 있음
- CRI(런타임 표준), CSI(스토리지 표준)와 같은 철학
CNI가 해주는 일:
- Pod가 생성되면 런타임이 CNI 플러그인 호출
- 플러그인이 네임스페이스에 가상 인터페이스(veth) 붙임
- IP 할당 (IPAM)
- 노드 간 라우팅/터널링 설정 (Overlay 또는 BGP)
CNI 표준
Container Runtime (containerd / CRI-O) → CNI 플러그인 호출 → CNI Plugin (Weave / Calico / Flannel) → 컨테이너 Network Namespace 설정
- CNI: 컨테이너 런타임과 네트워크 플러그인 간의 표준 인터페이스
- 런타임이 컨테이너 생성 시 CNI 플러그인을 호출하여 네트워크 구성
CNI 플러그인 책임
- 컨테이너 Network Namespace 생성
- 적절한 네트워크에 연결
- IP 주소 할당 (IPAM)
- 컨테이너 삭제 시 정리
CNI 구성 파일 위치
ls /etc/cni/net.d/ # CNI 설정 파일
ls /opt/cni/bin/ # CNI 플러그인 바이너리Docker는 CNI를 직접 지원하지 않고 CNM(Container Network Model)을 사용 → Kubernetes는 별도로 CNI를 호출
212. Cluster Networking
노드 포트 요구사항
| 컴포넌트 | 포트 | 방향 |
|---|---|---|
| kube-apiserver | 6443 | Inbound |
| kubelet | 10250 | Inbound |
| kube-scheduler | 10259 | Inbound (localhost) |
| kube-controller-manager | 10257 | Inbound (localhost) |
| etcd | 2379 | Inbound |
| etcd (peer) | 2380 | Inbound (multi-master) |
| NodePort Services | 30000-32767 | Inbound |
# 노드 네트워크 인터페이스 확인
ip link
ip addr show eth0
# 라우팅 테이블 확인
ip route
# 열린 포트 확인
ss -tulnp
netstat -tulnp214-215. Lab - Explore Environment
# 노드 IP 확인
kubectl get nodes -o wide
# 네트워크 인터페이스 확인
ip link show
ip addr show
# 브리지 인터페이스 확인
ip link show type bridge
# 라우팅 테이블
ip route show
# 열린 포트 (etcd, apiserver 등)
ss -tulnp | grep -E '6443|2379|10250'
# 연결 개수 세기
ss -tulnp state established | grep -c '2379'
216. Pod Networking
Kubernetes Pod 네트워킹 요구사항
- 모든 Pod는 고유한 IP를 가져야 함
- 같은 노드의 Pod끼리 IP로 통신 가능
- 다른 노드의 Pod끼리도 IP로 통신 가능 (NAT 없이)
수동 구성 스크립트 개념
# 각 노드에서 실행 (CNI 없이 수동 구성 개념)
# 1. Bridge 네트워크 생성 (노드마다)
ip link add v-net-0 type bridge
ip link set v-net-0 up
ip addr add 10.244.1.1/24 dev v-net-0 # node1
# ip addr add 10.244.2.1/24 dev v-net-0 # node2
# 2. Pod 네임스페이스 연결 (컨테이너 런타임이 수행)
# veth pair 생성 → 네임스페이스와 Bridge 연결 → IP 할당
# 3. 다른 노드 Pod와 통신 (라우트 추가)
ip route add 10.244.2.0/24 via 192.168.1.12 # node2 IPCNI 플러그인이 이 과정을 자동화함
217. CNI in Kubernetes
CNI 플러그인 설정 위치
# kubelet에 CNI 설정 전달
cat /var/lib/kubelet/config.yaml | grep -i cni
# 또는 kubelet 실행 옵션 확인
ps aux | grep kubelet | grep -i cni
# CNI 설정 파일
ls /etc/cni/net.d/
cat /etc/cni/net.d/10-weave.conf
# CNI 바이너리
ls /opt/cni/bin/주요 CNI 플러그인 비교
| 플러그인 | 특징 | Network Policy 지원 |
|---|---|---|
| Weave | 오버레이 네트워크, 간단한 설치 | ✅ |
| Calico | BGP 기반, 강력한 Network Policy | ✅ |
| Flannel | 단순, 경량 | ❌ |
| Cilium | eBPF 기반, 고성능 | ✅ |
219. CNI Weave
Weave 동작 방식
Node 1:
- Weave Agent ↔ weave Bridge (10.32.0.1/12)
- Bridge ↔ Pod A (10.32.0.2), Pod B (10.32.0.3)
Node 2:
- Weave Agent ↔ weave Bridge (10.44.0.1/12)
- Bridge ↔ Pod C (10.44.0.2)
Node 1 ↔ Node 2: Weave Tunnel (패킷 캡슐화)
- 각 노드에 Weave Agent(DaemonSet)가 실행
- 노드 간 트래픽은 캡슐화하여 전송
- 기본 Pod CIDR:
10.32.0.0/12
# Weave 설치
kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
# Weave 상태 확인
kubectl get pods -n kube-system | grep weave
kubectl exec -n kube-system weave-net-xxxxx -c weave -- /home/weave/weave --local status222. IPAM Weave
IPAM (IP Address Management)
- CNI 플러그인이 Pod IP 주소를 중복 없이 관리
- Weave: 전체 CIDR(
10.32.0.0/12)을 노드 수로 분할하여 각 노드에 할당 - host-local: CNI 내장 IPAM 플러그인 (로컬 파일 기반)
# CNI 설정에서 IPAM 확인
cat /etc/cni/net.d/net-script.conf
# {
# "ipam": {
# "type": "host-local",
# "subnet": "10.244.0.0/16",
# "routes": [{"dst": "0.0.0.0/0"}]
# }
# }223. Lab - Networking CNIs
# cni 종류 확인
ls /etc/cni/net.d
# flannel은 network polict 지원 안함
# flannel 제거 ( ds, cm, config 파일)
kubectl delete ds kube-flannel-ds -n kube-flannel
kubectl delete cm kube-flannel-cfg -n kube-flannel
rm /etc/cni/net.d/10-flannel.conflist
# policy 지원하는 calico 설치
# https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico
# 가이드 대로 따라하되 step 2 에서 받은 custom-resources.yaml에서 아래 cidr만 수정
---
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
calicoNetwork:
ipPools:
- name: default-ipv4-ippool
blockSize: 26
cidr: 172.17.0.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
---
kubectl apply -f custom-resources.yaml224. Service Networking
Service IP는 실제로 존재하지 않는다?
“Service의 ClusterIP는 가상 IP — 실제 인터페이스에 없고, iptables 규칙으로만 구현됨”
어떻게 동작하는가?
- Service 생성 시 K8s가 가상 IP(10.96.x.x 등) 할당
- kube-proxy가 각 노드의 iptables에 규칙 추가: “이 가상 IP로 가는 트래픽 → 실제 Pod IP 중 하나로 DNAT”
- Pod에서
curl service-ip하면 커널이 iptables 규칙에 따라 실제 Pod로 전달
왜 이렇게 설계했나?
- Service IP를 실제 인터페이스에 할당하면 → 노드마다 따로 붙여야 하고 라우팅 복잡
- iptables 규칙은 노드 독립적으로 각자 구성 → 확장성 좋음
- 로드밸런싱도 iptables random으로 자연스럽게 해결
Service IP (ClusterIP) 동작 원리
Pod (10.244.1.2) → 요청 10.96.0.10:80 → Service (ClusterIP) → kube-proxy iptables 규칙(DNAT) → Endpoint Pod (10.244.2.5:8080)
- Service IP는 가상 IP — 실제 인터페이스에 존재하지 않음
- kube-proxy가 각 노드에서 iptables/ipvs 규칙을 관리하여 트래픽 전달
kube-proxy 모드
| 모드 | 설명 |
|---|---|
iptables | 기본값, NAT 규칙으로 구현 |
ipvs | 고성능, L4 로드밸런서 |
userspace | 레거시, 비권장 |
iptables vs ipvs 언제 쓸지
| 항목 | iptables (기본) | ipvs |
|---|---|---|
| 규칙 처리 | 선형 탐색 O(n) | 해시 테이블 O(1) |
| 로드밸런싱 알고리즘 | 랜덤 | round-robin, least-conn, 등 8가지 |
| 대규모 클러스터 | Service 수천 개 넘어가면 느려짐 | 수만 개도 안정적 |
| 설치 조건 | 기본 포함 | ipvsadm, ipset 필요 |
| 적합한 규모 | 소규모~중규모 | 대규모 / 성능 민감 |
대부분 iptables가 기본이고 실무에서도 충분. Service가 5000개 이상 되거나 특정 로드밸런싱 알고리즘이 필요할 때 ipvs 고려.
Pod-to-Pod 통신 전체 흐름 (정리)
Pod A (Node 1) → Service → Pod B (Node 2) 로 통신할 때:
- Pod A가 DNS 조회 —
service-b.default→ CoreDNS 응답: ClusterIP10.96.0.42 - Pod A가
10.96.0.42로 패킷 전송 - Node 1의 iptables가 규칙에 따라 DNAT — 목적지를 Pod B의 실제 IP (
10.244.2.5)로 변경 - CNI 오버레이/라우팅으로 Node 2까지 전달
- Node 2의 Pod B에 도달
이 전체가 Linux 커널 수준에서 처리되고 kube-proxy는 규칙만 관리.
# kube-proxy 모드 확인
kubectl get configmap kube-proxy -n kube-system -o yaml | grep mode
# iptables 규칙 확인 (Service IP 관련)
iptables -t nat -L KUBE-SERVICES -n | grep <service-ip>
iptables -t nat -L KUBE-SVC-XXXXX -n
# Service CIDR 확인
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep service-cluster-ip-rangeService 타입별 범위
| 타입 | 접근 범위 | IP 범위 |
|---|---|---|
ClusterIP | 클러스터 내부만 | --service-cluster-ip-range |
NodePort | 외부에서 NodeIP:Port | 30000-32767 |
LoadBalancer | 클라우드 LB | 클라우드 할당 |
# Pod CIDR vs Service CIDR 확인
kubectl cluster-info dump | grep -E "cluster-cidr|service-cluster-ip"Service 생성 - imperative
# ── 방법 1: kubectl expose (이미 있는 Pod/Deployment 기반) ───
# 가장 빠름 - Selector 자동 추출
kubectl expose pod redis --port=6379 --name=redis-svc
kubectl expose deploy nginx --port=80 --target-port=8080 --name=web-svc
# NodePort 타입
kubectl expose deploy nginx --port=80 --type=NodePort --name=web-np
# LoadBalancer 타입
kubectl expose deploy nginx --port=80 --type=LoadBalancer
# YAML로 뽑기 (수정 후 apply 용도)
kubectl expose deploy nginx --port=80 --dry-run=client -o yaml > svc.yaml
# ── 방법 2: kubectl create service (Selector 수동 지정) ──────
kubectl create service clusterip my-svc --tcp=80:8080
kubectl create service nodeport my-svc --tcp=80:8080 --node-port=30080
kubectl create service loadbalancer my-svc --tcp=80:8080
# ── 방법 3: kubectl run --expose (Pod + Service 동시 생성) ──
kubectl run nginx --image=nginx --port=80 --expose
# → nginx Pod + nginx Service(ClusterIP) 동시 생성
# ── 참고: expose vs create service 차이 ────────────────────
# expose: 기존 리소스의 selector를 그대로 승계
# create service: selector는 이름과 동일하게 자동 설정됨 (수정 필요할 수 있음)Pod/Deploy가 이미 있으면
kubectl expose, 없으면kubectl create service
자주 쓰는 Service 패턴
# targetPort 지정
kubectl expose deploy web --port=80 --target-port=8080
# 다중 포트 (create service로만 가능)
kubectl create service clusterip my-svc --tcp=80:8080 --tcp=443:8443
# Headless Service (StatefulSet 용)
kubectl create service clusterip my-svc --clusterip=None --tcp=80:80
# 또는 --dry-run으로 뽑아서 clusterIP: None 수정
# ExternalName Service
kubectl create service externalname my-db --external-name=db.example.com225. Lab - Service Networking
# 클러스터 내 pod들의 ip 범위 확인
cat /etc/kubernetes/manifests/kube-controller-manager.yaml | grep cluster-cidr
# 클러스터 내 service들의 ip 범위 확인
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep cluster-ip-range
# kube-proxy 유형 확인
kubectl logs -n kube-system <kube-proxy-pod-name>
# I0428 09:16:01.530928 1 server_linux.go:53] "Using iptables proxy"
# kube-proxy가 모든 노드에 돌고 있는 것 확인
kubectl get ds -n kube-system227. DNS in Kubernetes
서비스 DNS 레코드
- Service:
web-service(Namespace:apps) →web-service.apps.svc.cluster.local - Pod IP:
10.244.1.5(Namespace:apps) →10-244-1-5.apps.pod.cluster.local
DNS 레코드 형식
# Service
<service-name>.<namespace>.svc.<cluster-domain>
web-service.apps.svc.cluster.local
# Pod (IP의 점을 대시로)
<pod-ip-dashes>.<namespace>.pod.<cluster-domain>
10-244-1-5.apps.pod.cluster.local
같은 네임스페이스에서는 단축 이름 사용 가능
# 같은 namespace
curl web-service
# 다른 namespace
curl web-service.apps
# 전체 FQDN
curl web-service.apps.svc.cluster.local228. CoreDNS in Kubernetes
CoreDNS 구성
# CoreDNS는 kube-system에 Deployment로 실행
kubectl get deploy -n kube-system coredns
kubectl get pods -n kube-system | grep coredns
# CoreDNS 설정 (ConfigMap)
kubectl get configmap coredns -n kube-system -o yamlCorefile 주요 설정
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa { # 클러스터 도메인
pods insecure # Pod DNS 레코드 활성화
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153 # 메트릭 노출
forward . /etc/resolv.conf # 외부 도메인 → 업스트림 DNS
cache 30
loop
reload
loadbalance
}
Pod DNS 설정
# Pod 내부 /etc/resolv.conf 확인
kubectl exec <pod-name> -- cat /etc/resolv.conf
# nameserver 10.96.0.10 ← CoreDNS Service IP
# search default.svc.cluster.local svc.cluster.local cluster.local
# CoreDNS Service 확인
kubectl get svc -n kube-system kube-dnsCoreDNS 트러블슈팅
# CoreDNS 로그 확인
kubectl logs -n kube-system -l k8s-app=kube-dns
# DNS 조회 테스트
kubectl run test --image=busybox --rm -it -- nslookup web-service
kubectl run test --image=busybox --rm -it -- nslookup web-service.default.svc.cluster.local231. Ingress
공식문서: Ingress / Ingress Controllers
Service가 있는데 Ingress가 왜 필요한가?
“여러 서비스를 한 진입점에서 경로/호스트 기반으로 라우팅하기 위함”
Service만으로 부족한 이유:
- 서비스가 10개면 → LoadBalancer 10개 만들면 비용 10배 + 외부 IP 10개
- “wear.com은 wear-svc, watch.com은 watch-svc로 보내고 싶다” — Service는 호스트/경로 라우팅 못함
- TLS 인증서 관리를 서비스마다 따로 하면 지옥
Ingress가 해결하는 것:
- 외부 LB 하나로 여러 서비스 내부 라우팅
- 경로(
/wear,/watch) / 호스트(wear.com) 기반 분기 - TLS 종료(termination) 를 Ingress에서 일괄 처리
- URL rewrite 등 L7 기능
구성 요소 2개 (혼동 주의):
- Ingress Resource: YAML로 정의한 “라우팅 규칙” (선언만)
- Ingress Controller: 실제로 트래픽 받아 라우팅 처리하는 Pod (nginx, traefik 등 — 별도 설치 필요)
Ingress 개념
외부 사용자 my-store.com/wear → Ingress Controller (nginx / traefik) → 경로/호스트별 분기:
-
/wear→wear-service:80 -
/watch→watch-service:80 -
*.my-store.com→ 기타 서비스 -
Ingress Controller: 실제로 트래픽을 처리하는 컴포넌트 (nginx, traefik, HAProxy 등)
-
Ingress Resource: 라우팅 규칙을 정의하는 Kubernetes 객체
Ingress Controller는 기본 설치되지 않음 — 별도로 배포해야 함
Ingress Controller 배포 (nginx)
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-controller
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app: ingress-nginx
template:
metadata:
labels:
app: ingress-nginx
spec:
serviceAccountName: ingress-nginx
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.21.0
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443Ingress Resource 예시
# 경로 기반 라우팅
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wear-watch
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: www.my-store.com
http:
paths:
- path: /wear
pathType: Prefix
backend:
service:
name: wear-service
port:
number: 80
- path: /watch
pathType: Prefix
backend:
service:
name: watch-service
port:
number: 80# 호스트 기반 라우팅 (가상 호스팅)
spec:
rules:
- host: wear.my-store.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: wear-service
port:
number: 80
- host: watch.my-store.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: watch-service
port:
number: 80Ingress 명령어
# Ingress 조회
kubectl get ingress
kubectl get ing # 약어
# 상세 확인 (Rules, Backends, Address)
kubectl describe ingress ingress-wear-watch
# Ingress 생성 (명령형)
kubectl create ingress ingress-test \
--rule="wear.my-store.com/wear*=wear-service:80"Ingress imperative
# ── 기본: 단일 경로 ────────────────────────────────────────
kubectl create ingress simple \
--rule="example.com/*=web-svc:80"
# ── 다중 경로 (path-based routing) ────────────────────────
kubectl create ingress multi-path \
--rule="store.com/wear*=wear-svc:80" \
--rule="store.com/watch*=watch-svc:80"
# ── 다중 호스트 (host-based routing) ──────────────────────
kubectl create ingress multi-host \
--rule="wear.store.com/*=wear-svc:80" \
--rule="watch.store.com/*=watch-svc:80"
# ── TLS 포함 ──────────────────────────────────────────────
kubectl create ingress secure \
--rule="example.com/*=web-svc:80,tls=example-tls"
# ── 특정 IngressClass 지정 ────────────────────────────────
kubectl create ingress nginx-ing \
--class=nginx \
--rule="example.com/*=web-svc:80"
# ── annotation 추가 (rewrite-target 등) ────────────────────
kubectl create ingress rewrite \
--annotation nginx.ingress.kubernetes.io/rewrite-target=/ \
--rule="example.com/app*=app-svc:80"
# ── YAML로 뽑기 (복잡한 수정 필요 시) ──────────────────────
kubectl create ingress test \
--rule="example.com/*=web-svc:80" \
--dry-run=client -o yaml > ing.yamlrule 문법 구조 (중요)
--rule="HOST/PATH*=SERVICE:PORT[,tls=SECRET]"
│ │ │ │ │ │
│ │ │ │ │ └─ 선택: TLS Secret
│ │ │ │ └─────────── 서비스 포트
│ │ │ └────────────────── 서비스 이름
│ │ └────────────────────── * 붙이면 pathType=Prefix (없으면 Exact)
│ └───────────────────────── 경로
└────────────────────────────── 호스트 (생략 가능)
233. Ingress - Annotations & rewrite-target
# rewrite-target: 백엔드로 전달 시 경로 재작성
# 요청: /wear/anything → 백엔드: /anything
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
# 또는 정규표현식 사용
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- http:
paths:
- path: /wear(/|$)(.*) # 캡처 그룹 $2
pathType: Prefix
backend:
service:
name: wear-service
port:
number: 80# SSL/TLS 설정
spec:
tls:
- hosts:
- www.my-store.com
secretName: my-store-tls # TLS Secret 참조
rules:
- host: www.my-store.com
http:
paths: ...234. Lab - CKA Ingress Networking - 1
# default 백엔드 확인
kubectl get deploy ingress-nginx-controller -n ingress-nginx -o yaml
#controlplane ~ ➜ kubectl get deploy ingress-nginx-controller -n ingress-#nginx -o yaml | grep default
# - --default-backend-service=app-space/default-backend-service
# schedulerName: default-scheduler
# defaultMode: 420
# ingress 수정
kubectl edit ingress ingress-wear-watch -n app-space
# ingress 생성 (namespace 지정, host 생략)
kubectl create ingress critical-ingress --namespace=critical-space --annotation nginx.ingress.kubernetes.io/rewrite-target=/ --rule="/pay=pay-service:8282"
# ingress.networking.k8s.io/critical-ingress created236. Lab - CKA Ingress Networking - 2
238-239. Gateway API (2025)
Gateway API란?
“Ingress의 한계를 해결하기 위한 차세대 표준”
Ingress의 문제점:
- annotation 의존: 고급 기능이 전부 컨트롤러(nginx, traefik…)별 annotation으로 구현 → 표준성 X, 이식 어려움
- 역할 분리 부족: 인프라팀/플랫폼팀/개발팀이 같은 Ingress 리소스에 다 손대야 함
- HTTP만 잘 지원: TCP/UDP/gRPC는 제한적
Gateway API의 해결 방식 — 역할별로 리소스 분리:
| 리소스 | 담당자 | 책임 |
|---|---|---|
| GatewayClass | 인프라팀 | 어떤 컨트롤러(nginx, envoy)를 쓸지 정의 |
| Gateway | 플랫폼팀 | 포트/프로토콜/TLS 설정 |
| HTTPRoute (등) | 개발팀 | 실제 라우팅 규칙만 작성 |
Ingress는 유지되지만 Gateway API가 향후 표준. 새 프로젝트는 Gateway API 권장.
Ingress vs Gateway API
| 항목 | Ingress | Gateway API |
|---|---|---|
| 성숙도 | 안정화 (GA) | GA (v1.0+) |
| 표현력 | 제한적 (annotation 의존) | 풍부한 네이티브 리소스 |
| 역할 분리 | 없음 | GatewayClass / Gateway / Route 분리 |
| 프로토콜 지원 | HTTP/HTTPS | HTTP, TCP, UDP, gRPC 등 |
Gateway API 주요 리소스
GatewayClass (인프라팀: 어떤 컨트롤러 사용할지) → Gateway (클러스터 관리자: 리스너 포트/TLS) → HTTPRoute (개발자: 라우팅 규칙) → Service (백엔드)
GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx
spec:
controllerName: k8s.nginx.org/nginx-gateway-controllerGateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: default
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: AllHTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-route
namespace: default
spec:
parentRefs:
- name: my-gateway # Gateway 참조
hostnames:
- "www.my-store.com"
rules:
- matches:
- path:
type: PathPrefix
value: /wear
backendRefs:
- name: wear-service
port: 80
- matches:
- path:
type: PathPrefix
value: /watch
backendRefs:
- name: watch-service
port: 80Gateway API 명령어
# Gateway API CRD 설치 확인
kubectl get crd | grep gateway
# Gateway / HTTPRoute 조회
kubectl get gatewayclass
kubectl get gateway
kubectl get httproute
# 상태 확인
kubectl describe gateway my-gateway
kubectl describe httproute my-route전체 Networking 흐름 요약
- 외부 트래픽 → (NodePort / LoadBalancer / Ingress / Gateway) → 노드 (kube-proxy iptables)
- Service ClusterIP → Endpoint 선택 → Pod (CNI로 네트워크 구성)
- Pod ↔ 다른 노드 Pod (CNI Overlay)
- Pod → DNS 조회 → CoreDNS (kube-dns Service)