컨테이너 기본 부하 분산 사용

이 페이지에서는 Google Kubernetes Engine에서 컨테이너 기본 부하 분산을 사용하는 방법을 설명합니다.

개요

HTTP(S) 부하 분산기컨테이너 기본 부하 분산을 통해 Pod를 직접 대상으로 지정하여 트래픽을 Pod에 균일하게 분산시킬 수 있습니다.

컨테이너 기본 부하 분산은 IP 포트 쌍으로 표시되는 네트워크 엔드포인트 모음인 네트워크 엔드포인트 그룹(NEG)이라는 데이터 모델을 활용합니다.

이점

컨테이너 기본 부하 분산의 이점은 다음과 같습니다.

Pod의 부하 분산을 최우선 처리
kube-proxy는 노드의 iptables 규칙을 구성하여 트래픽을 Pod에 분산합니다. 컨테이너 기본 부하 분산이 없으면 부하 분산기 트래픽은 노드 인스턴스 그룹으로 이동하여 iptables 규칙을 통해 같은 노드에 있거나 없을 수 있는 Pod로 라우팅됩니다. 컨테이너 기본 부하 분산을 사용하면 트래픽을 수신해야 하는 Pod에 부하 분산기 트래픽이 직접 분산되어 추가 네트워크 홉이 제거됩니다. 컨테이너 기본 부하 분산은 Pod를 직접 대상 지정하기 때문에 상태 확인 개선에도 도움이 됩니다.

기본 동작(왼쪽)과 컨테이너 기본 부하 분산기 동작을 비교한 다이어그램
네트워크 성능 향상
컨테이너 기본 부하 분산기가 Pod와 직접 통신하고 연결에서 네트워크 홉이 줄어들기 때문에 지연 시간과 처리량이 모두 향상됩니다.
가시성 향상
컨테이너 기본 부하 분산을 사용하면 Stackdriver UI 지원을 비롯하여 클라이언트에서 HTTP(S) 부하 분산기까지의 왕복 시간(RTT)을 확인할 수 있습니다. 이를 통해 NEG 수준에서 서비스 문제를 간편하게 해결할 수 있습니다.
HTTP(S) 부하 분산 기능 지원
컨테이너 기본 부하 분산은 기본적으로 HTTP(S) 부하 분산의 여러 가지 기능(예: Google Cloud Armor, Cloud CDN, Cloud Identity-Aware Proxy와 같은 GCP 서비스와 통합하는 기능)을 Google Kubernetes Engine에서 지원합니다. 또한 정확한 트래픽 분산을 위한 부하 분산 알고리즘을 제공합니다.
Traffic Director 지원
NEG 데이터 모델은 서비스 메시를 위한 GCP의 완전 관리형 트래픽 제어 영역인 Traffic Director를 사용하는 데 필요합니다.

Pod 준비

관련 Pod의 경우 해당 인그레스 컨트롤러는 cloud.google.com/load-balancer-neg-ready 유형의 준비 게이트를 관리합니다. 인그레스 컨트롤러는 NEG에 있는 모든 엔드포인트의 상태를 포함하여 부하 분산기의 상태 확인 상태를 폴링합니다. 부하 분산기의 상태 확인 상태가 특정 Pod에 해당하는 엔드포인트가 정상임을 나타내면 인그레스 컨트롤러는 Pod의 준비 게이트 값을 True로 설정합니다. 이 준비 게이트의 값과 Pod의 준비 프로브(정의된 경우)를 고려하여 각 노드에서 실행되는 kubelet이 Pod의 유효 준비를 계산합니다.

컨테이너 기본 부하 분산의 경우 Pod 준비 게이트가 다음 위치에서 자동으로 사용 설정됩니다.

  • v1.13.8 이상을 실행하는 v1.13 GKE 클러스터
  • v1.14.4 이상을 실행하는 v1.14 GKE 클러스터

준비 게이트는 순차적 업데이트 속도를 관리합니다. 위에 나열된 GKE 버전은 Pod에 준비 게이트를 자동으로 추가합니다. 순차적 업데이트를 시작하면 GKE에서 새 Pod를 만들 때 각 새 Pod의 엔드포인트가 NEG에 추가됩니다. 엔드포인트가 부하 분산기의 관점에서 정상이면 인그레스 컨트롤러가 준비 게이트를 True로 설정합니다. 따라서 새로 만든 Pod는 GKE에서 이전 Pod를 제거하기 전에 최소한 준비 게이트를 통과해야 합니다. 이렇게 하면 Pod의 해당 엔드포인트가 이미 부하 분산기의 상태 확인을 통과하고 백엔드 용량이 유지되도록 할 수 있습니다.

컨테이너 이미지가 잘못되었거나 부하 분산기 상태 확인이 잘못 구성되어 Pod의 준비 게이트가 Pod가 준비되었음을 나타내지 않으면 부하 분산기가 트래픽을 새 Pod로 전송하지 않습니다. 업데이트된 배포를 롤아웃하는 동안 이러한 오류가 발생하면 Pod의 준비 게이트가 True가 아니므로 새 Pod를 만들려고 시도할 때 롤아웃이 중지됩니다. 이 상황을 감지하고 해결하는 방법은 문제해결 섹션을 참조하세요.

컨테이너 기본 부하 분산 및 준비 게이트가 없으면 GKE는 Pod를 준비 상태로 표시하기 전에 부하 분산기의 엔드포인트가 정상인지 감지할 수 없습니다. 이전 Kubernetes 버전에서는 지연 시간(배포 사양에서 minReadySeconds)을 지정하여 Pod가 삭제되고 대체되는 속도를 관리합니다.

요구사항

Google Kubernetes Engine의 컨테이너 기본 부하 분산기의 요건은 다음과 같습니다.

Google Kubernetes Engine v1.13.8 또는 v1.14.4

컨테이너 기본 부하 분산기는 일반적으로 다음 클러스터에 사용할 수 있습니다.

  • v1.13.8 이상을 실행하는 v1.13 GKE 클러스터
  • v1.14.4 이상을 실행하는 v1.14 GKE 클러스터
VPC 네이티브

컨테이너 기본 부하 분산을 사용하려면 클러스터가 VPC 네이티브여야 합니다. 자세한 내용은 별칭 IP를 사용하여 VPC 네이티브 클러스터 만들기를 참조하세요.

HTTP 부하 분산

컨테이너 기본 부하 분산을 사용하려면 클러스터에서 HTTP 부하 분산을 사용하도록 설정해야 합니다. GKE 클러스터에는 기본적으로 HTTP 부하 분산이 사용 설정되어 있으며 사용 중지해서는 안됩니다.

제한사항

컨테이너 기본 부하 분산기는 이전 네트워크에서 작동하지 않습니다.

제한사항

컨테이너 기본 부하 분산기는 내부 부하 분산기 또는 네트워크 부하 분산기를 지원하지 않습니다.

가격 책정

이 가이드에서 만드는 인그레스에 의해 프로비저닝되는 HTTP(S) 부하 분산기에 대한 요금이 부과됩니다. 부하 분산기 가격 정보는 Compute Engine 가격 책정 페이지의 부하 분산 및 전달 규칙을 참조하세요.

컨테이너 기본 부하 분산 사용

다음 섹션에서는 Google Kubernetes Engine의 컨테이너 기본 부하 분산 구성을 설명합니다.

VPC 네이티브 클러스터 만들기

컨테이너 기본 부하 분산을 사용하려면 별칭 IP가 사용 설정된 클러스터를 만들어야 합니다.

예를 들어 다음 명령어는 us-central1-a 영역에 하위 네트워크가 자동 프로비저닝된 클러스터 neg-demo-cluster를 만듭니다.

gcloud container clusters create neg-demo-cluster \
    --enable-ip-alias \
    --create-subnetwork="" \
    --network=default \
    --zone=us-central1-a

배포 만들기

다음으로 워크로드를 클러스터에 배포합니다.

다음 샘플 배포 neg-demo-app은 컨테이너식 HTTP 서버의 단일 인스턴스를 실행합니다. Pod 준비 피드백을 사용하는 워크로드를 사용하는 것이 좋습니다. 자세한 내용과 GKE 버전 요구사항은 위의 Pod 준비 섹션을 참조하세요.

