HorizontalPodAutoscaler에서 사용할 수 있는 메트릭에는 custom metric이 존재한다.
prometheus에서 수집된 메트릭 데이터로 custom metric을 구성하는 방법을 정리한다.
/apis/custom.metrics.k8s.io/v1beta1/
https://github.com/kubernetes-sigs/prometheus-adapter/blob/master/docs/config.md (레퍼런스)
prometheus-adapter를 사용한 custom metrics api 서비스 구성도
helm을 사용해서 prometheus-adapter의 template 생성
helm template prometheus-adapter prometheus-adapter \
--repo https://prometheus-community.github.io/helm-charts \
--set prometheus.url="http://prometheus-operated.default.svc" \
--api-versions="apiregistration.k8s.io/v1" \
--dependency-update --include-crds > prometheus-adapter-deploy.yaml
prometheus의 경우 prometheus-operated
서비스를 통해서 연결이 가능하게 구성되어 있다.
kubernetes에 prometheus-operator(kube-prometheus-stack) 구성하고 모니터링하기
만약 kubernetes 22 버전 이상을 사용하고 --api-versions="apiregistration.k8s.io/v1"
옵션 없이 template을 생성했다면 생성된 prometheus-adapter-deploy.yaml
의 apiVersion
부분을 수정한다.
만약 api 버전이 맞지 않을 경우, 아래와 같은 오류가 발생된다.
# kubectl apply -f prometheus-adapter-deploy.yaml --server-side
serviceaccount/prometheus-adapter serverside-applied
configmap/prometheus-adapter serverside-applied
clusterrole.rbac.authorization.k8s.io/prometheus-adapter-resource-reader serverside-applied
clusterrole.rbac.authorization.k8s.io/prometheus-adapter-server-resources serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/prometheus-adapter-system-auth-delegator serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/prometheus-adapter-resource-reader serverside-applied
clusterrolebinding.rbac.authorization.k8s.io/prometheus-adapter-hpa-controller serverside-applied
rolebinding.rbac.authorization.k8s.io/prometheus-adapter-auth-reader serverside-applied
service/prometheus-adapter serverside-applied
deployment.apps/prometheus-adapter serverside-applied
error: resource mapping not found for name: "v1beta1.custom.metrics.k8s.io" namespace: "" from "prometheus-adapter-deploy.yaml": no matches for kind "APIService" in version "apiregistration.k8s.io/v1beta1"
ensure CRDs are installed first
prometheus-adapter-deploy.yaml
---
# Source: prometheus-adapter/templates/custom-metrics-apiservice.yaml
#apiVersion: apiregistration.k8s.io/v1beta1
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
helm.sh/chart: prometheus-adapter-4.11.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: metrics
app.kubernetes.io/part-of: prometheus-adapter
app.kubernetes.io/name: prometheus-adapter
app.kubernetes.io/instance: prometheus-adapter
app.kubernetes.io/version: "v0.12.0"
name: v1beta1.custom.metrics.k8s.io
spec:
service:
name: prometheus-adapter
namespace: "default"
group: custom.metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
apiVersion: apiregistration.k8s.io/v1beta1
을 apiVersion: apiregistration.k8s.io/v1
으로 변경한다. 이유는 v1.22에서 지원 끝났다.
https://kubernetes.io/docs/reference/using-api/deprecation-guide/
apiregistration.k8s.io/v1
수정 후, 아래와 같이 배포 진행한다.
# kubectl apply -f prometheus-adapter-deploy.yaml --server-side
custom metrics api 서비스 동작 확인
# kubectl get apiservices
NAME SERVICE AVAILABLE AGE
...
v1beta1.custom.metrics.k8s.io default/prometheus-adapter True 69s
...
v1beta1.metrics.k8s.io default/metrics-server True 168m
...
위와 같이 apiservices가 정상적으로 동작하는지 확인한다.
raw 데이터를 확인해본다.
# kubectl get --raw / | jq | grep custom
"/apis/custom.metrics.k8s.io",
"/apis/custom.metrics.k8s.io/v1beta1",
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 | jq
...
{
"name": "services/alertmanager_alerts_received",
"singularName": "",
"namespaced": true,
"kind": "MetricValueList",
"verbs": [
"get"
]
}
]
많은 데이터가 수집되고 있다.
custom metrics이 수집되는 rule이 저장되는 configmas 정보
prometheus-adapter에서 수집되는 메트릭의 룰 정보는 configmap에 저장되어있다.
아래 명령어로 확인이 가능하다.
# kubectl get configmaps prometheus-adapter
NAME DATA AGE
prometheus-adapter 1 4m21s
아래 명령어로 확인해보면 rule이 저정되어 있고,해당 룰로 prometheus에 저장된 메트릭을 수집한다.
# kubectl get configmaps prometheus-adapter -o yaml
prometheus-adapter의 Rule에 변경을 통한 간단한 메트릭 수집
prometheus-adapter을 통한 메트릭 수집 예제
kubernetes에 traefik로 Ingress를 구성하고 서비스 구성하기
위 가이드로 traefik을 설치가 되어 있고, 아래 가이드로 traefik을 메트릭이 수집되게 되어 있다는 가정하에 진행한다.
그리고 traefik loadbalancer로 /hello
호출을 몇 번했다고 가정한다.
위와 같은 상황이라면 traefik_service_requests_total
메트릭이 수집되고 있는 상황이다.
prometheus adapter rule을 추기화하고 traefik_service_requests_total
메트릭만 수집해본다.
아래와 같은 configmaps 파일 생성하고 적용한다, 그리고 prometheus adapter를 재시작한다.
prometheus-adapter-configmaps.yaml
apiVersion: v1
data:
config.yaml: |
rules:
- seriesQuery: 'traefik_service_requests_total'
seriesFilters: []
resources:
overrides:
namespace: {resource: "namespace"}
metricsQuery: "sum(increase(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)"
kind: ConfigMap
metadata:
name: prometheus-adapter
namespace: default
해당 파일을 적용해보면 아래와 같이 annotation 없어서 적용되지 않는 경우가 발생하는데, 다시 한번 배포하면 정상적으로 배포된다.
# kubectl apply -f prometheus-adapter-configmaps.yaml
Warning: resource configmaps/prometheus-adapter is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
configmap/prometheus-adapter configured
prometheus-adapter-configmaps.yaml 배포 및 prometheus-adapter 재시작
# kubectl apply -f prometheus-adapter-configmaps.yaml
configmap/prometheus-adapter unchanged
# kubectl rollout restart deployment prometheus-adapter
deployment.apps/prometheus-adapter restarted
적용 후, raw 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"
]
}
]
}
# kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1/namespaces/default/metrics/traefik_service_requests_total | jq
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {},
"items": [
{
"describedObject": {
"kind": "Namespace",
"name": "default",
"apiVersion": "/v1"
},
"metricName": "traefik_service_requests_total",
"timestamp": "2024-11-14T00:34:35Z",
"value": "0",
"selector": null
}
]
}
metrics-server를 생각해서 api를 호출해보면 recursive하게 api 리스트 매핑이 이쁘게 나오지 않는다.
결론은 룰을 찾아서 api에 대해서 정확하게 요청해야한다.
Custom Metrics 수집을 위한 Prometheus Adapter Rule에 대한 자세한 내용은 아래 페이지에서 이어서 진행한다.
prometheus adapter Rule 이해 - Deep Dive
https://blog.encicle.com/prometheus-adapter-rule-ihae-deep-dive