一文讀懂 Thanos 多集群監(jiān)控
在本文中,我們將看到Prometheus監(jiān)控技術(shù)棧的局限性,以及為什么移動(dòng)到基于Thanos的技術(shù)??梢蕴岣咧笜?biāo)留存率并降低總體基礎(chǔ)設(shè)施成本。
用于此演示的內(nèi)容可以在下面鏈接中獲取,并提交到他們各自的許可證。
- https://github.com/particuleio/teks/tree/main/terragrunt/live/thanos
- https://github.com/particuleio/terraform-kubernetes-addons/tree/main/modules/aws
Kubernetes普羅米修斯技術(shù)棧
在為我們的客戶(hù)部署Kubernetes基礎(chǔ)設(shè)施時(shí),在每個(gè)集群上部署監(jiān)控技術(shù)棧是標(biāo)準(zhǔn)做法。這個(gè)堆棧通常由幾個(gè)組件組成:
- Prometheus:收集度量標(biāo)準(zhǔn)
- 告警管理器:根據(jù)指標(biāo)查詢(xún)向各種提供者發(fā)送警報(bào)
- Grafana:可視化豪華儀表板
簡(jiǎn)化架構(gòu)如下:
注意事項(xiàng)
這種架構(gòu)有一些注意事項(xiàng),當(dāng)你想從其中獲取指標(biāo)的集群數(shù)量增加時(shí),它的伸縮性以及可擴(kuò)展性不太好。
多個(gè)Grafana
在這種設(shè)置中,每個(gè)集群都有自己的Grafana和自己的一組儀表板,維護(hù)起來(lái)很麻煩。
存儲(chǔ)指標(biāo)數(shù)據(jù)是昂貴的
Prometheus將指標(biāo)數(shù)據(jù)存儲(chǔ)在磁盤(pán)上,你必須在存儲(chǔ)空間和指標(biāo)保留時(shí)間之間做出選擇。如果你想長(zhǎng)時(shí)間存儲(chǔ)數(shù)據(jù)并在云提供商上運(yùn)行,那么如果存儲(chǔ)TB的數(shù)據(jù),塊存儲(chǔ)的成本可能會(huì)很高。同樣,在生產(chǎn)環(huán)境中,Prometheus經(jīng)常使用復(fù)制或分片或兩者同時(shí)運(yùn)行,這可能會(huì)使存儲(chǔ)需求增加兩倍甚至四倍。
解決方案
多個(gè)Grafana數(shù)據(jù)源
可以在外部網(wǎng)絡(luò)上公開(kāi)Prometheus的端點(diǎn),并將它們作為數(shù)據(jù)源添加到單個(gè)Grafana中。你只需要在Prometheus外部端點(diǎn)上使用TLS或TLS和基本認(rèn)證來(lái)實(shí)現(xiàn)安全性。此解決方案的缺點(diǎn)是不能基于不同的數(shù)據(jù)源進(jìn)行計(jì)算。
Prometheus聯(lián)邦
Prometheus聯(lián)邦允許從Prometheus中抓取Prometheus,當(dāng)你不抓取很多指標(biāo)數(shù)據(jù)時(shí),這個(gè)解決方案可以很好地工作。在規(guī)模上,如果你所有的Prometheus目標(biāo)的抓取持續(xù)時(shí)間都比抓取間隔長(zhǎng),可能會(huì)遇到一些嚴(yán)重的問(wèn)題。
Prometheus遠(yuǎn)程寫(xiě)
雖然遠(yuǎn)程寫(xiě)入是一種解決方案(也由Thanos receiver實(shí)現(xiàn)),但我們將不在本文中討論“推送指標(biāo)”部分。你可以在這里[1]閱讀關(guān)于推送指標(biāo)的利弊。建議在不信任多個(gè)集群或租戶(hù)的情況下(例如在將Prometheus構(gòu)建為服務(wù)提供時(shí)),將指標(biāo)作為最后的手段。無(wú)論如何,這可能是以后文章的主題,但我們將在這里集中討論抓取。
Thanos,它來(lái)了
Thanos是一個(gè)“開(kāi)源的,高可用的Prometheus系統(tǒng),具有長(zhǎng)期存儲(chǔ)能力”。很多知名公司都在使用Thanos,也是CNCF孵化項(xiàng)目的一部分。
Thanos的一個(gè)主要特點(diǎn)就是允許“無(wú)限”存儲(chǔ)空間。通過(guò)使用對(duì)象存儲(chǔ)(比如S3),幾乎每個(gè)云提供商都提供對(duì)象存儲(chǔ)。如果在前提環(huán)境下運(yùn)行,對(duì)象存儲(chǔ)可以通過(guò)rook或minio這樣的解決方案提供。
它是如何工作的?
Thanos和Prometheus并肩作戰(zhàn),從Prometheus開(kāi)始升級(jí)到Thanos是很常見(jiàn)的。
Thanos被分成幾個(gè)組件,每個(gè)組件都有一個(gè)目標(biāo)(每個(gè)服務(wù)都應(yīng)該這樣:)),組件之間通過(guò)gRPC進(jìn)行通信。
Thanos Sidecar
Thanos和Prometheus一起運(yùn)行(有一個(gè)邊車(chē)),每2小時(shí)向一個(gè)對(duì)象存儲(chǔ)庫(kù)輸出Prometheus指標(biāo)。這使得Prometheus幾乎是無(wú)狀態(tài)的。Prometheus仍然在內(nèi)存中保存著2個(gè)小時(shí)的度量值,所以在發(fā)生宕機(jī)的情況下,你可能仍然會(huì)丟失2個(gè)小時(shí)的度量值(這個(gè)問(wèn)題應(yīng)該由你的Prometheus設(shè)置來(lái)處理,使用HA/分片,而不是Thanos)。
Thanos sidecar與Prometheus運(yùn)營(yíng)者和Kube Prometheus棧一起,可以輕松部署。這個(gè)組件充當(dāng)Thanos查詢(xún)的存儲(chǔ)。
Thanos存儲(chǔ)
Thanos存儲(chǔ)充當(dāng)一個(gè)網(wǎng)關(guān),將查詢(xún)轉(zhuǎn)換為遠(yuǎn)程對(duì)象存儲(chǔ)。它還可以在本地存儲(chǔ)上緩存一些信息?;旧?,這個(gè)組件允許你查詢(xún)對(duì)象存儲(chǔ)以獲取指標(biāo)。這個(gè)組件充當(dāng)Thanos查詢(xún)的存儲(chǔ)。
Thanos Compactor
Thanos Compactor是一個(gè)單例(它是不可擴(kuò)展的),它負(fù)責(zé)壓縮和降低存儲(chǔ)在對(duì)象存儲(chǔ)中的指標(biāo)。下采樣是隨著時(shí)間的推移對(duì)指標(biāo)粒度的寬松。例如,你可能想將你的指標(biāo)保持2年或3年,但你不需要像昨天的指標(biāo)那么多數(shù)據(jù)點(diǎn)。這就是壓縮器的作用,它可以在對(duì)象存儲(chǔ)上節(jié)省字節(jié),從而節(jié)省成本。
Thanos Query
Thanos查詢(xún)是Thanos的主要組件,它是向其發(fā)送PromQL查詢(xún)的中心點(diǎn)。Thanos查詢(xún)暴露了一個(gè)與Prometheus兼容的端點(diǎn)。然后它將查詢(xún)分派給所有的“stores”。記住,Store可能是任何其他提供指標(biāo)的Thanos組件。Thanos查詢(xún)可以發(fā)送查詢(xún)到另一個(gè)Thanos查詢(xún)(他們可以堆疊)。
- Thanos Store
- Thanos Sidecar
- Thanos Query
還負(fù)責(zé)對(duì)來(lái)自不同Store或Prometheus的相同指標(biāo)進(jìn)行重復(fù)數(shù)據(jù)刪除。例如,如果你有一個(gè)度量值在Prometheus中,同時(shí)也在對(duì)象存儲(chǔ)中,Thanos Query可以對(duì)該指標(biāo)值進(jìn)行重復(fù)數(shù)據(jù)刪除。在Prometheus HA設(shè)置的情況下,重復(fù)數(shù)據(jù)刪除也基于Prometheus副本和分片。
Thanos Query Frontend
正如它的名字所暗示的,Thanos查詢(xún)前端是Thanos查詢(xún)的前端,它的目標(biāo)是將大型查詢(xún)拆分為多個(gè)較小的查詢(xún),并緩存查詢(xún)結(jié)果(在內(nèi)存或memcached中)。
還有其他組件,比如在遠(yuǎn)程寫(xiě)的情況下接收Thanos,但這仍然不是本文的主題。
多集群架構(gòu)
有多種方法可以將這些組件部署到多個(gè)Kubernetes集群中,根據(jù)用例的不同,有些方法比其他方法更好,在這里我們不能給出詳細(xì)的介紹。
我們的例子是在A(yíng)WS上運(yùn)行,使用tEKS[2]部署了2個(gè)集群,我們的all in one解決方案將生產(chǎn)就緒的EKS集群部署在A(yíng)WS上:
- 一個(gè)觀(guān)察者集群[3]
- 一個(gè)被觀(guān)察集群[4]
我們的部署使用了官方的kube-prometheus-stack和bitnami thanos圖表。
一切都是在我們的terraform-kubernetes-addons存儲(chǔ)庫(kù)中策劃的。
Thanos demo文件夾中的目錄結(jié)構(gòu)如下:.
- ├── env_tags.yaml
- ├── eu-west-1
- │ ├── clusters
- │ │ └── observer
- │ │ ├── eks
- │ │ │ ├── kubeconfig
- │ │ │ └── terragrunt.hcl
- │ │ ├── eks-addons
- │ │ │ └── terragrunt.hcl
- │ │ └── vpc
- │ │ └── terragrunt.hcl
- │ └── region_values.yaml
- └── eu-west-3
- ├── clusters
- │ └── observee
- │ ├── cluster_values.yaml
- │ ├── eks
- │ │ ├── kubeconfig
- │ │ └── terragrunt.hcl
- │ ├── eks-addons
- │ │ └── terragrunt.hcl
- │ └── vpc
- │ └── terragrunt.hcl
- └── region_values.yaml
這允許DRY(Don 't Repeat Yourself)基礎(chǔ)設(shè)施,并可以輕松地?cái)U(kuò)展AWS帳戶(hù)、區(qū)域和集群的數(shù)量。
觀(guān)察者集群
觀(guān)察者集群是我們的主集群,我們將從它查詢(xún)其他集群:
Prometheus正在運(yùn)行:
- Grafana啟用
- Thanos邊車(chē)上傳到特定的桶
- kube-prometheus-stack = {
- enabled = true
- allowed_cidrs = dependency.vpc.outputs.private_subnets_cidr_blocks
- thanos_sidecar_enabled = true
- thanos_bucket_force_destroy = true
- extra_values = <<-EXTRA_VALUES
- grafana:
- deploymentStrategy:
- type: Recreate
- ingress:
- enabled: true
- annotations:
- kubernetes.io/ingress.class: nginx
- cert-manager.io/cluster-issuer: "letsencrypt"
- hosts:
- - grafana.${local.default_domain_suffix}
- tls:
- - secretName: grafana.${local.default_domain_suffix}
- hosts:
- - grafana.${local.default_domain_suffix}
- persistence:
- enabled: true
- storageClassName: ebs-sc
- accessModes:
- - ReadWriteOnce
- size: 1Gi
- prometheus:
- prometheusSpec:
- replicas: 1
- retention: 2d
- retentionSize: "10GB"
- ruleSelectorNilUsesHelmValues: false
- serviceMonitorSelectorNilUsesHelmValues: false
- podMonitorSelectorNilUsesHelmValues: false
- storageSpec:
- volumeClaimTemplate:
- spec:
- storageClassName: ebs-sc
- accessModes: ["ReadWriteOnce"]
- resources:
- requests:
- storage: 10Gi
- EXTRA_VALUES
為觀(guān)察者集群生成一個(gè)CA證書(shū):
- 這個(gè)CA將被進(jìn)入sidecar的被觀(guān)察集群所信任
- 為T(mén)hanos querier組件生成TLS證書(shū),這些組件將查詢(xún)被觀(guān)察集群
Thanos組件部署:
- Thanos組件全部部署完成
- 查詢(xún)前端,作為Grafana的數(shù)據(jù)源端點(diǎn)
- 存儲(chǔ)網(wǎng)關(guān)用于查詢(xún)觀(guān)察者桶
- Query將對(duì)存儲(chǔ)網(wǎng)關(guān)和其他查詢(xún)器執(zhí)行查詢(xún)
部署的額外Thanos組件:
- 配置了TLS的Thanos查詢(xún)器對(duì)每個(gè)被觀(guān)察集群進(jìn)行查詢(xún)
- thanos-tls-querier = {
- "observee" = {
- enabled = true
- default_global_requests = true
- default_global_limits = false
- stores = [
- "thanos-sidecar.${local.default_domain_suffix}:443"
- ]
- }
- }
- thanos-storegateway = {
- "observee" = {
- enabled = true
- default_global_requests = true
- default_global_limits = false
- bucket = "thanos-store-pio-thanos-observee"
- region = "eu-west-3"
- }
被觀(guān)測(cè)集群
被觀(guān)測(cè)集群是Kubernetes集群,具有最小的Prometheus/Thanos安裝,將被觀(guān)測(cè)集群查詢(xún)。
Prometheus operator正在運(yùn)行:
- Thanos這邊就是上傳給觀(guān)察者特定的桶
- Thanos邊車(chē)與TLS客戶(hù)端認(rèn)證的入口對(duì)象一起發(fā)布,并信任觀(guān)察者集群CA
- kube-prometheus-stack = {
- enabled = true
- allowed_cidrs = dependency.vpc.outputs.private_subnets_cidr_blocks
- thanos_sidecar_enabled = true
- thanos_bucket_force_destroy = true
- extra_values = <<-EXTRA_VALUES
- grafana:
- enabled: false
- prometheus:
- thanosIngress:
- enabled: true
- ingressClassName: nginx
- annotations:
- cert-manager.io/cluster-issuer: "letsencrypt"
- nginx.ingress.kubernetes.io/ssl-redirect: "true"
- nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
- nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
- nginx.ingress.kubernetes.io/auth-tls-secret: "monitoring/thanos-ca"
- hosts:
- - thanos-sidecar.${local.default_domain_suffix}
- paths:
- - /
- tls:
- - secretName: thanos-sidecar.${local.default_domain_suffix}
- hosts:
- - thanos-sidecar.${local.default_domain_suffix}
- prometheusSpec:
- replicas: 1
- retention: 2d
- retentionSize: "6GB"
- ruleSelectorNilUsesHelmValues: false
- serviceMonitorSelectorNilUsesHelmValues: false
- podMonitorSelectorNilUsesHelmValues: false
- storageSpec:
- volumeClaimTemplate:
- spec:
- storageClassName: ebs-sc
- accessModes: ["ReadWriteOnce"]
- resources:
- requests:
- storage: 10Gi
- EXTRA_VALUES
Thanos組件部署:
- Thanos壓縮器來(lái)管理這個(gè)特定集群的下采樣
- thanos = {
- enabled = true
- bucket_force_destroy = true
- trusted_ca_content = dependency.thanos-ca.outputs.thanos_ca
- extra_values = <<-EXTRA_VALUES
- compactor:
- retentionResolution5m: 90d
- query:
- enabled: false
- queryFrontend:
- enabled: false
- storegateway:
- enabled: false
- EXTRA_VALUES
- }
再深入一點(diǎn)
讓我們檢查一下集群上正在運(yùn)行什么。關(guān)于觀(guān)察員,我們有:
- kubectl -n monitoring get pods
- NAME READY STATUS RESTARTS AGE
- alertmanager-kube-prometheus-stack-alertmanager-0 2/2 Running 0 120m
- kube-prometheus-stack-grafana-c8768466b-rd8wm 2/2 Running 0 120m
- kube-prometheus-stack-kube-state-metrics-5cf575d8f8-x59rd 1/1 Running 0 120m
- kube-prometheus-stack-operator-6856b9bb58-hdrb2 1/1 Running 0 119m
- kube-prometheus-stack-prometheus-node-exporter-8hvmv 1/1 Running 0 117m
- kube-prometheus-stack-prometheus-node-exporter-cwlfd 1/1 Running 0 120m
- kube-prometheus-stack-prometheus-node-exporter-rsss5 1/1 Running 0 120m
- kube-prometheus-stack-prometheus-node-exporter-rzgr9 1/1 Running 0 120m
- prometheus-kube-prometheus-stack-prometheus-0 3/3 Running 1 120m
- thanos-compactor-74784bd59d-vmvps 1/1 Running 0 119m
- thanos-query-7c74db546c-d7bp8 1/1 Running 0 12m
- thanos-query-7c74db546c-ndnx2 1/1 Running 0 12m
- thanos-query-frontend-5cbcb65b57-5sx8z 1/1 Running 0 119m
- thanos-query-frontend-5cbcb65b57-qjhxg 1/1 Running 0 119m
- thanos-storegateway-0 1/1 Running 0 119m
- thanos-storegateway-1 1/1 Running 0 118m
- thanos-storegateway-observee-storegateway-0 1/1 Running 0 12m
- thanos-storegateway-observee-storegateway-1 1/1 Running 0 11m
- thanos-tls-querier-observee-query-dfb9f79f9-4str8 1/1 Running 0 29m
- thanos-tls-querier-observee-query-dfb9f79f9-xsq24 1/1 Running 0 29m
- kubectl -n monitoring get ingress
- NAME CLASS HOSTS ADDRESS PORTS AGE
- kube-prometheus-stack-grafana <none> grafana.thanos.teks-tg.clusterfrak-dynamics.io k8s-ingressn-ingressn-afa0a48374-f507283b6cd101c5.elb.eu-west-1.amazonaws.com 80, 443 123m
被觀(guān)察者:
- kubectl -n monitoring get pods
- NAME READY STATUS RESTARTS AGE
- alertmanager-kube-prometheus-stack-alertmanager-0 2/2 Running 0 39m
- kube-prometheus-stack-kube-state-metrics-5cf575d8f8-ct292 1/1 Running 0 39m
- kube-prometheus-stack-operator-6856b9bb58-4cngc 1/1 Running 0 39m
- kube-prometheus-stack-prometheus-node-exporter-bs4wp 1/1 Running 0 39m
- kube-prometheus-stack-prometheus-node-exporter-c57ss 1/1 Running 0 39m
- kube-prometheus-stack-prometheus-node-exporter-cp5ch 1/1 Running 0 39m
- kube-prometheus-stack-prometheus-node-exporter-tnqvq 1/1 Running 0 39m
- kube-prometheus-stack-prometheus-node-exporter-z2p49 1/1 Running 0 39m
- kube-prometheus-stack-prometheus-node-exporter-zzqp7 1/1 Running 0 39m
- prometheus-kube-prometheus-stack-prometheus-0 3/3 Running 1 39m
- thanos-compactor-7576dcbcfc-6pd4v 1/1 Running 0 38m
- kubectl -n monitoring get ingress
- NAME CLASS HOSTS ADDRESS PORTS AGE
- kube-prometheus-stack-thanos-gateway nginx thanos-sidecar.thanos.teks-tg.clusterfrak-dynamics.io k8s-ingressn-ingressn-95903f6102-d2ce9013ac068b9e.elb.eu-west-3.amazonaws.com 80, 443 40m
我們的TLS查詢(xún)器應(yīng)該能夠查詢(xún)被觀(guān)測(cè)集群的度量標(biāo)準(zhǔn)。讓我們來(lái)看看它們的行為:
- k -n monitoring logs -f thanos-tls-querier-observee-query-687dd88ff5-nzpdh
- level=info ts=2021-02-23T15:37:35.692346206Z caller=storeset.go:387 component=storeset msg="adding new storeAPI to query storeset" address=thanos-sidecar.thanos.teks-tg.clusterfrak-dynamics.io:443 extLset="{cluster=\"pio-thanos-observee\", prometheus=\"monitoring/kube-prometheus-stack-prometheus\", prometheus_replica=\"prometheus-kube-prometheus-stack-prometheus-0\"}"
所以這個(gè)查詢(xún)器pods可以查詢(xún)我的其他集群,如果我們檢查Web,我們可以看到存儲(chǔ):
- kubectl -n monitoring port-forward thanos-tls-querier-observee-query-687dd88ff5-nzpdh 10902
太棒了,但是我只有一個(gè)存儲(chǔ),還記得我們說(shuō)過(guò)查詢(xún)器可以堆疊在一起嗎?在我們的觀(guān)察者集群中,我們有標(biāo)準(zhǔn)的http查詢(xún)器,它可以查詢(xún)架構(gòu)圖中的其他組件。
- kubectl -n monitoring port-forward thanos-query-7c74db546c-d7bp8 10902
這里我們可以看到所有的存儲(chǔ)已經(jīng)被添加到我們的中心查詢(xún)器:
- 觀(guān)察者把本地Thanos聚集
- 我們的存儲(chǔ)網(wǎng)關(guān)(一個(gè)用于遠(yuǎn)程觀(guān)測(cè)者集群,一個(gè)用于本地觀(guān)測(cè)者集群)
- 本地TLS查詢(xún)器,它可以查詢(xún)被觀(guān)察的sidecar
在Grafana可視化
最后,我們可以前往Grafana,看看默認(rèn)的Kubernetes儀表板是如何與多集群兼容的。
總結(jié)
Thanos是一個(gè)非常復(fù)雜的系統(tǒng),有很多移動(dòng)部件,我們沒(méi)有深入研究具體的自定義配置,因?yàn)樗鼤?huì)花費(fèi)太多的時(shí)間。
我們?cè)趖EKS存儲(chǔ)庫(kù)中提供了一個(gè)相當(dāng)完整的AWS實(shí)現(xiàn),它抽象了很多復(fù)雜性(主要是mTLS部分),并允許進(jìn)行很多定制。你也可以使用terraform-kubernetes-addons模塊作為獨(dú)立的組件。我們計(jì)劃在未來(lái)支持其他云提供商。不要猶豫,通過(guò)Github上的任何一個(gè)項(xiàng)目的問(wèn)題聯(lián)系我們。
根據(jù)你的基礎(chǔ)設(shè)施和需求,有許多可能適合你的Thanos實(shí)現(xiàn)。
如果你想深入研究Thanos,可以查看他們的官方kube-thanos存儲(chǔ)庫(kù),以及他們關(guān)于跨集群通信的建議[5]。
當(dāng)然,我們很樂(lè)意幫助你設(shè)置你的云原生監(jiān)控堆棧,歡迎聯(lián)系我們contact@particule.io:)
你也可以每天通過(guò)CNCF/Kubernetes Slack頻道聯(lián)系我們。