Pod 준비 상태 피드백 사용

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: k8s.gcr.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
  

하드코딩된 지연 사용

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: neg-demo-app # Label for the Deployment
  name: neg-demo-app # Name of Deployment
spec:
  minReadySeconds: 60 # Number of seconds to wait after a Pod is created and its status is Ready
  selector:
    matchLabels:
      run: neg-demo-app
  template: # Pod template
    metadata:
      labels:
        run: neg-demo-app # Labels Pods from this Deployment
    spec: # Pod specification; each Pod created by this Deployment has this specification
      containers:
      - image: k8s.gcr.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
        name: hostname # Container name
      # Note: The following line is necessary only on clusters running GKE v1.11 and lower.
      # For details, see https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts
      terminationGracePeriodSeconds: 60 # Number of seconds to wait for connections to terminate before shutting down Pods
  

이 배포에서 각 컨테이너는 HTTP 서버를 실행합니다. HTTP 서버는 단순히 애플리케이션 서버의 호스트 이름(서버가 실행되는 Pod의 이름)을 응답으로 반환합니다.

이 매니페스트를 neg-demo-app.yaml로 저장한 후 다음 명령을 실행하여 배포를 만듭니다.

kubectl apply -f neg-demo-app.yaml

컨테이너 기본 부하 분산기용 서비스 만들기

배포를 만든 후에 배포의 Pod를 서비스로 그룹화해야 합니다.

다음 샘플 서비스 neg-demo-svc는 이전 섹션에서 만든 샘플 배포를 대상으로 지정합니다.

apiVersion: v1
kind: Service
metadata:
  name: neg-demo-svc # Name of Service
  annotations:
    cloud.google.com/neg: '{"ingress": true}' # Creates an NEG after an Ingress is created
spec: # Service's specification
  type: NodePort
  selector:
    run: neg-demo-app # Selects Pods labelled run: neg-demo-app
  ports:
  - port: 80 # Service's port
    protocol: TCP
    targetPort: 9376

서비스의 주석인 cloud.google.com/neg: '{"ingress": true}'는 컨테이너 기본 부하 분산을 사용 설정합니다. 하지만 부하 분산기는 서비스용 인그레스를 만들 때까지 만들어지지 않습니다.

이 매니페스트를 neg-demo-svc.yaml로 저장한 후 다음 명령어를 실행하여 서비스를 만듭니다.

kubectl apply -f neg-demo-svc.yaml

서비스용 인그레스 만들기

다음 샘플 인그레스 neg-demo-ing는 만든 서비스를 대상으로 지정합니다.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: neg-demo-ing
spec:
  backend:
    serviceName: neg-demo-svc # Name of the Service targeted by the Ingress
    servicePort: 80 # Should match the port used by the Service

이 매니페스트를 neg-demo-ing.yaml로 저장한 후 다음 명령어를 실행하여 인그레스를 만듭니다.

kubectl apply -f neg-demo-ing.yaml

인그레스를 만들면 프로젝트에 HTTP(S) 부하 분산기가 생성되고 클러스터가 실행되는 각 영역에 NEG가 생성됩니다. NEG의 엔드포인트와 서비스의 엔드포인트는 동기화 상태로 유지됩니다.

인그레스 확인

워크로드를 배포하고 Pod를 서비스로 그룹화하고 서비스용 인그레스를 만든 후 인그레스가 컨테이너 기본 부하 분산기를 성공적으로 프로비저닝했는지 확인해야 합니다.

인그레스의 상태를 검색하려면 다음 명령어를 실행합니다.

kubectl describe ingress neg-demo-ing

명령어 출력에서 ADD 이벤트와 CREATE 이벤트를 찾습니다.

Events:
Type     Reason   Age                From                     Message
----     ------   ----               ----                     -------
Normal   ADD      16m                loadbalancer-controller  default/neg-demo-ing
Normal   Service  4s                 loadbalancer-controller  default backend set to neg-demo-svc:32524
Normal   CREATE   2s                 loadbalancer-controller  ip: 192.0.2.0

