APISIX、Prometheus、KEDAを使用してKubernetesでアプリケーションを弾力的にスケーリングする

Jintao Zhang

Jintao Zhang

February 17, 2023

Technology

はじめに

アプリケーションに入るトラフィック量は時とともに変化します。例えば、オンラインショッピングアプリケーションは、通常の日よりも休暇シーズンの方がはるかに忙しくなります。トラフィックに基づいてアプリケーションの容量を調整できるようになれば、ユーザー体験とサービスが大幅に向上します。

Apache APISIX は、アプリケーションのスケーリングが必要かどうかを判断するための有意義なメトリクスを提供できる高性能なクラウドネイティブAPIゲートウェイです。これは、アップストリームアプリケーションに送信されるすべてのトラフィックを処理するミドルウェアであり、その過程でトラフィックデータを収集することができます。

弾力的なスケーリングを実行するために、KEDAがコントローラーとして使用され、Prometheus がAPISIXによって提供されるメトリクスを取得するために使用されます。

KEDAを使用した自動スケーリング

KEDAでPrometheusスケーラーを使用する方法

KEDA はKubernetesのイベントベースのオートスケーラーで、さまざまなスケーラーを設定できます。この記事では、APISIXによって公開されたメトリクスを取得するためにPrometheusスケーラーを使用します。

KEDAのデプロイ

KEDAのデプロイは比較的簡単で、対応するHelmリポジトリを追加してインストールするだけです。

(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コントローラーではなく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を取得します: NOTE: 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プラグインを有効にします。具体的な設定方法と関連パラメータについては、以下の2つのドキュメントを参照してください。

有効にすると、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によって2つに自動拡張されていることがわかります。

(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の数が自動的に1インスタンスに縮小されていることがわかります。

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

まとめ

KEDAはPrometheusをスケーラーとして使用し、APISIX によって公開されたメトリクスを収集します。すべてのトラフィックが最初にAPISIXを通過するため、APISIX側で統計を取得する方がはるかに簡単で便利です。

ビジネスリクエストの量が増加すると、アプリケーションは自動的に拡張され、ビジネスリクエストの量が減少すると、アプリケーションは自動的に縮小されます。

この方法により、多くの本番環境での手動の拡張/縮小操作を軽減し、最高のユーザー体験を確保できます。

Tags: