🐥

PrometheusメトリクスによるPodの水平スケール

2022/08/04に公開

はじめに

Prometheusを活用して何らかのメトリクスを取得し、必要に応じてPodを自動的にスケールさせたいケースがあるかと思います。今回は、Prometheusとsidekiq-exporterを用いて、Redisの待機中のジョブの数を取得し、ジョブが多ければPodを水平スケール(HPA)させるようにします。

Prometheus on Kubernetes & HPAのアーキテクチャ

Prometheusは複数のコンポーネントによって成り立っています。今回はわかりやすくするために図を省略しており、厳密には以下の画像より多くのリソースが存在します。

prometheus-operaterの以下の図が理解しやすいと思います。

Ref: https://github.com/prometheus-operator/prometheus-operator/blob/9c0db5656f04e005de6a0413fd8eb8f11ec99757/Documentation/troubleshooting.md#troubleshooting-servicemonitor-changes

1. Redisとsidekiq-exporterを接続する

exporterの導入は至って簡単です。以下のようにDeploymentを作成します。REDIS_URLはElasticCache for Redisのエンドポイントとします。

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: sidekiq
  name: sidekiq-exporter
spec:
  selector:
    matchLabels:
      app: sidekiq-exporter
  replicas: 1
  template:
    metadata:
      labels:
        app: sidekiq-exporter
      name: sidekiq-exporter
    spec:
      containers:
      - name: sidekiq-exporter
        image: strech/sidekiq-prometheus-exporter:latest
        env:
        - name: REDIS_URL
          valueFrom:
            secretKeyRef:
              name: sidekiq-exporter-secret
              key: redis_url
        ports:
        - name: exporter
          containerPort: 9292

また、Prometheusがexporterからメトリクスを取得できるようにServiceとServiceMonitorを作成します。ServiceMonitorは、prometheus-operatorによって提供されるカスタムリソース定義(CRD)であり、サービスオブジェクトでEndpointsを検出し、PrometheusがこれらのPodを監視するように設定します。

apiVersion: v1
kind: Service
metadata:
  namespace: sidekiq
  name: sidekiq-exporter-service
  labels:
    app: sidekiq-exporter
spec:
  selector:
    app: sidekiq-exporter
  ports:
  - name: exporter
    port: 9292
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  namespace: sidekiq
  name: sidekiq-exporter-service-monitor
spec:
  selector:
    matchLabels:
      app: sidekiq-exporter
  endpoints:
  - port: exporter

sidekiq-exporterがRedisと接続できているか確認します。ポートフォワードを使ってsidekiq-exporterのPodをローカルに転送します。

kubectl port-forward -n sidekiq <redis-exporterのPod> 8080:9292

curlコマンドでメトリクスが表示されると接続は上手くいっています。

curl -s localhost:8080/metrics

2. prometheus-operaterの導入

prometheus-operatorはPrometheusおよび、その関連ツール(AlertmanagerやGrafana etc)をKubernetesリソースとして管理することができます。今回は必要なものだけインストールしていきます。

prometheus-operater.yaml
・
・
spec:
  project: default
  source:
    repoURL: https://github.com/prometheus-community/helm-charts.git
    path: charts/kube-prometheus-stack/crds/
    targetRevision: kube-prometheus-stack-37.0.0
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: default
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - Replace=true
---
・
・
spec:
  project: default
  source:
    repoURL: 'https://prometheus-community.github.io/helm-charts'
    targetRevision: 37.0.0
    helm:
      skipCrds: true
      values: |
        alertmanager:
          enabled: false
        grafana:
          enabled: false
        kubeApiServer:
          enabled: false
        kubelet:
          enabled: false
        kubeControllerManager:
          enabled: false
        coreDns:
          enabled: false
        kubeDns:
          enabled: false
        kubeEtcd:
          enabled: false
        kubeScheduler:
          enabled: false
        kubeProxy:
          enabled: false
        kubeStateMetrics:
          enabled: false
        nodeExporter:
          enabled: false
        prometheusOperator:
          admissionWebhooks:
            enabled: false
            patch:
              enabled: false
        prometheus:
          prometheusSpec:
            serviceMonitorSelectorNilUsesHelmValues: false
            serviceMonitorNamespaceSelector: {}
            serviceMonitorSelector: {}
    chart: kube-prometheus-stack
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: default
  syncPolicy:
    automated:
      prune: true
    syncOptions:
    - Replace=true

以下でPrometheusのコンソール画面が表示できると思います。sidekiq-exporterがUpになっていれば大丈夫です。

kubectl port-forward prometheus-prometheus-operator-kube-p-prometheus-0 8000:9090

3. prometheus-adapterがPrometheusからメトリクスを取得し、APIとして使えるようにする

・
・
spec:
  project: default
  source:
    repoURL: 'https://prometheus-community.github.io/helm-charts'
    targetRevision: 3.0.0
    helm:
      values: |
        rules:
          default: false
          custom:
          - seriesQuery: 'sidekiq_enqueued_jobs{namespace!="",service!=""}'
            resources:
              overrides:
                namespace:
                  resource: namespace
                service:
                  resource: service
            name:
              as: sidekiq_enqueued_jobs
            metricsQuery: '<<.Series>>{<<.LabelMatchers>>}'
        prometheus:
          url: http://prometheus-operator-kube-p-prometheus.default
        logLevel: 2
    chart: prometheus-adapter
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: default

以下のコマンドを打って表示されれば大丈夫です。

kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/sidekiq/services/sidekiq-exporter-service/sidekiq_enqueued_jobs | jq .

4. custom.metrics.k8s.io APIを使ってHPAする

カスタムメトリクスAPIに登録したsidekiq_enqueued_jobsの値に応じてPodの数をコントロールすることができます。metrics.object.target.valueで閾値を設定します。以下の設定で待機中のジョブが1つ以上になるとPodが水平スケールするようになります。

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa
  namespace: sidekiq
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: <水平スケーツの対象>
  minReplicas: 1
  maxReplicas: 2
  metrics:
  - type: Object
    object:
      describedObject:
        apiVersion: v1
        kind: Service
        name: sidekiq-exporter
      metric:
        name: sidekiq_enqueued_jobs
      target:
        type: Value
        value: 1

参考文献

sidekiq-exporter

https://github.com/Strech/sidekiq-prometheus-exporter

prometheus-operater

https://github.com/prometheus-operator/prometheus-operator

https://github.com/helm/charts/tree/master/stable/prometheus-operator

prometheus-adapter

https://qiita.com/masahata/items/062a2ee5762b108e8850

https://github.com/helm/charts/blob/master/stable/prometheus-adapter/README.md

https://github.com/kubernetes-sigs/prometheus-adapter/blob/master/docs/config-walkthrough.md

Horizontal Pod Autoscaling (HPA)

https://qiita.com/Ladicle/items/5ff251b89df2f1ebb821

https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#scaling-on-custom-metrics

その他

https://kubernetes.io/ja/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/

Discussion