我想完全理解 Prometheus-adapter 的配置
Kubernetes 的自动扩展默认提供了水平 Pod 自动扩展器。
如果你想根据CPU和内存的使用率进行扩展,这通常就足够了(当然有时候可能不够),但是我认为你可能会遇到希望根据请求数或队列数等进行扩展的情况。在这种情况下,你可以将外部指标作为HPA的指标。虽然有一些适配器可供选择,但我使用的是这个,它可以将Prometheus的指标转换为HPA的指标。
然而,由于设置有点复杂,我只是凭感觉使用而没有完全理解,所以这次我想要理解它。
電腦科學家通過檢查網絡上的大量資訊來解決這個問題。
《prometheus-adapter》的文档
https://github.com/kubernetes-sigs/prometheus-adapter/tree/master/docs
这里包含了全部的内容,所以这篇文章只需要对其进行解读。
关于HPA
https://kubernetes.io/ja/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
由于类型的多样性,我们关注与此相关的Pods Object External。
分类
在较大的分类中,有三种类型。
-
- rules
apiServiceで定義した、custom.metrics.k8s.ioで使用する
hpaでは type: Pods type: Object で使用する
resourceRules
hpaデフォルトで使用できるrecoucesを置き換えるものなのではないか、と思っている
ドキュメントに情報がないので今回これは放置で
externalRules
apiServiceで定義した、external.metrics.k8s.ioで使用する
hpaでは type: External で使用する
规则
设置示例
rules:
- seriesQuery: '{__name__=~"^container_.*",container!="POD",namespace!="",pod!=""}'
seriesFilters:
- isNot: "^container_fs_.+"
resources:
overrides:
namespace:
resource: namespace
pod:
resource: pod
name:
matches: ^container_(.*)_seconds_total$
as: ""
metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>,container!="POD"}[1m])) by (<<.GroupBy>>)
我们将按照从上到下的顺序查看设置项。
系列查询
决定要转换哪些Prometheus指标。
-
- 変換したいメトリクスがひとつだけの場合は、単純にメトリクス名を直接書くだけでよい
-
- 複数のメトリクスを変換したい場合は、クエリ形式でまとめて取得することもできる
その場合は例のように__name__を使用してごそっと取得
その他のlabelのフィルタも必要に応じて設定する
ここではあくまで、どのメトリクス(series)を変換対象にするか、を決める
系列过滤器
使用正则表达式进一步过滤从seriesQuery获取到的指标数据,例如在无法通过__name__一次性筛选完成的情况下使用。
is で一致したものを残す
isNot で一致したものを除外
资源
这是将Metrics和Kubernetes资源进行连接的设置。这部分是设置的关键,但很难用文字解释清楚。
举个例子,如果是关于pod的情况,
resources:
overrides:
<<メトリクスのnamespaceのlabel名>>:
resource: namespace
<<メトリクスのpodのlable名>>:
resource: pod
如果举例来说,更具体一点的例子是
如果想要转换名为some_metrics的指标,您可以在seriesQuery中指定该指标,例如:
seriesQuery = {kubernetes_namespace=”samplenamespace”,kubernetes_pod_name=”samplepodname”}
resources:
overrides:
kubernetes_namespace:
resource: namespace
kubernetes_pod_name:
resource: pod
可以这样表达:
不仅仅是pod,所有资源都可以进行转换。
实际上,需要指定api-group,但是pod是核心api,所以不需要指定。
例如,对于ingress来说,
resources:
overrides:
<<メトリクスのnamespaceのlabel名>>:
resource: namespace
<<メトリクスのingressのlable名>>:
group: networking.k8s.io
resource: ingress
意外的是,有很多常用的固定句型。
如果以下对应的标签名称相同,并且看起来不需要进行设置,但仍需编写定义:
some_metrics{namespace=”mynamespace”,pod=”mypodname”}
resources:
overrides:
namespace:
resource: namespace
pod:
resource: pod
如果有预先设定好的替换模式,可以通过模板进行批量转换。比如说
resources:
overrides:
kubernetes_pod_name:
resource: "pod"
kubernetes_namespace_name:
resource: "namespace"
这个设定可以按照以下方式进行设置。
resources:
template: "kubernetes_<<.Resource>>_name"
以下为该句的中文本地化的一种可能方式:
似乎可以使用<<.Group>>和<<.Resource>>作为变量,但是由于Group可以推测,所以不是必需的,这里有点追不上(因为似乎不太可能被使用)。
名字
在设置HPA时可以确定要使用的名称。
使用matches函数使用正则表达式从原始的度量名称中进行捕获,然后使用as来使用捕获结果来命名。
name:
matches: "^(.*)_total$"
as: "${1}_per_second"
在此设置中,名为container_requests_total的指标可以在HPA中以container_requests_per_second的名称使用。
如果没有指定matches,默认为 .* ,如果matches没有使用括号捕获,as的默认值为$0。这是否意味着如果没有指定任何内容,度量名称将原样使用?
当在匹配式中使用捕获组时,默认值为$1的as分组。
我在这个地方感受到了一种轻松神秘的氛围。
度量查询
对于给定的series,定义一个查询以计算指标值。使用以下变量(模板):
-
- <<.Series>>
メトリクス名
seriesQueryで__name__で正規表現を使わずに単一のメトリクスを設定する場合は、これを使わず直接メトリクス名を書くのでも問題ない
<<.LabelMatchers>>
resourcesでの設定を使用して作られたlabel matcher
上のresourceでの例だとこんな値になる
kubenetes_pod_name=~”samplepodname”,kubernetes_namespace=~”samplenamespace”
複数のpodのメトリクスを取得する場合は、正規表現で並ぶ pod=~”mypod1|mypod2″
他にlabelを指定したい場合は、前後にコンマで繋げてlabelを追加できる
{<<.LabelMatchers>>,container!=”POD”} {container!=”POD”,<<.LabelMatchers>>}
<<.GroupBy>>
.LabelMatchersで使用されているのと同じlabelのkeyがコンマ区切りで入る
基本上這三個就足夠了,但還有其他選項可供使用。
-
- <<.LabelValuesByName>>
.GroupByとは逆で、こっちは値のリスト
複数labelのを全部混ぜるんだろうか?namespaceとpodとか…
|で区切り
<<.GroupBySlice>>
GroupByのスライス…よくわからなかった…
外部规则
如果想将与POD等资源的关联性较低的指标转换为度量标准,请使用此处的externalRules。
例如,等待处理的工作队列数量将变为这个指标。
使用实例
externalRules:
- seriesQuery: '{__name__=~"^.*_queue_(length|size)$",namespace!=""}'
resources:
overrides:
namespace:
resource: namespace
name:
matches: ^.*_queue_(length|size)$
as: "$0"
metricsQuery: max(<<.Series>>{<<.LabelMatchers>>})
基本上,它的格式与rules相同,但在resources中减少了与kubernetes资源相关的部分。
在v0.8之前,需要指定namespace,所以必须在hpa所在的命名空间和具有相同namespace label的metrics上附加(由于可以进行转换,因此如果存在具有相同值的label,那么可以解决)。
在v0.9之后,也可以不指定namespace,但在v0.8之后存在与kubernetes-external-secret发生冲突的问题,所以我无法使用…
展示或演示
由于整体表达不够清楚,我决定简单演示以掩饰。将以以下设置启动prometheus-adapter。顺便提一句,版本为v0.7。
rules:
- seriesQuery: 'container_threads'
seriesFilters: []
resources:
overrides:
namespace:
resource: namespace
pod:
resource: pod
name:
matches: ""
as: pod_test
metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>,container!="POD",container!=""}) by (<<.GroupBy>>)'
- seriesQuery: 'kube_service_created'
seriesFilters: []
resources:
overrides:
namespace:
resource: namespace
service:
resource: service
name:
matches: ""
as: service_test
metricsQuery: 'time() - sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
externalRules:
- seriesQuery: container_fs_inodes_total
seriesFilters: []
resources:
overrides:
namespace:
resource: namespace
name:
matches: ""
as: "external_test"
metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>})'
我认为,如果使用了cAdvisor和kube-state-metrics的度量标准,就应该存在。也许。
-
- 1番目
メトリクスcontainer_threadsを変換してpod_testとして使用
podで使えるメトリクスを適当に選んだ
resourceはpodで、hpaではPodsで使用する
metricsQueryでlabel container がPODのものと空のものを除外する
2番目
メトリクスkube_service_createdを変換してservice_testとして使用
resourceはserviceで、hpaではObjectで使用する
metricsQueryでは、serviceが作られてからの経過時間を計算している
3番目
externalRules
メトリクスcontainer_fs_inodes_totalを変換してexternal_testとして使用
普通ならpodsで使うようなメトリクスだけど、デフォルトで出るメトリクスのうちexternalで使える良さそうなのが見当たらなかったので、externalとして使用する
metricsQueryでnamespace内にある全てのコンテナのcontainer_fs_inodes_totalを合計する
値を出すためなので特に意味はない
对于此设置,应用测试用的部署和服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
申请HPA
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: nginx
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
minReplicas: 2
maxReplicas: 5
metrics:
- type: Pods
pods:
metric:
name: pod_test
target:
type: AverageValue
averageValue: "10000"
- type: Object
object:
describedObject:
kind: service
name: nginx
metric:
name: service_test
target:
type: AverageValue
averageValue: "10000"
- type: External
external:
metric:
name: external_test
target:
type: Value
value: "10000"
我们将为每个 Prometheus 适配器设置的三个类型分别配置 HPA。
-
- 共通
type: Valueは取得した値をそのまま使う
値がすでにpodの数で割られてるならこっちを使用
type: AverageValueは取得した値を現在のpodの数で割って使う
1番目
type: Pods
prometheus-adapterで設定したresourceがpodの場合はtype: Podsを使用する
ValueとAverageValueどっちを使っていいのか迷ったけど、Valueで設定しようとするとエラーになるのでAverageValueを使っておけばよさそう
2番目
type: Object
resourceがpod以外のrulesはtype: Objectを使用して、describedObjectで対象リソース詳細を設定する
3番目
type: External
意外と語ることがない
我尝试描述一下HPA。
$ kubectl describe hpa nginx
Name: nginx
Namespace: default
Labels: <none>
Annotations: <none>
CreationTimestamp: Sun, 12 Dec 2021 23:28:54 +0900
Reference: Deployment/nginx
Metrics: ( current / target )
"pod_test" on pods: 3 / 10k
"service_test" on service/nginx (target average value): 85760m / 10k
"external_test" (target value): 74 / 10k
Min replicas: 2
Max replicas: 5
Deployment pods: 2 current / 2 desired
HPA用得很好。
调试
顺便说一下,我们也可以直接调用API来确认是否可以进行设置。
规则
kubectl get –raw “/apis/custom.metrics.k8s.io/v1beta2
外部规则
kubectl get –raw “/apis/external.metrics.k8s.io/v1beta1
度量细节
规则
kubectl get –raw “/apis/custom.metrics.k8s.io/v1beta2/namespaces/<<命名空间名称>>/<<资源类型(例如:pods)>>/<<pod名称(如果是所有pod,则为*)>>/<<度量名称>>”
外部规则
kubectl get –raw “/apis/external.metrics.k8s.io/v1beta1/namespaces/mynamespace/<<命名空间名称>>/<<度量名称>>”
在这种情况下
$ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/pod_test
$ kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/service/*/service_test
$ kubectl get --raw /apis/external.metrics.k8s.io/v1beta1/namespaces/default/external_test
可以这样调试
以上
这个状态有点太凌乱了
哎呀,这很难。