부하 분산기 기능 테스트

다음 섹션에서는 컨테이너 기본 부하 분산기의 기능을 테스트하는 방법을 설명합니다.

인그레스 IP 주소 방문

HTTP(S) 부하 분산기가 구성될 때까지 데 몇 분 정도 기다립니다.

인그레스의 IP 주소를 방문하여 컨테이너 기본 부하 분산기가 작동하는지 확인할 수 있습니다.

인그레스 IP 주소를 얻으려면 다음 명령어를 실행하세요.

kubectl get ingress neg-demo-ing

명령어 출력의 ADDRESS 열에 인그레스의 IP 주소가 표시됩니다. 웹브라우저에서 이 IP 주소를 방문합니다.

백엔드 서비스 상태 확인

부하 분산기의 백엔드 서비스 상태를 확인할 수도 있습니다.

먼저 프로젝트에서 실행되는 백엔드 서비스의 목록을 가져옵니다.

gcloud compute backend-services list

neg-demo-svc 같은 서비스 이름을 포함하는 백엔드 이름을 복사합니다. 그런 다음 백엔드 서비스의 상태를 확인합니다.

gcloud compute backend-services get-health [BACKEND_SERVICE_NAME] --global

인그레스 기능 확인

부하 분산기가 예상대로 작동하는지 테스트하는 또 다른 방법은 샘플 배포를 확장하고 테스트 요청을 인그레스에 전송하여 올바른 수의 복제본이 응답하는지 확인하는 것입니다.

다음 명령어는 neg-demo-app 배포를 한 인스턴스에서 두 인스턴스로 확장합니다.

kubectl scale deployment neg-demo-app --replicas 2

롤아웃이 완료될 때까지 몇 분 정도 기다립니다. 롤아웃이 완료되었는지 확인하려면 다음 명령어를 실행하세요.

kubectl get deployment neg-demo-app

사용할 수 있는 복제본이 2개 있는지 명령어 출력에서 확인합니다.

NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
neg-demo-app   2         2         2            2           26m

그러고 나서 다음 명령어를 실행하여 부하 분산기의 고유 응답 수를 계산합니다.

for i in `seq 1 100`; do \
  curl --connect-timeout 1 -s [IP_ADDRESS] && echo; \
done  | sort | uniq -c

여기서 [IP_ADDRESS]는 인그레스의 IP 주소입니다. kubectl describe ingress neg-demo-ing에서 인그레스의 IP 주소를 가져올 수 있습니다.

명령어 결과에서 고유 응답 수와 복제본 수가 같은지 관찰하여 모든 백엔드 Pod가 트래픽을 처리하고 있는지 확인합니다.

44 neg-demo-app-7f7dfd7bc6-dcn95
56 neg-demo-app-7f7dfd7bc6-jrmzf

삭제

이 페이지의 태스크를 완료한 후에는 다음 단계를 따라 리소스를 제거하여 계정에서 원치 않는 요금이 청구되지 않도록 합니다.

클러스터 삭제

gcloud

gcloud container clusters delete neg-demo-cluster

Console

  1. GCP Console에서 Google Kubernetes Engine 메뉴로 이동합니다.

    Google Kubernetes Engine 메뉴로 이동

  2. neg-demo-cluster를 선택합니다.

  3. 삭제를 클릭합니다.

문제해결

아래 기법을 사용하여 네트워킹 구성을 확인하세요. 다음 섹션에서는 컨테이너 기본 부하 분산과 관련된 구체적인 문제를 해결하는 방법을 설명합니다.

  • 네트워크 엔드포인트 그룹을 나열하는 방법은 부하 분산 문서를 참조하세요.

  • 서비스의 neg-status 주석에서 서비스에 해당하는 NEG의 이름과 영역을 찾을 수 있습니다. 다음을 사용하여 서비스 사양을 가져옵니다.

    kubectl get svc svc-name -o yaml

    metadata:annotations:cloud.google.com/neg-status 주석에는 서비스의 해당 NEG 이름과 NEG의 영역이 나와 있습니다.

  • 다음 명령어를 사용하여 NEG에 해당하는 백엔드 서비스의 상태를 확인할 수 있습니다.

    gcloud compute backend-service [--project PROJECT_NAME] \
      get-health BACKEND_SERVICE_NAME --global
    

    백엔드 서비스는 NEG와 이름이 같습니다.

  • 다음을 사용하여 서비스의 이벤트 로그를 인쇄합니다.

    kubectl describe svc [SERVICE_NAME]
    

    서비스의 이름 문자열에는 해당 GKE 서비스의 이름과 네임스페이스가 포함됩니다.

