인그레스를 사용한 HTTP(S) 부하 분산 설정

이 가이드에서는 인그레스 리소스를 구성하여 외부 HTTP 부하 분산기 뒤에서 웹 애플리케이션을 실행하는 방법을 설명합니다.

배경

Google Kubernetes Engine(GKE)은 공개적으로 액세스 가능한 애플리케이션을 위한 두 가지 유형의 Cloud Load Balancing을 통합 지원합니다.

  • 리소스 매니페스트에서 type:LoadBalancer를 지정하면 GKE는 LoadBalancer 유형의 서비스를 만듭니다. GKE는 적절한 Google Cloud API를 호출하여 외부 네트워크 부하 분산기 또는 내부 TCP/UDP 부하 분산기를 만듭니다. cloud.google.com/load-balancer-type: "Internal" 주석을 추가하면 GKE는 내부 TCP/UDP 부하 분산기를 만들고 그렇지 않으면 외부 네트워크 부하 분산기를 만듭니다.

    이러한 유형의 부하 분산기 중 어느 유형이나 HTTP(S) 트래픽에 사용할 수 있지만 부하 분산기는 OSI 계층 3/4에서 작동하며 HTTP 연결이나 개별 HTTP 요청 및 응답을 인식하지 못합니다. 또 다른 중요한 특징은 요청이 대상으로 프록시 처리되지 않는다는 점입니다.

  • 리소스 매니페스트에서 kind:Ingress를 지정하면 인그레스 리소스를 만들도록 GKE에게 지시할 수 있습니다. 주석과 지원 워크로드 및 서비스를 포함하면 커스텀 인그레스 컨트롤러를 만들 수 있습니다. 그렇지 않으면 GKE는 적절한 Google Cloud API를 호출하여 외부 HTTP(S) 부하 분산기를 만듭니다. 부하 분산기 URL 맵의 호스트 규칙과 경로 일치자는 백엔드 서비스를 한 개 이상 참조하며, 각 백엔드 서비스는 Ingress에서 참조된 NodePort 유형의 GKE 서비스에 해당합니다. 각 백엔드 서비스의 백엔드는 인스턴스 그룹 또는 네트워크 엔드포인트 그룹(NEG)입니다. NEG는 인그레스 구성의 일부로 컨테이너 기반 부하 분산을 구성할 때 생성됩니다. GKE는 해당 GKE 서비스에서 참조하는 워크로드의 준비 프로브 설정에 따라 백엔드 서비스마다 Google Cloud 상태 확인을 만듭니다.

    GKE에서 호스팅되는 HTTP(S) 서비스를 노출하는 경우, HTTP(S) 부하 분산이 권장되는 부하 분산 방식입니다.

시작하기 전에

다음 단계에 따라 Kubernetes Engine API를 사용 설정합니다.
  1. Google Cloud Console에서 Kubernetes Engine 페이지로 이동합니다.
  2. 프로젝트를 만들거나 선택합니다.
  3. API 및 관련 서비스가 사용 설정될 때까지 기다립니다. 몇 분 정도 걸릴 수 있습니다.
  4. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

이 가이드에 사용된 다음 명령줄 도구를 설치합니다.

  • gcloud는 Kubernetes Engine 클러스터를 만들고 삭제하는 데 사용됩니다. gcloudGoogle Cloud SDK에 포함되어 있습니다.
  • kubectl은 Kubernetes Engine에서 사용되는 클러스터 조정 시스템인 Kubernetes를 관리하는 데 사용됩니다. gcloud를 사용하여 kubectl을 설치할 수 있습니다.
    gcloud components install kubectl

gcloud 명령줄 도구의 기본값 설정

gcloud 명령줄 도구에 프로젝트 IDCompute Engine 영역 옵션을 입력하는 시간을 절약하려면 기본값을 설정하면 됩니다.
gcloud config set project project-id
gcloud config set compute/zone compute-zone

