자습서-NGINX Ingress Controller 속도 제한 설정

전 세계 K8s 클러스터의 65%는 NGINX Ingress Controller 사용하고 있습니다. NGINX Ingress Controller를 API Gateway로 배포할 수 있다는 사실은 알고 계신가요?

이번 자습서에는 NGINX Ingress Controller에 Rate Limiting 기능을 사용하여 쿠버네티스 API 보호하는 방법을 따라해봅니다.

조직이 Kubernetes에서 첫 번째 앱과 API를 출시했습니다. 많은 양의 트래픽이 예상된다는 말을 들었지만(NGINX Ingress Controller가 트래픽을 빠르게 라우팅할 수 있도록 이미 자동 크기 조정을 구현했습니다) API가 악의적인 공격의 대상이 될 수 있다는 우려가 있습니다. API가 대량의 HTTP 요청(무차별 암호 대입 또는 DDoS 공격 가능성 있음)을 수신하는 경우 API와 앱 모두 과부하가 걸리고 충돌이 발생할 수도 있습니다.

트래픽 제어 기술 “속도 제한”은 수신 요청 속도를 실제 사용자에게 일반적인 값으로 제한하는 API Gateway 사용 사례입니다. 속도 제한 정책을 구현하도록 NGINX Ingress Controller를 구성하면 앱과 API가 너무 많은 요청에 압도되는 것을 방지할 수 있습니다. 

목차

1. 실습 및 자습서 개요
2. 과제 1: 클러스터, 앱, API 및 Ingress Controller 배포

  2-1. Minikube 클러스터 생성
  2-2. Podinfo 앱 및 Podinfo API 설치

  2-3. NGINX Ingress Controller 배포
  2-4. 앱으로 트래픽 라우팅
  2-5. Ingress 구성 테스트
3. 과제 2: 앱 및 API 압도
  3-1. Locust 설치
  3-2. 트래픽 급증 시뮬레이션 및 성능에 대한 영향 관찰
4. 과제 3: Dual Ingress Controller 및 속도 제한(Rate Limiting)으로 앱 및 API 저장
  4-1. 클러스터 준비
  4-2. Locust 재구성
  4-3. 테스트 속도 제한 (Test Rate Limiting)

1. 실습 및 자습서 개요

이 모범 사례는 앱과 API가 과부하되는 것을 방지하기 위해 속도 제한 활성화와 결합된 여러 NGINX Ingress Controller를 사용하는 방법을 보여줍니다.

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

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

이 자습서에서는 다음 기술을 사용합니다.

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

  1. 클러스터, 앱, API 및 Ingress Controller 배포
  2. 앱과 API 압도
  3. Dual Ingress Controller 및 속도 제한(Rate Limiting)으로 앱 및 API 저장

2. 과제 1: 클러스터, 앱, API 및 Ingress Controller 배포

이 챌린지에서는 minikube 클러스터를 배포하고 Podinfo를 샘플 앱 및 API로 설치합니다.

2-1. Minikube 클러스터 생성

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

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

2-2. Podinfo 앱 및 Podinfo API 설치

1단계: 배포 만들기

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

1. 원하는 텍스트 편집기를 사용하여 다음 내용으로 1-apps.yaml이라는 YAML 파일을 만듭니다. 다음을 포함하는 배포를 정의합니다.

  • HTML 페이지를 렌더링하는 “Podinfo Frontend”라는 웹 앱
  • JSON 페이로드를 반환하는 “Podinfo API”라는 API
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: api 
spec: 
  selector: 
    matchLabels: 
      app: api 
  template: 
    metadata: 
      labels: 
        app: api 
    spec: 
      containers: 
        - name: api 
          image: stefanprodan/podinfo 
          ports: 
            - containerPort: 9898 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: api 
spec: 
  ports: 
    - port: 80 
      targetPort: 9898 
      nodePort: 30001 
  selector: 
    app: api 
  type: LoadBalancer 
--- 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: frontend 
spec: 
  selector: 
    matchLabels: 
      app: frontend 
  template: 
    metadata: 
      labels: 
        app: frontend 
    spec: 
      containers: 
        - name: frontend 
          image: stefanprodan/podinfo 
          ports: 
            - containerPort: 9898 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: frontend 
spec: 
  ports: 
    - port: 80 
      targetPort: 9898 
      nodePort: 30002 
  selector: 
    app: frontend 
  type: LoadBalancer 

2. 앱 및 API를 배포합니다.

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

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

