Cortex: 高可用和水平扩展的Prometheus监控系统
Prometheus已成为cloud-native世界中的默认监控应用程序和系统。对于真是使用案例,Prometheus应该是高可用的,这是有挑战的。一旦在高可用性模式下运行Prometheus,就会遇到很多问题,例如数据重复,为重复数据实现single pane等。为了解决此问题,Cortex诞生了。Cortex是一个CNCF sandbox project,旨在为使用Prometheus 收集的指标提供长期存储和全局指标视图。首先让我们看一下Cortex的主要目标,然后看一下它为Prometheus解决的一些问题。
水平可伸缩性– Cortex可以分成多个微服务,每个微服务都可以独立地水平伸缩。例如,如果许多Prometheus实例正在向Cortex发送数据,则可以扩展Ingester微服务。如果cortex有许多的查询,则可以扩展Querier或Query Frontend微服务。
高可用性– Cortex可以在实例之间复制数据replicate data。这样可以防止数据丢失,并避免度量标准数据出现间断,即使发生机器故障and/orpod被驱逐。
多租户–多个不受信任的parties可以共享同一群集。Cortex在从ingester到querying的整个生命周期中提供数据隔离。这对于为多个单元或应用程序存储数据的大型组织或运行SaaS服务的人员非常有用。
长期存储– Cortex将数据分块存储并为其生成索引。可以将Cortex配置为将其存储在自托管或云提供商支持的数据库或对象存储中。
Cortex的需求
Prometheus高可用性和数据去重
Prometheus默认情况下不具有高可用性。使Prometheus高可用的一种方式是运行多个实例去scraping相同的作业。这些实例在抓取指标时会因微小的时间间隔差异而在数据中产生细微差异。此外,如果其中一个实例宕机了几个小时,那么当查询转发到该实例时,将会出现数据空白。如果我们使用grafana这样的工具将指标展示为图形,我们可能会得到不同的样本值或有数据缺失的图形。
可以将Cortex配置为从多个HA Prometheus实例读取数据。它从一个主实例main接受指标,并从其他实例放弃该度量。一旦这个副本掉线,Cortex会无缝切换到另一副本并将其标记为主副本main。为此,Cortex着眼于两个标签,一个共同的标签与一个集群(或一组Prometheus)相关联,另一个识别副本。
全局指标视图
可以将Prometheus实例配置为对cortex执行远程写入。使用此功能,指标可以从多个集群聚合到一个运行cortes的集群中。这为我们提供了一个中心位置,在这里我们可以观察整个基础设施的指标。Cortex提供了与Prometheus/PromQL兼容的端点endpoint。可以将此端点endpoint作为数据源提供给grafana,并与普通Prometheus实例相同的方式执行查询。
长期储存
普罗米修斯的本地存储不是持久的长期存储。发送到cortex的指标被存储在已配置的存储服务中。如果使用云存储,这将使您从运行自己的数据库的麻烦中解脱出来。你还可以享受云提供商提供的SLA。Cortex还支持用于存储块的对象存储:
GCS
S3
多租户
当向cortex写入指标时,通过设置http头(X-Scope-OrgID)来提供多租户。查询时必须提供相同的值。在下面的例子中,这个headers是使用nginx反向代理设置的。
架构图
Cortex架构(源)
Nginx/gateway–一个位于cortex前面的反向代理,将收到的所有请求转发给相应的服务。
分发服务器Distributor–处理传入的指标,将其拆分为多个批次,然后将其传递给Ingesters。如果复制因子replication factor设置为> 1,则数据将发送到多个实例。
接收器Ingester–此服务负责将数据写入已配置的存储后端。Ingester是半状态的,因为它们保留了后12个小时的样本。这些样本将被批处理并压缩,然后再写入块存储。
查询前端Query Frontend–一个可选组件,用于对查询请求进行排队,并在失败时重试它们。结果也被缓存以提高性能
查询器Querier–查询器处理PromQL的求值。如果是近的数据,则从大块存储和或内部获取样本
其他组件:
Ruler–处理alertmanager产生的警报
Alertmanager –评估警报规则
ConfigsAPI –在Postgres中存储Ruler和Alertmanager的配置
Table Manager–负责在选定的块chunk/索引index存储后端中创建表
Consul –存储分发服务器distributor生成的一致的哈希环(hash ring)。分发服务器在发送指标时使用散列值来选择ingester。
与其他选项的异同
Thanos
Thanos和Cortex具有非常相似的目标:聚合指标,将其存储在块存储中,并为所有度量使用一块single pane。因此,两个项目重用大量Prometheus代码也就不足为奇了。但是,有一些关键差异可能会帮助您决定使用哪个。
Thanos Cortex
近的数据存储在Prometheus中 近的数据存储在Ingesters中(Cortex组件)
使用可以将数据写入块存储的Sidecar 通过prometheus的远程写将数据发送到cortex
单租户 多租户
手动分片 根据标签自动分片数据
Prom TSDB块 索引块 index
下采样:历史数据可以汇总(例如,将5秒的样本平均为1分钟的样本) 查询分片(将30天转换为30天的一天查询)
需要Ingress到运行Prometheus的集群中进行查询 运行Prometheus的集群仅需要出口Egress
演练
让我们通过安装一个真实的示例并通过多个Prometheus和Grafana对其进行配置以可视化数据来试用Cortex。
git clone https://github.com/kanuahs/cortex-demo.git
cd cortex-demo
1
2
Prometheus and Cortex with Docker Compose
为了简单设置,我们将使用docker-compose启动以下服务:
三个Prometheus容器
Consul
三个Cortex容器
Grafana
为了简单起见,我们将使用多功能的cortex配置。这将cortex作为一个独立的应用程序运行。我们将运行它的三个实例来检查复制。有三个Prometheus配置文件。它们具有外部标签,在执行远程写入时将标签添加到所有指标。Prometheus1和Prometheus3容器写入Cortex1,而Prometheus2容器写入Cortex2。我们将在Cortex3上运行查询。以下代码片段显示了三个Prometheus实例的配置差异。
# Prometheus one
global:
# ...
external_labels:
cluster: two
# ...
remote_write:
- url: http://cortex2:9009/api/prom/push
# Prometheus two
global:
# ...
external_labels:
cluster: two
# ...
remote_write:
- url: http://cortex1:9009/api/prom/push
# Prometheus three
global:
# ...
external_labels:
cluster: tree
# ...
remote_write:
- url: http://cortex1:9009/api/prom/push
使用docker-compose启动所有服务。
docker-compose -f docker-demo/docker-compose.yaml up
1
转到http://localhost:3000/explore,使用凭据admin/admin登录,然后选择cortex3作为数据源。运行示例查询(例如up)Cortex将返回所有3个Prometheus容器的指标:
完成后,运行以下命令进行清理
docker-compose -f docker-demo/docker-compose.yaml down
1
在Kubernetes中部署Cortex以及Prometheus的依赖
如架构所示,我们将Cortex部署为一组微服务。我们还需要Helm来部署依赖项(Cassandra)和其他服务(Grafana,Prometheus)。如果尚未安装Helm,则可以按照Helm文档中的快速入门指南进行操作。让我们开始吧,首先我们将部署cortex组件。
kubectl apply -f k8s/
1
我们还将使用Helm安装Prometheus。下面的命令将为我们完成这两项工作:
创建一个名为" cluster"的外部标签,并将该标签的值设置为"one"。这将有助于分离不同的Prometheus实例
设置cortex的远程写入。
helm install stable/prometheus \
--name prom-one \
--set server.global.external_labels.cluster=one \
--set serverFiles."prometheus\.yml".remote_write[0].url=http://nginx.default.svc.cluster.local:80/api/prom/push
现在,我们将部署Grafana。下面的命令使用Grafana的配置功能在Pod启动时将Cortex添加为数据源。
helm install stable/grafana --name=grafana \
--set datasources."datasources\.yaml".apiVersion=1 \
--set datasources."datasources\.yaml".datasources[0].name=cortex \
--set datasources."datasources\.yaml".datasources[0].type=prometheus \
--set datasources."datasources\.yaml".datasources[0].url=http://nginx.default.svc.cluster.local/api/prom \
--set datasources."datasources\.yaml".datasources[0].access=proxy \
--set datasources."datasources\.yaml".datasources[0].isDefault=true
kubectl port-forward svc/grafana 3000:80
运行以下命令以获取Grafana管理员密码。之后,打开localhost:3000/explore并使用用户名"admin"和打印的密码登录。
kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
1
以下是一些示例查询,您可以运行这些查询来测试Prometheus是否向Cortex发送指标:
up{cluster="one"}
prometheus_tsdb_head_samples_appended_total{cluster="one"}
1
2
Cleanup
kubectl delete -f k8s/
helm delete --purge prom-one
helm delete --purge grafana
1
2
3
ingester pods将卡在终止阶段。这是设计使然的,因为ingester是半状态的,并且将在终止之前尝试将其数据刷新到其他ingester。这使得升级和回滚成为可能,同时避免了数据丢失。在这种情况下,我们只是尝试一下,而不关心数据,因此我们可以使用以下命令强制将其删除:
kubectl delete pod -l name=ingester --grace-period=0 --force
1
具有数据去重功能的HA Prometheus设置
此设置与上一个非常相似。主要区别在于我们正在部署两个Prometheus实例。两者都具有被设置为相同值"one"的集群标签和的副本标签。分发器组件已配置为基于这两个标签执行重复数据删除。如果Cortex在当前规定的时间(超过30秒)内没有从当前副本接收指标,它将故障转移到下一个发送样本的副本。
kubectl apply -f k8s-ha/
helm install stable/prometheus \
--name prom-one \
--set server.global.external_labels.cluster=one \
--set server.global.external_labels.replica=one \
--set serverFiles."prometheus\.yml".remote_write[0].url=http://nginx.default.svc.cluster.local:80/api/prom/push
helm install stable/prometheus \
--name prom-two \
--set server.global.external_labels.cluster=one \
--set server.global.external_labels.replica=two \
--set serverFiles."prometheus\.yml".remote_write[0].url=http://nginx.default.svc.cluster.local:80/api/prom/push
helm install stable/grafana --name=grafana \
--set datasources."datasources\.yaml".apiVersion=1 \
--set datasources."datasources\.yaml".datasources[0].name=cortex \
--set datasources."datasources\.yaml".datasources[0].type=prometheus \
--set datasources."datasources\.yaml".datasources[0].url=http://nginx.default.svc.cluster.local/api/prom \
--set datasources."datasources\.yaml".datasources[0].access=proxy \
--set datasources."datasources\.yaml".datasources[0].isDefault=true
kubectl port-forward svc/grafana 3000:80
运行以下命令以获取grafana管理员密码。之后,打开localhost:3000/explore并使用用户名"admin"和打印的密码登录。
kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
1
以下是一些示例查询,您可以运行这些查询来测试Prometheus是否向Cortex发送指标:
up{cluster="one"}
prometheus_tsdb_head_samples_appended_total{cluster="one"}
1
2
要测试HA,我们可以尝试删除Prometheus窗格之一。
kubectl delete pod -l app=prometheus,component=server,release=prom-one
1
Grafana图中应该没有数据缺失,因为Cortex将故障转移到另一个实例。
清理
kubectl delete -f k8s/
helm delete --purge prom-one
helm delete --purge prom-two
helm delete --purge grafana
1
2
3
4
使用Cassandra作为索引和块存储
在前两个示例中,我们使用dynamodb-local作为索引存储,并使用fakes3作为块存储。在此示例中,我们将使用Apache Cassandra进行索引存储和块存储。
以下命令将启用helm incubator repo,使用helm安装Cassandra,并等待3个副本准备就绪。
helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/
helm install --wait --name=cassie incubator/cassandra
准备好Cassandra后,继续安装所有其他服务。
kubectl apply -f k8s-cassandra/
helm install stable/prometheus \
--name prom-one \
--set server.global.external_labels.cluster=one \
--set serverFiles."prometheus\.yml".remote_write[0].url=http://nginx.default.svc.cluster.local:80/api/prom/push
helm install stable/grafana --name=grafana \
--set datasources."datasources\.yaml".apiVersion=1 \
--set datasources."datasources\.yaml".datasources[0].name=cortex \
--set datasources."datasources\.yaml".datasources[0].type=prometheus \
--set datasources."datasources\.yaml".datasources[0].url=http://nginx.default.svc.cluster.local/api/prom \
--set datasources."datasources\.yaml".datasources[0].access=proxy \
--set datasources."datasources\.yaml".datasources[0].isDefault=true
kubectl port-forward svc/grafana 3000:80
运行以下命令以获取Grafana管理员密码。之后,打开localhost:3000/explore并使用用户名admin和打印的密码登录。
kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
1
以下是一些示例查询,您可以运行这些查询来测试Prometheus是否向Cortex发送指标:
up{cluster="one"}
prometheus_tsdb_head_samples_appended_total{cluster="one"}
1
2
清理
kubectl delete -f k8s/
helm delete --purge cassie
helm delete --purge prom-one
helm delete --purge grafana
结论
Cortex是一个强大的工具,可无缝地运行多个Prometheus服务器,同时简化了用户的操作和使用。虽然Thanos确实提供了非常相似的功能,但它们的实现方式却大不相同。通过尝试实现的用例将推动选择Cortex与Thanos。但是,Cortex确实使运行高度可扩展且具有弹性的基于Prometheus的监视系统变得容易。
翻译: 云原生生态圈 · Marionxue
作者: By Shaunak Deshmukh
原文: https://www.infracloud.io/blogs/cortex-prometheus-ha/
相关文章