DigitalOcean Kubernetesでワークロードを自動スケーリングする方法

前書き

Kubernetesで構築されたアプリケーションを使用する場合、開発者は、トラフィックのピーク時や負荷処理の増加を処理するために、追加のpodsをスケジュールする必要があります。 デフォルトでは、これらの追加ポッドのスケジュールは手動の手順です。開発者は、トラフィックの増加に対応するために、deployment object内の必要なreplicasの数を変更し、追加のポッドが不要になったら元に戻す必要があります。 手動介入へのこの依存は、多くのシナリオで理想的とは言えません。 たとえば、誰も目を覚ましてポッドのスケーリングを行っていない夜中にワークロードがピーク時間に達する可能性があります。また、手動応答では負荷に十分に対応できない場合、Webサイトで予期しないトラフィックの増加が発生する可能性があります。 このような状況で、最も効率的でエラーが発生しにくいアプローチは、Horizontal Pod Autoscaler (HPA)を使用してクラスターのスケーリングを自動化することです。

Metrics Serverからの情報を使用することにより、HPAはリソース使用量の増加を検出し、ワークロードをスケーリングすることで対応します。 これは特にマイクロサービスアーキテクチャで役立ち、KubernetesクラスターがCPU使用率などのメトリックに基づいて展開をスケーリングできるようになります。 コンテナ化されたアプリケーションをデプロイするためのプラットフォームを開発者に提供するマネージドKubernetesオファリングであるDigitalOcean Kubernetes (DOKS)と組み合わせると、HPAを使用して、トラフィックと負荷の変化にすばやく適応する自動インフラストラクチャを作成できます。

[。注意]##

Note:ワークロードに自動スケーリングを使用するかどうかを検討する場合、自動スケーリングはステートレスアプリケーション、特にアプリケーションの複数のインスタンスを実行してトラフィックを並行して受け入れることができるアプリケーションに最適であることに注意してください。 自動スケーリングの主な目的は、アプリケーションのワークロードをKubernetesクラスター内の複数のインスタンスに動的に分散し、単一のインスタンスを過負荷にすることなく、タイムリーかつ安定した方法でアプリケーションがトラフィックを処理するのに必要なリソースを確保することであるため、この並列処理は重要です

この並列性を示さないワークロードの例は、データベースの自動スケーリングです。 競合状態、データの整合性の問題、データの同期、データベースクラスターメンバーの継続的な追加と削除を考慮する必要があるため、データベースの自動スケーリングの設定は非常に複雑になります。 このような理由から、このチュートリアルのデータベースの自動スケーリング戦略を使用することはお勧めしません。

このチュートリアルでは、CPU負荷の増加に対応するために水平方向に自動スケーリングできるDOKSでのサンプルNginxデプロイメントをセットアップします。 これを実現するには、Metrics Serverをクラスターにデプロイして、HPAがスケーリングのタイミングを決定するときに使用するポッドメトリックを収集します。

前提条件

このガイドを始める前に、次のものが必要です。

  • 接続がkubectlのデフォルトとして構成されたDigitalOceanKubernetesクラスター。 kubectlを構成する方法の説明は、クラスターを作成するときのConnect to your Clusterステップの下に表示されます。 DigitalOceanでKubernetesクラスターを作成するには、Kubernetes Quickstartを参照してください。

  • ローカルマシンにインストールされたHelmパッケージマネージャー、およびクラスターにインストールされたTiller。 これを行うには、How To Install Software on Kubernetes Clusters with the Helm Package Managerチュートリアルのステップ1と2を完了します。

[[step-1 -—- creating-a-test-deployment]] ==ステップ1—テストデプロイメントの作成

HPAの効果を示すために、最初にオートスケールに使用するアプリケーションをデプロイします。 このチュートリアルでは、標準のNginx Docker imageをデプロイとして使用します。これは、並列で完全に動作でき、Nginx Ingress Controllerなどのツールを使用してKubernetes内で広く使用されており、セットアップが軽量であるためです。 このNginxデプロイメントは、ベースイメージに標準で付属する静的なWelcome to Nginx!ページを提供します。 既に展開を行っている場合は、その展開を自由に使用して、この手順をスキップしてください。

次のコマンドを発行して、Nginxベースイメージを使用してサンプル展開を作成します。 デプロイメントに別の名前を付けたい場合は、名前webを置き換えることができます。

kubectl create deployment web --image=nginx:latest

--image=nginx:latestフラグは、最新バージョンのNginxベースイメージからデプロイメントを作成します。

