자습서-Autoscaling으로 Kubernetes 지연시간 줄이기

조직에서 Kubernetes로 앱을 구축했으며 이제 인기를 얻고 있습니다! 하루에 몇 명의 방문자에서 수백 명(때로는 수천 명)으로 증가했습니다. 하지만 문제가 있습니다. 트래픽 증가로 인해 병목 현상이 발생하여 고객에게 지연 시간과 시간 초과가 발생합니다. 경험을 개선할 수 없다면 사람들은 앱 사용을 중단할 것입니다.

용감한 Kubernetes 엔지니어인 당신에게 솔루션이 있습니다. Ingress Controller를 배포하여 트래픽을 라우팅하고 트래픽 변동에 맞게 Ingress Controller Pod의 수가 즉시 확장 및 축소되도록 자동 크기 조정 정책을 설정합니다. 이제 Ingress Controller Pod가 트래픽 급증을 원활하게 처리합니다.

목차

1. 실습 및 모범 사례 개요
2. 과제 1: Kubernetes 클러스터에서 간단한 앱 구성
  2-1. Minikube 클러스터 생성
  2-2. Podinfo 앱 설치
3. 과제 2: NGINX Ingress Controller를 사용하여 앱으로 트래픽 라우팅
  3-1. NGINX Ingress Controller 배포
  3-2. 앱으로 트래픽 라우팅
4. 과제 3: 트래픽 생성 및 모니터링
  4-1. 사용 가능한 지표 나열
  4-2. 프로메테우스 배포
  4-3. Locust 설치
  4-4. 트래픽 급증 시뮬레이션 및 성능에 대한 영향 관찰
5. 과제 4: NGINX Ingress Controller Autoscale 조정
  5-1. KEDA 설치
  5-2. Autoscaling 정책 생성
  5-3. 트래픽 급증 시뮬레이션 및 Autoscaling이 성능에 미치는 영향 관찰
6. Next Steps

1. 실습 및 모범 사례 개요

이 모범 사례는 NGINX Ingress Controller를 사용하여 앱을 노출한 다음 높은 트래픽에 대한 응답으로 Ingress Controller Pod를 자동 크기 조정하는 방법을 보여줍니다.

자신의 환경에서 자습서로 수행하려면 다음이 포함된 머신이 필요합니다.

  • 2 CPU 이상
  • 2GB의 여유 메모리
  • 20GB의 디스크 여유 공간
  • 인터넷 연결
  • Docker, Hyperkit, Hyper-V, KVM, Parallels, Podman, VirtualBox 또는 VMware Fusion/Workstation과 같은 컨테이너 또는 가상 머신 관리자
  • minikube 설치
  • Helm 설치

이 모범 사례에서는 다음 기술을 사용합니다.

이 모범 사례에는 네 가지 과제가 포함되어 있습니다.

  1. Kubernetes 클러스터에서 단순 앱 구성
  2. NGINX Ingress Controller를 사용하여 앱으로 트래픽 라우팅
  3. 트래픽 생성 및 모니터링
  4. 자동 크기 조정 NGINX Ingress Controller

2. 과제 1: Kubernetes 클러스터에서 간단한 앱 구성

이 챌린지에서는 minikube 클러스터를 만들고 Podinfo 를 샘플 앱으로 설치합니다.

2-1. Minikube 클러스터 생성

minikube 클러스터를 만듭니다 . 몇 초 후 배포가 성공했음을 확인하는 메시지가 표시됩니다.

$ minikube start 
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default 

2-2. Podinfo 앱 설치

Podinfo 는 “Kubernetes에서 마이크로 서비스를 실행하는 모범 사례를 보여주는 Go로 만든 웹 애플리케이션”입니다. 설치 공간이 작기 때문에 샘플 앱으로 사용하고 있습니다.

1. 원하는 텍스트 편집기를 사용 하여 다음 내용으로 1-deployment.yaml 이라는 YAML 파일을 만듭니다 . 단일 복제본과 서비스가 있는 배포를 정의합니다.

apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: podinfo 
spec: 
  selector: 
    matchLabels: 
      app: podinfo 
  template: 
    metadata: 
      labels: 
        app: podinfo 
    spec: 
      containers: 
      - name: podinfo 
        image: stefanprodan/podinfo 
        ports: 
        - containerPort: 9898 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: podinfo 
spec: 
  ports: 
    - port: 80 
      targetPort: 9898 
      nodePort: 30001 
  selector: 
    app: podinfo 
  type: LoadBalancer 

2. 앱 배포:

$ kubectl apply -f 1-deployment.yaml 
deployment.apps/podinfo created 
service/podinfo created

3. STATUS 열에 Running 값으로 표시된 대로 Podinfo Pod가 배포되었는지 확인합니다.

$ kubectl get pods  
NAME                       	READY	STATUS    RESTARTS	AGE 
podinfo-5d76864686-rd2s5   	1/1	    Running   0         3m38s 

4. minikube service podinfo를 사용하여 브라우저에서 Podinfo를 엽니다. 다음 페이지는 Podinfo가 실행 중임을 나타냅니다.

3. 과제 2: NGINX Ingress Controller를 사용하여 앱으로 트래픽 라우팅

이 챌린지에서는 NGINX Ingress Controller를 배포 하고 트래픽을 Podinfo 앱 으로 라우팅하도록 구성합니다 .

3-1. NGINX Ingress Controller 배포

NGINX Ingress Controller를 설치하는 가장 빠른 방법은 Helm을 사용하는 것 입니다.

1. Helm에 NGINX 저장소를 추가합니다.

$ helm repo add nginx-stable https://helm.nginx.com/stable 

2. F5 NGINX에서 유지 관리하는 NGINX 오픈소스 기반 NGINX Ingress Controller를 다운로드하여 설치합니다. 출력의 마지막 줄은 성공적인 설치를 확인합니다.

$ helm install main nginx-stable/nginx-ingress \ 
--set controller.watchIngressWithoutClass=true \  
--set controller.service.type=NodePort \ 
--set controller.service.httpPort.nodePort=30005 
NAME: main 
LAST DEPLOYED: Tue Feb 22 19:49:17 2022 
NAMESPACE: default 
STATUS: deployed 
REVISION: 1 
TEST SUITE: None 
NOTES: The NGINX Ingress Controller has been installed. 

2. STATUS 열에 Running 값으로 표시된 대로 NGINX Ingress Controller Pod가 배포되었는지 확인합니다.

$ kubectl get pods  
NAME                                  READY   STATUS    RESTARTS   AGE 
main-nginx-ingress-779b74bb8b-mtdkr   1/1     Running   0          18s 
podinfo-5d76864686-fjncl  

3-2. 앱으로 트래픽 라우팅

1. 원하는 텍스트 편집기를 사용 하여 다음 내용으로 2-ingress.yaml 이라는 YAML 파일을 만듭니다 . 트래픽을 Podinfo로 라우팅하는 데 필요한 Ingress 매니페스트를 정의합니다.

apiVersion: networking.k8s.io/v1 
kind: Ingress 
metadata: 
  name: podinfo 
spec: 
  ingressClassName: nginx 
  rules: 
    - host: "example.com" 
      http: 
        paths: 
          - backend: 
              service: 
                name: podinfo 
                port: 
                  number: 80 
            path: / 
            pathType: Prefix 

2. Ingress 리소스를 배포합니다.

$ kubectl apply -f 2-ingress.yaml 
ingress.networking.k8s.io/podinfo created 

4. 과제 3: 트래픽 생성 및 모니터링

이 챌린지에서는 다양한 트래픽 부하에서 NGINX Ingress Controller의 성능을 관찰합니다. 준비 단계로 NGINX Ingress Controller에서 사용 가능한 메트릭을 나열하고 Prometheus를 배포하고 Locust를 설치 합니다. 그런 다음 Locust를 사용하여 트래픽 급증을 시뮬레이션하고 Prometheus의 성능에 미치는 영향을 추적합니다.

이미 발견한 것처럼 Ingress Controller는 Kubernetes와의 통합을 위한 일부 코드와 함께 Reverse Proxy(이 경우 NGINX)를 번들로 제공하는 일반 Kubernetes Pod입니다. 앱이 많은 트래픽을 수신하는 경우 NGINX Ingress Controller Pod 복제본의 수를 늘려야 NGINX Ingress Controller가 과부하될 때 발생하는 대기 시간을 방지할 수 있습니다.

4-1. 사용 가능한 지표 나열

확장 시기와 양을 알기 위해서는 NGINX Ingress Controller 성능에 대한 정확한 정보가 필요합니다. 이 튜토리얼에서 확장 시점을 결정하는 데 사용되는 NGINX 메트릭은 활성 연결 수입니다 (nginx_connections_active). 여기에서 NGINX Ingress Controller가 해당 지표를 추적하는지 확인합니다.

