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: