HTTP(S) 부하 분산용 GKE 인그레스

이 페이지에서는 HTTP(S) 부하 분산용 인그레스 작동 방식에 대한 일반적인 내용을 간략하게 설명합니다. Google Kubernetes Engine(GKE)은 GKE 인그레스라고 하는 관리형 인그레스 컨트롤러를 기본 제공합니다. 이 컨트롤러는 인그레스 리소스를 GKE의 HTTP(S) 워크로드용 Google Cloud 부하 분산기로 구현합니다.

개요

GKE에서 인그레스 객체는 HTTP(S) 트래픽을 클러스터에서 실행되는 애플리케이션으로 라우팅하는 규칙을 정의합니다. 인그레스 객체는 각각 Pod 집합에 연결된 서비스 객체 한 개 이상과 연결됩니다.

인그레스 객체를 만들면 GKE 인그레스 컨트롤러Google Cloud HTTP(S) 부하 분산기를 만들고 인그레스 및 연결된 서비스의 정보에 따라 구성합니다.

외부 및 내부 트래픽 인그레스

GKE 인그레스 리소스에는 두 가지 유형이 있습니다.

HTTP(S) 부하 분산 특징

인그레스에 의해 구성되는 HTTP(S) 부하 분산의 특징은 다음과 같습니다.

서비스를 위한 유연한 구성
인그레스는 트래픽이 서비스에 도달하는 방법과 트래픽이 애플리케이션으로 라우팅되는 방법을 정의합니다. 또한 인그레스는 클러스터의 여러 서비스에 단일 IP 주소를 제공할 수 있습니다.
Google Cloud 네트워크 서비스와 통합
인그레스는 Google 관리형 SSL 인증서(베타), Google Cloud Armor, Cloud CDN, IAP(Identity-Aware Proxy)와 같은 Google Cloud 기능을 구성할 수 있습니다.
여러 TLS 인증서 지원
인그레스는 요청 종료를 위한 여러 TLS 인증서 사용을 지정할 수 있습니다.

컨테이너 기반 부하 분산

컨테이너 기반 부하 분산네트워크 엔드포인트 그룹(NEG)을 사용하여 GKE의 Pod 엔드포인트로 직접 부하 분산을 수행하는 방법입니다.

NEG 이전에는 Compute Engine 부하 분산기가 노드 IP를 백엔드로 사용하여 트래픽을 인스턴스 그룹에 전송했습니다. 이 방법에는 다음과 같은 여러 가지 제한사항이 있습니다.

  • 2홉의 부하 분산이 발생합니다.
  • 지연 시간이 증가합니다.
  • Compute Engine 부하 분산기는 Pod를 직접 볼 수 없으므로 최적화되지 않은 트래픽 분산이 발생합니다.

NEG를 사용하면 트래픽은 노드 IP 또는 kube-proxy 네트워킹을 통과하지 않고 인그레스 프록시에서 Pod IP로 직접 부하 분산됩니다. 또한 Pod 준비 게이트가 구현되어 Kubernetes 준비 및 활성 확인뿐만 아니라 부하 분산기 관점에서 Pod 상태를 확인합니다. 이렇게 하면 Pod 시작, Pod 손실 또는 노드 손실과 같은 수명 주기 이벤트 중에 트래픽이 중단되지 않습니다.

NEG와 함께 인그레스를 배포하여 컨테이너 기반 부하 분산을 사용하는 것이 좋으며, 가능한 항상 사용해야 합니다. 이는 서비스의 기본 모드가 아니며 인그레스 규칙의 백엔드인 서비스에 cloud.google.com/neg 주석과 함께 명시적으로 적용되어야 합니다.

kind: Service
...
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
...

여러 백엔드 서비스

HTTP(S) 부하 분산기는 다양한 백엔드 서비스로 요청을 라우팅하는 데 사용할 수 있는 안정적인 IP 주소 하나를 제공합니다.

예를 들어 URL 경로에 따라 서로 다른 백엔드 서비스로 요청을 라우팅하도록 부하 분산기를 구성할 수 있습니다. your-store.example로 전송되는 요청은 정가 품목을 표시하는 백엔드 서비스로 라우팅될 수 있고, your-store.example/discounted로 전송되는 요청은 할인 품목을 표시하는 백엔드 서비스로 라우팅될 수 있습니다.

호스트 이름에 따라 요청을 라우팅하도록 부하 분산기를 구성할 수도 있습니다. your-store.example로 전송되는 요청과 your-experimental-store.example로 전송되는 요청은 서로 다른 백엔드 서비스로 라우팅될 수 있습니다.

GKE 클러스터에서는 Kubernetes Ingress 객체를 만들어 HTTP(S) 부하 분산기를 만들고 구성합니다. 인그레스 객체는 각각 Pod 집합과 연결된 서비스 객체 한 개 이상과 연결되어야 합니다.

다음은 my-ingress라는 인그레스의 매니페스트입니다.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