数秒後、webポッドが回転します。 このポッドを表示するには、次のコマンドを実行します。これにより、現在のネームスペースで実行されているポッドが表示されます。

kubectl get pods

これにより、次のような出力が得られます。

OutputNAME                                                   READY   STATUS             RESTARTS   AGE
web-84d7787df5-btf9h                                   1/1     Running            0          11s

元々デプロイされているポッドは1つだけであることに注意してください。 自動スケーリングがトリガーされると、より多くのポッドが自動的にスピンアップします。

これで、クラスター内で基本的な展開が実行されました。 これは、自動スケーリング用に構成する展開です。 次のステップは、このデプロイメントを構成して、リソース要求と制限を定義することです。

[[step-2 -—- setting-cpu-limits-and-requests-on-your-deployment]] ==ステップ2—デプロイメントでのCPU制限とリクエストの設定

このステップでは、デプロイメントのCPU使用率にrequests and limitsを設定します。 KubernetesのLimitsは、ポッドが使用できるリソース(CPUまたはメモリ)の最大量を表すためにデプロイに設定されます。 Requestsはデプロイメントに設定され、そのノードがスケジューリングの有効なノードと見なされるために、そのノードで必要なリソースの量を記述します。 たとえば、Webサーバーのメモリ要求が1GBに設定されている場合、少なくとも1GBの空きメモリがあるノードのみがスケジューリングの対象になります。 自動スケーリングの場合、スケーリングとスケジューリングの決定を行う際にHPAがこの情報を必要とするため、これらの制限と要求を設定する必要があります。

要求と制限を設定するには、作成したデプロイメントに変更を加える必要があります。 このチュートリアルでは、次のkubectl editコマンドを使用して、クラスターに格納されているAPIオブジェクト構成を変更します。 kubectl editコマンドは、KUBE_EDITORまたはEDITOR環境変数で定義されたエディターを開くか、Windowsの場合はデフォルトでvi for Linuxまたはnotepadにフォールバックします。

展開を編集します。

kubectl edit deployment web

展開の構成が表示されます。 デプロイメントのCPU使用率に指定されたリソース制限とリクエストを設定できるようになりました。 これらの制限により、この展開のポッドが個別に使用できる各リソースの量のベースラインが設定されます。 これを設定すると、ポッドが酷使されているかどうかを知るための参照フレームがHPAに与えられます。 たとえば、ポッドのCPUの上限limitが100ミリコアであり、ポッドが現在95ミリコアを使用している場合、HPAは95%の容量であることを認識します。 100ミリコアという制限を設けないと、HPAはポッドの全容量を解読できません。

resourcesセクションで制限とリクエストを設定できます。

展開構成ファイル

. . .
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: nginx:latest
        imagePullPolicy: Always
        name: nginx
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
. . .

このチュートリアルでは、CPUのrequests100mに設定し、メモリを250Miに設定します。 これらの値は、デモンストレーションを目的としています。すべてのワークロードは異なるため、これらの値は他のワークロードには意味がない場合があります。 一般的なルールとして、これらの値は、このワークロードのポッドが使用すると予想される最大値に設定する必要があります。 これらの値を決定するには、アプリケーションを監視し、低い時間とピーク時間でのアプリケーションのパフォーマンスに関するリソース使用状況データを収集することをお勧めします。 これらの値はいつでも調整および変更できるため、いつでも戻ってデプロイメントを最適化できます。

先に進み、Nginxコンテナのresourcesセクションの下に次の強調表示された行を挿入します。

展開構成ファイル

. . .
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web
    spec:
      containers:
      - image: nginx:latest
        imagePullPolicy: Always
        name: nginx
        resources:
          limits:
            cpu: 300m
          requests:
            cpu: 100m
            memory: 250Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
. . .

これらの行を挿入したら、ファイルを保存して終了します。 構文に問題がある場合、kubectlはファイルを再度開き、詳細についてはエラーが投稿されます。

制限とリクエストを設定したら、HPAがこれらの制限を監視して正しく遵守できるように、メトリックが収集されていることを確認する必要があります。 これを行うには、CPUメトリックを収集するサービスを設定します。 このチュートリアルでは、Metrics Serverプロジェクトを使用してこれらのメトリックを収集し、Helmチャートとともにインストールします。

[[step-3 -—- installing-metrics-server]] ==ステップ3—Metricsサーバーのインストール