컨테이너 클러스터 만들기

다음을 실행하여 loadbalancedcluster라는 컨테이너 클러스터를 만듭니다.

gcloud container clusters create loadbalancedcluster

1단계: 웹 애플리케이션 배포

포트 8080의 HTTP 서버를 리슨하는 샘플 웹 애플리케이션 컨테이너 이미지를 사용하여 배포를 만듭니다.

  1. web-deployment.yaml 매니페스트를 다운로드합니다.
  2. 리소스를 클러스터에 적용합니다.

    kubectl apply -f web-deployment.yaml
    

2단계: 내부적으로 배포를 서비스로 노출

서비스 리소스를 만들어 컨테이너 클러스터 내에서 web 배포에 도달할 수 있도록 합니다.

  1. web-service.yaml 매니페스트를 다운로드합니다.
  2. 리소스를 클러스터에 적용합니다.

    kubectl apply -f web-service.yaml
    

    이 명령어로 NodePort 유형의 서비스를 만들면 GKE는 클러스터의 모든 노드에서 무작위로 선택된 높은 포트 번호(예: 32640)에서 이 서비스를 사용할 수 있도록 합니다.

  3. 서비스가 생성되었고 노드 포트가 할당되었는지 확인하세요.

    kubectl get service web
    
    결과:
    NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    web       NodePort   10.35.245.219   <none>        8080:32640/TCP   5m
    

    위 샘플 출력에서 web 서비스의 노드 포트는 32640입니다. 또한 이 서비스에 할당된 외부 IP가 없습니다. GKE 노드는 기본적으로 외부에서 액세스할 수 없으므로 이 서비스를 만들어도 인터넷에서 애플리케이션에 액세스할 수 없습니다.

HTTP(S) 웹 서버 애플리케이션을 공개적으로 액세스 가능하게 만들려면 인그레스 리소스를 만들어야 합니다.

3단계: 인그레스 리소스 만들기

인그레스는 외부 HTTP(S) 트래픽을 내부 서비스로 라우팅하기 위한 규칙과 구성의 모음을 캡슐화하는 Kubernetes 리소스입니다.

GKE에서 인그레스는 Cloud Load Balancing을 사용하여 구현됩니다. 클러스터에서 인그레스를 만들면 GKE는 HTTP(S) 부하 분산기를 만들고 트래픽을 애플리케이션으로 라우팅하도록 구성합니다.

Kubernetes 인그레스는 베타 리소스이지만(즉, 인그레스 객체를 설명하는 방법이 바뀔 수 있습니다) GKE가 인그레스를 구현하기 위해 프로비저닝하는 Cloud 부하 분산기는 즉시 프로덕션 가능합니다.

다음 구성 파일은 트래픽을 web 서비스로 보내는 인그레스 리소스를 정의합니다.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: basic-ingress
spec:
  backend:
    serviceName: web
    servicePort: 8080

이 인그레스 리소스를 배포하려면 다음 안내를 따르세요.

  1. basic-ingress.yaml 매니페스트를 다운로드합니다.
  2. 리소스를 클러스터에 적용합니다.

    kubectl apply -f basic-ingress.yaml
    

이 매니페스트를 배포하면 Kubernetes가 클러스터에 인그레스 리소스를 만듭니다. GKE 인그레스 컨트롤러는 인그레스 정보에 따라 HTTP(S) 부하 분산기를 생성 및 구성하여 모든 외부 HTTP 트래픽(포트 80)을 노출된 web NodePort 서비스로 라우팅합니다.

4단계: 애플리케이션 방문

다음을 실행하여 애플리케이션을 제공하는 부하 분산기의 외부 IP 주소를 찾습니다.

kubectl get ingress basic-ingress
결과:
NAME            HOSTS     ADDRESS         PORTS     AGE
basic-ingress   *         203.0.113.12    80        2m

브라우저가 애플리케이션의 외부 IP 주소를 가리키도록 하고 다음과 같은 일반 텍스트 HTTP 응답을 확인합니다.

Hello, world!
Version: 1.0.0
Hostname: web-6498765b79-fq5q5

Cloud Console에서 부하 분산으로 이동하여 인그레스 컨트롤러가 만든 네트워킹 리소스를 검사할 수 있습니다.

5단계: (선택사항) 고정 IP 주소 구성

도메인 이름에서 웹 서버를 노출할 경우 애플리케이션의 외부 IP 주소는 변경되지 않는 고정 IP여야 합니다.

기본적으로 GKE는 인그레스를 통해 노출되는 HTTP 애플리케이션에 임시 외부 IP 주소를 할당합니다. 임시 주소는 변경될 수 있습니다. 웹 애플리케이션을 장시간 사용하려면 고정 외부 IP 주소를 사용해야 합니다.

인그레스 리소스에 대해 고정 IP를 구성하면 인그레스를 삭제해도 연결된 고정 IP 주소는 삭제되지 않습니다. 구성한 고정 IP 주소를 더 이상 사용하지 않으려면 반드시 삭제하세요.

옵션 1: 기존 임시 IP 주소를 고정 IP 주소로 변환

인그레스를 이미 배포했다면 Cloud Console에서 외부 IP 주소 섹션으로 이동하여 외부 IP 주소를 변경하지 않고 애플리케이션의 기존 임시 IP 주소를 예약된 고정 IP 주소로 변환할 수 있습니다.

옵션 2: 새 고정 IP 주소 예약

  1. web-static-ip라는 고정 외부 IP 주소를 예약합니다.

    gcloud

    gcloud compute addresses create web-static-ip --global
    

    구성 커넥터

    참고: 이 단계에는 구성 커넥터가 필요합니다. 설치 안내를 따라 클러스터에 구성 커넥터를 설치합니다.

    apiVersion: compute.cnrm.cloud.google.com/v1beta1
    kind: ComputeAddress
    metadata:
      name: web-static-ip
    spec:
      location: global
    이 매니페스트를 배포하려면 머신에 compute-address.yaml로 다운로드하고 다음을 실행합니다.
    kubectl apply -f compute-address.yaml

  2. 예약된 IP 주소를 사용하도록 기존 인그레스 리소스를 구성합니다. 앞에서 사용한 basic-ingress.yaml 매니페스트를 다음 매니페스트로 바꿉니다.

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: basic-ingress
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "web-static-ip"
    spec:
      backend:
        serviceName: web
        servicePort: 8080
    

    이렇게 변경하면 web-static-ip라는 고정 IP 리소스를 사용하라는 주석이 인그레스에 추가됩니다.

  3. 기존 인그레스에 다음 수정사항을 적용합니다.

    kubectl apply -f basic-ingress.yaml
    
  4. 외부 IP 주소를 확인합니다.

    kubectl get ingress basic-ingress
    

    애플리케이션의 IP 주소가 변경될 때까지 기다린 후 web-static-ip 리소스의 예약된 IP 주소를 사용합니다.

    기존 인그레스 리소스를 업데이트하고, 부하 분산기를 구성하고, 전 세계에 부하 분산 규칙을 전파하는 데 몇 분 정도 걸릴 수 있습니다. 이 작업이 완료되면 GKE는 이전에 애플리케이션에 할당된 임시 IP 주소를 해제합니다.

6단계: (선택사항) 부하 분산기에서 여러 애플리케이션 제공

인그레스에서 라우팅 규칙을 구성하여 단일 부하 분산기에서 여러 서비스를 실행할 수 있습니다. 동일한 인그레스에서 여러 서비스를 호스팅하면 인터넷에 노출되는 모든 서비스에 대해 추가 부하 분산기(청구 가능 리소스)를 생성하지 않아도 됩니다.

