Kubernetes에서 APISIX, Prometheus, KEDA를 사용해 애플리케이션을 탄력적으로 확장하기

Jintao Zhang

Jintao Zhang

February 17, 2023

Technology

소개

애플리케이션으로 유입되는 트래픽의 양은 때에 따라 다릅니다. 예를 들어, 온라인 쇼핑 애플리케이션은 휴일 시즌에 평소보다 훨씬 더 바쁩니다. 트래픽에 따라 애플리케이션의 용량을 조정할 수 있다면 사용자 경험과 서비스를 훨씬 더 개선할 수 있습니다.

Apache APISIX는 애플리케이션의 확장이 필요한지 여부를 결정하는 데 유용한 메트릭을 제공할 수 있는 고성능 클라우드 네이티브 API 게이트웨이입니다. 이는 업스트림 애플리케이션으로 전송된 모든 트래픽을 처리하는 미들웨어이므로, 이 과정에서 트래픽 데이터를 수집할 수 있습니다.

탄력적 확장을 수행하기 위해 KEDA가 컨트롤러로 사용되며, Prometheus는 APISIX가 제공하는 메트릭을 가져오는 데 사용됩니다.

KEDA를 사용한 자동 확장

KEDA에서 Prometheus Scaler 사용 방법

KEDA는 Kubernetes에서 이벤트 기반의 오토스케일러로, 다양한 스케일러를 구성할 수 있습니다. 이 글에서는 Prometheus 스케일러를 사용하여 APISIX가 노출한 메트릭을 가져오는 방법을 설명합니다.

KEDA 배포

KEDA의 배포는 비교적 간단하며, 해당 Helm repo를 추가하고 설치하면 됩니다.

(MoeLove) ➜ helm repo add kedacore https://kedacore.github.io/charts
"kedacore"가 저장소에 추가되었습니다.
(MoeLove) ➜ helm repo update kedacore
차트 저장소에서 최신 정보를 가져오는 중입니다...
..."kedacore" 차트 저장소에서 성공적으로 업데이트를 가져왔습니다.
업데이트 완료. ⎈Happy Helming!⎈
(MoeLove) ➜ helm install keda kedacore/keda --namespace keda --create-namespace
NAME: keda
LAST DEPLOYED: Thu Jan 19 00:01:00 2023
NAMESPACE: keda
STATUS: deployed
REVISION: 1
TEST SUITE: None

설치 후, Pod의 상태Running이면 설치가 완료된 것입니다.

(MoeLove) ➜ kubectl -n keda get pods
NAME                                               READY   STATUS    RESTARTS   AGE
keda-operator-metrics-apiserver-6d4db7dcff-ck9qg   1/1     Running   0          36s
keda-operator-5dd4748dcd-k8jjz                     1/1     Running   0          36s

Prometheus 배포

여기서는 Prometheus Operator를 사용하여 Prometheus를 배포합니다. Prometheus Operator는 Kubernetes에서 Prometheus 인스턴스를 빠르게 배포하고 선언적 구성을 통해 모니터링 규칙을 추가할 수 있게 도와줍니다.

다음 단계를 통해 Prometheus Operator의 설치를 완료합니다.

(MoeLove) ➜ https://github.com/prometheus-operator/prometheus-operator/releases/download/v0.62.0/bundle.yaml
(MoeLove) ➜ kubectl apply --server-side -f bundle.yaml
customresourcedefinition.apiextensions.k8s.io/alertmanagerconfigs.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/alertmanagers.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/podmonitors.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/probes.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/prometheuses.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/prometheusrules.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/servicemonitors.monitoring.coreos.com serverside-applied
customresourcedefinition.apiextensions.k8s.io/thanosrulers.monitoring.coreos.com serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/prometheus-operator serverside-applied
clusterrole.rbac.authorization.k8s.io/prometheus-operator serverside-applied
deployment.apps/prometheus-operator serverside-applied
serviceaccount/prometheus-operator serverside-applied
service/prometheus-operator serverside-applied

그런 다음 Prometheus의 구성으로 다음을 사용하고 Kubernetes 클러스터에 적용합니다.

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/metrics
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
  - configmaps
  verbs: ["get"]
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: default
---
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
spec:
  serviceAccountName: prometheus
  serviceMonitorSelector:
    matchLabels:
      app: apisix
  serviceMonitorNamespaceSelector:
    matchLabels:
      team: apisix
  resources:
    requests:
      memory: 400Mi
  enableAdminAPI: false
---
apiVersion: v1
kind: Service
metadata:
  name: prometheus
spec:
  type: LoadBalancer
  ports:
  - name: web
    port: 9090
    protocol: TCP
    targetPort: web
  selector:
    prometheus: prometheus

Kubernetes 클러스터에 적용한 후, default 네임스페이스 아래에 Prometheus 인스턴스가 생성된 것을 확인할 수 있습니다. Prometheus를 TYPE LoadBalancer로 구성했기 때문에, 사용자는 LoadBalancer의 공용 IP를 통해 Prometheus에 직접 접근할 수 있습니다.