NGINX Ingress Controller는 여러 메트릭을 노출합니다 . 이 자습서에서 소송을 제기하는 NGINX 오픈소스 기반 모델의 8개 메트릭과 NGINX Plus 기반 모델의 80개 이상의 메트릭.

1. 메트릭 목록을 쿼리할 수 있도록 NGINX Ingress Controller Pod의 IP 주소를 가져옵니다. 주소는 IP 필드에 표시되며 여기에서는 172.17.0.4입니다. (출력은 가독성을 위해 두 줄에 걸쳐 펼쳐집니다.)

$ kubectl get pods -o wide 
NAME                                  READY   STATUS    RESTARTS   AGE    ...  
main-nginx-ingress-779b74bb8b-6hdwx   1/1     Running   0          3m43s  ...    
podinfo-5d76864686-nl8ws              1/1     Running   0          5m49s  ...  

      ... IP           NODE       NOMINATED NODE   READINESS GATES 
      ... 172.17.0.4   minikube               
      ... 172.17.0.3   minikube     

2. Kubernetes 클러스터 내부의 호스트에 셸이 있는 임시 Pod를 생성합니다.

$ kubectl run -ti --rm=true busybox --image=busybox  
If you don't see a command prompt, try pressing enter. 
/ # 

3. NGINX Ingress Controller에서 생성된 메트릭을 나열하고 nginx_connections_active가 포함되어 있는지 확인합니다. 1단계의 값으로 대체합니다.

/# wget -qO- :9113/metrics  

4. 셸을 종료하여 Kubernetes 서버로 돌아갑니다.

/# exit 

4-2. 프로메테우스 배포

이제 NGINX Ingress Controller가 nginx_connections_active를 추적한다는 것을 알았으므로 메트릭을 수집(“스크레이핑”)하는 도구가 필요합니다. 이 자습서에서는 Prometheus를 사용합니다.

NGINX Ingress Controller의 경우 Helm 은 Prometheus를 설치하는 가장 빠른 방법입니다.

1. Prometheus 리포지토리를 Helm에 추가합니다.

$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts 

2. Prometheus 다운로드 및 설치:

$ helm install prometheus prometheus-community/prometheus \ 
--set server.service.type=NodePort --set server.service.nodePort=30010 

3. 일반적으로 완료하는 데 최대 60초가 소요되는 설치를 확인합니다. 다음 샘플 출력에서 확인 명령은 helm install 명령을 실행한 후 몇 초만에 실행되었으므로 일부 Prometheus Pod의 STATUS 필드에 보고된 ContainerCreating과 함께 설치가 진행 중인 것을 볼 수 있습니다. 모든 파드(Pod)이 Running 상태이면 설치가 완료된 것입니다. (RESTARTS 열은 가독성을 위해 출력에서 생략되었습니다. 값은 모든 Pod에 대해 0입니다.)

$ kubectl get pods 

NAME                                            READY  STATUS             ...  AGE 
main-nginx-ingress-779b74bb8b-mtdkr             1/1    Running            ...  3m23s 
podinfo-5d76864686-fjncl                        1/1    Running            ...  5m41s 
prometheus-alertmanager-d6d94cf4b-85ww5         0/2    ContainerCreating  ...  7s  
prometheus-kube-state-metrics-7cd8f95c7b-86hhs  0/1    Running            ...  7s  
prometheus-node-exporter-gqxfz                  1/1    Running            ...  7s  
prometheus-pushgateway-56745d8d8b-qnwcb         0/1    ContainerCreating  ...  7s  
prometheus-server-b78c9449f-kwhzp               0/2    ContainerCreating  ...  7s  

4. 프로메테우스를 엽니다. minikube 환경에서는 기본 브라우저에서 Prometheus 대시보드를 여는 minikube 서비스 prometheus-server로 수행됩니다. 다음과 같은 페이지는 서버가 작동 중임을 확인합니다.

5. 활성 연결 메트릭의 현재 값을 보려면 검색 창에 nginx_ingress_nginx_connections_active를 입력하십시오. 하나의 NGINX Ingress Controller Pod를 배포했으므로 하나의 활성 연결이 표시됩니다.

4-3. Locust 설치

다음 섹션에서는 오픈소스 부하 테스트 도구인 Locust를 사용하여 트래픽 급증을 시뮬레이션하여 Prometheus에서 NGINX Ingress Controller의 성능을 볼 수 있습니다. 먼저 배포해야 합니다.

