PrometheusとKEDAを使用したKubernetesアプリケーションの自動スケーリング

CimuanosのBalloonMan



スケーラビリティは、クラウドアプリケーションの重要な要件です。 Kubernetesを使用すると、アプリケーションのスケーリングは、適切な展開のためにレプリカの数を増やすのと同じくらい簡単ReplicaSetです。または、手動のプロセスです。



Kubernetesを使用すると、アプリケーションReplicaSetは、Horizo​​ntal Pod Autoscaler仕様を使用して、宣言的な方法で自動スケーリング(つまり、展開中のポッドまたはできます。自動スケーリングのデフォルトの基準はCPU使用率メト​​リック(リソースメトリック)ですが、カスタムメトリックと外部から提供されるメトリックを統合できます。 Mail.ruのKubernetesaaS



チーム外部メトリックを使用してKubernetesアプリケーションを自動的にスケーリングする方法に関する記事を翻訳しました。すべてがどのように機能するかを示すために、作成者はHTTPアクセス要求メトリックを使用し、Prometheusを使用して収集します。



水平ポッドを自動スケーリングする代わりに、Kubernetes Event Driven Autoscaling(KEDA)はオープンソースのKubernetesオペレーターです。水平ポッドオートスケーラーとネイティブに統合され、イベント駆動型ワークロードにスムーズな自動スケーリング(ゼロへ/ゼロからを含む)を提供します。コードはGitHubで入手できます



システム操作の概要







この図は、すべてがどのように機能するかについての簡単な説明を示しています。



  1. アプリケーションは、Prometheus形式でHTTPリクエストの数のメトリックを提供します。
  2. Prometheusは、これらのメトリックを収集するように設定されています。
  3. KEDAのPrometheusスケーラーは、HTTP要求の数に基づいてアプリケーションを自動的にスケーリングするように構成されています。


次に、各要素について詳しく説明します。



KEDAとプロメテウス



Prometheusは、Cloud Native Computing Foundationの一部である、オープンソースのシステム監視およびアラートツールキットです。さまざまなソースからメトリックを収集し、時系列データとして保存します。データを視覚化するには、GrafanaまたはKubernetesAPIと連携するその他の視覚化ツールを使用できます。



KEDAは、スケーラーの概念をサポートしています。これは、KEDAと外部システムの間のブリッジとして機能します。スケーラーの実装は各ターゲットシステムに固有であり、そこからデータを抽出します。次に、KEDAはそれらを使用して自動スケーリングを制御します。



スケーラーは、Kafka、Redis、Prometheusなどの複数のデータソースをサポートします。つまり、KEDAを使用して、Prometheusメトリックを基準として使用してKubernetesデプロイメントを自動的にスケーリングできます。



テストアプリケーション



GolangテストアプリケーションはHTTPアクセスを提供し、2つの重要な機能を提供します。



  1. Prometheus Goクライアントライブラリを使用してアプリケーションをインストルメント化し、ヒットカウンターを含むhttp_requestsメトリックを提供します。Prometheusメトリックを使用できるエンドポイントは、URIによって特定され/metricsます。



    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. 要求に応じて、GETアプリケーションaccess_countはRedisのキー(値をインクリメントしますこれは、HTTPハンドラーの一部としてジョブを実行し、Prometheusメトリックを確認する簡単な方法です。メトリック値はaccess_count、Redisの値と同じである必要があります



    func main() {
           http.Handle("/metrics", promhttp.Handler())
           http.HandleFunc("/test", func(w http.ResponseWriter, r 
    *http.Request) {
               defer httpRequestsCounter.Inc()
               count, err := client.Incr(redisCounterName).Result()
               if err != nil {
                   fmt.Println("Unable to increment redis counter", err)
                   os.Exit(1)
               }
               resp := "Accessed on " + time.Now().String() + "\nAccess count " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    


アプリはを介してKubernetesにデプロイされDeploymentます。ClusterIPPrometheusサーバーがアプリケーションメトリックを受信できるようにするサービスも作成されます。



これがアプリケーションのデプロイメントマニフェストです



プロメテウスサーバー



Prometheusデプロイメントマニフェストは次のもので構成されます。



  • ConfigMap -Prometheus構成を転送します。
  • Deployment --KubernetesクラスターにPrometheusをデプロイするため。
  • ClusterIP -UIPrometheusにアクセスするためのサービス。
  • ClusterRoleClusterRoleBindingおよびServiceAccount-Kubernetesでのサービスの自動検出(自動検出)用。


これがPrometheusを実行するためマニフェストです



KEDAプロメテウスScaledObject



スケーラーは、KEDAと、メトリックを取得する必要がある外部システムとの間のブリッジとして機能します。ScaledObjectカスタムリソースであるため、展開をイベントソース(この場合はPrometheus)と同期するために展開する必要があります。



ScaledObject展開スケーリング情報、イベントソースメタデータ(接続シークレット、キュー名など)、ポーリング間隔、回復期間、およびその他の情報が含まれます。これにより、展開をスケーリングするための適切な自動スケーリングリソース(HPA定義)が得られます。



オブジェクトScaledObjectが削除されると、対応するHPA定義がクリアされます。



これがこのScaledObjectの定義です。スケーラーを使用していますPrometheus



apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
 name: prometheus-scaledobject
 namespace: default
 labels:
   deploymentName: go-prom-app
spec:
 scaleTargetRef:
   deploymentName: go-prom-app
 pollingInterval: 15
 cooldownPeriod:  30
 minReplicaCount: 1
 maxReplicaCount: 10
 triggers:
 - type: prometheus
   metadata:
     serverAddress: 
http://prometheus-service.default.svc.cluster.local:9090
     metricName: access_frequency
     threshold: '3'
     query: sum(rate(http_requests[2m]))


次の点を考慮してください。



  1. Deploymentは名前で指してgo-prom-appます。
  2. トリガータイプ- PrometheusPrometheusサーバーのアドレスは、メトリック名、しきい値、および使用するPromQL要求とともに記載されています。PromQLクエリ- sum(rate(http_requests[2m]))
  3. pollingIntervalKEDAによると、15秒ごとにプロメテウスにターゲットを要求します。少なくとも1つのポッド(minReplicaCount)がサポートされており、ポッドの最大数はmaxReplicaCount(この例では10)を超えません


minReplicaCountゼロ に設定できます。この場合、KEDAは0対1の展開をアクティブにしてから、さらに自動スケーリングするためのHPAを提供します。逆の順序、つまり1から0へのスケーリングも可能です。この例では、これはHTTPサービスであり、オンデマンドのシステムではないため、ゼロを選択しませんでした。



自動スケーリング内の魔法



しきい値は、展開をスケーリングするためのトリガーとして使用されます。この例では、PromQLクエリsum(rate (http_requests [2m]))は、過去2分間に測定されたHTTPリクエストレート(1秒あたりのリクエスト数)の集計値を返します。



しきい値が3であるため、値が3sum(rate (http_requests [2m]))未満である限り、しきい値は1未満になります。値が増加すると、sum(rate (http_requests [2m]))3ずつ増加するたびにアンダーが追加されますたとえば、値が12〜14の場合、ポッドの数は4です。



それでは、構成してみましょう。



プリセット



必要なのは、Kubernetesクラスターとカスタマイズされたユーティリティだけkubectlです。この例ではクラスターを使用してminikubeいますが、他のクラスターを使用することもできます。クラスターをインストールするためのガイドがあります



Macに最新バージョンをインストールします。



curl -Lo minikube 
https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
&& chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/


kubectl インストールして、Kubernetesクラスターにアクセスします。



Macに最新バージョンをインストールします。



curl -LO 
"https://storage.googleapis.com/kubernetes-release/release/$(curl -s
https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version


KEDAのインストール



KEDAはいくつかの方法で展開できます。それらは、ドキュメントにリストされています私はモノリシックYAMLを使用しています:



kubectl apply -f
https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml


KEDAとそのコンポーネントは、名前空間にインストールされますkedaチェックするコマンド:



kubectl get pods -n keda


KEDAの下でオペレーターが起動したら、待ってください-に移動しRunning Stateます。そして続けます。



Helmを使用したRedisのインストール



Helmがインストールされていない場合は、このチュートリアルを使用してくださいMacにインストールするコマンド:



brew install kubernetes-helm
helm init --history-max 200


helm initローカルCLIを初期化Tillerし、Kubernetesクラスターにインストールします。



kubectl get pods -n kube-system | grep tiller


Tillerポッドが実行状態になるのを待ちます。



翻訳者注:著者はHelm @ 2を使用しており、Tillerサーバーコンポーネントをインストールする必要があります。Helm @ 3は現在関連しており、サーバー部分は必要ありません。



Helmをインストールした後、Redisを起動するには1つのコマンドで十分です。



helm install --name redis-server --set cluster.enabled=false --set 
usePassword=false stable/redis


Redisが正常に開始されたことを確認します。



kubectl get pods/redis-server-master-0


Redisの下が状態になるのを待ちRunningます。



アプリケーションをデプロイします



展開のためのコマンド:



kubectl apply -f go-app.yaml

//output
deployment.apps/go-prom-app created
service/go-prom-app-service created


すべてが開始されていることを確認します。



kubectl get pods -l=app=go-prom-app


Redisが状態に移行するのを待ちRunningます。



Prometheusサーバーの展開



Prometheus Manifestは、PrometheusにKubernetes ServiceDiscoveryを使用します。これにより、サービスラベルに基づいてアプリケーションポッドを動的に検出できます。



kubernetes_sd_configs:
   - role: service
   relabel_configs:
   - source_labels: [__meta_kubernetes_service_label_run]
     regex: go-prom-app-service
     action: keep


展開の場合:



kubectl apply -f prometheus.yaml

//output
clusterrole.rbac.authorization.k8s.io/prometheus created
serviceaccount/default configured
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
configmap/prom-conf created
deployment.extensions/prometheus-deployment created
service/prometheus-service created


すべてが開始されていることを確認します。



kubectl get pods -l=app=prometheus-server


プロメテウスの下で状態になるのを待ちRunningます。http:// localhost:9090にあるPrometheusユーザーインターフェイス(またはAPIサーバー)にアクセス



するkubectl port-forwardために使用します



kubectl port-forward service/prometheus-service 9090


KEDA自動スケーリング構成の展開



作成するコマンドScaledObject



kubectl apply -f keda-prometheus-scaledobject.yaml


KEDAオペレーターのログを確認してください。



KEDA_POD_NAME=$(kubectl get pods -n keda 
-o=jsonpath='{.items[0].metadata.name}')
kubectl logs $KEDA_POD_NAME -n keda


結果は次のようになります。



time="2019-10-15T09:38:28Z" level=info msg="Watching ScaledObject:
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="Created HPA with 
namespace default and name keda-hpa-go-prom-app"


アプリケーションの下で確認してください。1であるため、1つのインスタンスが実行されている必要がありますminReplicaCount



kubectl get pods -l=app=go-prom-app


HPAリソースが正常に作成されたことを確認します。



kubectl get hpa


次のようなものが表示されます。



NAME                   REFERENCE                TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (avg)   1         10        1          45s


ヘルスチェック:アプリケーションへのアクセス



アプリケーションのRESTエンドポイントにアクセスするには、次のコマンドを実行します。



kubectl port-forward service/go-prom-app-service 8080


これで、アドレスhttp:// localhost:8080を使用してGoアプリにアクセスできますこれを行うには、次のコマンドを実行します。



curl http://localhost:8080/test


結果は次のようになります。



Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Access count 1


この時点でもRedisを確認してください。キーがaccess_count1に増加していることがわかります



kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
"1"


メトリック値http_requestsが同じであることを確認してください



curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 1


負荷の作成



負荷を生成するユーティリティであるhey を使用します。



curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 
&& chmod a+x hey


LinuxまたはWindows 用のユーティリティをダウンロードすることもできます



それを実行します:



./hey http://localhost:8080/test


デフォルトでは、ユーティリティは200個の要求を送信します。これは、PrometheusメトリックとRedisを使用して確認できます。



curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201


実際のメトリック値を確認します(PromQLクエリによって返されます)。



curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'
//output
{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1571734214.228,"1.686057971014493"]}]}}


この場合、実際の結果は等しく1,686057971014493、フィールドに表示されますvalue設定したしきい値は3であるため、これはスケーリングには十分ではありません。



より多くの負荷!



新しいターミナルで、アプリケーションポッドの数を追跡します。



kubectl get pods -l=app=go-prom-app -w


次のコマンドを使用して負荷を増やしましょう。



./hey -n 2000 http://localhost:8080/test


しばらくすると、HPAが展開をスケーリングして新しいポッドを起動するのがわかります。HPAをチェックして、次のことを確認します。



kubectl get hpa
NAME                   REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (avg)   1         10        6          4m22s


負荷が一定でない場合、展開は1つのポッドのみが機能するポイントまで削減されます。実際のメトリック(PromQLクエリによって返される)を確認する場合は、次のコマンドを使用します。



curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'


クリーニング



//Delete KEDA
kubectl delete namespace keda
//Delete the app, Prometheus server and KEDA scaled object
kubectl delete -f .
//Delete Redis
helm del --purge redis-server


結論



KEDAを使用すると、外部メトリックからのデータに基づいて、Kubernetesデプロイメントを(ゼロから/に)自動的にスケーリングできます。たとえば、Prometheusメトリック、Redisのキューの長さ、Kafkaテーマの消費者の待ち時間に基づいています。



KEDAは外部ソースと統合し、Horizo​​ntal PodAutoscalerのメトリックサーバーを介してメトリックを提供します。



幸運を!



他に読むべきこと:



  1. 実稼働環境でコンテナとKubernetesを実行するためのベストプラクティスとガイドライン
  2. Kubernetesに役立つ90以上のツール:展開、管理、監視、セキュリティなど
  3. TelegramのKubernetes周辺のチャンネル



All Articles