【Kubernetes】Prometheus Adapterでカスタムメトリクス作成

スポンサーリンク

はじめに

Prometheus Adapterを使ってKubernetesのカスタムメトリクスを作成する方法をざっくり紹介します。

また、実際にローカルでIstioのメトリクスからカスタムメトリクスも作成してみたいと思います。

Promethues Adapterとは

Prometheus Adapterとは、Prometheusで使えるメトリクスからカスタムメトリクスが作成できるアダプタになります。

GitHub - kubernetes-sigs/prometheus-adapter: An implementation of the custom.metrics.k8s.io API using Prometheus
An implementation of the custom.metrics.k8s.io API using Prometheus - GitHub - kubernetes-sigs/prometheus-adapter: An implementation of the custom.metrics.k8s.i...

インストール

Helmを使ってインストールするのが簡単です。

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus-adapter prometheus-community/prometheus-adapter
helm-charts/charts/prometheus-adapter at prometheus-adapter-2.7.1 · prometheus-community/helm-charts
Prometheus community Helm charts. Contribute to prometheus-community/helm-charts development by creating an account on GitHub.

設定

Prometheus Adapterの設定はコンテナ実行時の引数で渡されています。

例えば、下記のようなものがあります。

  • --prometheus-url=<url>: 接続するPrometheusのURL
  • --config=<yaml-file>: メトリクスの設定をするyamlファイル

具体的には、下記のような感じになっています。

...

spec:
  containers:
  - args:
    - /adapter
    - --secure-port=6443
    - --cert-dir=/tmp/cert
    - --logtostderr=true
    - --prometheus-url=http://prometheus-server.monitoring.svc.cluster.local:9090
    - --metrics-relist-interval=1m
    - --v=4
    - --config=/etc/adapter/config.yaml

...

Helmを使っていれば、これらの設定はvalues.yamlで設定可能です。

カスタムメトリクスの定義

カスタムメトリクスはconfigファイルで定義します。(Helmであればvalues.yamlで設定可能)

カスタムメトリクスの定義は、下記の4つに分類できます。

  • Discovery: Prometheusからメトリクスをどう検索するか
  • Association: どのKubernetesリソースと関連しているか
  • Naming: カスタムメトリクスの名前
  • Querying: Prometheusへのクエリ(PromQL)

下記のようにカスタムメトリクスを定義します。

rules:
# Discovery
- seriesQuery: '{__name__=~"^container_.*",container!="POD",namespace!="",pod!=""}'
  # Association
  resources:
    overrides:
      namespace: # メトリクスのラベル
        resource: "namespace"
      pod: # メトリクスのラベル
        resource: "pod"
  # Naming
  name:
    matches: "^container_(.*)_seconds_total$"
    as: "${1}_per_second"
  # Querying
  metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>,container!="POD"}[2m])) by (<<.GroupBy>>)'

