20.4.클라우드 네이티브 리버스 프록시

트래픽(Traefik) * 클라우드 네이티브 리버스 프록시 도구 * 프록시를 적용하기 위해 애플리케이션별로 설정 파일을 따로 둘 필요 없이 컨테이너에 레이블을 추가하기만 하면 스스로 설정과 라우팅 맵을 구성한다. * 트래픽 등과 같은 컨테이너용 프록시의 가장 큰 장점은 동적 설정을 구성할 수 있다는 점이다. * 새로운 컨테이너를 모니터링하기 때문에 트래픽 실행 전에 모든 애플리케이션을 실행해 두지 않아도 된다. * 또 애플리케이션 설정이 변경돼도 트래픽을 재시작할 필요가 없다. * 프록시 적용도 애플리케이션 배포 영역의 일부가 되는 것 * 트래픽은 전용 API와 웹 UI를 갖추고 있으므로 아무 컨테이너도 없는 상태에서 트래픽을 실행하고 그 후 애플리케이션을 배포하며 자동으로 구성된 설정을 확인할 수 있다.

실습 먼저 기존 컨테이너를 모두 제거한다. 그다음에는 트래픽을 실행하고 UI를 살펴보면서 사용법을 익혀 보자.

# 트래픽 실행하기(리눅스 도커 엔진에 연결) docker-compose -f ./traefik/docker-compose.yml -f ./traefik/override-linux.yml up -d

# 웹 브라우저에서 http://localhost:8080

지금부터는 트래픽의 동작 과정 * 엔트리포인트: * 외부에서 들어오는 트래픽을 주시하는 포트다. * 이 포트와 컨테이너의 공개 포트가 매핑된다. * 나는 HTTP의 80번 포트와 HTTPS의 443번 포트, 트래픽 대시보드용 8080번 포트를 정의했다. * 라우터: * 인입된 요청을 배정할 컨테이너를 결정하는 규칙이다. * HTTP 라우터의 규칙은 호스트명, 경로 등으로 돼 있다. * 서비스: * 실제 콘텐츠를 제공하는 업스트림 컴포넌트다. * 미들웨어: * 라우터와 서비스 사이에서 서비스에 전달되는 요청을 변경하는 역할을 한다. * 요청에 포함된 경로 또는 헤더를 변경하거나 인증을 강제할 수 있다.

우선 클라이언트 요청과 이를 처리할 서비스를 연결하는 규칙을 정의해 라우터를 만들면 기본적인 설정을 충족한다.

실습 수정된 컴포즈 파일을 이용해 who-am-I 애플리케이션을 배포해 보자. 이 컴포즈 파일에는 트래픽의 라우팅을 적용하기 위한 레이블 정보가 추가됐다.

001) # 레이블이 추가된 오버라이드 파일로 애플리케이션 배포
002)  docker-compose -f ./whoami/docker-compose.yml -f ./whoami/override-traefik.yml up -d
003) 
004) # 트래픽의 라우터 정보 확인
005) # http://localhost:8080/dashboard/#/http/routers/whoami@docker
006) 
007) # 라우팅 동작 확인
008)  curl -i http://whoami.local
009) HTTP/1.1 200 OK
010) Content-Type: application/json; charset=utf-8
011) Date: Wed, 16 Aug 2023 12:45:32 GMT
012) Server: Kestrel
013) Content-Length: 112
014) 
015) "I'm bc95b3f89a94 running on CPU: Arm64; OS: Linux 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022"

예제 20-4 컨테이너 레이블을 이용한 트래픽 자동 설정 * 우리가 한 일은 컨테이너에 두 개의 레이블을 부여한 것뿐이다. * 하나는 트래픽에 자동 설정을 허용한다는 의미이고, 다른 하나는 연결할 요청의 호스트명을 지정하는 것이다.