인그레스를 만들면 GKE 인그레스 컨트롤러는 인그레스와 연결된 서비스의 정보에 따라 HTTP(S) 부하 분산기를 만들고 구성합니다. 또한 부하 분산기에는 도메인 이름과 연결할 수 있는 안정적인 IP 주소가 제공됩니다.

앞의 예시에서 부하 분산기의 IP 주소를 도메인 이름 your-store.example에 연결했다고 가정해 보세요. 클라이언트가 요청을 your-store.example에 전송하면 요청은 포트 60000에서 my-products라는 Kubernetes 서비스로 라우팅됩니다. 클라이언트가 요청을 your-store.example/discounted에 전송하면 요청은 포트 80에서 my-discounted-products라는 Kubernetes 서비스로 라우팅됩니다.

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

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

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

my-products 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-products
spec:
  type: NodePort
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50000

서비스 매니페스트에서 typeNodePort임에 유의하세요. 컨테이너 기반 부하 분산을 사용 설정하지 않는 한 HTTP(S) 부하 분산기를 구성하는 데 사용되는 인그레스에 필요한 유형입니다.

서비스 매니페스트에서 selector 필드는 app: products 라벨과 department: sales 라벨이 모두 있는 Pod가 이 서비스의 구성원임을 나타냅니다.

포트 60000에서 서비스에 도달하는 요청은 TCP 포트 50000에서 구성원 Pod 중 하나로 라우팅됩니다.

각 구성원 Pod에는 TCP 포트 50000에서 리슨하는 컨테이너가 있어야 합니다.

my-discounted-products 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-discounted-products
spec:
  type: NodePort
  selector:
    app: discounted-products
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

서비스 매니페스트에서 selector 필드는 app: discounted-products 라벨과 department: sales 라벨이 모두 있는 Pod가 이 서비스의 구성원임을 나타냅니다.

포트 80에서 서비스에 도달하는 요청은 TCP 포트 8080에서 구성원 Pod 중 하나로 라우팅됩니다.

각 구성원 Pod에는 TCP 포트 8080에서 리슨하는 컨테이너가 있어야 합니다.

기본 백엔드

인그레스 매니페스트에 backend 필드를 제공하여 기본 백엔드를 지정할 수 있습니다. rules 필드의 경로와 일치하지 않는 요청은 backend 필드에서 지정된 포트와 서비스로 전송됩니다. 예를 들어 다음 인그레스에서 / 또는 /discounted와 일치하지 않는 요청은 모두 포트 60001에서 my-products라는 서비스로 전송됩니다.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: my-products
    servicePort: 60001
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

기본 백엔드를 지정하지 않으면 GKE은 404를 반환하는 기본 백엔드를 제공합니다.

인그레스에서 Compute Engine으로 리소스 매핑

GKE 인그레스 컨트롤러는 클러스터에 배포된 인그레스 리소스에 따라 Compute Engine 부하 분산기 리소스를 배포 및 관리합니다. Compute Engine 리소스 매핑은 인그레스 리소스 구조에 따라 다릅니다. 이러한 리소스 매핑을 알고 있으면 계획, 설계, 문제해결이 수월해집니다.

여러 백엔드 서비스 섹션에 표시된 my-ingress 매니페스트는 서로 다른 Kubernetes 서비스 두 개를 참조하는 URL 경로 일치 두 개로 외부 인그레스 리소스를 지정합니다. 다음은 my-ingress를 대신하여 생성된 몇 가지 Compute Engine 리소스입니다.

  • forwardingRule에 해당하는 공개 VIP
  • 상태 확인용 트래픽과 애플리케이션 트래픽을 허용하는 Compute Engine 방화벽 규칙
  • 대상 HTTP 프록시. TLS가 구성되면 추가 HTTPS 프록시가 생성됩니다.
  • 단일 hostRule, /* 및 /discounted의 pathMatchers가 있는 URL 맵. 이는 해당 backendServices를 가리킵니다.
  • 각 서비스의 Pod IP 목록을 엔드포인트로 보관하는 NEG. 이는 my-discounted-productsmy-products 서비스의 결과로 생성됩니다. 다음 다이어그램은 인그레스에서 Compute Engine으로 리소스 매핑을 간략하게 보여줍니다.

인그레스에서 Compute Engine으로의 리소스 매핑 다이어그램

SSL 인증서 제공 옵션

HTTPS 부하 분산기에 SSL 인증서를 제공하는 방법에는 3가지가 있습니다.

Google 관리형 인증서
개발자 도메인의 Google 관리 SSL 인증서가 프로비저닝, 배포, 갱신, 관리됩니다. 관리형 인증서는 와일드 카드 도메인을 지원하지 않습니다.
Google Cloud와 공유되는 자체 관리형 인증서
자체 SSL 인증서를 프로비저닝하고 Google Cloud 프로젝트에 인증서 리소스를 만들 수 있습니다. 그런 다음 인그레스의 주석에 인증서 리소스를 나열하여 인증서를 사용하는 HTTP(S) 부하 분산기를 만들 수 있습니다. 자세한 내용은 사전 공유 인증서 안내를 참조하세요.
보안 비밀 리소스로서의 자체 관리형 인증서
자체 SSL 인증서를 프로비저닝하고 저장할 보안 비밀을 만들 수 있습니다. 그런 다음 인그레스 사양의 보안 비밀을 참조하여 인증서를 사용하는 HTTP(S) 부하 분산기를 만들 수 있습니다. 자세한 내용은 보안 비밀의 인증서 사용 안내를 참조하세요.

상태 확인

Ingress를 통해 노출되는 서비스는 부하 분산기의 상태 확인에 응답해야 합니다. 부하 분산된 트래픽의 최종 목적지인 모든 컨테이너는 정상 상태임을 표시하기 위해 다음 중 하나를 수행해야 합니다.

  • / 경로에서 GET 요청의 HTTP 200 상태가 포함된 응답을 제공합니다.

  • HTTP 준비 프로브를 구성합니다. 준비 프로브에서 지정한 path 경로에서 HTTP 200 상태가 포함된 응답을 GET 요청에 제공합니다. 인그레스를 통해 노출된 서비스는 준비 프로브가 사용 설정된 컨테이너 포트와 동일한 컨테이너 포트를 가리켜야 합니다.

    예를 들어 컨테이너가 다음 준비 프로브를 지정한다고 가정합니다.

    ...
    readinessProbe:
      httpGet:
        path: /healthy
    

    그런 다음 컨테이너의 /healthy 경로에 대한 핸들러가 HTTP 200 상태를 반환하면 부하 분산기는 컨테이너가 활성 상태이고 정상이라고 간주합니다.

여러 TLS 인증서 사용

HTTP(S) 부하 분산기로 your-store.example과 your-experimental-store.example이라는 두 가지 호스트 이름에서 콘텐츠를 제공하려 한다고 가정해 봅니다. 또한 부하 분산기가 your-store.example과 your-experimental-store.example에 각기 다른 인증서를 사용하도록 하려 합니다.

인그레스 매니페스트에서 여러 인증서를 지정할 수 있습니다. 부하 분산기는 인증서의 일반 이름(CN)이 요청에서 사용되는 호스트 이름과 일치하면 인증서를 선택합니다. 여러 인증서를 구성하는 방법에 대한 자세한 내용은 인그레스를 사용한 HTTP(S) 부하 분산에서 여러 SSL 인증서 사용을 참조하세요.

Kubernetes 서비스와 Google Cloud 백엔드 서비스 비교

Kubernetes 서비스Google Cloud 백엔드 서비스는 서로 다른 서비스입니다. 이 두 서비스 사이에는 밀접한 관계가 있지만 이 관계가 반드시 일대일 관계는 아닙니다. GKE 인그레스 컨트롤러는 인그레스 매니페스트에서 각 (serviceName, servicePort) 쌍을 위한 Google Cloud 백엔드 서비스를 만듭니다. 따라서 Kubernetes 서비스 객체 하나가 여러 Google Cloud 백엔드 서비스와 관련될 수 있습니다.

제한사항

  • 네임스페이스의 전체 길이와 인그레스 이름은 40자(영문 기준)를 초과할 수 없습니다. 이 가이드라인을 따르지 않으면 GKE 인그레스 컨트롤러가 비정상적으로 작동할 수 있습니다. 자세한 내용은 GitHub의 이 문제를 참조하세요.

  • URL 맵의 최대 규칙 수는 50개입니다. 즉, 인그레스에서 규칙을 최대 50개까지 지정할 수 있습니다.

  • GKE 인그레스 컨트롤러에서 NEG를 사용하지 않으면 GKE 클러스터의 노드 수는 1,000개로 제한됩니다. 서비스가 NEG로 배포되면 GKE 노드가 제한되지 않습니다. 인그레스를 통해 노출된 NEG가 아닌 서비스는 노드가 1000개 이상인 클러스터에서 올바르게 작동하지 않습니다.

  • GKE 인그레스 컨트롤러가 readinessProbes를 상태 확인으로 사용하려면 인그레스를 만들 때 인그레스의 Pod가 있어야 합니다. 복제본 크기를 0으로 조정하면 기본 상태 확인이 적용됩니다. 자세한 내용은 이 문제 설명을 참조하세요.

  • Pod의 readinessProbe 변경사항이 발생해도 인그레스는 영향을 받지 않습니다.

  • HTTPS 부하 분산기는 클라이언트와 부하 분산기 간의 지연 시간을 최소화하기 위해 전역으로 분산된 위치에서 TLS를 종료합니다. TLS 종료 지점을 지리적으로 제어해야 하는 경우 커스텀 인그레스 컨트롤러와 GCP 네트워크 부하 분산을 대신 사용하고 니즈에 적합한 리전에 있는 백엔드에서 TLS를 종료해야 합니다.

  • 여러 인그레스 리소스를 단일 Google Cloud 부하 분산기에 결합할 수 없습니다.

다음 단계