1. 원하는 텍스트 편집기를 사용 하여 다음 내용으로 3-locust.yaml 이라는 YAML 파일을 만듭니다 . 배포 및 서비스 개체는 Locust Pod를 정의합니다. ConfigMap 개체는 locustfile.py 라는 스크립트를 정의 하여 올바른 헤더와 함께 Pod에 보낼 요청을 생성합니다.

apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: locust-script 
data: 
  locustfile.py: |- 
    from locust import HttpUser, task, between 

    class QuickstartUser(HttpUser): 
        wait_time = between(0.7, 1.3) 

        @task 
        def hello_world(self): 
            self.client.get("/", headers={"Host": "example.com"}) 
--- 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: locust 
spec: 
  selector: 
    matchLabels: 
      app: locust 
  template: 
    metadata: 
      labels: 
        app: locust 
    spec: 
      containers: 
        - name: locust 
          image: locustio/locust 
          ports: 
            - containerPort: 8089 
          volumeMounts: 
            - mountPath: /home/locust 
              name: locust-script 
      volumes: 
        - name: locust-script 
          configMap: 
            name: locust-script 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: locust 
spec: 
  ports: 
    - port: 8089 
      targetPort: 8089 
      nodePort: 30015 
  selector: 
    app: locust 
  type: LoadBalancer 

2. Locust 배포:

$ kubectl apply -f  3-locust.yaml 
configmap/locust-script created 
deployment.apps/locust created 
service/locust created 

4-4. 트래픽 급증 시뮬레이션 및 성능에 대한 영향 관찰

1. minikube service locust브라우저에서 Locust를 여는 데 사용합니다.

2. 필드에 다음 값을 입력합니다.

3. Start swarming 버튼을 클릭하여 Podinfo 앱으로 트래픽을 보냅니다.

4. Prometheus 대시보드로 돌아가 NGINX Ingress Controller가 응답하는 방식을 확인하십시오. 변경 사항을 확인하려면 nginx_ingress_nginx_connections_active에 대해 새 쿼리를 수행해야 할 수 있습니다.

다음 화면 출력에서 ​​볼 수 있듯이 많은 수의 연결이 설정됨에 따라 단일 NGINX Ingress Controller Pod는 대기 시간 없이 증가된 트래픽을 처리하기 위해 고군분투합니다. Prometheus 그래프는 NGINX Ingress Controller Pod당 약 100개의 활성 연결이 대기 시간 급증의 티핑 포인트임을 보여줍니다. 이 정보를 사용하여 지연 시간 증가를 방지하기 위해 NGINX Ingress Controller 파드(Pod)의 수를 확장해야 하는 시기를 결정할 수 있습니다.

5. 과제 4: NGINX Ingress Controller Autoscale 조정

마지막 과제에서는 트래픽 양이 증가함에 따라 리소스를 자동 확장하는 구성을 구축합니다. 이 모범 사례에서는 자동 크기 조정에 KEDA 를 사용하므로 먼저 KEDA를 설치하고 크기 조정이 발생하는 시기와 방법을 정의 하는 정책을 만듭니다 . 챌린지 3에서와 같이 Locust를 사용하여 트래픽 급증을 시뮬레이션 하고 Prometheus를 사용하여 자동 크기 조정이 활성화된 경우 NGINX Ingress Controller 성능을 관찰합니다.

5-1. KEDA 설치

Kubernetes 이벤트 기반 자동 크기 조정기인 KEDA 는 메트릭 서버(Kubernetes에 대한 메트릭을 저장하고 변환하는 구성 요소)를 통합하고 Prometheus(및 기타 도구)에서 직접 메트릭을 사용할 수 있습니다. 이러한 메트릭으로 HPA(Horizontal Pod Autoscaler) 를 생성하고 Prometheus에서 수집한 메트릭을 연결하여 Kubernetes에 공급합니다.

NGINX Ingress Controller 및 Prometheus와 마찬가지로 이 자습서에서는 Helm을 사용하여 KEDA를 설치합니다.

1. KEDA를 Helm 저장소에 추가합니다.

$ helm repo add kedacore https://kedacore.github.io/charts 
"kedacore" has been added to your repositories 

2. KEDA 설치:

$ helm install keda kedacore/keda 
NAME: keda 
NAMESPACE: default 
STATUS: deployed 
REVISION: 1 
TEST SUITE: None 

3. KEDA가 두 개의 Pod로 실행되고 있는지 확인합니다. (RESTARTS 열은 가독성을 위해 출력에서 ​​생략되었습니다. 값은 모든 Pod에 대해 0입니다.)

$ kubectl get pods 

