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

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

배경

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

  1. 인그레스

  2. 외부 네트워크 부하 분산

이 가이드에서는 인그레스를 사용합니다.

인그레스

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

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

외부 네트워크 부하 분산

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

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

목표

  • GKE 클러스터 만들기
  • 샘플 웹 애플리케이션을 클러스터에 배포합니다.
  • 샘플 앱을 외부 HTTP(S) 부하 분산기 뒤에 있는 인터넷에 노출합니다.

시작하기 전에

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

이 튜토리얼에 사용된 다음 명령줄 도구를 설치합니다.

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

GitHub에서 샘플 코드를 클론합니다.

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/load-balancing

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

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

컨테이너 클러스터 만들기

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

gcloud container clusters create loadbalancedcluster

웹 애플리케이션 배포

다음 매니페스트는 포트 8080의 HTTP 서버에서 샘플 웹 애플리케이션 컨테이너 이미지를 실행하는 배포를 설명합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: default
spec:
  selector:
    matchLabels:
      run: web
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
        imagePullPolicy: IfNotPresent
        name: web
        ports:
        - containerPort: 8080
          protocol: TCP

리소스를 클러스터에 적용합니다.

kubectl apply -f web-deployment.yaml

클러스터에 배포 노출

다음 매니페스트는 컨테이너 클러스터 내에서 web 배포에 액세스할 수 있도록 하는 서비스를 설명합니다.

apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web
  type: NodePort
  1. 리소스를 클러스터에 적용합니다.

    kubectl apply -f web-service.yaml
    

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

  2. 서비스가 생성되고 노드 포트가 할당되었는지 확인합니다.

    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) 웹 서버 애플리케이션을 공개적으로 액세스 가능하게 만들려면 반드시 인그레스 리소스를 만들어야 합니다.

인그레스 리소스 만들기

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

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

다음 매니페스트는 트래픽을 web 서비스로 보내는 인그레스 리소스를 설명합니다.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: basic-ingress
spec:
  defaultBackend:
    service:
      name: web
      port:
        number: 8080

리소스를 클러스터에 적용합니다.

kubectl apply -f basic-ingress.yaml

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

애플리케이션 방문

다음을 실행하여 애플리케이션을 제공하는 부하 분산기의 외부 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에서 부하 분산으로 이동하여 GKE 인그레스 컨트롤러에서 만든 네트워킹 리소스를 검사할 수 있습니다.

(선택사항)고정 IP 주소 구성

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

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

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

고정 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. basic-ingress-static.yaml 매니페스트는 인그레스에 주석을 추가해 web-static-ip라는 고정 IP 리소스를 사용하도록 합니다.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: basic-ingress
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "web-static-ip"
    spec:
      defaultBackend:
        service:
          name: web
          port:
            number: 8080
    

    매니페스트 보기

    cat basic-ingress-static.yaml
    
  3. 리소스를 클러스터에 적용합니다.

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

    kubectl get ingress basic-ingress
    

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

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

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

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

다음 매니페스트는 동일한 웹 애플리케이션의 2.0 버전을 사용하는 배포를 설명합니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web2
  namespace: default
spec:
  selector:
    matchLabels:
      run: web2
  template:
    metadata:
      labels:
        run: web2
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
        imagePullPolicy: IfNotPresent
        name: web2
        ports:
        - containerPort: 8080
          protocol: TCP

리소스를 클러스터에 적용합니다.

kubectl apply -f web-deployment-v2.yaml

다음 매니페스트는 web2라는 NodePort 서비스의 클러스터에 web2를 내부적으로 노출하는 서비스를 설명합니다.

apiVersion: v1
kind: Service
metadata:
  name: web2
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web2
  type: NodePort

리소스를 클러스터에 적용합니다.

kubectl apply -f web-service-v2.yaml

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

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

리소스를 클러스터에 적용합니다.

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 서비스로 라우팅되기 때문).

인그레스의 path 필드에서 지원되는 유일한 와일드카드 문자는 * 문자입니다. * 문자는 슬래시(/) 다음에 와야 하며, 패턴의 마지막 문자여야 합니다. 예를 들어 /*, /foo/*, /foo/bar/*는 유효한 패턴이지만, *, /foo/bar*, /foo/*/bar는 그렇지 않습니다.

보다 구체적인 패턴이 덜 구체적인 패턴보다 우선합니다. /foo/*/foo/bar/*가 있다면 /foo/bar/*에 맞춰 /foo/bar/bat가 사용됩니다.

경로 제한사항과 패턴 일치에 대한 자세한 내용은 URL 맵 문서를 참조하세요.

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

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

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

  1. Google Cloud Console의 모니터링 페이지로 이동합니다.

    모니터링으로 이동

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

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

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

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

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

을 참조하세요.

발언 인용

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

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

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

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

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

삭제

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

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

    GKE 인그레스 컨트롤러 관리 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

    선택사항 단계를 따라 경로별로 요청을 라우팅하는 인그레스를 만든 경우 다음 인그레스를 삭제합니다.

    kubectl delete ingress fanout-ingress

  3. 고정 IP 주소 삭제: 고정 IP 주소를 만드는 선택사항 단계를 수행한 경우에만 이 단계를 완료합니다.

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

    • '옵션 2'에 따라 새 고정 IP 주소를 만든 경우 다음 명령어를 실행하여 고정 IP 주소를 삭제합니다.

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

    gcloud container clusters delete loadbalancedcluster

다음 단계