# prometheus-adapter v0.12.0 serving custom.metrics.k8s.io from one rule: the Micrometer gauge # app.inflight.requests, which Prometheus stores as app_inflight_requests. apiVersion: v1 kind: ServiceAccount metadata: {name: prometheus-adapter, namespace: monitoring} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: {name: prometheus-adapter} rules: - apiGroups: [""] resources: [namespaces, pods, services, nodes] verbs: [get, list, watch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: {name: prometheus-adapter} roleRef: {apiGroup: rbac.authorization.k8s.io, kind: ClusterRole, name: prometheus-adapter} subjects: [{kind: ServiceAccount, name: prometheus-adapter, namespace: monitoring}] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: {name: prometheus-adapter-auth-delegator} roleRef: {apiGroup: rbac.authorization.k8s.io, kind: ClusterRole, name: system:auth-delegator} subjects: [{kind: ServiceAccount, name: prometheus-adapter, namespace: monitoring}] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: {name: prometheus-adapter-auth-reader, namespace: kube-system} roleRef: {apiGroup: rbac.authorization.k8s.io, kind: Role, name: extension-apiserver-authentication-reader} subjects: [{kind: ServiceAccount, name: prometheus-adapter, namespace: monitoring}] --- # The HPA controller reads custom metrics as this service account. apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: {name: custom-metrics-reader} rules: - apiGroups: [custom.metrics.k8s.io] resources: ["*"] verbs: [get, list] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: {name: hpa-custom-metrics-reader} roleRef: {apiGroup: rbac.authorization.k8s.io, kind: ClusterRole, name: custom-metrics-reader} subjects: [{kind: ServiceAccount, name: horizontal-pod-autoscaler, namespace: kube-system}] --- apiVersion: v1 kind: ConfigMap metadata: {name: prometheus-adapter, namespace: monitoring} data: config.yaml: | rules: # Micrometer "app.inflight.requests" -> Prometheus "app_inflight_requests" (dots become # underscores; a gauge gets no suffix). The series carries namespace/pod labels from the # scrape config, which is how the adapter attributes it to a pod. - seriesQuery: 'app_inflight_requests{namespace!="",pod!=""}' resources: overrides: namespace: {resource: namespace} pod: {resource: pod} name: matches: "^app_inflight_requests$" as: "app_inflight_requests" metricsQuery: 'avg_over_time(<<.Series>>{<<.LabelMatchers>>}[30s])' --- apiVersion: apps/v1 kind: Deployment metadata: {name: prometheus-adapter, namespace: monitoring} spec: replicas: 1 selector: {matchLabels: {app: prometheus-adapter}} template: metadata: {labels: {app: prometheus-adapter}} spec: serviceAccountName: prometheus-adapter containers: - name: adapter image: registry.k8s.io/prometheus-adapter/prometheus-adapter:v0.12.0 imagePullPolicy: Never args: - --prometheus-url=http://prometheus.monitoring.svc:9090/ - --metrics-relist-interval=15s - --config=/etc/adapter/config.yaml - --secure-port=6443 - --cert-dir=/tmp/cert ports: [{containerPort: 6443}] resources: {requests: {cpu: 50m, memory: 64Mi}, limits: {memory: 256Mi}} volumeMounts: - {name: config, mountPath: /etc/adapter} - {name: tmp, mountPath: /tmp} volumes: - {name: config, configMap: {name: prometheus-adapter}} - {name: tmp, emptyDir: {}} --- apiVersion: v1 kind: Service metadata: {name: prometheus-adapter, namespace: monitoring} spec: selector: {app: prometheus-adapter} ports: [{port: 443, targetPort: 6443}] --- apiVersion: apiregistration.k8s.io/v1 kind: APIService metadata: {name: v1beta1.custom.metrics.k8s.io} spec: service: {name: prometheus-adapter, namespace: monitoring} group: custom.metrics.k8s.io version: v1beta1 insecureSkipTLSVerify: true # the adapter generated a self-signed cert; use cert-manager in real clusters groupPriorityMinimum: 100 versionPriority: 100