개요
기본 AWS LoadBalancer
AWS Load Balancer Controller
Host Header
AWS ELB의 Host Header
결론
기본 AWS LoadBalancer
AWS Console이든 Terraform 이든,
추가 설정 없이 간단하게 AWS ELB(Elastic Load Balancer)를 셋팅할 수 있습니다.
이런 구성에서 다른 서브 도메인을 사용하고 싶을 경우,
아래와 같이 a.example.com → b.example.com 으로 변경할 수 있습니다.
하지만 AWS EKS 환경에서 aws-load-balancer-controller
를 사용하여 Ingress를 통해서 로드밸런서를 생성하게 되면, 위 방법이 통하지 않습니다.
AWS Load Balancer Controller
AWS Load Balancer Controller를 alb 방식으로 배포하엿
metadata.annotations
이 정상적으로 기입되어있다고 가정하더라도,spec.rules[0].host
에 기록된 a.example.com 이 문제가 됩니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: eg-name
namespace: eg-namespace
annotations:
# ...
spec:
selector:
app: eg-name
ingressClassName: alb
rules:
- host: a.example.com
http:
paths:
- backend:
service:
name: eg-name
port:
number: 80
serviceName: null
path: /
pathType: Prefix
실제로 이 K8s Manifest 파일로 생성한 ALB가 있다고 생각해봅시다.
이 ALB의 HTTPS(443) Listener를 보면 처음 보는 2가지 옵션이 존재합니다.
위 스크린샷을 보면 조건(인 경우) 쪽에 경로 패턴과 HTTP 호스트 헤더가 존재합니다.
여기서 호스트 헤더가 a.example.com으로 되어 있기 때문에, b.example.com에서 들어온 요청은 서버에 전달이 되지 않습니다.
Host Header
RFC 2616 — Hypertext Transfer Protocol — HTTP/1.1, Host Header MDN을 살펴보면, Host Header는 HTTP/1.1 통신에서 요청자를 특정하기 위해서 사용된 필수 항목임을 알 수 있습니다.
특히 MDN 문서가 참조하고 있는 RFC 9110 — HTTP Semantics # 7.2 Host and :authority를 살펴보면, 다음과 같이 HTTP/1.1에서 Host Header의 형태를 보여주고 있습니다.
GET /pub/WWW/ HTTP/1.1
Host: www.example.org
실제로 어떤 웹사이트든 접속해보면 Request Headers 쪽에 Host Header가 존재함을 알 수 있습니다.
HTTP/1.2(HTTPS) 초창기에는 이 부분이 문제가 되었습니다.
전송 본문이 암호화 되면서 서버는 요청(HTTPS Reuqest)이 어떤 Host에 대한 것인지 구분할 수 없게 되었습니다. 이에 따라서 어떤 TLS Certificate인지를 구분할 수 없게 되었습니다.
이에 따라서 서버는 사용자의 요청이 기본 호스트(Default Host)를 향하고 있다고 가정하게 되었습니다. 즉, 이 당시에는 서버 1개당 1개의 Host를 가질 수 있었다는 말입니다.
ELB
이 부분은 SNI(Server Name Idication) 기술이 나오면서 해결되었습니다.
즉, 서버 1개가 다수의 Host에 대해서 로드 밸런싱을 할 수 있게 되었습니다.
ELB
AWS ELB의 Host Header
이때, AWS Load Balancer Controller에서 HTTPS(443) Listener에 있는 Host Header는 무슨 기능일까요.
만약, 하나의 로드 밸런서에서 여러 목적의 서버를 겨냥하려면 어떻게 해야 할까요?
Protocol | Port | Domain | Server |
---|---|---|---|
HTTPS | 443 | a.example.com | A EC2 Instance |
HTTPS | 443 | b.example.com | B EC2 Instance |
이 경우, a.example.com을 통해서 들어온 친구가 A, B 중 어디로 가야할지를 알려면 조금 명확한 라우팅 기능이 필요할 것 같습니다. 이것이 Host Header 기반의 AWS ALB Routing 기능입니다.
결론
일반적으로 코드 레벨에서 사용하는 라우팅 외에도
클라우드 레벨에서 사용할 수 있는 Host-Based Routing Support기능이었습니다.
다만, 해당 기능의 Condition Syntax로 인해서 로드 밸런서가 작동하지 않은 것이었습니다.
따라서 a.example.com → b.example.com 으로 도메인 변경 시,
해당 Host-Based Routing Support에 대해서 아래의 3가지 조치 중 한가지를 해야 합니다.
A Record 변경 이전, Host Header Condition 변경
AND Option이 아닌 OR 옵션을 사용해서 a.~, b.~를 모두 허용하도록 설정 변경하기