별칭 IP로 클러스터를 만들 수 없음

증상
별칭 IP를 사용하여 클러스터를 만들려고 할 때 다음과 같은 오류가 나타날 수 있습니다.
ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
가능한 원인
이전 네트워크도 사용하는 별칭 IP로 클러스터를 만들려고 하면 이 오류가 발생합니다.
해결 방법
별칭 IP와 이전 네트워크가 동시에 사용 설정된 상태로 클러스터를 만들지 않아야 합니다. 별칭 IP 사용에 대한 자세한 내용은 별칭 IP를 사용하여 VPC 네이티브 클러스터 만들기를 참조하세요.

트래픽이 엔드포인트에 도달하지 않음

증상
502 오류가 표시되거나 연결이 거부됩니다.
가능한 원인

새 엔드포인트는 일반적으로 부하 분산기에 연결한 후에 도달 가능합니다. 단, 엔드포인트가 상태 확인에 응답해야 합니다. 트래픽이 엔드포인트에 도달할 수 없으면 502 오류가 발생하거나 연결이 거부될 수 있습니다.

502 오류 및 연결 거부는 SIGTERM을 처리하지 않는 컨테이너로 인해 발생할 수도 있습니다. 컨테이너가 명시적으로 SIGTERM을 처리하지 않으면 즉시 종료되고 요청 처리가 중지됩니다. 부하 분산기는 수신 트래픽을 종료된 컨테이너로 계속 전송하므로 오류가 발생합니다.

해결 방법

SIGTERM을 처리하고 종료 유예 기간(기본적으로 30초) 동안 요청에 계속 응답하도록 컨테이너를 구성합니다. SIGTERM을 수신할 때 상태 확인에 실패하도록 Pod를 구성합니다. 그러면 엔드포인트의 디프로그래밍이 진행되는 동안 부하 분산기가 Pod로 트래픽 전송을 중지합니다.

자세한 내용은 Pod 종료에 대한 문서Pod 종료 권장사항 관련 게시물을 참조하세요.

엔드포인트에 도달하지 않는 트래픽의 문제를 해결하려면 방화벽 규칙이 130.211.0.0/22 범위와 35.191.0.0/16 범위에서 엔드포인트로 들어오는 TCP 트래픽을 허용하는지 확인합니다. 자세한 내용은 Cloud Load Balancing 문서의 상태 확인 추가를 참조하세요.

프로젝트의 백엔드 서비스를 확인합니다. 관련 백엔드 서비스의 이름 문자열에는 해당 Google Kubernetes Engine 서비스의 이름 및 네임스페이스가 포함됩니다.

gcloud compute backend-services list

백엔드 서비스에서 백엔드 상태를 검색합니다.

gcloud compute backend-services get-health [BACKEND_SERVICE_NAME]

모든 백엔드가 비정상이라면 방화벽, 인그레스또는 서비스가 잘못 구성되었을 수 있습니다.

일부 백엔드가 잠깐 동안 비정상이라면 네트워크 프로그래밍 지연 시간이 원인일 수 있습니다.

일부 백엔드가 백엔드 서비스 목록에 나타나지 않으면 프로그래밍 지연 시간이 원인일 수 있습니다. 이것은 다음 명령어를 실행하여 확인할 수 있습니다. 여기서 [NEG]는 백엔드 서비스의 이름입니다. (NEG와 백엔드 서비스는 이름이 같습니다).

gcloud compute network-endpoint-groups list-network-endpoints [NEG]