$ kubectl get pods  
NAME                       	READY	STATUS    RESTARTS	AGE 
api-7574cf7568-c6tr6        1/1     Running   0          87s 
frontend-6688d86fc6-78qn7   1/1     Running   0          87s 

2-3. NGINX Ingress Controller 배포

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

Helm을 사용하여 별도의 네임스페이스(“nginx”)에 NGINX Ingress Controller를 설치합니다.

1. 네임스페이스를 만듭니다.

 kubectl create namespace nginx

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

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

3. 클러스터에 NGINX Ingress Controller를 다운로드하고 설치합니다.

 helm install main nginx-stable/nginx-ingress \ 
 --set controller.watchIngressWithoutClass=true \ 
 --set controller.ingressClass=nginx \ 
 --set controller.service.type=NodePort \ 
 --set controller.service.httpPort.nodePort=30010 \ 
 --set controller.enablePreviewPolicies=true \ 
 --namespace nginx 

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

$ kubectl get pods –namespace nginx 
NAME                                  READY   STATUS    RESTARTS   AGE 
main-nginx-ingress-779b74bb8b-d4qtc   1/1     Running   0          92s 

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

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

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

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

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

2-5. Ingress 구성 테스트

1. 임시 Pod를 생성합니다.

Ingress 구성이 예상대로 작동하는지 확인하기 위해 임시 Pod를 사용하여 테스트합니다. 클러스터에서 일회용 busybox Pod를 시작합니다.

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

2. Podinfo API를 테스트합니다.

호스트 이름이 “api.example.com”인 NGINX Ingress Controller Pod에 요청을 발행합니다.

wget --header="Host: api.example.com" -qO- main-nginx-ingress.nginx 

API가 트래픽을 제대로 수신하면 다음을 얻을 수 있습니다.

{ 
  "hostname": "api-687fd448f8-t7hqk", 
  "version": "6.0.3", 
  "revision": "", 
  "color": "#34577c", 
  "logo": "https://raw.githubusercontent.com/stefanprodan/podinfo/gh-pages/cuddle_clap.gif", 
  "message": "greetings from podinfo v6.0.3", 
  "goos": "linux", 
  "goarch": "arm64", 
  "runtime": "go1.16.9", 
  "num_goroutine": "6", 
  "num_cpu": "4" 
} 

3. Podinfo 프론트엔드 테스트

동일한 busybox를 사용하여 웹 브라우저를 시뮬레이션하고 다음을 입력하여 웹 페이지를 검색합니다.

wget --header="Host: example.com" --header="User-Agent: Mozilla" -qO- main-nginx-ingress.nginx 

성공하면 다음으로 시작하는 긴 응답이 표시됩니다.

<!DOCTYPE html> 
<html> 
<head> 
  <title>frontend-596d5c9ff4-xkbdc</title> 

minikube 서비스 프론트엔드를 사용하여 브라우저에서 Podinfo 앱을 엽니다. 환영 페이지가 표시되어야 합니다.

축하합니다! NGINX Ingress Controller가 요청을 수신하고 앱과 API로 디스패치합니다.

Kubernetes 서버로 돌아가려면 임시 파드(Pod)의 명령 프롬프트에서 exit를 입력하여 busybox 세션을 종료하십시오.

3. 과제 2: 앱 및 API 압도

이 챌린지에서는 오픈소스 부하 테스트 도구인 Locust를 사용하여 API를 압도하고 앱 충돌을 일으키는 트래픽 급증을 시뮬레이션합니다.

3-1. Locust 설치

먼저 앱과 API가 트래픽에 응답하는 것을 볼 수 있도록 트래픽 생성기 Locust를 배포해야 합니다.

1. 원하는 텍스트 편집기를 사용하여 다음 내용으로 3-locust.yaml이라는 YAML 파일을 만듭니다. 배포 및 서비스 개체는 Locust Pod를 정의합니다. ConfigMap 개체는 locustfile.py라는 스크립트를 정의하여 올바른 헤더와 함께 Pod에 보낼 요청을 생성합니다. 트래픽은 앱과 API 간에 고르게 분산되지 않습니다. 요청은 Podinfo API로 치우쳐지고 1/5 요청만 Podinfo Frontend로 이동합니다.

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(1) 
        def visit_website(self): 
            with self.client.get("/", headers={"Host": "example.com", "User-Agent": "Mozilla"}, timeout=0.2, catch_response=True) as response: 
                if response.request_meta["response_time"] > 200: 
                    response.failure("Frontend failed") 
                else: 
                    response.success() 
  

        @task(5) 
        def visit_api(self): 
            with self.client.get("/", headers={"Host": "api.example.com"}, timeout=0.2) as response: 
                if response.request_meta["response_time"] > 200: 
                    response.failure("API failed") 
                else: 
                    response.success() 
