외부 애플리케이션 부하 분산기용 인그레스 구성


이 페이지에서는 Kubernetes 인그레스 객체를 만들어 외부 애플리케이션 부하 분산기를 구성하는 방법을 설명합니다.

이 페이지를 읽기 전에 GKE 네트워킹 개념을 숙지해야 합니다.

시작하기 전에

시작하기 전에 다음 태스크를 수행했는지 확인합니다.

  • Google Kubernetes Engine API를 사용 설정합니다.
  • Google Kubernetes Engine API 사용 설정
  • 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치한 경우 gcloud components update를 실행하여 최신 버전을 가져옵니다.

HttpLoadBalancing 부가기능 사용 설정

클러스터에 HttpLoadBalancing 부가기능이 사용 설정되어 있어야 합니다. 이 부가기능은 기본적으로 사용 설정되어 있습니다. Autopilot 클러스터에서는 이 부가기능을 사용 중지할 수 없습니다.

Google Cloud 콘솔 또는 Google Cloud CLI를 사용하여 HttpLoadBalancing 부가기능을 사용 설정할 수 있습니다.

콘솔

  1. Google Cloud 콘솔에서 Google Kubernetes Engine 페이지로 이동합니다.

    Google Kubernetes Engine으로 이동

  2. 수정할 클러스터의 이름을 클릭합니다.

  3. 네트워킹 아래 HTTP 부하 분산 필드에서 HTTP 부하 분산 수정을 클릭합니다.

  4. HTTP 부하 분산 사용 설정 체크박스를 선택합니다.

  5. 변경사항 저장을 클릭합니다.

gcloud

gcloud container clusters update CLUSTER_NAME --update-addons=HttpLoadBalancing=ENABLED

CLUSTER_NAME을 클러스터 이름으로 바꿉니다.

고정 IP 주소 만들기

외부 애플리케이션 부하 분산기는 하나 이상의 서비스로 요청을 라우팅하는 데 사용할 수 있는 하나의 안정적인 IP 주소를 제공합니다. 영구 IP 주소가 필요하면 인그레스를 만들기 전 전역 고정 외부 IP 주소를 예약해야 합니다.

기존 인그레스에서 임시 IP 주소 대신 고정 IP 주소를 사용하도록 수정하면 GKE가 부하 분산기의 전달 규칙을 다시 만들 때 부하 분산기의 IP 주소를 변경할 수 있습니다.

외부 애플리케이션 부하 분산기 만들기

이 연습에서는 외부 애플리케이션 부하 분산기를 구성하여 URL 경로에 따라 서로 다른 서비스로 요청을 라우팅합니다.


Google Cloud 콘솔에서 이 태스크에 대한 단계별 안내를 직접 수행하려면 둘러보기를 클릭합니다.

둘러보기


배포 및 서비스 만들기

이름이 hello-world-1hello-world-2인 서비스로 두 가지 배포를 만듭니다.

  1. 다음 매니페스트를 hello-world-deployment-1.yaml로 저장합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-world-deployment-1
    spec:
      selector:
        matchLabels:
          greeting: hello
          version: one
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
            version: one
        spec:
          containers:
          - name: hello-app-1
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
            env:
            - name: "PORT"
              value: "50000"
    

    이 매니페스트는 3개 복제본이 있는 샘플 배포를 기술합니다.

  2. 클러스터에 매니페스트를 적용합니다.

    kubectl apply -f hello-world-deployment-1.yaml
    
  3. 다음 매니페스트를 hello-world-service-1.yaml로 저장합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-world-1
    spec:
      type: NodePort
      selector:
        greeting: hello
        version: one
      ports:
      - protocol: TCP
        port: 60000
        targetPort: 50000
    

    이 매니페스트는 다음 속성을 사용해서 서비스를 기술합니다.

    • greeting: hello 라벨과 version: one 라벨이 모두 있는 포드는 서비스의 구성원입니다.
    • GKE는 TCP 포트 60000으로 서비스에 전송된 요청을 TCP 포트 50000의 구성원 포드 중 하나로 전달합니다.
    • 서비스 유형은 NodePort이며, 이는 컨테이너 기반 부하 분산을 사용하지 않은 경우에 필요합니다. 컨테이너 기반 부하 분산을 사용하는 경우에는 서비스 유형에 대한 제한이 없습니다. type: ClusterIP 사용을 권장합니다.
  4. 클러스터에 매니페스트를 적용합니다.

    kubectl apply -f hello-world-service-1.yaml
    
  5. 다음 매니페스트를 hello-world-deployment-2.yaml로 저장합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-world-deployment-2
    spec:
      selector:
        matchLabels:
          greeting: hello
          version: two
      replicas: 3
      template:
        metadata:
          labels:
            greeting: hello
            version: two
        spec:
          containers:
          - name: hello-app-2
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
            env:
            - name: "PORT"
              value: "8080"
    

    이 매니페스트는 3개 복제본이 있는 샘플 배포를 기술합니다.

  6. 클러스터에 매니페스트를 적용합니다.

    kubectl apply -f hello-world-deployment-2.yaml
    
  7. 다음 매니페스트를 hello-world-service-2.yaml로 저장합니다.

    apiVersion: v1
    kind: Service
    metadata:
      name: hello-world-2
    spec:
      type: NodePort
      selector:
        greeting: hello
        version: two
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8080
    

    이 매니페스트는 다음 속성을 사용해서 서비스를 기술합니다.

    • greeting: hello 라벨과 version: two 라벨이 모두 있는 포드는 서비스의 구성원입니다.
    • GKE는 TCP 포트 80으로 서비스에 전송된 요청을 TCP 포트 8080의 구성원 포드 중 하나로 전달합니다.
  8. 클러스터에 매니페스트를 적용합니다.

    kubectl apply -f hello-world-service-2.yaml
    

인그레스 만들기

요청의 URL 경로에 따라 요청을 라우팅하는 규칙을 지정하는 인그레스를 만듭니다. 인그레스를 만들면 GKE 인그레스 컨트롤러가 외부 애플리케이션 부하 분산기를 만들고 구성합니다.

  1. 다음 매니페스트를 my-ingress.yaml로 저장합니다.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-ingress
      annotations:
        # If the class annotation is not specified it defaults to "gce".
        kubernetes.io/ingress.class: "gce"
    spec:
      rules:
      - http:
          paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: hello-world-1
                port:
                  number: 60000
          - path: /v2
            pathType: ImplementationSpecific
            backend:
              service:
                name: hello-world-2
                port:
                  number: 80
    

    이 매니페스트는 다음 속성을 사용하여 인그레스를 기술합니다.

    • 두 가지 GKE 인그레스 클래스가 있습니다. 인그레스 클래스를 지정하려면 kubernetes.io/ingress.class 주석을 사용해야 합니다. spec.ingressClassName을 사용하여 GKE 인그레스를 지정할 수 없습니다.

    • gce 클래스는 외부 애플리케이션 부하 분산기를 배포합니다.

    • gce-internal 클래스는 내부 애플리케이션 부하 분산기를 배포합니다.

    • spec.ingressClassNamekubernetes.io/ingress.class 주석이 없는 인그레스 리소스를 배포하면 GKE가 외부 애플리케이션 부하 분산기를 만듭니다. 이는 kubernetes.io/ingress.class: gce 주석을 지정할 때 발생하는 동작과 동일합니다. 자세한 내용은 GKE 인그레스 컨트롤러 동작을 참조하세요.

    • GKE는 각 backend.service에 대해 Google Cloud 백엔드 서비스를 만듭니다.

    • 클라이언트가 URL 경로 /를 사용하여 부하 분산기로 요청을 보내면 GKE가 포트 60000에서 hello-world-1 서비스로 요청을 전달합니다. 클라이언트가 URL 경로 /v2를 사용하여 부하 분산기로 요청을 보내면 GKE가 포트 80에서 hello-world-2 서비스로 요청을 전달합니다. pathpathType 속성에 대한 자세한 내용은 URL 경로를 참조하세요.

  2. 클러스터에 매니페스트를 적용합니다.

    kubectl apply -f my-ingress.yaml
    

