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 -p

206. Prerequisite - DNS

/etc/hosts (로컬 호스트 파일)

# /etc/hosts
192.168.1.11    db
192.168.1.10    web
 
# 이름으로 접근 가능
ping db
ssh web

DNS 서버

# DNS 서버 지정
# /etc/resolv.conf
nameserver 192.168.1.100
search mycompany.com    # 도메인 자동 붙이기
 
# 조회 순서: /etc/nsswitch.conf
# hosts: files dns  → /etc/hosts 먼저, 없으면 DNS 서버

DNS 레코드 타입

레코드설명예시
A호스트명 → IPv4web.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은 플러그인 체인 형태. 요청이 위에서 아래로 플러그인을 통과하며 처리됨.

플러그인역할
kubernetesService/Pod → IP 변환 (K8s DNS 핵심)
forward해결 못한 쿼리를 상위 DNS로 전달 (8.8.8.8 등)
cacheDNS 응답 캐싱 (TTL 기반)
loopDNS 무한 루프 감지
reloadCorefile 변경 시 자동 재로드
errors에러를 로그로 출력
health/health 엔드포인트 (liveness probe용)
ready/ready 엔드포인트 (readiness probe용)
prometheus메트릭 노출 (:9153)
loadbalanceA/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.2

Linux 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.5

210. 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:80

211. Prerequisite - CNI

CNI란?

“컨테이너에 네트워크를 붙여주는 플러그인 표준”

왜 표준이 필요한가?

  • 컨테이너 런타임(containerd)과 네트워크 구현체(Calico/Flannel 등)가 각자 다른 API로 붙이면 조합 수만큼 어댑터 필요
  • CNI라는 통일된 인터페이스를 만들어서 → 런타임은 한 번만 구현하면 모든 CNI 플러그인 쓸 수 있음
  • CRI(런타임 표준), CSI(스토리지 표준)와 같은 철학

CNI가 해주는 일:

  1. Pod가 생성되면 런타임이 CNI 플러그인 호출
  2. 플러그인이 네임스페이스에 가상 인터페이스(veth) 붙임
  3. IP 할당 (IPAM)
  4. 노드 간 라우팅/터널링 설정 (Overlay 또는 BGP)

CNI 표준

Container Runtime (containerd / CRI-O) → CNI 플러그인 호출 → CNI Plugin (Weave / Calico / Flannel) → 컨테이너 Network Namespace 설정

  • CNI: 컨테이너 런타임과 네트워크 플러그인 간의 표준 인터페이스
  • 런타임이 컨테이너 생성 시 CNI 플러그인을 호출하여 네트워크 구성

CNI 플러그인 책임

  1. 컨테이너 Network Namespace 생성
  2. 적절한 네트워크에 연결
  3. IP 주소 할당 (IPAM)
  4. 컨테이너 삭제 시 정리

CNI 구성 파일 위치

ls /etc/cni/net.d/       # CNI 설정 파일
ls /opt/cni/bin/         # CNI 플러그인 바이너리

Docker는 CNI를 직접 지원하지 않고 CNM(Container Network Model)을 사용 → Kubernetes는 별도로 CNI를 호출


212. Cluster Networking

노드 포트 요구사항

컴포넌트포트방향
kube-apiserver6443Inbound
kubelet10250Inbound
kube-scheduler10259Inbound (localhost)
kube-controller-manager10257Inbound (localhost)
etcd2379Inbound
etcd (peer)2380Inbound (multi-master)
NodePort Services30000-32767Inbound
# 노드 네트워크 인터페이스 확인
ip link
ip addr show eth0
 
# 라우팅 테이블 확인
ip route
 
# 열린 포트 확인
ss -tulnp
netstat -tulnp

214-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 네트워킹 요구사항

  1. 모든 Pod는 고유한 IP를 가져야 함
  2. 같은 노드의 Pod끼리 IP로 통신 가능
  3. 다른 노드의 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 IP

CNI 플러그인이 이 과정을 자동화함


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오버레이 네트워크, 간단한 설치
CalicoBGP 기반, 강력한 Network Policy
Flannel단순, 경량
CiliumeBPF 기반, 고성능

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 status

222. 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.yaml

224. 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:80Service (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) 로 통신할 때:

  1. Pod A가 DNS 조회service-b.default → CoreDNS 응답: ClusterIP 10.96.0.42
  2. Pod A가 10.96.0.42로 패킷 전송
  3. Node 1의 iptables가 규칙에 따라 DNAT — 목적지를 Pod B의 실제 IP (10.244.2.5)로 변경
  4. CNI 오버레이/라우팅으로 Node 2까지 전달
  5. 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-range

Service 타입별 범위

타입접근 범위IP 범위
ClusterIP클러스터 내부만--service-cluster-ip-range
NodePort외부에서 NodeIP:Port30000-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.com

225.  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-system

227. 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.local

228. 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 yaml

Corefile 주요 설정

.: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-dns

CoreDNS 트러블슈팅

# 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.local

231. Ingress

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/wearIngress Controller (nginx / traefik) → 경로/호스트별 분기:

  • /wearwear-service:80

  • /watchwatch-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: 443

Ingress 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: 80

Ingress 명령어

# 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.yaml

rule 문법 구조 (중요)

--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 created

236. 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

항목IngressGateway API
성숙도안정화 (GA)GA (v1.0+)
표현력제한적 (annotation 의존)풍부한 네이티브 리소스
역할 분리없음GatewayClass / Gateway / Route 분리
프로토콜 지원HTTP/HTTPSHTTP, 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-controller

Gateway

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: All

HTTPRoute

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: 80

Gateway 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 흐름 요약

  1. 외부 트래픽 → (NodePort / LoadBalancer / Ingress / Gateway) → 노드 (kube-proxy iptables)
  2. Service ClusterIP → Endpoint 선택 → Pod (CNI로 네트워크 구성)
  3. Pod ↔ 다른 노드 Pod (CNI Overlay)
  4. Pod → DNS 조회 → CoreDNS (kube-dns Service)