--- 
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 
Locust reads the `locustfile.py`, which is stored in a ConfigMap: 
from locust import HttpUser, task, between 
class QuickstartUser(HttpUser): 
    wait_time = between(0.7, 1.3) 

    @task(1) 
    def visit_website(self): 
        with self.client.get("/", headers={"Host": "example.com", "User-Agent": "Mozilla"}, timeout=0.2, catch_response=True) as response: 
            if response.request_meta["response_time"] > 200: 
                response.failure("Frontend failed") 
            else: 
                response.success() 
    @task(5) 
    def visit_api(self): 
        with self.client.get("/", headers={"Host": "api.example.com"}, timeout=0.2) as response: 
            if response.request_meta["response_time"] > 200: 
                response.failure("API failed") 
            else: 
                response.success() 

2. Locust 배포:

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

3. kubectl get pods를 사용하여 Pod를 검색하여 Locust 배포를 확인합니다. Locust Pod는 이 시점에서 여전히 “ContainerCreating” 상태일 수 있습니다. 다음 섹션을 계속하기 전에 “실행 중”이 표시될 때까지 기다리십시오.

NAME                        READY   STATUS              RESTARTS   AGE 
api-7574cf7568-c6tr6        1/1     Running             0          33m 
frontend-6688d86fc6-78qn7   1/1     Running             0          33m 
locust-77c699c94d-hc76t     0/1     ContainerCreating   0          4s 

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

1. minikube service locust를 사용하여 브라우저에서 Locust를 엽니다.

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

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

  • Charts Tab: 이 탭은 트래픽을 그래픽으로 보여줍니다. API 요청이 증가함에 따라 Podinfo API 응답 시간이 악화되는 것을 지켜보십시오.
  • Failures Tab: 웹 앱과 API가 Ingress Controller를 공유하기 때문에 웹 앱이 곧 오류를 반환하고 API 요청 증가로 인해 실패함을 알 수 있습니다.

API를 사용하는 단일 불량 행위자가 API뿐만 아니라 동일한 Ingress Controller에서 제공하는 모든 앱을 중단시킬 수 있기 때문에 문제가 됩니다!

4. 과제 3: Dual Ingress Controller 및 속도 제한(Rate Limiting)으로 앱 및 API 저장

마지막 챌린지에서는 이전 배포의 제한 사항을 해결합니다.

먼저 아키텍처 문제를 해결하는 방법을 살펴보겠습니다. 이전 챌린지에서는 API 요청으로 NGINX Ingress Controller를 압도했으며 이는 앱 Podinfo Frontend에도 영향을 미쳤습니다. 이는 단일 Ingress Controller가 앱 및 API에 대한 트래픽 라우팅을 담당했기 때문에 발생했습니다.

각 서비스에 대해 별도의 NGINX Ingress Controller Pod를 실행하면 앱이 너무 많은 API 요청의 영향을 받는 것을 방지할 수 있습니다. 모든 사용 사례에 반드시 필요한 것은 아니지만 시뮬레이션에서 여러 Ingress Controller를 실행하는 것의 이점을 쉽게 확인할 수 있습니다.

Podinfo API가 과부하되는 것을 방지하는 솔루션의 두 번째 부분은 NGINX Ingress Controller를 API Gateway로 사용하여 속도 제한(Rate Limiting)을 구현하는 것입니다.

속도 제한(Rate Limiting)이란 무엇입니까?

속도 제한은 사용자가 주어진 기간 동안 만들 수 있는 요청 수를 제한합니다. 예를 들어 DDoS 공격을 받는 경우 속도 제한을 사용하여 수신 요청 속도를 실제 사용자에게 일반적인 값으로 제한할 수 있습니다. 속도 제한이 NGINX로 구현되면 너무 많은 요청을 제출하는 클라이언트는 API에 부정적인 영향을 미치지 않도록 오류 페이지로 리디렉션됩니다.

API Gateway란 무엇입니까?

API Gateway는 클라이언트의 API 요청을 적절한 서비스로 라우팅합니다. 이 간단한 정의에 대한 큰 오해는 API Gateway가 고유한 기술이라는 생각입니다. 그렇지 않다. 오히려 “API Gateway”는 다양한 유형의 프록시(가장 일반적으로 ADC 또는 로드 밸런서 및 리버스 프록시, 그리고 점점 더 Ingress Controller 또는 Service Mesh)를 통해 구현될 수 있는 일련의 사용 사례를 설명합니다. 속도 제한은 API Gateway 배포의 일반적인 사용 사례입니다.