services:
  whoami:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(``whoami.local``)"
  • 좀 더 복잡한 라우팅 설정도 가능하다.
  • 호스트명과 경로 외에 경로의 앞부분만을 일치 기준으로 삼고 나중에 미들웨어에서 이 앞부분을 제외하도록 요청을 수정하는 방법이다.
  • 복잡하게 들리지만, image-gallery 애플리케이션의 API에서 유용한 설정이다.
  • 이렇게 해야 주 애플리케이션 도메인의 하위 경로를 통해 API를 사용할 수 있다.
  • 먼저 요청 경로가 'api'로 시작하는 요청을 주시하게끔 설정한다.
  • 그다음에는 인입된 요청의 URI 경로 앞부분에서 'api'를 삭제한다.
  • 이 앞부분을 삭제하는 이유는 실제 서비스에서는 이 경로가 존재하지 않기 때문이다.

실습 트래픽 설정 적용 대상임을 나타내는 컨테이너 레이블을 적용한 오버라이드 파일과 함께 image-gallery 애플리케이션을 배포하면 라우팅 규칙이 자동으로 설정된다

001) # 새로운 레이블을 부여해 애플리케이션을 배포
002)  docker-compose -f ./image-gallery/docker-compose.yml -f ./image-gallery/override-traefik.yml up -d
003) 
004) # 웹 애플리케이션 동작 확인
005)  curl --head http://image-gallery.local
006) HTTP/1.1 200 OK
007) Content-Length: 781
008) Content-Type: text/html; charset=utf-8
009) Date: Wed, 16 Aug 2023 12:55:18 GMT
010) 
011) # API 동작 확인
012)  curl --head http://image-gallery.local/api/image
013) HTTP/1.1 200 OK
014) Content-Length: 165
015) Content-Type: application/json;charset=UTF-8
016) Date: Wed, 16 Aug 2023 12:55:48 GMT
  • API 호출과 동일한 결과를 볼 수 있을 것이다.
  • 트래픽이 http://image-gallery.local/api/image 에 대한 요청을 http://iotd/image 로 변환해 API 컨테이너에 전달했기 때문이다.
  • 먼저 라우터와 미들웨어를 정의한 다음, 미들웨어를 라우터에 연결해야 한다.
  • image-gallery/override-traefik.yml 파일에서 이 설정을 볼 수 있다.
services:
  iotd:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.image-gallery-api.rule=(Host(``image-gallery.local``) && PathPrefix(``/api``))"
      - "traefik.http.middlewares.image-gallery-api-stripprefix.stripprefix.prefixes=/api,/api/"
      - "traefik.http.routers.image-gallery-api.middlewares=image-gallery-api-stripprefix@docker"
...

nginx vs traefik * 라우팅, 로드 밸런싱, SSL 적용은 리버스 프록시의 주요 기능이다. * 트래픽의 경우, 캐시를 지원하지 않는다(버전 2.1 기준). 따라서 캐싱 프록시를 적용하려면 엔진엑스를 사용해야 한다. * 반면 SSL 지원은 트래픽이 훨씬 충실하다. 인증서 제공 서비스와 통합이 잘돼 있기 때문에 Let's Encrypt 서비스를 통해 자동으로 인증서가 갱신된다. * 개발 환경에 사용하는 것이 목적이라면 별도의 인증서 관리 없이 자체 서명 인증서를 그대로 사용해도 무방하다.

실습 image-gallery 애플리케이션과 API에 SSL 지원을 추가하려면 복잡한 트래픽 설정이 필요하다. HTTPS 엔트리포인트를 추가하고, HTTP 엔트리포인트는 HTTPS 엔트리포인트로 리다이렉트해야 한다. 이러한 설정 역시 레이블 부여만으로 가능하다.

001) # HTTPS 적용을 위한 레이블을 추가해 애플리케이션을 실행
002)  docker-compose -f ./image-gallery/docker-compose.yml -f ./image-gallery/override-traefik-ssl.yml up -d
003) 
004) # HTTPS를 통한 사이트 접근
005)  curl --head --insecure https://image-gallery.local
006) HTTP/2 200 
007) content-type: text/html; charset=utf-8
008) date: Thu, 17 Aug 2023 03:05:26 GMT
009) content-length: 781
010) 
011) # HTTPS를 통한 API 접근
012)  curl --insecure https://image-gallery.local/api/image
013) {"url":"https://apod.nasa.gov/apod/image/2308/NGC-7284-7285-LRGB-crop-CDK-1000-7-August-2023x1024.jpg","caption":"Arp 93: A Cosmic Embrace","copyright":"Mike Selby"}
  • insecure 옵션은 인증서를 신뢰할 수 없더라도 그대로 접속을 진행하라는 의미
  • nginx 때와 다르게 인증서를 생성하거나 복사하지 않고 트래픽 자동 설정 과정에 포함됐다.

스티키 세션(sticky session) * 엔진엑스에서는 설정이 까다롭지만 트래픽에서 쉽게 적용할 수 있는 기능 * 기존 애플리케이션은 상태가 있는 구성 요소를 많이 포함하고 있어서 이들 애플리케이션을 컨테이너로 이주하려면 같은 사용자의 요청은 같은 컨테이너로 계속 라우팅할 필요가 생긴다.

실습 who-am-I 애플리케이션은 스티키 세션을 적용하기에 적당하다. 현재 배포된 애플리케이션의 컨테이너 수를 늘려 확장한 다음 반복적으로 호출한다. 그러면 이 요청이 컨테이너에 고르게 분배된다. 그다음에는 스터키 세션이 적용된 버전으로 애플리케이션을 업데이트한다. 새 버전에 대한 요청은 모두 같은 컨테이너에서 처리되는 것 을 볼 수 있다.

001) # who-am-I 애플리케이션을 세 개의 컨테이너로 실행
002)  docker-compose -f whoami/docker-compose.yml -f whoami/override-traefik.yml up -d --scale whoami=3
003) 
004) # 컨테이너 간 로드 밸런싱 적용 확인
005)  curl -c c.txt -b c.txt http://whoami.local
006) "I'm 3ea075b43044 running on CPU: Arm64; OS: Linux 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022"
007) 
008)  curl -c c.txt -b c.txt http://whoami.local
009) "I'm 5caaf5a0129e running on CPU: Arm64; OS: Linux 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022"
010) 
011) # 스티키 세션을 적용해 애플리케이션 업데이트
012)  docker-compose -f whoami/docker-compose.yml -f whoami/override-traefik-sticky.yml up -d --scale whoami=3
013) "I'm af69a65a7519 running on CPU: Arm64; OS: Linux 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022"
014) 
015) # 모든 요청이 한 컨테이너에서 처리되는 것을 확인
016)  curl -c c.txt -b c.txt http://whoami.local
017) "I'm af69a65a7519 running on CPU: Arm64; OS: Linux 5.15.49-linuxkit #1 SMP PREEMPT Tue Sep 13 07:51:32 UTC 2022"
  1. 005~009: 스티키 세션을 적용하지 않으면 요청이 모든 컨테이너에 고르게 로드 밸런싱된다.
  2. 012~017: 스티키 세션을 적용하면 쿠키에 포함된 정보를 이용해 특정 사용자의 요청을 이전에 처리했던 컨테이너로만 전달한다. curl 명령은 텍스트 파일을 쿠키로 사용하는 기능이 있어 브라우저를 흉내 낼 수 있다.

  3. 스티키 세션을 활성화하면, 클라이언트에 컨테이너를 식별할 수 있는 쿠키가 부여되므로 해당 사용자의 요청을 계속 같은 컨테이너로 라우팅한다.

  4. 브라우저 세션의 쿠키나 c.txt 파일을 살펴보면 쿠키에 삽입된 컨테이너의 IP 주소를 볼 수 있다.

links

social