Queryingでは、下記のテンプレートが用意されています。

  • Series: メトリクス名
  • LabelMatchers: Associationで設定したラベル
  • GroupBy: グループ化するためのラベル((LabelMatchersと同じラベル)

作成したメトリクスの確認

下記のコマンドで設定されているカスタムメトリクスを確認できます。バージョンはkubectl get apiservicesで確認してください。

kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1

そのままだと見づらいので、下記のようにjqで整形して、grepで確認したいメトリクスを指定するのがいいかと思います。

kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jq | grep -A 7 -B 1 {metrics}

やってみる

ローカルでIstioのistio_requests_totalからreqeusts_per_secondというカスタムメトリクスを作成してみます。

作成するファイルは下記のとおりです。

.
├── prometheus
│   ├── helmfile.yaml
│   └── prometheus.yaml
├── prometheus-adapter
│   ├── helmfile.yaml
│   └── prometheus-adapter.yaml
├── helmfile.yaml
├── istio.yaml
├── deployment.yaml
└── service.yaml

helmfileを使って、PrometheusとPrometheus Adapterをデプロイします。

Istioのインストール

Istioのインストールをします。

istioctl install --set profile=demo -y

default Namespaceでサイドカーの有効化をします。

kubectl label namespace default istio-injection=enabled

デモアプリのデプロイ

次にデモアプリ用のDeployment、Service、Virtual Service、Gatewayをデプロイします。

deployment.yamlは下記の通りです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - containerPort: 80

service.yamlは下記の通りです。

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
  - protocol: TCP
    name: http
    port: 8000
    targetPort: 80
  selector:
    app: nginx

istio.yamlは下記の通りです。

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: nginx-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx
spec:
  hosts:
  - "*"
  gateways:
  - nginx-gateway
  http:
  - route:
    - destination:
        host: nginx-svc
        port:
          number: 8000

それぞれデプロイします。

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f istio.yaml

デモアプリの確認

次にIstioのingressgateway経由でデモアプリにアクセスしてみます。

一度もアクセスしないと、Istioのメトリクスが取得できず、カスタムメトリクスが作成できない可能性があります。

まずはingressgatewayのポート番号を環境変数として設定します。

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')

設定した環境変数を使って、ポートフォワードします。

kubectl -n istio-system port-forward svc/istio-ingressgateway $INGRESS_PORT:80

curlでアクセスしてみます。

curl localhost:$INGRESS_PORT

PrometheusとPrometheus Adapterのデプロイ

続いて、PrometheusとPrometheus Adapterをhelmfileを使ってデプロイします。

Prometheus

prometheus/helmfile.yamlは下記の通りです。

releases:
  - name: prometheus
    namespace: monitoring
    chart: prometheus-community/prometheus
    values:
      - ./prometheus.yaml

prometheus/prometheus.yamlは下記の通りです。

alertmanager:
  enabled: false
kubeStateMetrics:
  enabled: false
pushgateway:
  enabled: false
nodeExporter:
  enabled: false

server:
  service:
    servicePort: 9090
helm-charts/charts/prometheus at prometheus-adapter-2.7.1 · prometheus-community/helm-charts
Prometheus community Helm charts. Contribute to prometheus-community/helm-charts development by creating an account on GitHub.

Prometheus Adapter

prometheus-adapter/helmfile.yamlは下記の通りです。

releases:
  - name: prometheus-adapter
    namespace: monitoring
    chart: prometheus-community/prometheus-adapter
    values:
      - ./prometheus-adapter.yaml

prometheus-adapter/prometheus-adapter.yamlは下記の通りです。ここでカスタムメトリクスの定義を記入しています。

prometheus:
  url: http://prometheus-server.monitoring.svc.cluster.local
  port: 9090

rules:
  custom:
  - seriesQuery: 'istio_requests_total'
    resources:
      overrides:
        destination_service_namespace:
          resource: "namespace"
        destination_service_name:
          resource: "service"
    name:
      as: "requests_per_second"
    metricsQuery: 'sum(rate(<<.Series>>{<<.LabelMatchers>>, reporter=“destination”}[5m])) by (<<.GroupBy>>)'
helm-charts/charts/prometheus-adapter at prometheus-adapter-2.7.1 · prometheus-community/helm-charts
Prometheus community Helm charts. Contribute to prometheus-community/helm-charts development by creating an account on GitHub.

デプロイ

最後にhelmfile.yamlを作成して、PrometheusとPrometheus Adapterをデプロイします。

helmfiles:
  - ./prometheus/helmfile.yaml
  - ./prometheus-adapter/helmfile.yaml
helmfile apply

メトリクスの確認

APIのバージョンを確認します。

❯ kubectl get apiservices

NAME                                   SERVICE                         AVAILABLE   AGE

...

v1alpha3.networking.istio.io           Local                           True        5m58s
v1beta1.custom.metrics.k8s.io          monitoring/prometheus-adapter   True        4m43s
v1beta1.flowcontrol.apiserver.k8s.io   Local                           True        8m42s

...

作成したカスタムメトリクスを確認してみます。

❯ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jq | grep -A 7 -B 1 requests_per_second

    {
      "name": "services/requests_per_second",
      "singularName": "",
      "namespaced": true,
      "kind": "MetricValueList",
      "verbs": [
        "get"
      ]
    },
--
    {
      "name": "namespaces/requests_per_second",
      "singularName": "",
      "namespaced": false,
      "kind": "MetricValueList",
      "verbs": [
        "get"
      ]
    },

これで作成したカスタムメトリクスをHPA(Horizontal Pod Autoscaler)で使えるようになりました。

参考

タイトルとURLをコピーしました