클러스터 밖에서 안으로 트래픽 들여보내기
6장에서 LoadBalancer 타입 Service가 서비스마다 클라우드 로드밸런서를 하나씩 만든다고 했습니다. 서비스가 하나둘일 땐 괜찮지만, api.example.com, admin.example.com, blog.example.com처럼 도메인이 여러 개로 늘어나면 로드밸런서도 그만큼 늘어나고 비용도 그만큼 붙습니다. Ingress는 이 여러 도메인을 하나의 진입점으로 모으는 리소스입니다.
Ingress 리소스만으로는 아무 일도 일어나지 않는다
여기서 초보자가 가장 많이 걸리는 함정을 먼저 짚습니다. Ingress 리소스를 클러스터에 적용해도, 그 자체로는 아무 것도 처리하지 않습니다. Ingress는 라우팅 규칙을 선언한 것일 뿐이고, 이 규칙을 실제로 해석해서 트래픽을 처리하는 건 Ingress Controller라는 별도의 소프트웨어입니다. Deployment를 만들면 컨트롤러 매니저가 자동으로 딸려오는 것과 달리, Ingress Controller는 클러스터에 기본으로 설치되어 있지 않은 경우가 많습니다. kind로 만든 클러스터에도 없습니다.
# ingress-nginx를 kind 클러스터에 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl get pods -n ingress-nginx
# ingress-nginx-controller-xxxxx 1/1 Running관리형 클러스터(EKS, GKE 등)를 쓴다면 클라우드 제공자가 만든 Ingress Controller를 쓰거나, ingress-nginx를 직접 설치하는 것 둘 다 흔한 선택입니다. 어느 쪽이든 "Ingress 리소스를 적용했는데 아무 반응이 없다"면 제일 먼저 Ingress Controller가 떠 있는지부터 확인하는 게 순서입니다.
도메인과 경로로 라우팅하기
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-api
port:
number: 80
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-panel
port:
number: 80이 하나의 Ingress로 두 도메인의 트래픽을 각각 다른 Service로 나눠 보냅니다. 클라우드 로드밸런서는 ingress-nginx가 뜬 Service(보통 LoadBalancer 타입 하나) 앞에만 붙어 있으면 되고, 뒤에서 도메인별로 나누는 건 전부 Ingress Controller 내부의 nginx 설정으로 처리됩니다. 도메인이 열 개로 늘어나도 클라우드 로드밸런서는 여전히 하나입니다.
로컬에서 확인하려면 /etc/hosts에 가짜 도메인을 등록해서 테스트합니다.
echo "127.0.0.1 api.example.com admin.example.com" | sudo tee -a /etc/hosts
curl http://api.example.comannotation이 사실상의 설정 API다
위 예제에 있는 nginx.ingress.kubernetes.io/rewrite-target 같은 annotation을 눈여겨봐야 합니다. Ingress 리소스의 스펙 자체는 쿠버네티스 표준이라 어떤 Ingress Controller를 쓰든 동일하지만, 실제로 자주 필요한 세부 동작(경로 재작성, 요청 크기 제한, rate limit, TLS 설정 등)은 대부분 이런 annotation을 통해 각 Ingress Controller가 독자적으로 제공합니다. 즉 "표준 스펙"과 "실제로 쓸 만한 기능" 사이의 간극을 annotation이 메우고 있는 셈인데, 이 annotation들은 Controller마다 이름과 동작이 다릅니다. ingress-nginx용 annotation을 그대로 다른 Controller(Traefik, AWS ALB Controller 등)에 붙여넣으면 조용히 무시되거나 에러가 납니다. 문서를 볼 때 "어떤 Ingress Controller 기준의 문서인지"부터 확인하는 습관이 필요합니다.
TLS 인증서를 붙여 HTTPS로 서비스하는 방법도 있지만(spec.tls 필드와 cert-manager 조합이 가장 흔한 패턴입니다), 인증서 발급과 갱신 자동화까지 들어가면 이 책 한 장으로 다루기엔 범위가 넓어 별도로 찾아보시길 권합니다.