指標に基づいて Pod の自動スケーリングを最適化する

このチュートリアルでは、Cloud Monitoring から取得できる指標に基づいて Google Kubernetes Engine(GKE)ワークロードを自動的にスケーリングする方法を説明します。

このチュートリアルでは、次のいずれかの指標に基づいて自動スケーリングを設定します。

Pub/Sub

Pub/Sub バックログ

Pub/Sub サブスクリプションに残っている未確認のメッセージ数を報告する外部指標に基づいてスケーリングします。問題が発生する前にレイテンシを効果的に削減できますが、CPU 使用率に基づく自動スケーリングよりも多くのリソースが使用される可能性があります。

カスタム指標

Prometheus カスタム指標

Google Managed Prometheus を介して Prometheus 形式でエクスポートされたカスタム ユーザー定義指標に基づいてスケーリングします。Prometheus 指標のタイプは Gauge にする必要があります。

基本的に、自動スケーリングとは費用とレイテンシの許容可能なバランスを見つけるプロセスです。これらの指標と他の指標を組み合わせて試し、最適なポリシーを探してください。

カスタム指標アダプタのデプロイ

カスタム指標アダプタを使用すると、クラスタで Cloud Monitoring との指標の送受信を行うことができます。

Pub/Sub

カスタム指標アダプタをインストールする手順は、Workload Identity Federation for GKE を有効にしているクラスタと有効にしていないクラスタで異なります。クラスタを作成する際に選択した設定に合うオプションを選択します。

Workload Identity

必要な認可ロールを作成する権限をユーザーに付与します。

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

クラスタにカスタム指標アダプタをデプロイします。

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

このアダプタは、custom-metrics Namespace の custom-metrics-stackdriver-adapter Kubernetes サービス アカウントを使用します。モニタリング閲覧者ロールを割り当て、このサービス アカウントで Cloud Monitoring の指標を読み取ることを許可します。

gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
  --role roles/monitoring.viewer \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter

以前の認証

必要な認可ロールを作成する権限をユーザーに付与します。

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

クラスタにカスタム指標アダプタをデプロイします。

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

カスタム指標

カスタム指標アダプタをインストールする手順は、Workload Identity Federation for GKE を有効にしているクラスタと有効にしていないクラスタで異なります。クラスタを作成する際に選択した設定に合うオプションを選択します。

Workload Identity

必要な認可ロールを作成する権限をユーザーに付与します。

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

クラスタにカスタム指標アダプタをデプロイします。

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

このアダプタは、custom-metrics Namespace の custom-metrics-stackdriver-adapter Kubernetes サービス アカウントを使用します。モニタリング閲覧者ロールを割り当て、このサービス アカウントで Cloud Monitoring の指標を読み取ることを許可します。

gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
  --role roles/monitoring.viewer \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter

以前の認証

必要な認可ロールを作成する権限をユーザーに付与します。

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

クラスタにカスタム指標アダプタをデプロイします。

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

指標を使用したアプリケーションのデプロイ

このチュートリアルのアプリケーション コードを含むリポジトリをダウンロードします。

Pub/Sub

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/databases/cloud-pubsub

カスタム指標

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/observability/custom-metrics-autoscaling/google-managed-prometheus

リポジトリには、Cloud Monitoring に指標をエクスポートするコードが含まれています。

Pub/Sub

このアプリケーションは、Pub/Sub サブスクリプションをポーリングし、新しいメッセージの着信を確認します。Pub/Sub サブスクリプションの指標は Cloud Monitoring によって自動的に収集されます。

from google import auth
from google.cloud import pubsub_v1


def main():
    """Continuously pull messages from subsciption"""

    # read default project ID
    _, project_id = auth.default()
    subscription_id = 'echo-read'

    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(
        project_id, subscription_id)

    def callback(message: pubsub_v1.subscriber.message.Message) -> None:
        """Process received message"""
        print(f"Received message: ID={message.message_id} Data={message.data}")
        print(f"[{datetime.datetime.now()}] Processing: {message.message_id}")
        time.sleep(3)
        print(f"[{datetime.datetime.now()}] Processed: {message.message_id}")
        message.ack()

    streaming_pull_future = subscriber.subscribe(
        subscription_path, callback=callback)
    print(f"Pulling messages from {subscription_path}...")

    with subscriber:
        try:
            streaming_pull_future.result()
        except Exception as e:
            print(e)

カスタム指標

