ワークロードを外部イベント駆動で自動水平スケーリングする
PFCP では、KEDA (Kubernetes Event Driven Autoscaler) を利用した外部イベント駆動でワークロードを自動水平スケーリングする機能を提供しています。
利用可能な KEDA リソース
PFCP で利用できる主要な KEDA リソースは以下の 2 つです。
ScaledObject
ScaledObject は、スケーリング対象のワークロード(Deployment、StatefulSet など)と、そのスケーリングを制御するトリガーを定義するリソースです。
詳細については、ScaledObject の公式ドキュメントを参照してください。
TriggerAuthentication
TriggerAuthentication は、外部システムへの認証情報を管理するリソースです。
詳細については、TriggerAuthentication の公式ドキュメントを参照してください。
PFCP Prometheus メトリクスを利用したスケーリング
PFCP では、 Prometheus によるメトリクスモニタリング機能 を提供しています。ここでは、この機能を利用して Deployment の Pod レプリカ数を自動的にスケーリングする方法を説明します。
以下は、Prometheus メトリクスに基づいてアプリケーションのスケーリングを行うための KEDA の設定例です。ScaledObject リソースを作成し、myapp という名前の Deployment をスケーリング対象として指定しています。しきい値が 50 に対して、Prometheus のクエリは常に 100 を返すため、Pod のレプリカ数は 2 にスケーリングされます。
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: app-scaler
spec:
  scaleTargetRef:
    name: myapp # スケーリング対象の Deployment 名を指定
  maxReplicaCount: 3 # 最大レプリカ数を指定
  minReplicaCount: 0 # 最小レプリカ数を指定
  triggers:
    - type: prometheus
      metadata:
        serverAddress: http://prometheus-k8s.monitoring-org-<org-name>.svc.cluster.local.:9090 # org-name: 組織名
        query: "vector(100)" # 監視対象とするメトリクスを指定(ここでは常に 100 を返すクエリを指定)
        threshold: "50" # スケーリングする条件を指定(ここではメトリクスが 50 を超えたとき)
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: stefanprodan/podinfo
        name: podinfo
        ports:
        - containerPort: 9898
Prometheus で Pod のメトリクスを収集する方法については、メトリクスモニタリングとアラーティングを参照してください。
AWS Managed Prometheus メトリクスを利用したスケーリング
ここでは、外部リソースである AWS の Managed Prometheus(AMP)メトリクスを利用して Deployment の Pod レプリカ数を自動的にスケーリングする方法を例に説明します。
AWS IAM の設定
AMP メトリクスを利用するには、KEDA が AMP をクエリできる必要があります。以下の手順で設定してください。
- IAM で OpenID Connect(OIDC)ID プロバイダーをパブリッククラウドと ID 連携を構成するを参照して作成します。
 - 利用している AMP ワークスペースの ARN を控えておきます。
AMPのセットアップ方法については、AWSのドキュメントを参照してください。
 - KEDA が AMP のメトリクスをクエリするためのポリシーを作成します。Resource には利用している AMP ワークスペースの ARN を指定します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "aps:QueryMetrics" ], "Resource": [ "arn:aws:aps:<aws_region>:<aws_account_id>:workspace/<workspace_id>" ] } ] } - 先ほど作成したポリシーをアタッチする IAM ロールを作成し、KEDA のシステムコンポーネントに関連付けます。Principal には手順 1 で作成した OIDC プロバイダーを指定します。Condition に設定する KEDA Operator の Namespace は組織ごとに異なります。以下はその例です。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRoleWithWebIdentity", "Principal": { "Federated": "arn:aws:iam::<aws_account_id>:oidc-provider/token.<pfcp_region>.kubernetes.pfcomputing.com" }, "Condition": { "StringEquals": { "token.<pfcp_region>.kubernetes.pfcomputing.com:aud": [ "sts.amazonaws.com" ], "token.<pfcp_region>.kubernetes.pfcomputing.com:sub": [ "system:serviceaccount:keda-org-<pfcp_org_name>:keda-operator" ] } } } ] } - 作成したロールの ARN を控えておきます。この ARN は後で KEDA の設定で使用します。
 
KEDA リソースの作成
以下は、AMP メトリクスに基づいてアプリケーションのスケーリングを行うための KEDA の設定例です。
TriggerAuthentication の.spec.podIdentity.roleArnに先ほど控えた IAM ロールの ARN を指定すると、KEDA はそのロールを使用して AMP のメトリクスをクエリします。
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: amp-query-role
spec:
  podIdentity:
    provider: aws
    roleArn: <roleArn> # 先ほど控えた IAM ロールの ARN を指定
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: app-scaler
spec:
  scaleTargetRef:
    name: myapp
  maxReplicaCount: 10
  minReplicaCount: 0
  triggers:
    - type: prometheus
      authenticationRef:
        name: amp-query-role
      metadata:
        awsRegion: <aws_region> # AMP のリージョンを指定する
        serverAddress: https://aps-workspaces.<aws_region>.amazonaws.com/workspaces/<workspace_id> # AMP のエンドポイントを指定する
        query: "sum(rate(http_requests_total[1m]))" # 監視対象とするメトリクスを指定(ここでは 1 分間の HTTP リクエスト数)
        threshold: "50" # スケーリングする条件を指定(ここではリクエスト数が 50 を超えたとき)
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: stefanprodan/podinfo
        name: podinfo
        ports:
        - containerPort: 9898