VictorialMetrics 集羣模式的使用
前面我們介紹了單節點版本的 VictorialMetrics 的使用,對於低於每秒一百萬個數據點的攝取率,建議使用單節點版本而不是集羣版本。單節點版本可根據 CPU 內核、RAM 和可用存儲空間的數量進行擴展。單節點版本比集羣版本更容易配置和操作,所以在使用集羣版本之前要三思而後行。上面我們介紹了 VM 的單節點版本的基本使用,接下來我們來介紹下如何使用集羣版。
集羣版主要特點:
-
支持單節點版本的所有功能。
-
性能和容量水平擴展。
-
支持時間序列數據的多個獨立命名空間(多租戶)。
-
支持多副本。
組件
前面我們瞭解了 VM 的基本架構,對於集羣模式下主要包含以下幾個服務:
-
vmstorage:存儲原始數據並返回指定標籤過濾器在給定時間範圍內的查詢數據,當-storageDataPath指向的目錄包含的可用空間少於-storage.minFreeDiskSpaceBytes時,vmstorage節點會自動切換到只讀模式,vminsert節點也會停止向此類節點發送數據並開始將數據重新路由到剩餘的vmstorage節點。 -
vminsert:接受攝取的數據並根據指標名稱及其所有標籤的一致性哈希將其分散存儲到vmstorage節點。 -
vmselect:通過從所有配置的vmstorage節點獲取所需數據來執行查詢。
每個服務都可以進行獨立擴展,vmstorage 節點之間互不瞭解、互不通信,並且不共享任何數據。這樣可以增加集羣的可用性,並且簡化了集羣的維護和擴展。最小的集羣必須包含以下節點:
-
帶有
-retentionPeriod和-storageDataPath參數的單vmstorage節點 -
帶有
-storageNode=<vmstorage_host>的單vminsert節點 -
帶有
-storageNode=<vmstorage_host>的單vmselect節點
但是我們建議爲每個服務組件運行至少兩個節點以實現高可用性,這樣當單個節點暫時不可用時,集羣會繼續工作,而且其餘節點還可以處理增加的工作負載。如果你的集羣規模較大,那麼可以運行多個小型的 vmstorage 節點,因爲這樣可以在某些 vmstorage 節點暫時不可用時減少剩餘 vmstorage 節點上的工作負載增加。
各個服務除了可以通過參數標誌進行配置之外,也可以通過環境變量的方式進行配置:
-
-envflag.enable標誌必須設置 -
每個標誌中的
.必須替換爲_,例如-insert.maxQueueDuration <duration>可以轉換爲insert_maxQueueDuration=<duration> -
對於重複的標誌,可以使用另一種語法,通過使用
,作爲分隔符將不同的值連接成一個,例如-storageNode <nodeA> -storageNode <nodeB>將轉換爲-storageNode=<nodeA>,<nodeB> -
可以使用
-envflag.prefix爲環境變量設置前綴,例如設置了-envflag.prefix=VM*,則環境變量參數必須以VM*開頭
多租戶
VM 集羣也支持多個獨立的租戶(也叫命名空間),租戶由 accountID 或 accountID:projectID 來標識,它們被放在請求的 urls 中。
-
每個
accountID和projectID都由一個 [0 .. 2^32] 範圍內的任意 32 位整數標識,如果缺少projectID,則自動將其分配爲 0。有關租戶的其他信息,例如身份驗證令牌、租戶名稱、限額、計費等,將存儲在一個單獨的關係型數據庫中。此數據庫必須由位於 VictoriaMetrics 集羣前面的單獨服務管理,例如vmauth或vmgateway。 -
當第一個數據點寫入指定租戶時,租戶被自動創建。
-
所有租戶的數據均勻分佈在可用的
vmstorage節點中,當不同租戶有不同的數據量和不同的查詢負載時,這保證了vmstorage節點之間的均勻負載。 -
數據庫性能和資源使用不依賴於租戶的數量,它主要取決於所有租戶中活躍時間序列的總數。如果一個時間序列在過去一小時內至少收到一個樣本,或者在過去一小時內被查詢,則認爲時間序列是活躍的。
-
VictoriaMetrics 不支持在單個請求中查詢多個租戶。
集羣擴展
VM 集羣的性能和容量可以通過兩種方式進行擴展:
-
通過向集羣中的現有節點添加更多資源(CPU、RAM、磁盤 IO、磁盤空間、網絡帶寬),也叫垂直可擴展性。
-
通過向集羣添加更多節點,又叫水平擴展性。
對於集羣擴展有一些通用的建議:
-
向現有
vmselect節點添加更多 CPU 和內存,可以提高複雜查詢的性能,這些查詢可以處理大量的時間序列和大量的原始樣本。 -
添加更多
vmstorage節點可以增加集羣可以處理的活躍時間序列的數量,這也提高了對高流失率 (churn rate) 的時間序列的查詢性能。集羣穩定性也會隨着vmstorage節點數量的增加而提高,當一些vmstorage節點不可用時,活躍的vmstorage節點需要處理較低的額外工作負載。 -
向現有
vmstorage節點添加更多 CPU 和內存,可以增加集羣可以處理的活躍時間序列的數量。與向現有vmstorage節點添加更多 CPU 和內存相比,最好添加更多vmstorage節點,因爲更多的vmstorage節點可以提高集羣穩定性,並提高對高流失率的時間序列的查詢性能。 -
添加更多的
vminsert節點會提高數據攝取的最大速度,因爲攝取的數據可以在更多的vminsert節點之間進行拆分。 -
添加更多的
vmselect節點可以提高查詢的最大速度,因爲傳入的併發請求可能會在更多的vmselect節點之間進行拆分。
集羣可用性
-
HTTP 負載均衡器需要停止將請求路由到不可用的
vminsert和vmselect節點。 -
如果至少存在一個
vmstorage節點,則集羣仍然可用: -
vminsert將傳入數據從不可用的vmstorage節點重新路由到健康的vmstorage節點 -
如果至少有一個
vmstorage節點可用,則vmselect會繼續提供部分響應。如果優先考慮可用性的一致性,則將-search.denyPartialResponse標誌傳遞給vmselect或將請求中的deny_partial_response=1查詢參數傳遞給vmselect。
去重
如果 -dedup.minScrapeInterval 命令行標誌設置爲大於 0 的時間,VictoriaMetrics 會去除重複數據點。例如,-dedup.minScrapeInterval=60s 將對同一時間序列上的數據點進行重複數據刪除,如果它們位於同一離散的 60 秒存儲桶內,最早的數據點將被保留。在時間戳相等的情況下,將保留任意數據點。
-dedup.minScrapeInterval 的推薦值是等於 Prometheus 配置中的 scrape_interval 的值,建議在所有抓取目標中使用一個 scrape_interval 配置。
如果 HA 中多個相同配置的 vmagent 或 Prometheus 實例將數據寫入同一個 VictoriaMetrics 實例,則重複數據刪除會減少磁盤空間使用。這些 vmagent 或 Prometheus 實例在其配置中必須具有相同的 external_labels 部分,因此它們將數據寫入相同的時間序列。
容量規劃
集羣容量隨着可用資源的增加而線性擴展,每個節點類型所需的 CPU 和內存數量很大程度上取決於工作負載 - 活躍時間序列的數量、序列流失率、查詢類型、查詢 QPS 等。建議爲你的生產工作負載部署一個測試的 VictoriaMetrics 集羣,並反覆調整每個節點的資源和每個節點類型的節點數量,直到集羣變得穩定。同樣也建議爲集羣設置監控,有助於確定集羣設置中的瓶頸問題。
指定保留所需的存儲空間(可以通過 vmstorage 中的 -retentionPeriod 命令行標誌設置)可以從測試運行中的磁盤空間使用情況推斷出來。例如,如果在生產工作負載上運行一天後的存儲空間使用量爲 10GB,那麼對於 -retentionPeriod=100d(100 天保留期)來說,它至少需要 10GB*100=1TB 的磁盤空間。可以使用 VictoriaMetrics 集羣的官方 Grafana 儀表板 (https://grafana.com/grafana/dashboards/11176) 監控存儲空間使用情況。
建議留出以下數量的備用資源。
-
所有節點類型中 50% 的空閒內存,以減少工作負載臨時激增時因爲 OOM 崩潰的可能性。
-
所有節點類型中 50% 的空閒 CPU,以減少工作負載臨時高峯期間的慢速概率。
-
vmstorage節點上-storageDataPath命令行標誌指向的目錄中至少有 30% 的可用存儲空間。
VictoriaMetrics 集羣的一些容量規劃技巧:
-
副本集將集羣所需的資源量最多增加 N 倍,其中 N 是複製因子。
-
可以通過添加更多
vmstorage節點和 / 或通過增加每個vmstorage節點的內存和 CPU 資源來增加活躍時間序列的集羣容量。 -
可以通過增加
vmstorage節點的數量和 / 或通過增加每個vmselect節點的內存和 CPU 資源來減少查詢延遲。 -
所有
vminsert節點所需的 CPU 內核總數可以通過攝取率計算:CPUs = ingestion_rate / 100K。 -
vminsert節點上的-rpc.disableCompression命令行標誌可以增加攝取容量,但代價是vminsert和vmstorage之間的網絡帶寬使用率會更高。
副本和數據安全
默認情況下,VictoriaMetrics 的數據複製依賴 -storageDataPath 指向的底層存儲來完成。
但是我們也可以手動通過將 -replicationFactor=N 命令參數傳遞給 vminsert 來啓用複製,這保證瞭如果多達 N-1 個 vmstorage 節點不可用,所有數據仍可用於查詢。集羣必須至少包含 2*N-1 個 vmstorage 節點,其中 N 是複製因子,以便在 N-1 個存儲節點丟失時爲新攝取的數據維持指定的複製因子。
例如,當 -replicationFactor=3 傳遞給 vminsert 時,它將所有攝取的數據複製到 3 個不同的 vmstorage 節點,因此最多可以丟失 2 個 vmstorage 節點而不會丟失數據。vmstorage 節點的最小數量應該等於 2*3-1 = 5,因此當 2 個 vmstorage 節點丟失時,剩餘的 3 個 vmstorage 節點可以爲新攝取的數據提供服務。
啓用複製後,必須將 -dedup.minScrapeInterval=1ms 命令行標誌傳遞給 vmselect 節點,當多達 N-1 個 vmstorage 節點響應緩慢和 / 或暫時不可用時,可以將可選的 -replicationFactor=N 參數傳遞給 vmselect 以提高查詢性能,因爲 vmselect 不等待來自多達 N-1 個 vmstorage 節點的響應。有時,vmselect 節點上的 -replicationFactor 可能會導致部分響應。-dedup.minScrapeInterval=1ms 在查詢期間對複製的數據進行重複數據刪除,如果重複數據從配置相同的 vmagent 實例或 Prometheus 實例推送到 VictoriaMetrics,則必須根據重複數據刪除文檔將 -dedup.minScrapeInterval 設置爲更大的值。
請注意,複製不會從災難中保存,因此建議執行定期備份。另外 複製會增加資源使用率 - CPU、內存、磁盤空間、網絡帶寬 - 最多 -replicationFactor 倍。所以可以將複製轉移 -storageDataPath 指向的底層存儲來做保證,例如 Google Compute Engine 永久磁盤,該磁盤可以防止數據丟失和數據損壞,它還提供始終如一的高性能,並且可以在不停機的情況下調整大小。對於大多數用例來說,基於 HDD 的永久性磁盤應該足夠了。
備份
建議從即時快照執行定期備份,以防止意外數據刪除等錯誤。必須爲每個 vmstorage 節點執行以下步驟來創建備份:
-
可以通過訪問
/snapshot/create這個 HTTP handler 來創建即時快照,它將創建快照並返回其名稱。 -
使用
vmbackup組件從<-storageDataPath>/snapshots/<snapshot_name>文件夾歸檔創建的快照。歸檔過程不會干擾vmstorage工作,因此可以在任何合適的時間執行。 -
通過
/snapshot/delete?snapshot=<snapshot_name>或/snapshot/delete_all刪除未使用的快照,以釋放佔用的存儲空間。 -
無需在所有
vmstorage節點之間同步備份。
從備份恢復:
-
使用
kill -INT停止vmstorage節點。 -
使用
vmrestore組件將備份中的數據還原到-storageDataPath目錄。 -
啓動
vmstorage節點。
在瞭解了 VM 集羣的一些配置細節後,接下來我們就來開始部署 VM 集羣。
部署
如果你已經對 VM 組件非常瞭解了,那麼推薦使用 Helm Chart 的方式進行一鍵安裝。
☸ ➜ helm repo add vm https://victoriametrics.github.io/helm-charts/
☸ ➜ helm repo update
# 導出默認的 values 值到 values.yaml 文件中
☸ ➜ helm show values vm/victoria-metrics-cluster > values.yaml
# 根據自己的需求修改 values.yaml 文件配置
# 執行下面的命令進行一鍵安裝
☸ ➜ helm install victoria-metrics vm/victoria-metrics-cluster -f values.yaml -n NAMESPACE
# 獲取 vm 運行的 pods 列表
☸ ➜ kubectl get pods -A | grep 'victoria-metrics'
我們這裏選擇手動方式進行部署,之所以選擇手動部署的方式是爲了能夠了解各個組件的更多細節。
由於 vmstorage 組件是無狀態的,這裏我們先使用 StatefulSet 進行部署,由於該組件也是可以進行擴展的,這裏我們首先部署兩個副本,對應的資源清單如下所示:
# cluster-vmstorage.yaml
apiVersion: v1
kind: Service
metadata:
name: cluster-vmstorage
namespace: kube-vm
labels:
app: vmstorage
spec:
clusterIP: None
ports:
- port: 8482
targetPort: http
name: http
- port: 8401
targetPort: vmselect
name: vmselect
- port: 8400
targetPort: vminsert
name: vminsert
selector:
app: vmstorage
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: vmstorage
namespace: kube-vm
labels:
app: vmstorage
spec:
serviceName: cluster-vmstorage
selector:
matchLabels:
app: vmstorage
replicas: 2
podManagementPolicy: OrderedReady
template:
metadata:
labels:
app: vmstorage
spec:
containers:
- name: vmstorage
image: "victoriametrics/vmstorage:v1.77.0-cluster"
imagePullPolicy: "IfNotPresent"
args:
- "--retentionPeriod=1"
- "--storageDataPath=/storage"
- --envflag.enable=true
- --envflag.prefix=VM_
- --loggerFormat=json
ports:
- name: http
containerPort: 8482
- name: vminsert
containerPort: 8400
- name: vmselect
containerPort: 8401
livenessProbe:
failureThreshold: 10
initialDelaySeconds: 30
periodSeconds: 30
tcpSocket:
port: http
timeoutSeconds: 5
readinessProbe:
failureThreshold: 3
initialDelaySeconds: 5
periodSeconds: 15
timeoutSeconds: 5
httpGet:
path: /health
port: http
volumeMounts:
- name: storage
mountPath: /storage
volumeClaimTemplates:
- metadata:
name: storage
spec:
storageClassName: longhorn
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "2Gi"
首先需要創建一個 Headless 的 Service,因爲後面的組件需要訪問到每一個具體的 Pod,在 vmstorage 啓動參數中通過 --retentionPeriod 參數指定指標數據保留時長,1 表示一個月,這也是默認的時長,然後通過 --storageDataPath 參數指定了數據存儲路徑,記得要將該目錄進行持久化。
同樣直接應用該資源即可:
☸ ➜ kubectl apply -f https://p8s.io/docs/victoriametrics/manifests/cluster-vmstorage.yaml
☸ ➜ kubectl get pods -n kube-vm -l app=vmstorage
NAME READY STATUS RESTARTS AGE
vmstorage-0 1/1 Running 0 5m40s
vmstorage-1 1/1 Running 0 3m31s
☸ ➜ kubectl get svc -n kube-vm -l app=vmstorage
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cluster-vmstorage ClusterIP None <none> 8482/TCP,8401/TCP,8400/TCP 5m46s
接着可以部署 vmselect 組件,由於該組件是無狀態的,我們可以直接使用 Deployment 來進行管理,對應的資源清單文件如下所示:
# cluster-vmselect.yaml
apiVersion: v1
kind: Service
metadata:
name: vmselect
namespace: kube-vm
labels:
app: vmselect
spec:
ports:
- name: http
port: 8481
targetPort: http
selector:
app: vmselect
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vmselect
namespace: kube-vm
labels:
app: vmselect
spec:
selector:
matchLabels:
app: vmselect
template:
metadata:
labels:
app: vmselect
spec:
containers:
- name: vmselect
image: "victoriametrics/vmselect:v1.77.0-cluster"
imagePullPolicy: "IfNotPresent"
args:
- "--cacheDataPath=/cache"
- --storageNode=vmstorage-0.cluster-vmstorage.kube-vm.svc.cluster.local:8401
- --storageNode=vmstorage-1.cluster-vmstorage.kube-vm.svc.cluster.local:8401
- --envflag.enable=true
- --envflag.prefix=VM_
- --loggerFormat=json
ports:
- name: http
containerPort: 8481
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
tcpSocket:
port: http
initialDelaySeconds: 5
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
其中最重要的部分是通過 --storageNode 參數指定所有的 vmstorage 節點地址,上面我們使用的 StatefulSet 部署的,所以可以直接使用 FQDN 的形式進行訪問。直接應用上面的對象:
☸ ➜ kubectl apply -f https://p8s.io/docs/victoriametrics/manifests/cluster-vmselect.yaml
☸ ➜ kubectl get pods -n kube-vm -l app=vmselect
NAME READY STATUS RESTARTS AGE
vmselect-bcb54965f-5rkml 1/1 Running 0 2m4s
☸ ➜ kubectl get svc -n kube-vm -l app=vmselect
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
vmselect ClusterIP 10.107.227.214 <none> 8481/TCP 2m17s
如果要進行查詢,那麼我們可以直接對外暴露 vmselect 這個 Service 服務即可,修改 Grafana 數據源地址爲 http://<select-service>/select/0/prometheus/。
接着就需要部署用來接收指標數據插入的 vminsert 組件,同樣該組件是無狀態的,其中最重要的也是需要通過 --storageNode 參數指定所有的 vmstorage 節點:
# cluster-vminsert.yaml
apiVersion: v1
kind: Service
metadata:
name: vminsert
namespace: kube-vm
labels:
app: vminsert
spec:
ports:
- name: http
port: 8480
targetPort: http
selector:
app: vminsert
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: vminsert
namespace: kube-vm
labels:
app: vminsert
spec:
selector:
matchLabels:
app: vminsert
template:
metadata:
labels:
app: vminsert
spec:
containers:
- name: vminsert
image: "victoriametrics/vminsert:v1.77.0-cluster"
imagePullPolicy: "IfNotPresent"
args:
# - -replicationFactor=2 # 可以開啓數據副本
- --storageNode=vmstorage-0.cluster-vmstorage.kube-vm.svc.cluster.local:8400
- --storageNode=vmstorage-1.cluster-vmstorage.kube-vm.svc.cluster.local:8400
- --envflag.enable=true
- --envflag.prefix=VM_
- --loggerFormat=json
ports:
- name: http
containerPort: 8480
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
livenessProbe:
tcpSocket:
port: http
initialDelaySeconds: 5
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
由於本身是無狀態的,所以可以根據需要增加副本數量,也可以配置 HPA 進行自動擴縮容。直接應用上面的資源清單:
☸ ➜ kubectl apply -f https://p8s.io/docs/victoriametrics/manifests/cluster-vminsert.yaml
☸ ➜ kubectl get pods -n kube-vm -l app=vminsert
NAME READY STATUS RESTARTS AGE
vminsert-66c88cd497-l64ps 1/1 Running 0 2m27s
☸ ➜ kubectl get svc -n kube-vm -l app=vminsert
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
vminsert ClusterIP 10.96.125.134 <none> 8480/TCP 70s
集羣模式的相關組件部署完成後,同樣我們可以先去配置前面的 Prometheus,將其數據遠程寫入到 VM 中來,修改 remote_write 的地址爲 http://vminsert:8480/insert/0/prometheus/,注意和單節點模式的 API 路徑不一樣,如下所示:
# vm-prom-config3.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: kube-vm
data:
prometheus.yaml: |
global:
scrape_interval: 15s
scrape_timeout: 15s
remote_write: # 寫入到遠程 VM 存儲,url 是遠程寫入接口地址
- url: http://vminsert:8480/insert/0/prometheus/
# queue_config: # 如果 Prometheus 抓取指標很大,可以加調整 queue,但是會提高內存佔用
# max_samples_per_send: 10000 # 每次發送的最大樣本數
# capacity: 20000
# max_shards: 30 # 最大分片數,即併發量。
scrape_configs:
- job_name: "nodes"
static_configs:
- targets: ['192.168.0.109:9111', '192.168.0.110:9111', '192.168.0.111:9111']
relabel_configs: # 通過 relabeling 從 __address__ 中提取 IP 信息,爲了後面驗證 VM 是否兼容 relabeling
- source_labels: [__address__]
regex: "(.*):(.*)"
replacement: "${1}"
target_label: 'ip'
action: replace
更新 Prometheus 配置,然後啓動 Prometheus,前面的單機模式的 VM 可以先停掉:
☸ ➜ kubectl apply -f https://p8s.io/docs/victoriametrics/manifests/vm-prom-config3.yaml
☸ ➜ kubectl scale deploy victoria-metrics --replicas=0 -n kube-vm
☸ ➜ kubectl scale deploy prometheus --replicas=1 -n kube-vm
配置成功後正常數據就可以開始寫入到 vmstorage 了,查看 vmstorage 日誌可以看到成功創建了 partition,證明現在已經在開始接收數據了:
☸ ➜ kubectl logs -f vmstorage-0 -n kube-vm
......
{"ts":"2022-05-06T08:35:15.786Z","level":"info","caller":"VictoriaMetrics/lib/storage/partition.go:206","msg":"creating a partition \"2022_05\" with smallPartsPath=\"/storage/data/small/2022_05\", bigPartsPath=\"/storage/data/big/2022_05\""}
{"ts":"2022-05-06T08:35:15.802Z","level":"info","caller":"VictoriaMetrics/lib/storage/partition.go:222","msg":"partition \"2022_05\" has been created"}
然後可以去 Grafana 重新查看 Dashboard 是否正常:
如果現在需要新增 vmstorage 節點,那麼需要按照下面的步驟進行操作:
-
使用與集羣中現有節點相同的
-retentionPeriod配置啓動新的vmstorage節點。 -
逐步重新啓動所有的
vmselect節點,添加新的-storageNode參數包含<new_vmstorage_host>。 -
逐步重新啓動所有的
vminsert節點,添加新的-storageNode參數包含<new_vmstorage_host>。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/NDPgeCxNnz84etMHNt0wJg