このアプリケーションは、Prometheus 形式を使用した定数値の指標で、/metrics パスへのウェブ リクエストに応答します。

metric := prometheus.NewGauge(
	prometheus.GaugeOpts{
		Name: *metricName,
		Help: "Custom metric",
	},
)
prometheus.MustRegister(metric)
metric.Set(float64(*metricValue))

http.Handle("/metrics", promhttp.Handler())
log.Printf("Starting to listen on :%d", *port)
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)

リポジトリには、アプリケーションをクラスタにデプロイするための Kubernetes マニフェストも含まれています。Deployment は、クラスタ内のノードに分散された Pod の複数のレプリカを実行できる Kubernetes API オブジェクトです。

Pub/Sub

マニフェストは、Workload Identity Federation for GKE を有効にしているクラスタと有効にしていないクラスタで異なります。クラスタを作成する際に選択した設定に合うオプションを選択します。

Workload Identity

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      serviceAccountName: pubsub-sa
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2

以前の認証

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      volumes:
      - name: google-cloud-key
        secret:
          secretName: pubsub-key
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2
        volumeMounts:
        - name: google-cloud-key
          mountPath: /var/secrets/google
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/secrets/google/key.json

カスタム指標

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: custom-metrics-gmp
  name: custom-metrics-gmp
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      run: custom-metrics-gmp
  template:
    metadata:
      labels:
        run: custom-metrics-gmp
    spec:
      containers:
      # sample container generating custom metrics
      - name: prometheus-dummy-exporter
        image: us-docker.pkg.dev/google-samples/containers/gke/prometheus-dummy-exporter:v0.2.0
        command: ["./prometheus-dummy-exporter"]
        args:
        - --metric-name=custom_prometheus
        - --metric-value=40
        - --port=8080

PodMonitoring リソースを使用して、Google Cloud Managed Service for Prometheus は Prometheus 指標を Cloud Monitoring にエクスポートします。

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: "custom-metrics-exporter"
spec:
  selector:
    matchLabels:
      run: custom-metrics-gmp
  endpoints:
  - port: 8080
    path: /metrics
    interval: 15s

GKE Standard バージョン 1.27 以降または GKE Autopilot バージョン 1.25 以降では、Google Cloud Managed Service for Prometheus が有効になっています。以前のバージョンのクラスタで Google Cloud Managed Service for Prometheus を有効にするには、マネージド コレクションを有効にするをご覧ください。

アプリケーションをクラスタにデプロイします。

Pub/Sub

アプリケーションのデプロイ手順は、Workload Identity Federation for GKE が有効になっているクラスタと有効になっていない場合で異なります。クラスタを作成する際に選択した設定に合うオプションを選択します。

Workload Identity

  1. プロジェクトで Pub/Sub API を有効にします。

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. Pub/Sub トピックとサブスクリプションを作成します。

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. アプリケーションをクラスタにデプロイします。

    kubectl apply -f deployment/pubsub-with-workload-identity.yaml
    
  4. このアプリケーションは、pubsub-sa Kubernetes サービス アカウントを定義します。アプリケーションが Pub/Sub トピックにメッセージを公開できるように、Pub/Sub サブスクライバーのロールを割り当てます。

    gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
      --role=roles/pubsub.subscriber \
      --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/default/sa/pubsub-sa
    

    上記のコマンドは、IAM が Kubernetes サービス アカウントを直接参照できるようにするプリンシパル識別子を使用します。

    ベスト プラクティス:

    プリンシパル識別子を使用しますが、代替方法の説明の制限を考慮してください。

以前の認証

  1. プロジェクトで Pub/Sub API を有効にします。

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. Pub/Sub トピックとサブスクリプションを作成します。

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. Pub/Sub にアクセスできるサービス アカウントを作成します。

    gcloud iam service-accounts create autoscaling-pubsub-sa
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member "serviceAccount:autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/pubsub.subscriber"
    
  4. サービス アカウント キー ファイルをダウンロードします。

    gcloud iam service-accounts keys create key.json \
      --iam-account autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com
    
  5. サービス アカウント キーを Secret としてクラスタにインポートします。

    kubectl create secret generic pubsub-key --from-file=key.json=./key.json
    
  6. アプリケーションをクラスタにデプロイします。

    kubectl apply -f deployment/pubsub-with-secret.yaml
    

カスタム指標

kubectl apply -f custom-metrics-gmp.yaml

アプリケーションがデプロイされるまで待ちます。デプロイされると、すべての Pod が Ready 状態になります。

