mirror of
https://github.com/rancher/rancher-docs.git
synced 2026-09-29 14:38:50 +00:00
993 lines
51 KiB
JavaScript
993 lines
51 KiB
JavaScript
"use strict";
|
|
(self["webpackChunkrancher_docs"] = self["webpackChunkrancher_docs"] || []).push([[99544],{
|
|
|
|
/***/ 3905:
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ Zo: () => (/* binding */ MDXProvider),
|
|
/* harmony export */ kt: () => (/* binding */ createElement)
|
|
/* harmony export */ });
|
|
/* unused harmony exports MDXContext, useMDXComponents, withMDXComponents */
|
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(67294);
|
|
|
|
|
|
function _defineProperty(obj, key, value) {
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value: value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function _extends() {
|
|
_extends = Object.assign || function (target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i];
|
|
|
|
for (var key in source) {
|
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
};
|
|
|
|
return _extends.apply(this, arguments);
|
|
}
|
|
|
|
function ownKeys(object, enumerableOnly) {
|
|
var keys = Object.keys(object);
|
|
|
|
if (Object.getOwnPropertySymbols) {
|
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
if (enumerableOnly) symbols = symbols.filter(function (sym) {
|
|
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
});
|
|
keys.push.apply(keys, symbols);
|
|
}
|
|
|
|
return keys;
|
|
}
|
|
|
|
function _objectSpread2(target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i] != null ? arguments[i] : {};
|
|
|
|
if (i % 2) {
|
|
ownKeys(Object(source), true).forEach(function (key) {
|
|
_defineProperty(target, key, source[key]);
|
|
});
|
|
} else if (Object.getOwnPropertyDescriptors) {
|
|
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
} else {
|
|
ownKeys(Object(source)).forEach(function (key) {
|
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
});
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
if (source == null) return {};
|
|
var target = {};
|
|
var sourceKeys = Object.keys(source);
|
|
var key, i;
|
|
|
|
for (i = 0; i < sourceKeys.length; i++) {
|
|
key = sourceKeys[i];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
target[key] = source[key];
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
function _objectWithoutProperties(source, excluded) {
|
|
if (source == null) return {};
|
|
|
|
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
|
|
var key, i;
|
|
|
|
if (Object.getOwnPropertySymbols) {
|
|
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
|
|
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
key = sourceSymbolKeys[i];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
var isFunction = function isFunction(obj) {
|
|
return typeof obj === 'function';
|
|
};
|
|
|
|
var MDXContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createContext({});
|
|
var withMDXComponents = function withMDXComponents(Component) {
|
|
return function (props) {
|
|
var allComponents = useMDXComponents(props.components);
|
|
return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
|
|
components: allComponents
|
|
}));
|
|
};
|
|
};
|
|
var useMDXComponents = function useMDXComponents(components) {
|
|
var contextComponents = react__WEBPACK_IMPORTED_MODULE_0__.useContext(MDXContext);
|
|
var allComponents = contextComponents;
|
|
|
|
if (components) {
|
|
allComponents = isFunction(components) ? components(contextComponents) : _objectSpread2(_objectSpread2({}, contextComponents), components);
|
|
}
|
|
|
|
return allComponents;
|
|
};
|
|
var MDXProvider = function MDXProvider(props) {
|
|
var allComponents = useMDXComponents(props.components);
|
|
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(MDXContext.Provider, {
|
|
value: allComponents
|
|
}, props.children);
|
|
};
|
|
|
|
var TYPE_PROP_NAME = 'mdxType';
|
|
var DEFAULTS = {
|
|
inlineCode: 'code',
|
|
wrapper: function wrapper(_ref) {
|
|
var children = _ref.children;
|
|
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, {}, children);
|
|
}
|
|
};
|
|
var MDXCreateElement = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.forwardRef(function (props, ref) {
|
|
var propComponents = props.components,
|
|
mdxType = props.mdxType,
|
|
originalType = props.originalType,
|
|
parentName = props.parentName,
|
|
etc = _objectWithoutProperties(props, ["components", "mdxType", "originalType", "parentName"]);
|
|
|
|
var components = useMDXComponents(propComponents);
|
|
var type = mdxType;
|
|
var Component = components["".concat(parentName, ".").concat(type)] || components[type] || DEFAULTS[type] || originalType;
|
|
|
|
if (propComponents) {
|
|
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(Component, _objectSpread2(_objectSpread2({
|
|
ref: ref
|
|
}, etc), {}, {
|
|
components: propComponents
|
|
}));
|
|
}
|
|
|
|
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(Component, _objectSpread2({
|
|
ref: ref
|
|
}, etc));
|
|
});
|
|
MDXCreateElement.displayName = 'MDXCreateElement';
|
|
function createElement (type, props) {
|
|
var args = arguments;
|
|
var mdxType = props && props.mdxType;
|
|
|
|
if (typeof type === 'string' || mdxType) {
|
|
var argsLength = args.length;
|
|
var createElementArgArray = new Array(argsLength);
|
|
createElementArgArray[0] = MDXCreateElement;
|
|
var newProps = {};
|
|
|
|
for (var key in props) {
|
|
if (hasOwnProperty.call(props, key)) {
|
|
newProps[key] = props[key];
|
|
}
|
|
}
|
|
|
|
newProps.originalType = type;
|
|
newProps[TYPE_PROP_NAME] = typeof type === 'string' ? type : mdxType;
|
|
createElementArgArray[1] = newProps;
|
|
|
|
for (var i = 2; i < argsLength; i++) {
|
|
createElementArgArray[i] = args[i];
|
|
}
|
|
|
|
return react__WEBPACK_IMPORTED_MODULE_0__.createElement.apply(null, createElementArgArray);
|
|
}
|
|
|
|
return react__WEBPACK_IMPORTED_MODULE_0__.createElement.apply(null, args);
|
|
}
|
|
|
|
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 80007:
|
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
|
|
__webpack_require__.r(__webpack_exports__);
|
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
/* harmony export */ assets: () => (/* binding */ assets),
|
|
/* harmony export */ contentTitle: () => (/* binding */ contentTitle),
|
|
/* harmony export */ "default": () => (/* binding */ MDXContent),
|
|
/* harmony export */ frontMatter: () => (/* binding */ frontMatter),
|
|
/* harmony export */ metadata: () => (/* binding */ metadata),
|
|
/* harmony export */ toc: () => (/* binding */ toc)
|
|
/* harmony export */ });
|
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(67294);
|
|
/* harmony import */ var _mdx_js_react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3905);
|
|
/* @jsxRuntime classic */ /* @jsx mdx */ /* @jsxFrag React.Fragment */ function _define_property(obj, key, value) {
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value: value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
return obj;
|
|
}
|
|
function _object_spread(target) {
|
|
for(var i = 1; i < arguments.length; i++){
|
|
var source = arguments[i] != null ? arguments[i] : {};
|
|
var ownKeys = Object.keys(source);
|
|
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
}));
|
|
}
|
|
ownKeys.forEach(function(key) {
|
|
_define_property(target, key, source[key]);
|
|
});
|
|
}
|
|
return target;
|
|
}
|
|
function ownKeys(object, enumerableOnly) {
|
|
var keys = Object.keys(object);
|
|
if (Object.getOwnPropertySymbols) {
|
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
if (enumerableOnly) {
|
|
symbols = symbols.filter(function(sym) {
|
|
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
});
|
|
}
|
|
keys.push.apply(keys, symbols);
|
|
}
|
|
return keys;
|
|
}
|
|
function _object_spread_props(target, source) {
|
|
source = source != null ? source : {};
|
|
if (Object.getOwnPropertyDescriptors) {
|
|
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
} else {
|
|
ownKeys(Object(source)).forEach(function(key) {
|
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
});
|
|
}
|
|
return target;
|
|
}
|
|
function _object_without_properties(source, excluded) {
|
|
if (source == null) return {};
|
|
var target = _object_without_properties_loose(source, excluded);
|
|
var key, i;
|
|
if (Object.getOwnPropertySymbols) {
|
|
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
for(i = 0; i < sourceSymbolKeys.length; i++){
|
|
key = sourceSymbolKeys[i];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
return target;
|
|
}
|
|
function _object_without_properties_loose(source, excluded) {
|
|
if (source == null) return {};
|
|
var target = {};
|
|
var sourceKeys = Object.keys(source);
|
|
var key, i;
|
|
for(i = 0; i < sourceKeys.length; i++){
|
|
key = sourceKeys[i];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
target[key] = source[key];
|
|
}
|
|
return target;
|
|
}
|
|
|
|
|
|
const frontMatter = {
|
|
title: 'Prometheus Custom Metrics Adapter'
|
|
};
|
|
const contentTitle = undefined;
|
|
const metadata = {
|
|
"unversionedId": "explanations/integrations-in-rancher/cluster-monitoring/custom-metrics",
|
|
"id": "version-2.0-2.4/explanations/integrations-in-rancher/cluster-monitoring/custom-metrics",
|
|
"title": "Prometheus Custom Metrics Adapter",
|
|
"description": "After you've enabled cluster level monitoring, You can view the metrics data from Rancher. You can also deploy the Prometheus custom metrics adapter then you can use the HPA with metrics stored in cluster monitoring.",
|
|
"source": "@site/versioned_docs/version-2.0-2.4/explanations/integrations-in-rancher/cluster-monitoring/custom-metrics.md",
|
|
"sourceDirName": "explanations/integrations-in-rancher/cluster-monitoring",
|
|
"slug": "/explanations/integrations-in-rancher/cluster-monitoring/custom-metrics",
|
|
"permalink": "/v2.0-v2.4/explanations/integrations-in-rancher/cluster-monitoring/custom-metrics",
|
|
"draft": false,
|
|
"editUrl": "https://github.com/rancher/rancher-docs/edit/main/versioned_docs/version-2.0-2.4/explanations/integrations-in-rancher/cluster-monitoring/custom-metrics.md",
|
|
"tags": [],
|
|
"version": "2.0-2.4",
|
|
"lastUpdatedAt": 1705104464,
|
|
"formattedLastUpdatedAt": "Jan 13, 2024",
|
|
"frontMatter": {
|
|
"title": "Prometheus Custom Metrics Adapter"
|
|
},
|
|
"sidebar": "tutorialSidebar",
|
|
"previous": {
|
|
"title": "Cluster Metrics",
|
|
"permalink": "/v2.0-v2.4/explanations/integrations-in-rancher/cluster-monitoring/cluster-metrics"
|
|
},
|
|
"next": {
|
|
"title": "Prometheus Expressions",
|
|
"permalink": "/v2.0-v2.4/explanations/integrations-in-rancher/cluster-monitoring/expression"
|
|
}
|
|
};
|
|
const assets = {};
|
|
const toc = [
|
|
{
|
|
value: 'Deploy Prometheus Custom Metrics Adapter',
|
|
id: 'deploy-prometheus-custom-metrics-adapter',
|
|
level: 2
|
|
},
|
|
{
|
|
value: 'Configuration of prometheus custom metrics adapter',
|
|
id: 'configuration-of-prometheus-custom-metrics-adapter',
|
|
level: 2
|
|
},
|
|
{
|
|
value: 'Discovery',
|
|
id: 'discovery',
|
|
level: 3
|
|
},
|
|
{
|
|
value: 'Association',
|
|
id: 'association',
|
|
level: 3
|
|
},
|
|
{
|
|
value: 'Naming',
|
|
id: 'naming',
|
|
level: 3
|
|
},
|
|
{
|
|
value: 'Querying',
|
|
id: 'querying',
|
|
level: 3
|
|
}
|
|
];
|
|
const layoutProps = {
|
|
toc
|
|
};
|
|
const MDXLayout = "wrapper";
|
|
function MDXContent(_param) {
|
|
var { components } = _param, props = _object_without_properties(_param, [
|
|
"components"
|
|
]);
|
|
return /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)(MDXLayout, _object_spread_props(_object_spread({}, layoutProps, props), {
|
|
components: components,
|
|
mdxType: "MDXLayout"
|
|
}), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `After you've enabled `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("a", {
|
|
parentName: "p",
|
|
"href": "/v2.0-v2.4/explanations/integrations-in-rancher/cluster-monitoring/"
|
|
}, `cluster level monitoring`), `, You can view the metrics data from Rancher. You can also deploy the Prometheus custom metrics adapter then you can use the HPA with metrics stored in cluster monitoring.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("h2", {
|
|
"id": "deploy-prometheus-custom-metrics-adapter"
|
|
}, `Deploy Prometheus Custom Metrics Adapter`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `We are going to use the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("a", {
|
|
parentName: "p",
|
|
"href": "https://github.com/DirectXMan12/k8s-prometheus-adapter/releases/tag/v0.5.0"
|
|
}, `Prometheus custom metrics adapter`), `, version v0.5.0. This is a great example for the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("a", {
|
|
parentName: "p",
|
|
"href": "https://github.com/kubernetes-incubator/custom-metrics-apiserver"
|
|
}, `custom metrics server`), `. And you must be the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("em", {
|
|
parentName: "p"
|
|
}, `cluster owner`), ` to execute following steps.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, `Get the service account of the cluster monitoring is using. It should be configured in the workload ID: `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `statefulset:cattle-prometheus:prometheus-cluster-monitoring`), `. And if you didn't customize anything, the service account name should be `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `cluster-monitoring`), `.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, `Grant permission to that service account. You will need two kinds of permission.
|
|
One role is `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `extension-apiserver-authentication-reader`), ` in `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `kube-system`), `, so you will need to create a `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `Rolebinding`), ` to in `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `kube-system`), `. This permission is to get api aggregation configuration from config map in `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `kube-system`), `.`))), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: RoleBinding
|
|
metadata:
|
|
name: custom-metrics-auth-reader
|
|
namespace: kube-system
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: Role
|
|
name: extension-apiserver-authentication-reader
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: cluster-monitoring
|
|
namespace: cattle-prometheus
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The other one is cluster role `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `system:auth-delegator`), `, so you will need to create a `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `ClusterRoleBinding`), `. This permission is to have subject access review permission.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `apiVersion: rbac.authorization.k8s.io/v1
|
|
kind: ClusterRoleBinding
|
|
metadata:
|
|
name: custom-metrics:system:auth-delegator
|
|
roleRef:
|
|
apiGroup: rbac.authorization.k8s.io
|
|
kind: ClusterRole
|
|
name: system:auth-delegator
|
|
subjects:
|
|
- kind: ServiceAccount
|
|
name: cluster-monitoring
|
|
namespace: cattle-prometheus
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, `Create configuration for custom metrics adapter. Following is an example configuration. There will be a configuration details in next session.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: adapter-config
|
|
namespace: cattle-prometheus
|
|
data:
|
|
config.yaml: |
|
|
rules:
|
|
- seriesQuery: '{__name__=~"^container_.*",container_name!="POD",namespace!="",pod_name!=""}'
|
|
seriesFilters: []
|
|
resources:
|
|
overrides:
|
|
namespace:
|
|
resource: namespace
|
|
pod_name:
|
|
resource: pod
|
|
name:
|
|
matches: ^container_(.*)_seconds_total$
|
|
as: ""
|
|
metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}[1m])) by (<<.GroupBy>>)
|
|
- seriesQuery: '{__name__=~"^container_.*",container_name!="POD",namespace!="",pod_name!=""}'
|
|
seriesFilters:
|
|
- isNot: ^container_.*_seconds_total$
|
|
resources:
|
|
overrides:
|
|
namespace:
|
|
resource: namespace
|
|
pod_name:
|
|
resource: pod
|
|
name:
|
|
matches: ^container_(.*)_total$
|
|
as: ""
|
|
metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}[1m])) by (<<.GroupBy>>)
|
|
- seriesQuery: '{__name__=~"^container_.*",container_name!="POD",namespace!="",pod_name!=""}'
|
|
seriesFilters:
|
|
- isNot: ^container_.*_total$
|
|
resources:
|
|
overrides:
|
|
namespace:
|
|
resource: namespace
|
|
pod_name:
|
|
resource: pod
|
|
name:
|
|
matches: ^container_(.*)$
|
|
as: ""
|
|
metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}) by (<<.GroupBy>>)
|
|
- seriesQuery: '{namespace!="",__name__!~"^container_.*"}'
|
|
seriesFilters:
|
|
- isNot: .*_total$
|
|
resources:
|
|
template: <<.Resource>>
|
|
name:
|
|
matches: ""
|
|
as: ""
|
|
metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)
|
|
- seriesQuery: '{namespace!="",__name__!~"^container_.*"}'
|
|
seriesFilters:
|
|
- isNot: .*_seconds_total
|
|
resources:
|
|
template: <<.Resource>>
|
|
name:
|
|
matches: ^(.*)_total$
|
|
as: ""
|
|
metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)
|
|
- seriesQuery: '{namespace!="",__name__!~"^container_.*"}'
|
|
seriesFilters: []
|
|
resources:
|
|
template: <<.Resource>>
|
|
name:
|
|
matches: ^(.*)_seconds_total$
|
|
as: ""
|
|
metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)
|
|
resourceRules:
|
|
cpu:
|
|
containerQuery: sum(rate(container_cpu_usage_seconds_total{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)
|
|
nodeQuery: sum(rate(container_cpu_usage_seconds_total{<<.LabelMatchers>>, id='/'}[1m])) by (<<.GroupBy>>)
|
|
resources:
|
|
overrides:
|
|
instance:
|
|
resource: node
|
|
namespace:
|
|
resource: namespace
|
|
pod_name:
|
|
resource: pod
|
|
containerLabel: container_name
|
|
memory:
|
|
containerQuery: sum(container_memory_working_set_bytes{<<.LabelMatchers>>}) by (<<.GroupBy>>)
|
|
nodeQuery: sum(container_memory_working_set_bytes{<<.LabelMatchers>>,id='/'}) by (<<.GroupBy>>)
|
|
resources:
|
|
overrides:
|
|
instance:
|
|
resource: node
|
|
namespace:
|
|
resource: namespace
|
|
pod_name:
|
|
resource: pod
|
|
containerLabel: container_name
|
|
window: 1m
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, `Create HTTPS TLS certs for your api server. You can use following command to create a self-signed cert.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-bash"
|
|
}, `openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out serving.crt -keyout serving.key -subj "/C=CN/CN=custom-metrics-apiserver.cattle-prometheus.svc.cluster.local"
|
|
# And you will find serving.crt and serving.key in your path. And then you are going to create a secret in cattle-prometheus namespace.
|
|
kubectl create secret generic -n cattle-prometheus cm-adapter-serving-certs --from-file=serving.key=./serving.key --from-file=serving.crt=./serving.crt
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, `Then you can create the prometheus custom metrics adapter. And you will need a service for this deployment too. Creating it via Import YAML or Rancher would do. Please create those resources in `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `cattle-prometheus`), ` namespaces.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Here is the prometheus custom metrics adapter deployment.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
labels:
|
|
app: custom-metrics-apiserver
|
|
name: custom-metrics-apiserver
|
|
namespace: cattle-prometheus
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: custom-metrics-apiserver
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: custom-metrics-apiserver
|
|
name: custom-metrics-apiserver
|
|
spec:
|
|
serviceAccountName: cluster-monitoring
|
|
containers:
|
|
- name: custom-metrics-apiserver
|
|
image: directxman12/k8s-prometheus-adapter-amd64:v0.5.0
|
|
args:
|
|
- --secure-port=6443
|
|
- --tls-cert-file=/var/run/serving-cert/serving.crt
|
|
- --tls-private-key-file=/var/run/serving-cert/serving.key
|
|
- --logtostderr=true
|
|
- --prometheus-url=http://prometheus-operated/
|
|
- --metrics-relist-interval=1m
|
|
- --v=10
|
|
- --config=/etc/adapter/config.yaml
|
|
ports:
|
|
- containerPort: 6443
|
|
volumeMounts:
|
|
- mountPath: /var/run/serving-cert
|
|
name: volume-serving-cert
|
|
readOnly: true
|
|
- mountPath: /etc/adapter/
|
|
name: config
|
|
readOnly: true
|
|
- mountPath: /tmp
|
|
name: tmp-vol
|
|
volumes:
|
|
- name: volume-serving-cert
|
|
secret:
|
|
secretName: cm-adapter-serving-certs
|
|
- name: config
|
|
configMap:
|
|
name: adapter-config
|
|
- name: tmp-vol
|
|
emptyDir: {}
|
|
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Here is the service of the deployment.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: custom-metrics-apiserver
|
|
namespace: cattle-prometheus
|
|
spec:
|
|
ports:
|
|
- port: 443
|
|
targetPort: 6443
|
|
selector:
|
|
app: custom-metrics-apiserver
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, `Create API service for your custom metric server.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `apiVersion: apiregistration.k8s.io/v1beta1
|
|
kind: APIService
|
|
metadata:
|
|
name: v1beta1.custom.metrics.k8s.io
|
|
spec:
|
|
service:
|
|
name: custom-metrics-apiserver
|
|
namespace: cattle-prometheus
|
|
group: custom.metrics.k8s.io
|
|
version: v1beta1
|
|
insecureSkipTLSVerify: true
|
|
groupPriorityMinimum: 100
|
|
versionPriority: 100
|
|
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, `Then you can verify your custom metrics server by `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1`), `. If you see the return datas from the api, it means that the metrics server has been successfully set up.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, `You create HPA with custom metrics now. Here is an example of HPA. You will need to create a nginx deployment in your namespace first.`))), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `kind: HorizontalPodAutoscaler
|
|
apiVersion: autoscaling/v2beta1
|
|
metadata:
|
|
name: nginx
|
|
spec:
|
|
scaleTargetRef:
|
|
# point the HPA at the nginx deployment you just created
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
name: nginx
|
|
# autoscale between 1 and 10 replicas
|
|
minReplicas: 1
|
|
maxReplicas: 10
|
|
metrics:
|
|
# use a "Pods" metric, which takes the average of the
|
|
# given metric across all pods controlled by the autoscaling target
|
|
- type: Pods
|
|
pods:
|
|
metricName: memory_usage_bytes
|
|
targetAverageValue: 5000000
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `And then, you should see your nginx is scaling up. HPA with custom metrics works.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("h2", {
|
|
"id": "configuration-of-prometheus-custom-metrics-adapter"
|
|
}, `Configuration of prometheus custom metrics adapter`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("blockquote", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "blockquote"
|
|
}, `Refer to `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("a", {
|
|
parentName: "p",
|
|
"href": "https://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/config.md"
|
|
}, `https://github.com/DirectXMan12/k8s-prometheus-adapter/blob/master/docs/config.md`))), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The adapter determines which metrics to expose, and how to expose them,
|
|
through a set of "discovery" rules. Each rule is executed independently
|
|
(so make sure that your rules are mutually exclusive), and specifies each
|
|
of the steps the adapter needs to take to expose a metric in the API.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Each rule can be broken down into roughly four parts:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("em", {
|
|
parentName: "p"
|
|
}, `Discovery`), `, which specifies how the adapter should find all Prometheus
|
|
metrics for this rule.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("em", {
|
|
parentName: "p"
|
|
}, `Association`), `, which specifies how the adapter should determine which
|
|
Kubernetes resources a particular metric is associated with.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("em", {
|
|
parentName: "p"
|
|
}, `Naming`), `, which specifies how the adapter should expose the metric in
|
|
the custom metrics API.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("em", {
|
|
parentName: "p"
|
|
}, `Querying`), `, which specifies how a request for a particular metric on one
|
|
or more Kubernetes objects should be turned into a query to Prometheus.`))), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `A basic config with one rule might look like:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `rules:
|
|
# this rule matches cumulative cAdvisor metrics measured in seconds
|
|
- seriesQuery: '{__name__=~"^container_.*",container_name!="POD",namespace!="",pod_name!=""}'
|
|
resources:
|
|
# skip specifying generic resource<->label mappings, and just
|
|
# attach only pod and namespace resources by mapping label names to group-resources
|
|
overrides:
|
|
namespace: {resource: "namespace"},
|
|
pod_name: {resource: "pod"},
|
|
# specify that the \`container_\` and \`_seconds_total\` suffixes should be removed.
|
|
# this also introduces an implicit filter on metric family names
|
|
name:
|
|
# we use the value of the capture group implicitly as the API name
|
|
# we could also explicitly write \`as: "$1"\`
|
|
matches: "^container_(.*)_seconds_total$"
|
|
# specify how to construct a query to fetch samples for a given series
|
|
# This is a Go template where the \`.Series\` and \`.LabelMatchers\` string values
|
|
# are available, and the delimiters are \`<<\` and \`>>\` to avoid conflicts with
|
|
# the prometheus query language
|
|
metricsQuery: "sum(rate(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}[2m])) by (<<.GroupBy>>)"
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("h3", {
|
|
"id": "discovery"
|
|
}, `Discovery`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Discovery governs the process of finding the metrics that you want to
|
|
expose in the custom metrics API. There are two fields that factor into
|
|
discovery: `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `seriesQuery`), ` and `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `seriesFilters`), `.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `seriesQuery`), ` specifies Prometheus series query (as passed to the
|
|
`, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `/api/v1/series`), ` endpoint in Prometheus) to use to find some set of
|
|
Prometheus series. The adapter will strip the label values from this
|
|
series, and then use the resulting metric-name-label-names combinations
|
|
later on.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `In many cases, `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `seriesQuery`), ` will be sufficient to narrow down the list of
|
|
Prometheus series. However, sometimes (especially if two rules might
|
|
otherwise overlap), it's useful to do additional filtering on metric
|
|
names. In this case, `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `seriesFilters`), ` can be used. After the list of
|
|
series is returned from `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `seriesQuery`), `, each series has its metric name
|
|
filtered through any specified filters.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Filters may be either:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `is: <regex>`), `, which matches any series whose name matches the specified
|
|
regex.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", {
|
|
parentName: "li"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `isNot: <regex>`), `, which matches any series whose name does not match the
|
|
specified regex.`))), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `For example:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `# match all cAdvisor metrics that aren't measured in seconds
|
|
seriesQuery: '{__name__=~"^container_.*_total",container_name!="POD",namespace!="",pod_name!=""}'
|
|
seriesFilters:
|
|
isNot: "^container_.*_seconds_total"
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("h3", {
|
|
"id": "association"
|
|
}, `Association`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Association governs the process of figuring out which Kubernetes resources
|
|
a particular metric could be attached to. The `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `resources`), ` field controls
|
|
this process.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `There are two ways to associate resources with a particular metric. In
|
|
both cases, the value of the label becomes the name of the particular
|
|
object.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `One way is to specify that any label name that matches some particular
|
|
pattern refers to some group-resource based on the label name. This can
|
|
be done using the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `template`), ` field. The pattern is specified as a Go
|
|
template, with the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `Group`), ` and `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `Resource`), ` fields representing group and
|
|
resource. You don't necessarily have to use the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `Group`), ` field (in which
|
|
case the group is guessed by the system). For instance:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `# any label \`kube_<group>_<resource>\` becomes <group>.<resource> in Kubernetes
|
|
resources:
|
|
template: "kube_<<.Group>>_<<.Resource>>"
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The other way is to specify that some particular label represents some
|
|
particular Kubernetes resource. This can be done using the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `overrides`), `
|
|
field. Each override maps a Prometheus label to a Kubernetes
|
|
group-resource. For instance:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `# the microservice label corresponds to the apps.deployment resource
|
|
resource:
|
|
overrides:
|
|
microservice: {group: "apps", resource: "deployment"}
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `These two can be combined, so you can specify both a template and some
|
|
individual overrides.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The resources mentioned can be any resource available in your kubernetes
|
|
cluster, as long as you've got a corresponding label.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("h3", {
|
|
"id": "naming"
|
|
}, `Naming`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Naming governs the process of converting a Prometheus metric name into
|
|
a metric in the custom metrics API, and vice versa. It's controlled by
|
|
the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `name`), ` field.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Naming is controlled by specifying a pattern to extract an API name from
|
|
a Prometheus name, and potentially a transformation on that extracted
|
|
value.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The pattern is specified in the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `matches`), ` field, and is just a regular
|
|
expression. If not specified, it defaults to `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `.*`), `.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The transformation is specified by the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `as`), ` field. You can use any
|
|
capture groups defined in the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `matches`), ` field. If the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `matches`), ` field
|
|
doesn't contain capture groups, the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `as`), ` field defaults to `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `$0`), `. If it
|
|
contains a single capture group, the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `as`), ` field defautls to `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `$1`), `.
|
|
Otherwise, it's an error not to specify the as field.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `For example:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `# match turn any name <name>_total to <name>_per_second
|
|
# e.g. http_requests_total becomes http_requests_per_second
|
|
name:
|
|
matches: "^(.*)_total$"
|
|
as: "\${1}_per_second"
|
|
`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("h3", {
|
|
"id": "querying"
|
|
}, `Querying`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Querying governs the process of actually fetching values for a particular
|
|
metric. It's controlled by the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `metricsQuery`), ` field.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `metricsQuery`), ` field is a Go template that gets turned into
|
|
a Prometheus query, using input from a particular call to the custom
|
|
metrics API. A given call to the custom metrics API is distilled down to
|
|
a metric name, a group-resource, and one or more objects of that
|
|
group-resource. These get turned into the following fields in the
|
|
template:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `Series`), `: the metric name`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `LabelMatchers`), `: a comma-separated list of label matchers matching the
|
|
given objects. Currently, this is the label for the particular
|
|
group-resource, plus the label for namespace, if the group-resource is
|
|
namespaced.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `GroupBy`), `: a comma-separated list of labels to group by. Currently,
|
|
this contains the group-resource label used in `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `LabelMatchers`), `.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `For instance, suppose we had a series `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `http_requests_total`), ` (exposed as
|
|
`, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `http_requests_per_second`), ` in the API) with labels `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `service`), `, `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `pod`), `,
|
|
`, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `ingress`), `, `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `namespace`), `, and `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `verb`), `. The first four correspond to
|
|
Kubernetes resources. Then, if someone requested the metric
|
|
`, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `pods/http_request_per_second`), ` for the pods `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `pod1`), ` and `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `pod2`), ` in the
|
|
`, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `somens`), ` namespace, we'd have:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `Series: "http_requests_total"`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `LabelMatchers: "pod=~\\"pod1|pod2",namespace="somens"`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `GroupBy`), `: `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `pod`))), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `Additionally, there are two advanced fields that are "raw" forms of other
|
|
fields:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("ul", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `LabelValuesByName`), `: a map mapping the labels and values from the
|
|
`, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `LabelMatchers`), ` field. The values are pre-joined by `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `|`), `
|
|
(for used with the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `=~`), ` matcher in Prometheus).`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("li", {
|
|
parentName: "ul"
|
|
}, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `GroupBySlice`), `: the slice form of `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "li"
|
|
}, `GroupBy`), `.`)), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `In general, you'll probably want to use the `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `Series`), `, `, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `LabelMatchers`), `, and
|
|
`, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("inlineCode", {
|
|
parentName: "p"
|
|
}, `GroupBy`), ` fields. The other two are for advanced usage.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `The query is expected to return one value for each object requested. The
|
|
adapter will use the labels on the returned series to associate a given
|
|
series back to its corresponding object.`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("p", null, `For example:`), /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("pre", null, /*#__PURE__*/ (0,_mdx_js_react__WEBPACK_IMPORTED_MODULE_1__/* .mdx */ .kt)("code", {
|
|
parentName: "pre",
|
|
"className": "language-yaml"
|
|
}, `# convert cumulative cAdvisor metrics into rates calculated over 2 minutes
|
|
metricsQuery: "sum(rate(<<.Series>>{<<.LabelMatchers>>,container_name!="POD"}[2m])) by (<<.GroupBy>>)"
|
|
`)));
|
|
}
|
|
MDXContent.isMDXComponent = true;
|
|
|
|
|
|
/***/ })
|
|
|
|
}]); |