NAME                                                READY   STATUS   ...  AGE 
keda-operator-8644dcdb79-492x5                      1/1     Running       59s 
keda-operator-metrics-apiserver-66d6c4454-dp6lq     1/1     Running       59s 
locust-77c699c94d-dvb5n                             1/1     Running       8m59s 
main-nginx-ingress-779b74bb8b-v7ggw                 1/1     Running       48m 
podinfo-5d76864686-c98rb                            1/1     Running       50m 
prometheus-alertmanager-d6d94cf4b-8gzq2             2/2     Running       37m 
prometheus-kube-state-metrics-7cd8f95c7b-9hsbm      1/1     Running       37m 
prometheus-node-exporter-j4qf4                      1/1     Running       37m 
prometheus-pushgateway-56745d8d8b-9n4nl             1/1     Running       37m 
prometheus-server-b78c9449f-6ktn9                   2/2     Running       37m   

5-2. Autoscaling 정책 생성

이제 NGINX Ingress Controller가 KEDA 개체 ScaledObject를 사용하여 확장하는 방법을 지시하는 확장 매개변수를 정의합니다. 다음 구성:

  • Prometheus에서 수집한 nginx_connections_active 메트릭 값을 기반으로 자동 크기 조정을 트리거합니다.
  • 기존 Pod가 각각 100개의 활성 연결에 도달하면 새 포드를 배포합니다.
  • 단일 Pod에서 최대 20개의 Pod로 NGINX Ingress Controller Pod 자동 확장

1. 원하는 텍스트 편집기를 사용하여 다음 내용으로 4-scaled-object.yaml이라는 YAML 파일을 만듭니다. KEDA ScaledObject를 정의합니다.

apiVersion: keda.sh/v1alpha1 
kind: ScaledObject 
metadata: 
name: nginx-scale 
spec: 
scaleTargetRef: 
   kind: Deployment 
   name: main-nginx-ingress 
minReplicaCount: 1 
maxReplicaCount: 20 
cooldownPeriod: 30 
pollingInterval: 1 
triggers: 
- type: prometheus 
   metadata: 
     serverAddress: http://prometheus-server 
     metricName: nginx_connections_active_keda 
     query: | 
       sum(avg_over_time(nginx_ingress_nginx_connections_active{app="main-nginx-ingress"}[1m])) 
     threshold: "100" 

2. 배포 ScaledObject:

$ kubectl apply -f 4-scaled-object.yaml 
scaledobject.keda.sh/nginx-scale created 

5-3. 트래픽 급증 시뮬레이션 및 Autoscaling이 성능에 미치는 영향 관찰

자동 크기 조정의 효율성을 실제로 테스트하려면 챌린지 3에 비해 연결 수를 두 배로 늘립니다.

1. 브라우저에서 Locust 서버로 돌아갑니다. 필드에 다음 값을 입력하고 스웜 시작 버튼을 클릭합니다.

2. Prometheus 및 Locust 대시보드로 돌아갑니다. Prometheus 그래프 아래의 분홍색 상자는 확장 및 축소되는 NGINX Ingress Controller Pod의 수를 나타냅니다.

KEDA HPA 수동 검사

3. 터미널로 다시 전환하고 KEDA HPA를 수동으로 검사하십시오. 출력의 REPLICAS 필드는 배포된 Pod 복제본의 현재 수를 보여줍니다. (출력은 가독성을 위해 두 줄에 걸쳐 펼쳐집니다.)

$ kubectl get hpa  

NAME                   REFERENCE                       TARGETS            ...     
keda-hpa-nginx-scale   Deployment/main-nginx-ingress   101500m/100 (avg)  ... 

      ... MINPODS   MAXPODS   REPLICAS   AGE 
      ... 1         20        10         2m45s    

6. Next Steps

활성 연결 수만 기준으로 자동 크기 조정을 수행하는 경우 잠재적인 제한이 있습니다. 확장을 사용하더라도 NGINX Ingress Controller가 너무 바빠서 연결을 끊어야 하는 경우 자동 확장 처리는 활성 연결을 더 적게 보고 이를 요청이 거부되었음을 의미하는 것으로 해석하고 복제본 수를 줄입니다. 그렇게 하면 성능이 저하될 수 있지만 메트릭 조합을 활용하면 이러한 일이 발생하지 않도록 할 수 있습니다. 예를 들어, nginxplus_connections_dropped(NGINX Plus에서 사용 가능)는 삭제된 클라이언트 연결을 추적합니다.

NGINX STORE 뉴스레터 및 최신 소식 구독하기

* indicates required