次に、Kubernetes Metric Serverをインストールします。 これは、ポッドメトリックをスクレイピングするサーバーであり、HPAが自動スケーリングが必要かどうかを判断するために使用するメトリックを収集します。

Helmを使用してMetrics Serverをインストールするには、次のコマンドを実行します。

helm install stable/metrics-server --name metrics-server

これにより、Metrics Serverの最新の安定バージョンがインストールされます。 --nameフラグは、このリリースにmetrics-serverという名前を付けます。

このポッドが初期化されるのを待ったら、kubectl top podコマンドを使用してポッドのメトリックを表示してみてください。

kubectl top pod

このコマンドは、クラスター内のリソース使用量をポッドレベルで表示することを目的としていますが、DOKSがDNSを処理する方法のため、このコマンドはこの時点でエラーを返します。

OutputError: Metrics not available for pod

Error from server (ServiceUnavailable): the server is currently unable to handle the request (get pods.metrics.k8s.io)

このエラーは、DOKSノードが自身のDNSレコードを作成せず、Metrics Serverがホスト名を介してノードに接続するため、ホスト名が適切に解決されないために発生します。 この問題を修正するには、次のコマンドを使用してMetrics Serverコンテナにランタイムフラグを追加して、Metrics Serverがノードと通信する方法を変更します。

kubectl edit deployment metrics-server

commandセクションの下にフラグを追加します。

メトリックサーバー構成ファイル

. . .
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: metrics-server
        release: metrics-server
    spec:
      affinity: {}
      containers:
      - command:
        - /metrics-server
        - --cert-dir=/tmp
        - --logtostderr
        - --secure-port=8443
        image: gcr.io/google_containers/metrics-server-amd64:v0.3.4
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
. . .

追加するフラグは--kubelet-preferred-address-types=InternalIPです。 このフラグは、ホスト名ではなくinternalIPを使用してノードに接続するようにメトリックサーバーに指示します。 このフラグを回避策として使用して、内部IPアドレスを介してノードと通信できます。

また、--metric-resolutionフラグを追加して、メトリクスサーバーがメトリクスをスクレイプするデフォルトのレートを変更します。 このチュートリアルでは、60sごとにデータポイントを作成するようにMetrics Serverを設定しますが、より多くのメトリックスデータが必要な場合は、10sまたは20sごとにメトリックスをスクレイプするようにMetricsServerに要求できます。 s。 これにより、期間ごとのリソース使用量のデータポイントが増えます。 ニーズに合わせてこの解像度を自由に微調整してください。

次の強調表示された行をファイルに追加します。

メトリックサーバー構成ファイル

. . .
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: metrics-server
        release: metrics-server
    spec:
      affinity: {}
      containers:
      - command:
        - /metrics-server
        - --cert-dir=/tmp
        - --logtostderr
        - --secure-port=8443
        - --metric-resolution=60s
        - --kubelet-preferred-address-types=InternalIP
        image: gcr.io/google_containers/metrics-server-amd64:v0.3.4
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3
          httpGet:
            path: /healthz
. . .

フラグを追加したら、エディターを保存して終了します。

Metrics Serverが実行されていることを確認するには、数分後にkubectl top podを使用します。 前と同様に、このコマンドはポッドレベルでのリソース使用量を提供します。 今回は、稼働中のメトリックサーバーにより、各ポッドのメトリックを表示できます。

kubectl top pod

これにより、Metrics Serverポッドが実行された状態で、次の出力が得られます。

OutputNAME                             CPU(cores)   MEMORY(bytes)
metrics-server-db745fcd5-v8gv6   3m           12Mi
web-555db5bf6b-f7btr             0m           2Mi

これで、機能的なMetricsサーバーができ、クラスター内のポッドのリソース使用量を表示および監視できるようになりました。 次に、このデータを監視し、CPU使用率が高い期間に対応するようにHPAを構成します。

[[step-4 -—-水平ポッドオートスケーラーの作成と検証]] ==ステップ4—水平ポッドオートスケーラーの作成と検証

最後に、展開用の水平ポッドオートスケーラー(HPA)を作成します。 HPAは、Metrics Serverから収集されたCPU使用率データを定期的にチェックし、ステップ2で設定したしきい値に基づいて展開をスケーリングする実際のKubernetesオブジェクトです。

kubectl autoscaleコマンドを使用してHPAを作成します。

kubectl autoscale deployment web  --max=4 --cpu-percent=80

このコマンドは、webデプロイメントのHPAを作成します。 また、--maxフラグを使用して、webをスケーリングできる最大レプリカを設定します。この場合は4として設定します。