외부 애플리케이션 부하 분산기 테스트

부하 분산기가 구성될 때까지 5분 정도 기다린 후 외부 애플리케이션 부하 분산기를 테스트합니다.

  1. 인그레스를 확인합니다.

    kubectl get ingress my-ingress --output yaml
    

    출력에 외부 애플리케이션 부하 분산기의 IP 주소가 표시됩니다.

    status:
      loadBalancer:
        ingress:
        - ip: 203.0.113.1
    
  2. / 경로를 테스트합니다.

    curl LOAD_BALANCER_IP_ADDRESS/
    

    LOAD_BALANCER_IP_ADDRESS를 부하 분산기의 외부 IP 주소로 바꿉니다.

    출력은 다음과 비슷합니다.

    Hello, world!
    Version: 1.0.0
    Hostname: ...
    

    출력에 404 오류가 포함되었으면 몇 분 정도 기다립니다.

  3. /v2 경로를 테스트합니다.

    curl load-balancer-ip/v2
    

    출력은 다음과 비슷합니다.

    Hello, world!
    Version: 2.0.0
    Hostname: ...
    

외부 부하 분산을 위한 인그레스 작동 방법

외부 애플리케이션 부하 분산기는 클라이언트와 애플리케이션 사이의 프록시 역할을 합니다. 클라이언트의 HTTPS 요청을 수락하려는 경우 부하 분산기에 인증서가 있어야 부하 분산기가 클라이언트에게 ID를 증명할 수 있습니다. 또한 부하 분산기에 비공개 키가 있어야 HTTPS 핸드셰이크를 완료할 수 있습니다. 자세한 내용은 다음을 참고하세요.

URL 경로

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

보다 구체적인 패턴이 덜 구체적인 패턴보다 우선합니다. /foo/*/foo/bar/*가 있다면 /foo/bar/*에 맞춰 /foo/bar/bat가 사용됩니다. 경로 제한사항과 패턴 일치에 대한 자세한 내용은 URL 맵 문서를 참조하세요.

1.21.3-gke.1600 이전 버전을 실행하는 GKE 클러스터에서는 pathType 필드가 ImplementationSpecific 값으로만 지원됩니다. 버전 1.21.3-gke.1600 이상을 실행하는 클러스터의 경우 PrefixExact 값도 pathType에 지원됩니다.

HTTP 중지

클라이언트와 부하 분산기 간의 모든 트래픽에 HTTPS를 사용하려면 HTTP를 중지하면 됩니다. 자세한 내용은 HTTP 중지를 참조하세요.

부하 분산기와 애플리케이션 간 HTTPS

GKE pod에서 실행되는 애플리케이션이 HTTPS 요청을 수신할 수 있는 경우 요청을 애플리케이션으로 전달할 때 HTTPS를 사용하도록 부하 분산기를 구성할 수 있습니다. 자세한 내용은 부하 분산기와 애플리케이션 간 HTTPS(TLS)를 참조하세요.

클라이언트와 부하 분산기 간 HTTP/2

클라이언트는 HTTP/2를 사용하여 부하 분산기에 요청을 보낼 수 있습니다. 별도로 구성할 필요는 없습니다.

부하 분산기와 애플리케이션 간 HTTP/2

GKE pod에서 실행되는 애플리케이션이 HTTP/2 요청을 수신할 수 있는 경우 요청을 애플리케이션으로 전달할 때 HTTP/2를 사용하도록 부하 분산기를 구성할 수 있습니다. 자세한 내용은 인그레스를 사용한 부하 분산용 HTTP/2를 참조하세요

네트워크 엔드포인트 그룹

클러스터가 컨테이너 기반 부하 분산을 지원하는 경우 네트워크 엔드포인트 그룹(NEG)을 사용하는 것이 좋습니다. GKE 클러스터 1.17 이후 및 특정 조건에서는 컨테이너 기반 부하 분산이 기본적으로 사용되므로 명시적인 cloud.google.com/neg: '{"ingress": true}' 서비스 주석이 필요하지 않습니다.

공유 VPC

인그레스 리소스를 배포하는 GKE 클러스터가 서비스 프로젝트에 있고 GKE 제어 영역에서 호스트 프로젝트의 방화벽 리소스를 관리하도록 하려면 서비스 프로젝트의 GKE 서비스 계정에 공유 VPC가 있는 클러스터의 방화벽 리소스 관리에 따라 호스트 프로젝트의 적절한 IAM 권한이 부여되어야 합니다. 이렇게 하면 인그레스 컨트롤러가 인그레스 트래픽 및 Google Cloud 상태 확인을 위한 트래픽을 모두 허용하도록 방화벽 규칙을 만들 수 있습니다.

다음은 인그레스 리소스 로그에 존재할 수 있는 이벤트의 예시입니다. 이 오류는 권한이 올바르게 구성되지 않은 경우 인그레스 컨트롤러가 Google Cloud 상태 확인에 대한 인그레스 트래픽을 허용하는 방화벽 규칙을 만들 수 없는 경우에 발생합니다.

Firewall change required by security admin: `gcloud compute firewall-rules update <RULE_NAME> --description "GCE L7 firewall rule" --allow tcp:<PORT> --source-ranges 130.211.0.0/22,35.191.0.0/16 --target-tags <TARGET_TAG> --project <HOST_PROJECT>

호스트 프로젝트에서 방화벽 규칙을 수동으로 프로비저닝하려는 경우 인그레스 리소스에 networking.gke.io/suppress-firewall-xpn-error: "true" 주석을 추가하여 firewallXPNError 이벤트를 숨길 수 있습니다.

외부 인그레스 주석 요약

인그레스 주석

주석 설명
kubernetes.io/ingress.allow-http 클라이언트와 HTTP(S) 부하 분산기 간에 HTTP 트래픽을 허용할지 여부를 지정합니다. 가능한 값은 'true', 'false'입니다. 기본값은 'true'입니다. HTTP 중지를 참조하세요.
ingress.gcp.kubernetes.io/pre-shared-cert 이 주석을 사용하여 GKE 인그레스 리소스에 인증서 리소스를 연결합니다. 자세한 내용은 외부 애플리케이션 부하 분산기에 여러 SSL 인증서 사용을 참조하세요.
kubernetes.io/ingress.global-static-ip-name 이 주석을 사용하여 부하 분산기에서 이전에 만든 고정 외부 IP 주소를 사용하도록 지정합니다. HTTP(S) 부하 분산기의 고정 IP 주소를 참조하세요.
networking.gke.io/v1beta1.FrontendConfig 이 주석을 사용하여 부하 분산기의 클라이언트 연결 구성을 맞춤설정합니다. 자세한 내용은 인그레스 구성을 참조하세요.
networking.gke.io/suppress-firewall-xpn-error 인그레스 부하 분산기의 경우, Kubernetes가 권한 부족으로 인해 방화벽 규칙을 변경할 수 없으면 몇 분 간격으로 firewallXPNError 이벤트가 발생합니다. GLBC 1.4 이상에서는 인그레스 리소스에 networking.gke.io/suppress-firewall-xpn-error: "true" 주석을 추가하여 firewallXPNError 이벤트가 발생하지 않도록 할 수 있습니다. 이 주석을 삭제하면 이벤트가 다시 발생합니다. 가능한 값은 truefalse입니다. 기본값은 false입니다.
주석 설명
cloud.google.com/app-protocols 이 주석을 사용하여 부하 분산기와 애플리케이션 간의 통신 프로토콜을 설정합니다. 가능한 프로토콜은 HTTP, HTTPS, HTTP2입니다. 부하 분산기와 애플리케이션 간 HTTPS인그레스를 사용한 부하 분산용 HTTP/2를 참조하세요.
cloud.google.com/backend-config 이 주석을 사용하여 서비스와 연결된 백엔드 서비스를 구성합니다. 자세한 내용은 인그레스 구성을 참조하세요.
cloud.google.com/neg 이 주석을 사용하여 부하 분산기에서 네트워크 엔드포인트 그룹을 사용하도록 지정합니다. 컨테이너 기반 부하 분산 사용을 참조하세요.

다음 단계