동일한 웹 애플리케이션의 2.0 버전을 사용하여 다른 웹 서버 배포를 만듭니다.

web-deployment-v2.yaml을 다운로드한 후 리소스를 클러스터에 적용합니다.

kubectl apply -f web-deployment-v2.yaml

그런 다음 web2라는 NodePort 서비스의 클러스터에 web2 배포를 내부적으로 노출합니다.

web-service-v2.yaml을 다운로드한 후 리소스를 클러스터에 적용합니다.

kubectl apply -f web-service-v2.yaml

다음 매니페스트는 다음과 같은 인그레스 리소스를 설명합니다.

  • 경로가 /v2/로 시작하는 요청을 web2 서비스로 라우팅합니다.
  • 다른 모든 요청을 web 서비스로 라우팅합니다.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: fanout-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: web
          servicePort: 8080
      - path: /v2/*
        backend:
          serviceName: web2
          servicePort: 8080

이 매니페스트를 배포하려면 fanout-ingress.yaml에 저장하고 다음을 실행합니다.

kubectl create -f fanout-ingress.yaml

인그레스가 배포되면 kubectl get ingress fanout-ingress를 실행하여 클러스터의 공개 IP 주소를 찾습니다.

그런 다음 IP 주소로 이동하여 동일한 부하 분산기에서 두 애플리케이션 모두에 도달할 수 있는지 확인합니다.

  • http://<IP_ADDRESS>/로 이동하여 응답에 Version: 1.0.0이 포함되어 있는지 확인합니다(요청이 web 서비스로 라우팅되기 때문).
  • http://<IP_ADDRESS>/v2/로 이동하여 응답에 Version: 2.0.0이 포함되어 있는지 확인합니다(요청이 web2 서비스로 라우팅되기 때문).

GKE 인그레스의 path 필드에 지원되는 유일한 와일드 카드 패턴 일치는 * 문자를 통하는 것입니다. 예를 들어 /* 또는 /foo/bar/*와 같은 path 필드가 있는 규칙을 가질 수 있습니다. path 제한은 URL 맵 문서를 참조하세요.

7단계: (선택사항) 서비스 가용성 및 지연 시간 모니터링

Google Cloud 업타임 체크는 사용자의 관점에서 애플리케이션의 블랙박스 모니터링을 수행하여 여러 외부 IP에서 부하 분산기 IP 주소까지의 지연 시간과 가용성을 확인합니다. 반면에 Google Cloud 상태 확인은 Pod IP에 대한 내부 확인을 수행하여 인스턴스 수준에서 가용성을 판단합니다. 업타임 체크와 상태 확인은 상호 보완적이며 이들을 통해 애플리케이션 상태를 전체적으로 파악할 수 있습니다.

Google Cloud Console, Cloud Monitoring API 또는 Cloud Monitoring 클라이언트 라이브러리를 사용하여 업타임 체크를 만들 수 있습니다. 자세한 내용은 업타임 체크 관리를 참조하세요. Google Cloud Console을 사용하여 업타임 체크를 만들려면 다음 단계를 따르세요.

  1. Google Cloud Console에서 Monitoring을 선택하거나 다음 버튼을 클릭합니다.

    Monitoring으로 이동

  2. Monitoring 탐색창에서 업타임 체크를 선택한 다음 업타임 체크 만들기를 클릭합니다.

  3. 업타임 체크의 대상에 대해 다음 필드를 설정합니다.

    • 프로토콜 유형을 TCP로 선택합니다.
    • 리소스 유형으로 URL을 선택합니다.
    • 호스트 이름으로 부하 분산기의 IP 주소를 입력합니다.
    • 포트 필드에 부하 분산기 포트 번호를 입력합니다.

    업타임 체크의 모든 필드에 대한 전체 문서는 업타임 체크 만들기를 참조하세요.

업타임 체크를 모니터링하려면 알림 정책을 만들거나 업타임 체크 대시보드를 봅니다. 업타임 체크에 실패할 경우 알림 정책이 이메일이나 다른 채널을 통해 알려줍니다. 알림 정책에 대한 일반적인 정보는 알림 소개를 참조하세요.

을 참조하세요.

비고

기본적으로 인그레스는 / 경로에 GET 요청을 통해 정기적으로 상태 확인을 수행하여 애플리케이션 상태를 확인하고 HTTP 200 응답을 기다립니다. 다른 경로를 확인하거나 다른 응답 코드를 원하는 경우에는 커스텀 상태 확인 경로를 사용하면 됩니다.

인그레스는 다음과 같은 고급 사용 사례를 지원합니다.

  • 이름 기반 가상 호스팅: 인그레스를 사용하여 여러 도메인 이름과 하위 도메인에 부하 분산기를 다시 사용하고 단일 IP 주소와 부하 분산기에서 여러 서비스를 노출합니다. 이러한 태스크용 인그레스를 구성하는 방법은 간단한 팬아웃이름 기반 가상 호스팅 예시를 참조하세요.

  • HTTPS 종료: Cloud 부하 분산기를 사용하여 HTTPS 트래픽을 종료하도록 인그레스를 구성할 수 있습니다.

인그레스가 삭제되면 인그레스 컨트롤러는 연결된 리소스(예약된 고정 IP 주소 제외)를 자동으로 삭제합니다.

삭제

이 가이드에서 사용한 리소스에 대한 비용이 Google Cloud Platform 계정에 청구되지 않도록 다음을 따릅니다.

  1. 수동으로 생성된 전달 규칙과 인그레스를 참조하는 대상 프록시를 삭제합니다.

    인그레스 컨트롤러 관리 URL 맵을 참조하는 허상 대상 프록시는 GKE 버전 1.15.4-gke.22 이상에서 인그레스 삭제 실패를 유발합니다. 인그레스 리소스를 검사하여 다음과 유사한 오류 메시지가 있는 이벤트를 찾을 수 있습니다.

     Error during GC: error running load balancer garbage collection routine: googleapi: Error 400: The url_map resource 'projects/project-id/global/urlMaps/k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82' is already being used by 'projects/project-id/global/targetHttpsProxies/k8s2-um-tlw9rhgp-default-my82-target-proxy', resourceInUseByAnotherResource
     

    위의 샘플 오류 메시지에서 k8s2-um-tlw9rhgp-default-my82-target-proxy는 인그레스 컨트롤러에 의해 생성되고 관리된 URL 맵 k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82를 여전히 참조하고 있는 수동으로 생성된 대상 https 프록시입니다.

    따라서 수동으로 생성된 프런트엔드 리소스(전달 규칙과 대상 프록시 모두)를 삭제해야 인그레스 삭제를 진행할 수 있습니다.

  2. 인그레스 삭제: 이렇게 하면 임시 외부 IP 주소 및 애플리케이션에 연결된 부하 분산 리소스의 할당이 취소됩니다.

    kubectl delete ingress basic-ingress

    '6단계'를 따른 경우, 다음을 실행하여 인그레스를 삭제합니다.

    kubectl delete ingress fanout-ingress

  3. 고정 IP 주소 삭제: 5단계를 수행한 경우에만 이를 실행합니다.

    • 5단계의 '옵션 1'을 수행하여 기존 임시 IP 주소를 고정 IP로 변환한 경우 Cloud Console로 이동하여 고정 IP를 삭제합니다.

    • 5단계의 '옵션 2'를 수행한 경우에는 다음 명령어를 실행하여 고정 IP 주소를 삭제합니다.

      gcloud compute addresses delete web-static-ip --global
  4. 클러스터 삭제: 컨테이너 클러스터와 클러스터의 배포와 같은 기타 리소스의 컴퓨팅 노드가 삭제됩니다.

    gcloud container clusters delete loadbalancedcluster

다음 단계