4-1. 클러스터 준비

1. Ingress 정의를 삭제합니다.

이 새로운 아키텍처와 정책을 구현하려면 먼저 원래 Ingress 정의를 삭제해야 합니다.

kubectl delete -f 2-ingress.yaml 
ingress.networking.k8s.io "first" deleted 

2. 두 개의 네임스페이스를 만듭니다.

이제 각 NGINX Ingress Controller에 대해 하나씩 두 개의 새 네임스페이스를 만듭니다.

Podinfo Frontend 앱 제공:

kubectl create namespace nginx-web 
namespace/nginx-web created 

Podinfo API 제공:

kubectl create namespace nginx-api 
namespace/nginx-api created 

nginx-web NGINX Ingress Controller 설치

1. NGINX Ingress Controller 설치

이 NGINX Ingress Controller Pod는 Podinfo Frontend에 대한 요청을 처리합니다.

helm install web nginx-stable/nginx-ingress  
  --set controller.ingressClass=nginx-web \ 
  --set controller.service.type=NodePort \ 
  --set controller.service.httpPort.nodePort=30020 \ 
  --namespace nginx-web  

2. Ingress 매니페스트를 만듭니다.

Podinfo Frontend 앱에 대해 4-ingress-web.yaml이라는 Ingress 매니페스트를 생성합니다.

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

3. 새 매니페스트를 배포합니다.

kubectl apply -f 4-ingress-web.yaml 
ingress.networking.k8s.io/frontend created  

nginx-api NGINX Ingress Controller 설치

마지막 섹션에서 생성한 매니페스트는 ingressClassName 필드에 표시된 대로 nginx-web Ingress Controller 전용입니다. 다음으로, API가 과부하되는 것을 방지하기 위한 속도 제한 정책을 포함하여 Podinfo API용 Ingress Controller를 설치합니다.

NGINX Ingress Controller로 속도 제한을 구성하는 방법에는 두 가지가 있습니다.

Option 1: NGINX Ingress 리소스

NGINX Ingress 리소스는 Kubernetes 사용자 지정 리소스의 대안입니다. 다음을 포함하여 Ingress 로드 밸런싱 기능의 구현을 단순화하는 기본, 유형 안전 및 들여쓰기 구성 스타일을 제공합니다.

  • 회로 차단(Circuit breaking) – 애플리케이션 오류의 적절한 처리.
  • 정교한 라우팅 – A/B 테스트 및 블루-그린 배포용.
  • 헤더 조작 – NGINX 인그레스 컨트롤러로 애플리케이션 로직을 오프로딩하기 위한 것입니다.
  • 상호 TLS 인증(mTLS) – 제로 트러스트 또는 ID 기반 보안용.
  • 웹 애플리케이션 방화벽(WAF) – HTTP 취약점 공격으로부터 보호합니다.

Option 2: Snippets

이 모범 사례에서는 스니펫이 작동하지만 오류가 발생하기 쉽고 작업하기 어렵고 세부적인 제어를 제공하지 않으며 보안 문제가 있을 수 있으므로 가능한 한 스니펫을 피하는 것이 좋습니다.

속도 제한을 위한 다양한 구성 옵션을 제공하는 NGINX Ingress 리소스를 사용합니다. 이 챌린지에서는 세 가지 필수 속도 제한 매개변수만 사용합니다.

  • Rate: 허용된 요청 비율입니다. 속도는 초당 요청 수(r/s) 또는 분당 요청 수(r/m)로 지정됩니다.
  • Key: 속도 제한이 적용되는 키입니다. 텍스트, 변수 또는 이들의 조합을 포함할 수 있습니다.
  • Zone Size: 공유 메모리 영역의 크기 – MB 또는 KB로 구성 가능 NGINX Worker 프로세스가 요청을 추적하는 데 필요합니다.

예제에서 해당 매개변수를 살펴보겠습니다. 여기에서 NGINX Ingress Controller가 고유한 IP 주소를 기반으로 제한하도록 지시하는 NGINX 변수 ${binary_remote_addr}에 따라 클라이언트가 초당 1개의 요청으로 제한되는 것을 볼 수 있습니다.

    rateLimit: 
      rate: 1r/s 
      key: ${binary_remote_addr} 
      zoneSize: 10M 

1. NGINX Ingress Controller 설치

이 NGINX Ingress Controller Pod는 Podinfo API에 대한 요청을 처리합니다.

