AWS Load Balancer Controller과 Host Header

이민석's avatar
Jun 27, 2024
AWS Load Balancer Controller과 Host Header

개요

  1. 기본 AWS LoadBalancer

  2. AWS Load Balancer Controller

  3. Host Header

  4. AWS ELB의 Host Header

  5. 결론

기본 AWS LoadBalancer

AWS Console이든 Terraform 이든,
추가 설정 없이 간단하게 AWS ELB(Elastic Load Balancer)를 셋팅할 수 있습니다.

이런 구성에서 다른 서브 도메인을 사용하고 싶을 경우,
아래와 같이 a.example.comb.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

  1. a.example.com

이 부분은 SNI(Server Name Idication) 기술이 나오면서 해결되었습니다.
즉, 서버 1개가 다수의 Host에 대해서 로드 밸런싱을 할 수 있게 되었습니다.

ELB

  1. a.example.com

  2. b.example.com

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.comb.example.com 으로 도메인 변경 시,
해당 Host-Based Routing Support에 대해서 아래의 3가지 조치 중 한가지를 해야 합니다.

  1. A Record 변경 이전, Host Header Condition 변경

    1. AND Option이 아닌 OR 옵션을 사용해서 a.~, b.~를 모두 허용하도록 설정 변경하기

참고 자료

  1. Stackoverflow | What is HTTP “Host” Header?

  2. AWS New Blog | New — Host-Based Routing Support for AWS Application Load Balancer

Share article

Unchaptered