--- sort: 9 --- # Quick start Operator serves to make running VictoriaMetrics applications on top of Kubernetes as easy as possible while preserving Kubernetes-native configuration options. ## Installing by Manifest Obtain release from releases page: [https://github.com/VictoriaMetrics/operator/releases](https://github.com/VictoriaMetrics/operator/releases) We suggest use the latest release. ```console # Get latest release version from https://github.com/VictoriaMetrics/operator/releases/latest export VM_VERSION=`basename $(curl -fs -o/dev/null -w %{redirect_url} https://github.com/VictoriaMetrics/operator/releases/latest)` wget https://github.com/VictoriaMetrics/operator/releases/download/$VM_VERSION/bundle_crd.zip unzip bundle_crd.zip ``` > TIP, operator use monitoring-system namespace, but you can install it to specific namespace with command > sed -i "s/namespace: monitoring-system/namespace: YOUR_NAMESPACE/g" release/operator/* First of all, you have to create [custom resource definitions](https://github.com/VictoriaMetrics/operator) ```console kubectl apply -f release/crds ``` Then you need RBAC for operator, relevant configuration for the release can be found at release/operator/rbac.yaml Change configuration for operator at `release/operator/manager.yaml`, possible settings: [operator-settings](/vars.MD) and apply it: ```console kubectl apply -f release/operator/ ``` Check the status of operator ```console kubectl get pods -n monitoring-system #NAME READY STATUS RESTARTS AGE #vm-operator-667dfbff55-cbvkf 1/1 Running 0 101s ``` ## Installing by Kustomize You can install operator using [Kustomize](https://kustomize.io/) by pointing to the remote kustomization file. ```yaml # Get latest release version from https://github.com/VictoriaMetrics/operator/releases/latest export VM_VERSION=`basename $(curl -fs -o/dev/null -w %{redirect_url} https://github.com/VictoriaMetrics/operator/releases/latest)` cat << EOF > kustomization.yaml apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - github.com/VictoriaMetrics/operator/config/default?ref=${VM_VERSION} images: - name: victoriametrics/operator newTag: ${VM_VERSION} EOF ``` You can change [operator-settings](/vars.MD), or use your custom namespace see [kustomize-example](https://github.com/YuriKravetc/yurikravetc.github.io/tree/main/Operator/kustomize-example). Build template ```console kustomize build . -o monitoring.yaml ``` Apply manifests ```console kubectl apply -f monitoring.yaml ``` Check the status of operator ```console kubectl get pods -n monitoring-system #NAME READY STATUS RESTARTS AGE #vm-operator-667dfbff55-cbvkf 1/1 Running 0 101s ``` ## Installing to ARM There is no need in an additional configuration for ARM. Operator and VictoriaMetrics have full support for it. ## Create related resources The VictoriaMetrics Operator introduces additional resources in Kubernetes to declare the desired state of a Victoria Metrics applications and Alertmanager cluster as well as the Prometheus resources configuration. The resources it introduces are: * [VMSingle](#vmsingle) * [VMCluster](#vmcluster) * [VMAgent](#vmagent) * [VMAlert](#vmalert) * [VMAlertmanager](#vmalertmanager) * [VMServiceScrape](#vmservicescrape) * [VMRule](#vmrule) * [VMPodScrape](#vmpodscrape) * [VMProbe](#vmprobe) * [VMStaticScrape](#vmstaticscrape) * [VMAuth](#vmauth) * [VMUser](#vmuser) * [Selectors](#object-selectors) ## VMSingle [VMSingle](https://github.com/VictoriaMetrics/VictoriaMetrics/) represents database for storing metrics, for all possible config options check api [doc](https://docs.victoriametrics.com/operator/api.html#vmsingle): ```yaml cat < 1` {% raw %} ```yaml cat << 'EOF' | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMRule metadata: name: example-vmrule-reload-config labels: project: devops spec: groups: - name: vmalert rules: - alert: vmalert config reload error expr: delta(vmalert_config_last_reload_errors_total[5m]) > 0 for: 10s labels: severity: major job: "{{ $labels.job }}" annotations: value: "{{ $value }}" description: 'error reloading vmalert config, reload count for 5 min {{ $value }}' EOF ``` {% endraw %} Ensure, that new alert was started: ```console kubectl logs vmalert-example-vmalert-6f8748c6f9-hcfrr vmalert 2020-08-03T09:07:49.772Z info VictoriaMetrics/app/vmalert/web.go:45 api config reload was called, sending sighup 2020-08-03T09:07:49.772Z info VictoriaMetrics/app/vmalert/main.go:115 SIGHUP received. Going to reload rules ["/etc/vmalert/config/vm-example-vmalert-rulefiles-0/*.yaml"] ... 2020-08-03T09:07:49.772Z info VictoriaMetrics/app/vmalert/manager.go:83 reading rules configuration file from "/etc/vmalert/config/vm-example-vmalert-rulefiles-0/*.yaml" 2020-08-03T09:07:49.773Z info VictoriaMetrics/app/vmalert/group.go:169 group "vmAlertGroup": received stop signal 2020-08-03T09:07:49.773Z info VictoriaMetrics/app/vmalert/main.go:124 Rules reloaded successfully from ["/etc/vmalert/config/vm-example-vmalert-rulefiles-0/*.yaml"] 2020-08-03T09:07:49.773Z info VictoriaMetrics/app/vmalert/group.go:153 group "vmalert" started with interval 30s ``` Let's trigger it by adding some incorrect rule {% raw %} ```yaml cat << 'EOF' | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMRule metadata: name: example-vmrule-incorrect-rule labels: project: devops spec: groups: - name: incorrect rule rules: - alert: vmalert bad config expr: bad expression for: 10s labels: severity: major annotations: value: "{{ $badValue | bad function }}" EOF ``` {% endraw %} `VMAlert` will report incorrect rule config and fire alert: ```console 2020-08-03T09:11:40.672Z info VictoriaMetrics/app/vmalert/main.go:115 SIGHUP received. Going to reload rules ["/etc/vmalert/config/vm-example-vmalert-rulefiles-0/*.yaml"] ... 2020-08-03T09:11:40.672Z info VictoriaMetrics/app/vmalert/manager.go:83 reading rules configuration file from "/etc/vmalert/config/vm-example-vmalert-rulefiles-0/*.yaml" 2020-08-03T09:11:40.673Z error VictoriaMetrics/app/vmalert/main.go:119 error while reloading rules: cannot parse configuration file: invalid group "incorrect rule" in file "/etc/vmalert/config/vm-example-vmalert-rulefiles-0/default-example-vmrule-incorrect-rule.yaml": invalid rule "incorrect rule"."vmalert bad config": invalid expression: unparsed data left: "expression" ``` Clean up incorrect rule: ```console kubectl delete vmrule example-vmrule-incorrect-rule ``` ## VMNodeScrape `VMNodeScrape` is useful for node exporters monitoring, lets create scraper for cadvisor metrics: ```yaml cat << EOF | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMNodeScrape metadata: name: cadvisor-metrics spec: scheme: "https" tlsConfig: insecureSkipVerify: true caFile: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" bearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token" relabelConfigs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - targetLabel: __address__ replacement: kubernetes.default.svc:443 - sourceLabels: [__meta_kubernetes_node_name] regex: (.+) targetLabel: __metrics_path__ replacement: /api/v1/nodes/$1/proxy/metrics/cadvisor EOF ``` ## VMProbe `VMProbe` required `VMAgent` and some external prober, blackbox exporter in our case. Ensure that you have `VMAgent` and `VMSingle`: ```yaml cat < 443/TCP 4h21m prometheus-blackbox-exporter ClusterIP 10.105.251.80 9115/TCP 4m36s vmagent-example-vmagent ClusterIP 10.102.31.47 8429/TCP 12m vmsingle-example-vmsingle-persisted ClusterIP 10.107.69.7 8429/TCP 12m ``` So, we will probe `VMAgent` with url - `vmagent-example-vmagent.default.svc:9115/heath` with blackbox url: `prometheus-blackbox-exporter.default.svc:9115` and module: `http_2xx` it was specified at blackbox configmap. ```yaml cat << EOF | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMProbe metadata: name: probe-agent spec: jobName: static-probe vmProberSpec: # by default scheme http, and path is /probe url: prometheus-blackbox-exporter.default.svc:9115 module: http_2xx targets: staticConfig: targets: - vmagent-example-vmagent.default.svc:8429/health interval: 2s EOF ``` Now new target must be added to `VMAgent` configuration, and it starts probing itself throw blackbox exporter. Let's try another target probe type - `Ingress`. Create ingress rule for `VMSingle` and create `VMProbe` for it: ```yaml cat << EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: labels: app: victoria-metrics-single name: victoria-metrics-single spec: rules: - host: vmsingle.example.com http: paths: - backend: serviceName: vmsingle-example-vmsingle-persisted servicePort: 8428 path: / - host: vmsingle2.example.com http: paths: - backend: serviceName: vmsingle-example-vmsingle-persisted servicePort: 8428 path: / --- apiVersion: operator.victoriametrics.com/v1beta1 kind: VMProbe metadata: name: probe-single-ingress spec: vmProberSpec: # by default scheme http, and path is /probe url: prometheus-blackbox-exporter.default.svc:9115 module: http_2xx targets: ingress: selector: matchLabels: app: victoria-metrics-single interval: 10s EOF ``` This configuration will add 2 additional targets for probing: `vmsingle2.example.com` and `vmsingle.example.com`. But probes will be unsuccessful, coz there is no such hosts. ## VMStaticScrape It generates config part of `VMAgent` with static_configs, targets for targetEndpoint is a required parameter. It has various options for scraping configuration of target (with basic auth,tls access, by specific port name etc). Add `VMAgent` and Example app from step above and continue this step. With simple configuration: ```yaml cat << EOF | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMStaticScrape metadata: name: vmstaticscrape-sample spec: jobName: static targetEndpoints: - targets: ["192.168.0.1:9100","196.168.0.50:9100"] labels: env: dev project: operator EOF ``` 2 targets must be added to `VMAgent` scrape config: ```console static_configs: added targets: 2, removed targets: 0; total targets: 2 ``` ## VMAuth [VMAuth](https://docs.victoriametrics.com/vmauth.html) allows protecting application with authentication and route traffic by rules. api docs [link](https://docs.victoriametrics.com/operator/api.html#vmauthspec) First create `VMAuth` configuration: ```yaml cat << EOF | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMAuth metadata: name: example namespace: default spec: ingress: {} selectAllByDefault: true EOF ``` It will catch all `VMUser` at any kubernetes namespace and create `Ingress` record for it. ```text kubectl get pods NAME READY STATUS RESTARTS AGE vmauth-example-ffcc78fcc-xddk7 2/2 Running 0 84s kubectl get ingress NAME CLASS HOSTS ADDRESS PORTS AGE vmauth-example * 80 106s kubectl get secret -l app.kubernetes.io/name=vmauth NAME TYPE DATA AGE vmauth-config-example Opaque 1 2m32s ``` Generated configuration can be retrieved with command: {% raw %} ```text kubectl get secrets/vmauth-config-example -o=go-template='{{index .data "config.yaml.gz"}}' | base64 -d | gunzip users: - url_prefix: http://localhost:8428 bearer_token: some-default-token ``` {% endraw %} Operator generates default config, if `VMUser`s for given `VMAuth` wasn't found. ## VMUser `VMUser` configures `VMAuth`. api doc [link](https://docs.victoriametrics.com/operator/api.html#vmuserspec) There are two authentication mechanisms: `bearerToken` and `basicAuth` with `username` and `password`. Only one of them can be used with `VMUser` at one time. If you need to provide access with different mechanisms for single endpoint, create multiple `VMUsers`. If `username` is empty, metadata.name from `VMUser` used as `username`. If `password` is empty, operator generates random password for `VMUser`. This password added to the `Secret` for this `VMUser` at `data.password` field. Operator creates `Secret` for every `VMUser` with name - `vmuser-{VMUser.metadata.name}`. It places `username` + `password` or `bearerToken` into `data` section. `TargetRefs` is required field for `VMUser`, it allows to configure routing with: - `static` ref: ```yaml - static: url: http://vmalertmanager.service.svc:9093 ``` - `crd` ref, allows to target CRD kind of operator, this `CRDObject` must exist. ```yaml - crd: kind: VMAgent name: example namespace: default ``` Supported kinds are: `VMAgent, VMSingle, VMAlert, VMAlertmanager, VMCluster/vminsert, VMCluster/vmselect, VMCluster/vmstorage` `paths` - configures allowed routing paths for given `targetRef`. Let's create example, with access to `VMSingle` and `VMAlert` as static target: ```yaml cat << EOF | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMSingle metadata: name: example namespace: default spec: retentionPeriod: "2d" --- apiVersion: operator.victoriametrics.com/v1beta1 kind: VMAlert metadata: name: example spec: replicaCount: 1 datasource: url: "http://vmsingle-example.default.svc:8429" notifier: url: "http://vmalertmanager-example.default.svc:9093" evaluationInterval: "20s" ruleSelector: {} EOF ``` Check its status ```console kubectl get pods NAME READY STATUS RESTARTS AGE vmalert-example-775b8dfbc9-vzlnv 1/2 Running 0 3s vmauth-example-ffcc78fcc-xddk7 2/2 Running 0 29m vmsingle-example-6496b5c95d-k6hhp 1/1 Running 0 3s ``` Then create `VMUser` ```yaml cat << EOF | kubectl apply -f - apiVersion: operator.victoriametrics.com/v1beta1 kind: VMUser metadata: name: example spec: username: simple-user password: simple-password targetRefs: - crd: kind: VMSingle name: example namespace: default paths: ["/.*"] - static: url: http://vmalert-example.default.svc:8080 paths: ["/api/v1/groups","/api/v1/alerts"] EOF ``` Configuration changes for `VMAuth` takes some time, coz of mounted secret, its eventually updated by kubelet. Check vmauth log for changes: ```console kubectl logs vmauth-example-ffcc78fcc-xddk7 vmauth -f --tail 10 2021-05-31T10:46:40.171Z info VictoriaMetrics/app/vmauth/auth_config.go:168 Loaded information about 1 users from "/opt/vmauth/config.yaml" 2021-05-31T10:46:40.171Z info VictoriaMetrics/app/vmauth/main.go:37 started vmauth in 0.000 seconds 2021-05-31T10:46:40.171Z info VictoriaMetrics/lib/httpserver/httpserver.go:82 starting http server at http://:8427/ 2021-05-31T10:46:40.171Z info VictoriaMetrics/lib/httpserver/httpserver.go:83 pprof handlers are exposed at http://:8427/debug/pprof/ 2021-05-31T10:46:45.077Z info VictoriaMetrics/app/vmauth/auth_config.go:143 SIGHUP received; loading -auth.config="/opt/vmauth/config.yaml" 2021-05-31T10:46:45.077Z info VictoriaMetrics/app/vmauth/auth_config.go:168 Loaded information about 1 users from "/opt/vmauth/config.yaml" 2021-05-31T10:46:45.077Z info VictoriaMetrics/app/vmauth/auth_config.go:150 Successfully reloaded -auth.config="/opt/vmauth/config.yaml" 2021-05-31T11:18:21.313Z info VictoriaMetrics/app/vmauth/auth_config.go:143 SIGHUP received; loading -auth.config="/opt/vmauth/config.yaml" 2021-05-31T11:18:21.313Z info VictoriaMetrics/app/vmauth/auth_config.go:168 Loaded information about 1 users from "/opt/vmauth/config.yaml" 2021-05-31T11:18:21.313Z info VictoriaMetrics/app/vmauth/auth_config.go:150 Successfully reloaded -auth.config="/opt/vmauth/config.yaml" ``` Now lets try to access protected endpoints, i will use port-forward for that: ```console kubectl port-forward vmauth-example-ffcc78fcc-xddk7 8427 # at separate terminal execute: # vmsingle response curl http://localhost:8427 -u 'simple-user:simple-password' # vmalert response curl localhost:8427/api/v1/groups -u 'simple-user:simple-password' ``` Check create secret for application access: ```console kubectl get secrets vmuser-example NAME TYPE DATA AGE vmuser-example Opaque 2 6m33s ``` ## Migration from prometheus-operator objects By default, the operator converts all existing prometheus-operator API objects into corresponding VictoriaMetrics Operator objects You can control this behaviour by setting env variable for operator: ```console #disable convertion for each object VM_ENABLEDPROMETHEUSCONVERTER_PODMONITOR=false VM_ENABLEDPROMETHEUSCONVERTER_SERVICESCRAPE=false VM_ENABLEDPROMETHEUSCONVERTER_PROMETHEUSRULE=false VM_ENABLEDPROMETHEUSCONVERTER_PROBE=false ``` Otherwise, VictoriaMetrics Operator would try to discover prometheus-operator API and convert it. Conversion of api objects can be controlled by annotations, added to `VMObject`s, there are following annotations: - `operator.victoriametrics.com/merge-meta-strategy` - it controls syncing of metadata labels and annotations between `VMObject`s and `Prometheus` api objects during updates to `Prometheus` objects. By default, it has `prefer-prometheus`. And annotations and labels will be used from `Prometheus` objects, manually set values will be dropped. You can set it to `prefer-victoriametrics`. In this case all labels and annotations applied to `Prometheus` object will be ignored and `VMObject` will use own values. Two additional strategies annotations -`merge-victoriametrics-priority` and `merge-prometheus-priority` merges labelSets into one combined labelSet, with priority. Example: ```yaml apiVersion: operator.victoriametrics.com/v1beta1 kind: VMServiceScrape metadata: annotations: meta.helm.sh/release-name: prometheus operator.victoriametrics.com/merge-meta-strategy: prefer-victoriametrics labels: release: prometheus name: prometheus-monitor spec: endpoints: [] ``` - `operator.victoriametrics.com/ignore-prometheus-updates` - it controls updates from Prometheus api objects. By default, it set to `disabled`. You define it to `enabled` state and all updates from Prometheus api objects will be ignored. ```yaml apiVersion: operator.victoriametrics.com/v1beta1 kind: VMServiceScrape metadata: annotations: meta.helm.sh/release-name: prometheus operator.victoriametrics.com/ignore-prometheus-updates: enabled labels: release: prometheus name: prometheus-monitor spec: endpoints: [] ``` By default the operator doesn't make converted objects disappear after original ones are deleted. To change this behaviour configure adding `OwnerReferences` to converted objects: ```console VM_ENABLEDPROMETHEUSCONVERTEROWNERREFERENCES=true ``` Converted objects will be linked to the original ones and will be deleted by kubernetes after the original ones are deleted. ### prometheus Rule duplication `Prometheus` allows to specify rules with the same content with-in one group at Rule spec, but its forbidden by vmalert. You can tell operator to deduplicate this rules by adding annotation to the `VMAlert` crd definition. In this case operator skips rule with the same values, see example below. ```yaml apiVersion: operator.victoriametrics.com/v1beta1 kind: VMAlert metadata: name: example-vmalert-with-dedup annotations: operator.victoriametrics.com/vmalert-deduplicate-rules: "true" spec: replicaCount: 1 datasource: url: "http://vmsingle-example-vmsingle-persisted.default.svc:8429" notifier: url: "http://vmalertmanager-example-alertmanager.default.svc:9093" evaluationInterval: "30s" ruleNamespaceSelector: {} ruleSelector: {} ``` Now operator will transform this `VMRule`: ```yaml apiVersion: operator.victoriametrics.com/v1beta1 kind: VMRule metadata: name: example-vmrule-reload-config labels: project: devops spec: groups: - name: vmalert rules: - alert: vmalert config reload error expr: delta(vmalert_config_last_reload_errors_total[5m]) > 0 for: 10s labels: severity: major - alert: vmalert config reload error expr: delta(vmalert_config_last_reload_errors_total[5m]) > 0 for: 10s labels: severity: major - alert: vmalert config reload error expr: delta(vmalert_config_last_reload_errors_total[5m]) > 0 for: 2m labels: severity: critical ``` to the rule config: ```yaml groups: - name: vmalert rules: - alert: vmalert config reload error expr: delta(vmalert_config_last_reload_errors_total[5m]) > 0 for: 10s labels: severity: major - alert: vmalert config reload error expr: delta(vmalert_config_last_reload_errors_total[5m]) > 0 for: 2m labels: severity: critical ``` ## Expose the VMSingle API > WARNING: Please protect delete endpoint before exposing it [doc](https://github.com/VictoriaMetrics/VictoriaMetrics#how-to-delete-time-series) Example for Kubernetes Nginx ingress [doc](https://kubernetes.github.io/ingress-nginx/examples/auth/basic/) ```console #generate creds htpasswd -c auth foo #create basic auth secret cat <