helm install api nginx-stable/nginx-ingress  
  --set controller.ingressClass=nginx-api \ 
  --set controller.service.type=NodePort \ 
  --set controller.service.httpPort.nodePort=30030 \ 
  --set controller.enablePreviewPolicies=true \ 
  --namespace nginx-api 

2. Ingress 매니페스트를 만듭니다.

5-ingress-api.yaml이라는 Ingress Controller 생성

apiVersion: k8s.nginx.org/v1 
kind: Policy 
metadata: 
  name: rate-limit-policy 
spec: 
  rateLimit: 
    rate: 10r/s 
    key: ${binary_remote_addr} 
    zoneSize: 10M 
--- 
apiVersion: k8s.nginx.org/v1 
kind: VirtualServer 
metadata: 
  name: api-vs 
spec: 
  ingressClassName: nginx-api 
  host: api.example.com 
  policies: 
  - name: rate-limit-policy 
  upstreams: 
  - name: api 
    service: api 
    port: 80 
  routes: 
  - path: / 
    action: 
      pass: api 

3. 새 매니페스트를 배포합니다.

kubectl apply -f 5-ingress-api.yaml 
ingress.networking.k8s.io/api created 

4-2. Locust 재구성

이제 Locust 실험을 반복합니다. 다음 두 가지 변경 사항을 확인할 수 있습니다.

  • Podinfo API가 오버로드되지 않습니다.
  • Podinfo API로 전송된 요청의 수와 상관없이 Podinfo Frontend에는 영향이 없습니다.
  1. Locust 스크립트를 다음과 같이 변경합니다.

Locust는 대시보드에서 단일 URL을 지원하므로 YAML 파일 6-locust.yaml을 사용하여 Python 스크립트의 값을 하드코딩합니다. 각 “작업”의 URL을 기록해 두십시오.

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(1) 
        def visit_website(self): 
            with self.client.get("http://web-nginx-ingress.nginx-web/", headers={"Host": "example.com", "User-Agent": "Mozilla"}, timeout=0.2, catch_response=True) as response: 
                if response.request_meta["response_time"] > 200: 
                    response.failure("Frontend failed") 
                else: 
                    response.success() 
  

        @task(5) 
        def visit_api(self): 
            with self.client.get("http://api-nginx-ingress.nginx-api/", headers={"Host": "api.example.com"}, timeout=0.2) as response: 
                if response.request_meta["response_time"] > 200: 
                    response.failure("API failed") 
                else: 
                    response.success() 
--- 
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. 스크립트 변경 구현:

새 YAML 파일을 제출하십시오. 스크립트가 변경되고(“구성됨”) 나머지는 변경되지 않은 상태로 남아 있음을 확인하는 이 출력을 얻어야 합니다.

kubectl apply -f 6-locust.yaml 
configmap/locust-script configured 
deployment.apps/locust unchanged 
service/locust unchanged 

3. 강제로 새로고침:

새 구성 맵을 강제로 다시 로드하려면 Locust 파드(Pod)을 삭제하십시오. 다음 명령은 동시에 Pod를 검색하고 Locust Pod를 삭제합니다. 여기에는 일부 Linux 명령과 파이프가 포함됩니다.

kubectl delete pod `kubectl get pods | grep locust | awk {'print $1'}` 

마지막으로 Pod를 검색하고 Locust가 다시 로드되었는지 확인합니다. Locust Pod 사용 기간이 불과 몇 초밖에 안 된 것을 볼 수 있습니다.

kubectl get pods 
NAME                        READY   STATUS    RESTARTS   AGE 
api-7574cf7568-jrlvd        1/1     Running   0          9m57s 
frontend-6688d86fc6-vd856   1/1     Running   0          9m57s 
locust-77c699c94d-6chsg     1/1     Running   0          6s 

4-3. 테스트 속도 제한 (Test Rate Limiting)

  1. Locust로 돌아가서 매개변수를 변경합니다.
  2. Start swarming 버튼을 클릭 하여 Podinfo 앱 및 API로 트래픽을 보냅니다.

사용자 수가 증가하기 시작하면 오류율도 증가하는 것을 볼 수 있습니다. 그러나 Locust UI에서 실패를 클릭하면 더 이상 웹 프론트엔드가 아니라 API 서비스에서 오는 것임을 알 수 있습니다. 또한 NGINX는 ‘서비스를 일시적으로 사용할 수 없음’ 메시지를 다시 제공하고 있습니다. 이것은 속도 제한 기능의 일부이며 사용자 지정할 수 있습니다. API는 속도가 제한되어 있으며 웹 애플리케이션은 항상 사용할 수 있습니다.