はじめに
Prometheus Adapterを使ってKubernetesのカスタムメトリクスを作成する方法をざっくり紹介します。
また、実際にローカルでIstioのメトリクスからカスタムメトリクスも作成してみたいと思います。
Promethues Adapterとは
Prometheus Adapterとは、Prometheusで使えるメトリクスからカスタムメトリクスが作成できるアダプタになります。
インストール
Helmを使ってインストールするのが簡単です。
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus-adapter prometheus-community/prometheus-adapter
設定
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
kube-state-metrics:
enabled: false
prometheus-pushgateway:
enabled: false
prometheus-node-exporter:
enabled: false
server:
service:
servicePort: 9090
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>>)'
デプロイ
最後に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)で使えるようになりました。
参考
- kubernetes-sigs/prometheus-adapter: An implementation of the custom.metrics.k8s.io API using Prometheus
- helm-charts/charts/prometheus-adapter at prometheus-adapter-2.7.1 · prometheus-community/helm-charts
- helm-charts/charts/prometheus at prometheus-adapter-2.7.1 · prometheus-community/helm-charts
- prometheus-adapter/config.md at master · kubernetes-sigs/prometheus-adapter