(MoeLove) ➜ kubectl get svc
NAME                  TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)          AGE
kubernetes            ClusterIP      10.43.0.1       <none>         443/TCP          96m
prometheus-operator   ClusterIP      None            <none>         8080/TCP         92m
prometheus-operated   ClusterIP      None            <none>         9090/TCP         41m
prometheus            LoadBalancer   10.43.125.194   216.6.66.66    9090:30099/TCP   41m

API 게이트웨이 배포 및 모니터링 활성화 방법

다음으로, APISIX Ingress 컨트롤러를 배포하고 Prometheus를 사용하여 메트릭을 수집합니다.

APISIX Ingress Controller 대신 APISIX만 사용하는 사용자도 방법은 유사합니다. 여기서는 별도로 설명하지 않겠습니다.

여기서는 Helm을 사용하여 배포하며, APISIX Ingress 컨트롤러와 APISIX를 동시에 클러스터에 배포할 수 있습니다.

(MoeLove) ➜ helm repo add apisix https://charts.apiseven.com
"apisix"가 이미 동일한 구성으로 존재하므로 건너뜁니다.
(MoeLove) ➜ helm repo update apisix
차트 저장소에서 최신 정보를 가져오는 중입니다...
..."apisix" 차트 저장소에서 성공적으로 업데이트를 가져왔습니다.
업데이트 완료. ⎈Happy Helming!⎈
(MoeLove) ➜ helm upgrade --install apisix apisix/apisix --create-namespace  --namespace apisix --set gateway.type=LoadBalancer --set ingress-controller.enabled=true --set ingress-controller.config.apisix.serviceNamespace=apisix
Release "apisix"가 업그레이드되었습니다. Happy Helming!
NAME: apisix
LAST DEPLOYED: Thu Jan 19 02:11:23 2023
NAMESPACE: apisix
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. 다음 명령어를 실행하여 애플리케이션 URL을 가져옵니다:
     참고: LoadBalancer IP가 사용 가능해지기까지 몇 분이 걸릴 수 있습니다.
           'kubectl get --namespace apisix svc -w apisix-gateway'를 실행하여 상태를 확인할 수 있습니다.
  export SERVICE_IP=$(kubectl get svc --namespace apisix apisix-gateway --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
  echo http://$SERVICE_IP:80

다음으로, APISIX의 Prometheus 플러그인을 활성화합니다. 구체적인 구성 방법과 관련 매개변수는 다음 두 문서를 참조하십시오.

활성화되면, Prometheus는 ServiceMonitor 리소스를 생성하여 APISIX가 노출한 메트릭을 캡처할 수 있습니다.

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: example-app
  labels:
    app: apisix
spec:
  selector:
    matchLabels:
      app: apisix
  endpoints:
  - port: web

애플리케이션의 탄력적 확장 기능 검증

먼저 애플리케이션을 생성합니다.

(MoeLove) ➜ kubectl create deploy httpbin --image=kennethreitz/httpbin --port=80
deployment.apps/httpbin created
(MoeLove) ➜ kubectl expose deploy httpbin --port 80

다음 라우팅 규칙을 생성하고 Kubernetes 클러스터에 적용하여 APISIX를 통해 요청을 프록시합니다.

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - local.httpbin.org
      paths:
      - /*
    backends:
       - serviceName: httpbin
         servicePort: 80

다음으로, KEDA ScaledObject를 생성하고 Prometheus 관련 구성을 설정합니다.

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: prometheus-scaledobject
  namespace: default
spec:
  scaleTargetRef:
    name: httpbin
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus.default.svc:9090
      metricName: apisix_http_status
      threshold: '10'
      query: sum(rate(apisix_http_status{route="httpserver-route"}[1m]))

위 구성은 sum(rate(apisix_http_status{route="httpserver-route"}[1m]))를 쿼리 표현식으로 사용하며, 결과가 10에 도달하면 확장이 시작된다는 의미입니다. (여기서의 구성은 데모용이며, 실제 상황에 맞게 수정하십시오). 그런 다음, curl을 통해 httpbin 서비스에 지속적으로 요청을 보냅니다.

이후 애플리케이션 Pod를 확인하면 KEDA에 의해 두 개로 확장된 것을 확인할 수 있습니다.

(MoeLove) ➜ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
httpbin-d46d778d7-chtdw   1/1     Running   0          12m
httpbin-d46d778d7-xanbj   1/1     Running   0          10s

일정 시간 후 애플리케이션이 유휴 상태가 되면, Pod 수가 자동으로 하나의 인스턴스로 축소된 것을 확인할 수 있습니다.

(MoeLove) ➜ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
httpbin-d46d778d7-chtdw   1/1     Running   0          32m

요약

KEDA는 Prometheus를 스케일러로 사용하여 APISIX가 노출한 메트릭을 수집합니다. 모든 트래픽이 APISIX를 먼저 통과하기 때문에, APISIX 측에서 통계를 얻는 것이 훨씬 더 간단하고 편리합니다.

비즈니스 요청량이 증가하면 애플리케이션이 자동으로 확장되고, 비즈니스 요청량이 감소하면 애플리케이션이 자동으로 축소됩니다.

이 방법은 많은 프로덕션 환경에서 수동 확장/축소 작업을 완화하여 최상의 사용자 경험을 보장할 수 있습니다.

Tags: