prometheus adapter의 rule 수정을 통해 다양한 사례를 예제로 살펴보고 깊이 이해하는 섹션을 갖는다.
prometheus-adapter Rule의 Resouce 추가를 통한 API 리소스 분리 예제
traefik_service_requests_total
메트릭은 아래와 같이 code, container, ... , namespace, pod, service, ingress와 같은 라벨이 붙어 있다.
Prometheus에 수집된 메트릭 정보
traefik_service_requests_total
{
code="200",
container="traefik",
endpoint="metrics",
ingress="echo-server-ing",
instance="10.233.71.2:9100",
job="default/traefik-pod-monitor",
method="GET",
namespace="default",
pod="traefik-664df7d9f4-6rj5q",
protocol="http",
service="default-echo-server-svc-80@kubernetes"
}
prometheus-adapter-configmaps.yaml에 아래와 같이 resource가 정의되어 있다.
resources:
overrides:
namespace: {resource: "namespace"}
여기에 위에 정의된 라벨 중, pod를 추가해서 prometheus adapter에 적용한다.
prometheus-adapter-configmaps.yaml
apiVersion: v1
data:
config.yaml: |
rules:
- seriesQuery: 'traefik_service_requests_total'
seriesFilters: []
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
metricsQuery: "sum(increase(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)"
kind: ConfigMap
metadata:
name: prometheus-adapter
namespace: default
prometheus adapter configmaps 적용
# kubectl apply -f prometheus-adapter-configmaps.yaml
configmap/prometheus-adapter configured
# kubectl rollout restart deployment prometheus-adapter
deployment.apps/prometheus-adapter restarted
적용 후, api를 호출해본다.
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ | jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "namespaces/traefik_service_requests_total",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "pods/traefik_service_requests_total",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
즉 기존에 "namespaces/traefik_service_requests_total"
만 분류하는 형태에서, "pods/traefik_service_requests_total"
추가로 분류해준다.
새롭게 생성된 api로 데이터를 호출해본다.
라벨 중 pod는 pod="traefik-664df7d9f4-6rj5q"
로 저장된다.
호출은 주소는 /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/traefik-664df7d9f4-6rj5q/traefik_service_requests_total
이것이 된다.
# kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/traefik-664df7d9f4-6rj5q/traefik_service_requests_total" |jq
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {},
"items": [
{
"describedObject": {
"kind": "Pod",
"namespace": "default",
"name": "traefik-664df7d9f4-6rj5q",
"apiVersion": "/v1"
},
"metricName": "traefik_service_requests_total",
"timestamp": "2024-11-14T01:27:43Z",
"value": "98",
"selector": null
}
]
}
pod resource의 경우 아래와 같이 asterisk(*) 호출해서 여러 개의 pod 호출이 가능하다.
# kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/traefik_service_requests_total" |jq
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {},
"items": [
{
"describedObject": {
"kind": "Pod",
"namespace": "default",
"name": "traefik-664df7d9f4-6rj5q",
"apiVersion": "/v1"
},
"metricName": "traefik_service_requests_total",
"timestamp": "2024-11-14T01:30:07Z",
"value": "116",
"selector": null
}
]
}
아래는 traefik pod를 2개로 늘린 후, asterisk(*) 호출 결과이다.
# kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/traefik_service_requests_total" |jq
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {},
"items": [
{
"describedObject": {
"kind": "Pod",
"namespace": "default",
"name": "traefik-664df7d9f4-49524",
"apiVersion": "/v1"
},
"metricName": "traefik_service_requests_total",
"timestamp": "2024-11-14T01:31:43Z",
"value": "32812m",
"selector": null
},
{
"describedObject": {
"kind": "Pod",
"namespace": "default",
"name": "traefik-664df7d9f4-6rj5q",
"apiVersion": "/v1"
},
"metricName": "traefik_service_requests_total",
"timestamp": "2024-11-14T01:31:43Z",
"value": "58",
"selector": null
}
]
}
prometheus-adapter의 메트릭 이름 변경
심플한 메트릭 명칭 변경
prometheus adapter에 수집된 데이터는 "traefik_service_requests_total"
이름을 가진다.
메트릭 쿼리가 아래와 같이 sum + increase 1m으로 진행된다. (결론 저장된 메트릭 이름이 마음에 들지 않는다.)
metricsQuery: "sum(increase(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)"
sum_incr_1m_traefik_service_requests_total
메트릭 이름으로 저장되는 예제는 아래와 같다.
prometheus-adapter-configmaps.yaml
apiVersion: v1
data:
config.yaml: |
rules:
- seriesQuery: 'traefik_service_requests_total'
seriesFilters: []
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
as: "sum_incr_1m_traefik_service_requests_total"
metricsQuery: "sum(increase(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)"
kind: ConfigMap
metadata:
name: prometheus-adapter
namespace: defaultㅁㅁ
적용 후, api를 호출하면 아래와 같이 반영되었다.
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ |jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "pods/sum_incr_1m_traefik_service_requests_total",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "namespaces/sum_incr_1m_traefik_service_requests_total",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
기존 메트릭 명칭에서 regexp를 통한 메트릭 명칭 추출
"traefik_service_requests_total"
이름에서 단순하게 _total을 제거하고 싶은 경우가 있다.
regexp rule로 생각해보면 ^(.*)_total$
과 같다.
prometheus-adapter-configmaps.yaml
apiVersion: v1
data:
config.yaml: |
rules:
- seriesQuery: 'traefik_service_requests_total'
seriesFilters: []
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "^(.*)_total$"
metricsQuery: "sum(increase(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)"
kind: ConfigMap
metadata:
name: prometheus-adapter
namespace: default
적용 결과
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ |jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "pods/traefik_service_requests",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "namespaces/traefik_service_requests",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
matches: "^(.*)_total$"
field가 있고, as 필드가 없다면 regexp에서 ${1}
의 결과를 메트릭 명칭으로 사용한다.
그럼 as를 사용해서 추출된 ${1}
데이터 _sum_incr_1m
라는 문자열을 붙여본다.
prometheus-adapter-configmaps.yaml
apiVersion: v1
data:
config.yaml: |
rules:
- seriesQuery: 'traefik_service_requests_total'
seriesFilters: []
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
name:
matches: "^(.*)_total$"
as: "${1}_sum_incr_1m"
metricsQuery: "sum(increase(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)"
kind: ConfigMap
metadata:
name: prometheus-adapter
namespace: default
적용 후, 결과
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ |jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "namespaces/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "pods/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
regexp를 사용해서 다양하게 문자를 추출할 수 있고, 이를 조합해서 메트릭 명칭을 수정할 수 있다.
traefik의 데이터를 ingress 메트릭으로 수집하기
traefik_service_requests_total
{
code="200",
container="traefik",
endpoint="metrics",
ingress="echo-server-ing",
instance="10.233.71.2:9100",
job="default/traefik-pod-monitor",
method="GET",
namespace="default",
pod="traefik-664df7d9f4-6rj5q",
protocol="http",
service="default-echo-server-svc-80@kubernetes"
}
수집된 메트릭 중, ingress Label은 additionalPodMonitors에 설정해서 강제로 추가한 설정이다.
# kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
echo-server-ing traefik * 192.168.122.11 80 47h
ingress 데이터를 확인해도 수집된 ingress 레벨의 데이터와 동일하게 매핑된다.
위에서 설명했듯이 ingress를 추가하려면 resource에 ingress로 수집하도록 아래와 같이 추가한다.
prometheus-adapter-configmaps.yaml
apiVersion: v1
data:
config.yaml: |
rules:
- seriesQuery: 'traefik_service_requests_total'
seriesFilters: []
resources:
overrides:
namespace: {resource: "namespace"}
pod: {resource: "pod"}
ingress: {resource: "ingress"}
name:
matches: "^(.*)_total$"
as: "${1}_sum_incr_1m"
metricsQuery: "sum(increase(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)"
kind: ConfigMap
metadata:
name: prometheus-adapter
namespace: default
prometheus adapter에 적용 후, 수집된 메트릭을 확인해보면 아래와 같다.
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ |jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "pods/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "ingresses.networking.k8s.io/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "namespaces/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
ingress를 resurce로 수집된 데이터는 기존과 다르게 ingresses.networking.k8s.io/traefik_service_requests_sum_incr_1m
매핑되어 있다.
호출 주소는 아래와 같다.
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/ingresses.networking.k8s.io/echo-server-ing/traefik_service_requests_sum_incr_1m | jq
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {},
"items": [
{
"describedObject": {
"kind": "Ingress",
"namespace": "default",
"name": "echo-server-ing",
"apiVersion": "networking.k8s.io/v1"
},
"metricName": "traefik_service_requests_sum_incr_1m",
"timestamp": "2024-11-15T04:22:48Z",
"value": "112",
"selector": null
}
]
}
prometheus-adapter API 호출 주소 생성 룰
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/ |jq
{
"kind": "APIResourceList",
"apiVersion": "v1",
"groupVersion": "custom.metrics.k8s.io/v1beta1",
"resources": [
{
"name": "pods/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "ingresses.networking.k8s.io/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
},
{
"name": "namespaces/traefik_service_requests_sum_incr_1m",
"singularName": "",
"namespaced": false,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
}
위와 같을 경우, 표시해주는 메트릭의 호출 주소는 "Resouce" / "메트릭 이름"으로 표시된다.
1. "namespaced": true
일경우, Resource 앞 뒤로, "/namespaces/[Resouce namespace]"/"Resouce"/"[Resouce Label Data]"가 붙는다.
2. Resource Case에 몇 가지 경우 [Resouce Label Data]을 asterisk(*)로 대체할 수 있다. (예 : pod, node)
pods/traefik_service_requests_sum_incr_1m
의 경우, 아래와 같은 메트릭이 사용되었다면
traefik_service_requests_total
{
code="200",
container="traefik",
endpoint="metrics",
ingress="echo-server-ing",
instance="10.233.71.2:9100",
job="default/traefik-pod-monitor",
method="GET",
namespace="default",
pod="traefik-664df7d9f4-6rj5q",
protocol="http",
service="default-echo-server-svc-80@kubernetes"
}
메트릭 호출 주소에는 아래와 같은 정보가 사용되었다.
- namespace -> default
- pod -> traefik-664df7d9f4-6rj5q
[Resouce namespace] : default
Resouece : pod이나 pods로 수집 / pod, pods 모두 호출 가능
[Resouce Label Data] : traefik-664df7d9f4-6rj5q
"/namespaces/default/pods/traefik-664df7d9f4-6rj5q/traefik_service_requests_sum_incr_1m"
와 같이 호출하면 된다.
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/traefik-664df7d9f4-6rj5q/traefik_service_requests_sum_incr_1m | jq
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {},
"items": [
{
"describedObject": {
"kind": "Pod",
"namespace": "default",
"name": "traefik-664df7d9f4-6rj5q",
"apiVersion": "/v1"
},
"metricName": "traefik_service_requests_sum_incr_1m",
"timestamp": "2024-11-15T04:36:18Z",
"value": "58",
"selector": null
}
]
}