--cpu-percentフラグは、ステップ2で設定した制限の使用率でオートスケールをトリガーすることをHPAに通知します。 これは、リクエストを使用して、スケールアップされたポッドを初期リソース割り当てに対応できるノードにスケジュールするのにも役立ちます。 この例では、手順1で展開に設定した制限が100ミリコア(100m)の場合、ポッドが平均CPU使用率で80mに達すると、このコマンドは自動スケールをトリガーします。 これにより、展開はCPUリソースを使い果たす前に自動スケーリングできます。

展開が自動的にスケーリングできるようになったので、次はこれをテストします。

検証するには、クラスターをしきい値を超える負荷を生成し、オートスケーラーが引き継ぐのを監視します。 開始するには、2番目のターミナルを開いて、現在スケジュールされているポッドを監視し、2秒ごとにポッドのリストを更新します。 これを実行するには、次の2番目の端末でwatchコマンドを使用します。

watch "kubectl top pods"

watchコマンドは、引数として指定されたコマンドを継続的に発行し、端末に出力を表示します。 繰り返し間の期間は、-nフラグを使用してさらに構成できます。 このチュートリアルでは、デフォルトの2秒の設定で十分です。

端末は最初にkubectl top podsの出力を表示し、その後2秒ごとに、そのコマンドが生成する出力を更新します。これは次のようになります。

OutputEvery 2.0s: kubectl top pods

NAME                              CPU(cores)   MEMORY(bytes)
metrics-server-6fd5457684-7kqtz   3m           15Mi
web-7476bb659d-q5bjv              0m           2Mi

webに現在デプロイされているポッドの数に注意してください。

元の端末に切り替えます。 ここで、kubectl execを使用して現在のwebポッド内のターミナルを開き、人工的な負荷を作成します。 これは、ポッドに移動してstress CLI toolをインストールすることで実現できます。

kubectl execを使用してポッドを入力し、強調表示されたポッド名をwebポッドの名前に置き換えます。

kubectl exec -it web-f765fd676-s9729 /bin/bash

このコマンドの概念は、sshを使用して別のマシンにログインするのと非常に似ています。 /bin/bashは、ポッドにbashシェルを確立します。

次に、ポッド内のbashシェルから、リポジトリメタデータを更新し、stressパッケージをインストールします。

apt update; apt-get install -y stress

[。注意]##

Note: CentOSベースのコンテナーの場合、これは次のようになります。

yum install -y stress

次に、stressコマンドを使用してポッドにCPU負荷を生成し、実行させます。

stress -c 3

次に、2番目のターミナルでwatchコマンドに戻ります。 Metrics ServerがHPAの定義済みのしきい値を超えるCPUデータを収集するまで数分待ちます。 メトリックは、デフォルトで、メトリックサーバーの構成時に--metric-resolutionを等しく設定したレートで収集されることに注意してください。 使用メトリックが更新されるまで、1分程度かかる場合があります。

約2分後、追加のwebポッドがスピンアップします。

OutputEvery 2.0s: kubectl top pods

NAME                             CPU(cores)   MEMORY(bytes)
metrics-server-db745fcd5-v8gv6   6m           16Mi
web-555db5bf6b-ck98q             0m           2Mi
web-555db5bf6b-f7btr             494m         21Mi
web-555db5bf6b-h5cbx             0m           1Mi
web-555db5bf6b-pvh9f             0m           2Mi

これで、HPAがMetrics Serverによって収集されたCPU負荷に基づいて新しいポッドをスケジュールしたことがわかります。 この検証に満足したら、CTRL+Cを使用して最初のターミナルでstressコマンドを停止し、ポッドのbashシェルを終了します。

結論

この記事では、CPU負荷に基づいて自動スケーリングするデプロイメントを作成しました。 CPUリソースの制限とリクエストをデプロイメントに追加し、Helmを使用してクラスターにMetrics Serverをインストールおよび構成し、スケーリングの決定を行うためにHPAを作成しました。

これは、Metrics ServerとHPAの両方のデモ展開です。 これで、特定のユースケースに合わせて構成を調整できます。 requests and limitationsのヘルプと情報については、必ずKubernetes HPAのドキュメントを調べてください。 また、Metrics Server projectを確認して、ユースケースに適用される可能性のあるすべての調整可能な設定を確認してください。

Kubernetesをさらに活用したい場合は、Kubernetes Community pageにアクセスするか、Managed Kubernetes serviceを調べてください。

Related