20.2.리버스 프록시의 라우팅과 SSL 적용하기

  • 조금 전, 다음과 같은 방법으로 리버스 프록시에 새로운 애플리케이션을 추가했다.
  • 먼저 애플리케이션 컨테이너를 시작하고, 사이트 설정 파일을 엔진엑스 컨테이너에 복사한 다음, 엔진엑스 컨테이너를 재시작했다.
  • 이 순서가 중요한 이유는 엔진엑스를 재시작할 때 사이트별 설정 파일을 모두 읽은 다음 해당 설정의 업스트림이 모두 접근 가능한지 확인을 거치기 때문이다.
  • 업스트림 중 하나라도 접근이 불가능한 것이 있다면 엔진엑스는 그대로 종료된다.
  • 업스트림에 모두 접근이 가능하다면, 그다음에는 호스트명과 IP 주소를 연결한 내부 라우팅 리스트를 만든다.
  • 이 리스트가 프록시가 맡아 처리해 주는 첫 번째 인프라스트럭처 관련 사항이다.
  • 업스트림 컨테이너가 여러 개 존재한다면 이들 간의 로드 밸런싱까지 처리해 준다.

실습 이번에는 image-gallery 애플리케이션을 실행하며, 주 웹 애플리케이션에 리버스 프록시를 적용한다. 웹 애플리케이션 컴포넌트를 스케일링하면 늘어난 컨테이너 간의 로드 밸런싱을 엔진엑스가 처리해 준다.

001) # 도메인을 hosts 파일에 추가(맥 또는 리눅스)
002)  echo $'\n127.0.0.1 image-gallery.local' | sudo tee -a /etc/hosts
003) 
004) # 애플리케이션을 세 개의 컨테이너로 스케일링해 실행
005)  docker-compose -f ./image-gallery/docker-compose.yml up -d --scale image-gallery=3
006) 
007) # 사이트 설정 파일을 엔진엑스 설정 파일 디렉터리로 복사하고 엔진엑스 재시작
008)  cp ./nginx/sites-available/image-gallery.local ./nginx/sites-enabled/
009) 
010)  docker-compose -f nginx/docker-compose.yml restart nginx
011) 
012) # 웹 애플리케이션에 접근
013)  curl -i --head http://image-gallery.local
014) HTTP/1.1 200 OK
015) Server: nginx/1.17.6
016) Date: Tue, 15 Aug 2023 11:48:08 GMT
017) Content-Type: text/html; charset=utf-8
018) Content-Length: 821
019) Connection: keep-alive
020) X-Proxy: 09a7df57ce06
021) X-Upstream: 172.20.0.6:80
  1. 013~021: 엔진엑스가 세 개의 컨테이너에 요청을 고르게 분배한다. 응답의 헤더에는 실제 요청을 처리한 컨테이너의 IP 주소 정보가 있다. 여러 번 호출하면 이 주소가 변화하는 것을 볼 수 있다

  2. 단일 도커 호스트에서도 이제 애플리케이션에 로드 밸런싱을 적용할 수 있다.

  3. 도커 엔진을 스월 모드로 전환하거나 쿠버네티스 클러스터를 꾸리지 않아도 된다.
  4. 애플리케이션 코드나 설정도 전혀 수정하지 않았다. 그저 리버스 프록시를 적용했을 뿐이다.

실습 image-gallery 애플리케이션은 REST API를 사용한다. HTTP 요청 경로를 이용해 엔진엑스에 이 API의 프록시를 설정할 수 있다. 이 API는 별도의 컨테이너에서 실행되지만 웹 UI와 마찬가지로 image-gallery 애플리케이션의 일부다

  • 지금까지는 한 환경에서 여러 애플리케이션을 실행할 때처럼 호스트명을 통해 엔진엑스가 컨테이너를 구별하도록 했다.
  • 엔진엑스 라우팅 기능을 이용하면 훨씬 더 세세한 설정이 가능하다.
  • 같은 도메인을 가진 컨테이너 간에도 선택적으로 컨테이너를 노출시킬 수 있다.
001) # image-gallery 애플리케이션의 기존 설정 파일 삭제
002)  rm ./nginx/sites-enabled/image-gallery.local
003) 
004) # 새로운 설정 파일을 복사하고 엔진엑스 재시작
005)  cp ./nginx/sites-available/image-gallery-2.local ./nginx/sites-enabled/image-gallery.local
006) 
007)  docker-compose -f ./nginx/docker-compose.yml restart nginx
008) 
009)  curl -i http://image-gallery.local/api/image
010) HTTP/1.1 200 
011) Server: nginx/1.17.6
012) Date: Tue, 15 Aug 2023 12:07:31 GMT
013) Content-Type: application/json;charset=UTF-8
014) Transfer-Encoding: chunked
015) Connection: keep-alive
016) X-Proxy: 09a7df57ce06
017) X-Upstream: 172.20.0.5:80
018) 
019) {
020)   "url":"https://apod.nasa.gov/apod/image/2308/TripleIceland_Zarzycka_1080.jpg",
021)   "caption":"A Triply Glowing Night Sky over Iceland",
022)   "copyright":"\nWioleta Gorecka;\nText: Natalia Lewandowska \n(SUNY Oswego)\n"
023) }
  1. 002: 새 사이트별 설정에는 경로 /api/image를 API 컨테이너로 연결하는 프록시 설정이 포함된다. 같은 도메인이라도 이 외의 경로에 대한 요청은 다른 컨테이너로 전달된다.
  2. 009~023: 웹 컨테이너에 접근하는 데 사용하던 image-gallery.local 도메인으로 API 컨테이너에도 접근할 수 있게 됐다.

  3. 애플리케이션 스택의 일부분만 노출시키고 싶을 때 매우 유용한 패턴이며, 여러 개의 컴포넌트를 하나의 도메인 아래에 묶어 내고 싶을 때도 유용하다.

실습 image-gallery 애플리케이션에서 사용할 SSL 인증서를 생성하고 엔진엑스에서 이 인증서를 사용해 HTTPS 프록시를 적용한다.

  • 로드 밸런싱과 라우팅까지 갖추면 개발용 또는 테스트용 단일 컴퓨터에서 운영 환경과 비슷한 조건을 만들 수 있다.
  • 여기에 한 가지를 더 보태자면 SSL 종료 프록시가 있다.
  • 애플리케이션이 HTTPS 사이트(요즘은 응당 그래야 한다)로 돼 있다면 이를 위한 설정과 인증서가 어딘가에 위치해야 한다.
  • 그리고 모든 애플리케이션 컴포넌트마다 따로 이를 두는 것보다는 중앙의 프록시에 두는 것이 훨씬 나을 것이다.
  • 엔진엑스는 Let's Encrypt 같은 실제 도메인 제공자나 서비스에서 발급한 실제 인증서를 설정에 포함할 수 있다.
  • 하지만 운영 외 환경에서는 자체 서명 인증서를 만들어 사용해도 된다.
001) # 자체 서명 인증서 생성하기(리눅스 컨테이너)
002)  docker container run -v "$(pwd)/nginx/certs:/certs" -e HOST_NAME=image-gallery.local diamol/cert-generator
003) 
004) # 기존 설정 파일 삭제
005)  rm ./nginx/sites-enabled/image-gallery.local
006) 
007) # SSL이 포함된 사이트별 설정 파일 복사
008)  cp ./nginx/sites-available/image-gallery-3.local ./nginx/sites-enabled/image-gallery.local
009) 
010)  docker-compose -f nginx/docker-compose.yml restart nginx
011) 
012) # 웹 브라우저에서 http://image-gallery.local
  1. 002: OpenSSL 이라는 도구를 사용해 자체 서명 인증서를 생성하고 로컬 컴퓨터의 certs 디렉터리로 복사한다. 이 디텍터리는 엔진엑스 컨테이너에 바인드 마운트된다.

  2. HTTP 프로토콜로 애플리케이션에 접근해 보면 HTTPS로 리다이렉트되는 것을 볼 수 있다.

  3. 브라우저에서 자체 서명 인증서로 인한 경고 메시지가 나온다.
  4. 자체 서명 인증서는 가짜 웹 사이트에 이용될 수 있기 때문이다.
  5. 테스트 목적으로는 아무 문제가 없으므로 경고를 무시하고 그대로 진행한다.

예제 20-2 HTTP 연결을 리다이렉트하는 HTTPS 사이트 설정 * HTTP 사이트가 80번 포트를 주시하다가 301 응답을 보내 클라이언트를 443번 포트를 사용하는 HTT PS 사이트로 리다이렉트하는 것을 볼 수 있다. * 설정에 지정된 인증서와 키 파일을 컨테이너 파일 시스템에서 읽어 들인다. * 인증서와 키 파일 쌍은 하나의 도메인에 한해서만 유효하므로 애플리케이션 하나마다 인증서와 키 파일 세트가 필요하다. * 인증서와 키 파일은 민감한 정보이므로 운영 환경에서는 비밀값 형태로 클러스터에 저장된다. * HTTPS를 적용하지 않으면 애플리케이션 컨테이너의 설정과 인증서 관리 부담이 그만큼 줄어들며(인증서 관리는 프록시로 옮겨 온 인프라스트럭처 문제다), 개발자는 단순 HTTP 버전으로 테스트를 진행할 수 있다.

server {
  server_name image-gallery.local;
  listen 80;
    return 301 https://$server_name$request_uri;
}

server {
    server_name  image-gallery.local;
    listen 443 ssl;

    ssl_certificate        /etc/nginx/certs/server-cert.pem;
    ssl_certificate_key    /etc/nginx/certs/server-key.pem;
    ssl_protocols          TLSv1 TLSv1.1 TLSv1.2;
  ...

links

social