Pub/Sub

kubectl get pods

出力:

NAME                     READY   STATUS    RESTARTS   AGE
pubsub-8cd995d7c-bdhqz   1/1     Running   0          58s

カスタム指標

kubectl get pods

出力:

NAME                                  READY   STATUS    RESTARTS   AGE
custom-metrics-gmp-865dffdff9-x2cg9   1/1     Running   0          49s

Cloud Monitoring での指標の表示

アプリケーションを実行すると、Cloud Monitoring に指標が書き込まれます。

Metrics Explorer を使用してモニタリング対象リソースの指標を表示するには、次の操作を行います。

  1. Google Cloud コンソールで [Metrics explorer] のページに移動します。

    [Metrics Explorer] に移動

    検索バーを使用してこのページを検索する場合は、小見出しが [Monitoring] の結果を選択します。

  2. [指標] 要素で [指標を選択] メニューを開き、リソースタイプと指標タイプを選択します。たとえば、仮想マシンの CPU 使用率をグラフ化する手順は次のとおりです。
    1. (省略可)メニューのオプションを減らすには、フィルタバーに指標名の一部を入力します。この例では、「utilization」と入力します。
    2. [有効なリソース] メニューで、[VM インスタンス] を選択します。
    3. [有効な指標カテゴリ] メニューで、[インスタンス] を選択します。
    4. [有効な指標] メニューで [CPU utilization] を選択し、[適用] をクリックします。
  3. 表示される時系列をフィルタするには、[フィルタ] 要素を使用します。

  4. 時系列を結合するには、[集計] 要素のメニューを使用します。たとえば、ゾーンに基づいて VM の CPU 使用率を表示するには、最初のメニューを [平均] に設定し、2 番目のメニューを [ゾーン] に設定します。

    [集計] 要素の最初のメニューが [未集計] になっている場合は、すべての時系列が表示されます。[集計] 要素のデフォルトは、選択した指標タイプによって決まります。

リソースタイプと指標は次のとおりです。

Pub/Sub

Metrics Explorer

Resource type: pubsub_subscription

Metric: pubsub.googleapis.com/subscription/num_undelivered_messages

カスタム指標

Metrics Explorer

Resource type: prometheus_target

Metric: prometheus.googleapis.com/custom_prometheus/gauge

指標によっては、多くのアクティビティが Cloud Monitoring Metrics Explorer に表示されていないことがあります。指標が更新されていなくても気にしないでください。

HorizontalPodAutoscaler オブジェクトの作成

Cloud Monitoring に指標が表示されたら、HorizontalPodAutoscaler をデプロイして、指標に基づいて Deployment のサイズを変更できます。

Pub/Sub

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: pubsub
spec:
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - external:
      metric:
       name: pubsub.googleapis.com|subscription|num_undelivered_messages
       selector:
         matchLabels:
           resource.labels.subscription_id: echo-read
      target:
        type: AverageValue
        averageValue: 2
    type: External
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: pubsub

カスタム指標

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: custom-metrics-gmp-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: custom-metrics-gmp
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Pods
    pods:
      metric:
        name: prometheus.googleapis.com|custom_prometheus|gauge
      target:
        type: AverageValue
        averageValue: 20

HorizontalPodAutoscaler をクラスタにデプロイします。

Pub/Sub

kubectl apply -f deployment/pubsub-hpa.yaml

カスタム指標

kubectl apply -f custom-metrics-gmp-hpa.yaml

負荷の生成

指標によっては、自動スケーリングを確認するために負荷の生成が必要になることがあります。

Pub/Sub

Pub/Sub トピックに 200 件のメッセージを公開します。

for i in {1..200}; do gcloud pubsub topics publish echo --message="Autoscaling #${i}"; done

カスタム指標

なし: このサンプルで使用されているコードは、カスタム指標の定数値 40 をエクスポートします。HorizontalPodAutoscaler が 20 のターゲット値で設定されているため、Deployment が自動的にスケールアップされます。

HorizontalPodAutoscaler が指標の変更に応答するまで数分かかることがあります。

HorizontalPodAutoscaler のスケールアップの監視

Deployment の現在のレプリカの数を確認するには、次のコマンドを実行します。

kubectl get deployments

指標が反映されるまでしばらく待ってから、Deployment は 5 つの Pod を作成してバックログを処理します。

また、次のコマンドを実行することで、HorizontalPodAutoscaler の状態と最近のアクティビティを調べることもできます。

kubectl describe hpa