본문 바로가기
WIKI 기술 지식 베이스

동적 요청 라우팅 구성

원문 보기 위키 갱신

동적 요청 라우팅 구성 (Configuring Dynamic Request Routing)

Gateway API의 HTTPRoute를 활용해 헤더 기반으로 HTTP 트래픽을 동적 라우팅하는 방법을 실제 예제(podinfo)로 배우는 문서예요.

출처: Linkerd Configuring Dynamic Request Routing

본문

사전 요구사항 (Prerequisites)

이 가이드를 사용하려면 클러스터에 Linkerd가 설치되어 있고, Helm CLI가 설치되어 있어야 해요.

동적 요청 라우팅 (Dynamic request routing)

동적 요청 라우팅을 사용하면 요청 헤더의 내용을 기반으로 HTTP 트래픽을 라우팅할 수 있어요. 이는 A/B 테스트나 트래픽 관리 전략 같은 작업에 유용합니다.

핵심 구성 메커니즘은 Gateway API 타입인 HTTPRoute와 GRPCRoute입니다. 이 예제에서는 HTTPRoute 타입을 사용하는 일반적인 사용 사례를 살펴볼게요.

이 튜토리얼에서는 podinfo 프로젝트를 사용해 동적 요청 라우팅을 보여줍니다. 클러스터에 backend 두 개와 frontend 한 개의 podinfo 파드를 배포할 거예요. 트래픽은 처음에 한 backend로만 흐르고, 이후 frontend 요청에 헤더를 추가하는 것만으로 다른 backend로 트래픽을 전환해 볼게요.

설치 (Setup)

먼저 test 네임스페이스를 만들고 linkerd로 annotation을 달아, 그곳에 생성되는 모든 파드에 linkerd 프록시가 주입되도록 합니다:

`kubectl create ns test --dry-run=client -o yaml \
  | linkerd inject - \
  | kubectl apply -f -
`

그 다음 podinfo의 Helm repo를 추가하고, 두 개의 인스턴스를 설치합니다. 첫 번째는 "A backend"라는 메시지로 응답하고, 두 번째는 "B backend"로 응답할 거예요.

`helm repo add podinfo https://stefanprodan.github.io/podinfo
helm install backend-a -n test \
  --set ui.message='A backend' podinfo/podinfo
helm install backend-b -n test \
  --set ui.message='B backend' podinfo/podinfo
`

첫 번째 backend 인스턴스 backend-a로만 요청을 보내는 podinfo 인스턴스를 하나 더 추가합니다:

`helm install frontend -n test \
  --set backend=http://backend-a-podinfo:9898/env podinfo/podinfo
`

세 파드가 모두 실행되면, 로컬 머신에서 frontend로 요청을 port-forward할 수 있어요:

`kubectl -n test port-forward svc/frontend-podinfo 9898 &
`

요청 보내기 (Sending Requests)

frontend 파드의 9898 포트 /echo로 보내는 요청은 Service backend-a-podinfo가 가리키는 파드로 전달됩니다:

`$ curl -sX POST localhost:9898/echo \
  | grep -o 'PODINFO_UI_MESSAGE=. backend'

PODINFO_UI_MESSAGE=A backend
`

HTTPRoute 소개 (Introducing HTTPRoute)

헤더 기반 라우팅을 활성화하기 위해 다음 HTTPRoute 리소스를 적용해 볼게요:

`cat 
apiVersion: policy.linkerd.io/v1beta2
kind: HTTPRoute
metadata:
  name: backend-router
  namespace: test
spec:
  parentRefs:
    - name: backend-a-podinfo
      kind: Service
      group: core
      port: 9898
  rules:
    - matches:
      - headers:
        - name: "x-request-id"
          value: "alternative"
      backendRefs:
        - name: "backend-b-podinfo"
          port: 9898
    - backendRefs:
      - name: "backend-a-podinfo"
        port: 9898
EOF
`

parentRefs에는 이 HTTPRoute 인스턴스가 작용할 리소스를 지정합니다. 여기서는 HTTPRoute의 네임스페이스(test)에 있는 backend-a-podinfo Service를 가리키고, Service의 포트 번호(Service의 target port가 아니라)를 지정했어요.

다음으로, 해당 Service로 들어오는 트래픽에 작용할 규칙 리스트를 제공합니다.

첫 번째 규칙에는 matches와 backendRefs 두 항목이 들어 있어요.

matches에는 이 특정 규칙이 매칭해야 할 조건을 나열합니다. 하나의 matches만 충족되면 규칙이 발동합니다(조건은 OR로 결합됩니다). 그 안에서 headers를 사용해 특정 헤더 키와 값에 대한 매칭을 지정할 수 있어요. 여러 헤더를 지정하면 모두 매칭되어야 합니다(matcher는 AND로 결합). 값에 대한 정규식 매칭을 원한다면 type: RegularExpression 필드를 추가할 수도 있습니다. 여기서처럼 type을 지정하지 않으면 Exact 타입으로 매칭합니다.

backendRefs에는 현재 규칙에 매칭되는 요청의 최종 목적지를 Service의 name과 port로 지정합니다.

여기서는 x-request-id: alternative 헤더를 가진 모든 요청을 backend-b-podinfo로 라우팅하도록 지정했어요. 헤더가 없으면 엔진은 matches 항목이 없고 backend-a-podinfo Service를 가리키는 마지막 규칙으로 폴백합니다.

앞선 요청들은 여전히 backend-a-podinfo로만 도달해야 해요:

`$ curl -sX POST localhost:9898/echo \
  | grep -o 'PODINFO_UI_MESSAGE=. backend'

PODINFO_UI_MESSAGE=A backend
`

하지만 x-request-id: alternative 헤더를 추가하면 backend-b-podinfo로 라우팅됩니다:

`$ curl -sX POST \
  -H 'x-request-id: alternative' \
  localhost:9898/echo \
  | grep -o 'PODINFO_UI_MESSAGE=. backend'

PODINFO_UI_MESSAGE=B backend
`

구현 참고사항 (Implementation notes)

위 예제에서 우리는 podinfo가 전달하는 일반적인 헤더인 x-request-id를 사용했어요. 하지만 애플리케이션이 헤더를 전달하기만 하면, 같은 기법이 임의의 헤더에서도 동작합니다.

또한 동적 요청 라우팅은 클라이언트 측 동작이라는 점에 주의하세요. 그래서 트래픽 소스(여기서는 frontend 파드)는 메시에 포함되어야 하지만, 엄밀히 말하면 목적지는 메시에 포함될 필요가 없습니다.

더 알아보기 (Learn more)

  • Linkerd의 동적 요청 라우팅 기능 개요
  • 라우팅 정책 구성 가이드