예상되는 모든 엔드포인트가 NEG에 있는지 확인하세요.

롤아웃 중단

증상
업데이트된 배포 롤아웃이 중단되고 최신 복제본 수가 원하는 복제본 수와 일치하지 않습니다.
가능한 원인

배포 상태 확인이 실패합니다. 컨테이너 이미지가 손상되었거나 상태 확인이 잘못 구성되었을 수 있습니다. Pod의 순차적 교체는 새로 시작된 Pod가 Pod 준비 게이트를 통과할 때까지 대기합니다. 이는 Pod가 부하 분산기 상태 확인에 응답하는 경우에만 발생합니다. Pod가 응답하지 않거나 상태 확인이 잘못 구성된 경우 준비 게이트 조건을 충족할 수 없으며 롤아웃을 계속할 수 없습니다.

kubectl 1.13 이상을 사용하는 경우 다음 명령어를 사용하여 Pod의 준비 게이트 상태를 확인할 수 있습니다.

kubectl get my-Pod -o wide

READINESS GATES 열을 확인합니다.

kubectl 1.12 이하에는 이 열이 존재하지 않습니다. READY 상태로 표시된 Pod는 준비 게이트가 실패했을 수 있습니다. 이를 확인하려면 다음 명령어를 사용하세요.

kubectl get my-pod -o yaml

준비 게이트와 해당 상태가 출력에 나열됩니다.

해결 방법

배포 Pod 사양의 컨테이너 이미지가 제대로 작동하고 있고 상태 확인에 응답할 수 있는지 확인합니다. 상태 확인이 올바르게 구성되어 있는지 확인합니다.

알려진 문제

Google Kubernetes Engine의 컨테이너 기본 부하 분산에는 다음과 같은 알려진 문제가 있습니다.

불완전한 가비지 컬렉션

Google Kubernetes Engine 가비지는 2분마다 컨테이너 기본 부하 분산기를 수집합니다. 부하 분산기가 완전히 제거되기 전에 클러스터가 삭제되면 부하 분산기의 NEG를 수동으로 삭제해야 합니다.

프로젝트의 NEG를 보려면 다음 명령어를 실행합니다.

gcloud compute network-endpoint-groups list

명령어 출력에서 관련 NEG를 찾습니다.

NEG를 삭제하려면 다음 명령어를 실행하세요. 여기서 [NEG]는 NEG의 이름입니다.

gcloud compute network-endpoint-groups delete [NEG]

워크로드 롤아웃을 엔드포인트 전파에 정렬

워크로드를 클러스터에 배포하거나 기존 워크로드를 업데이트할 때 컨테이너 기본 부하 분산기가 새 엔드포인트를 전파하는 시간이 워크로드 롤아웃을 완료하는 시간보다 길어질 수 있습니다. 이 가이드에서 배포하는 샘플 배포는 terminationGracePeriodSeconds 필드와 minReadySeconds 필드를 사용하여 롤아웃을 엔드포인트 전파에 정렬합니다.

terminationGracePeriodSeconds는 Pod 삭제 예약 후 연결이 종료될 때까지 기다려 Pod가 정상적으로 종료되도록 합니다.

minReadySeconds는 Pod가 생성된 후 지연 시간을 추가합니다. 컨테이너의 비정상 종료 없이 Pod가 사용 가능한 것으로 간주되도록 새 Pod가 Ready 상태로 있어야 하는 최소 시간(초)을 지정합니다.

워크로드 롤아웃으로 인해 서비스가 중단되지 않도록 하려면 워크로드의 minReadySeconds 값과 terminationGracePeriodSeconds 값을 60초 이상으로 구성해야 합니다.

terminationGracePeriodSeconds는 모든 Pod 사양에서 사용할 수 있으며, minReadySeconds는 배포와 DaemonSet에 사용할 수 있습니다.

롤아웃 미세 조정에 대한 자세한 내용은 RollingUpdateStrategy를 참조하세요.

다음 단계

이 페이지가 도움이 되었나요? 평가를 부탁드립니다.

다음에 대한 의견 보내기...

Kubernetes Engine 문서