$ oc adm policy add-role-to-user alertingrules.loki.grafana.com-v1-admin -n <namespace> <username>
您可以配置一个LokiStack
CR 来存储应用程序、审核和基础设施相关的日志。
Loki 是一个水平可扩展、高可用、多租户日志聚合系统,作为 Red Hat OpenShift 的通用日志存储提供,可以使用 OpenShift 可观测性 UI 进行可视化。OpenShift Logging 提供的 Loki 配置是一个短期日志存储,旨在使用户能够使用收集的日志快速进行故障排除。为此,Red Hat OpenShift 的 Loki 日志配置具有短期存储,并针对最近的查询进行了优化。
对于长期存储或长时间段的查询,用户应查找集群外部的日志存储。Loki 的大小仅针对短期存储(最长 30 天)进行了测试和支持。 |
您已使用 CLI 或 Web 控制台安装了 Loki Operator。
您在创建ClusterLogForwarder
的同一命名空间中拥有一个serviceAccount
。
serviceAccount
被分配了collect-audit-logs
、collect-application-logs
和collect-infrastructure-logs
集群角色。
管理员可以通过将集群角色绑定到用户名来允许用户创建和管理他们自己的警报和记录规则。集群角色定义为包含用户所需基于角色的访问控制 (RBAC) 权限的ClusterRole
对象。
以下集群角色可用于 LokiStack 的警报和记录规则
规则名称 | 描述 |
---|---|
|
拥有此角色的用户具有管理警报规则的管理员级访问权限。此集群角色授予在 |
|
拥有此角色的用户可以查看与 |
|
拥有此角色的用户有权创建、更新和删除 |
|
拥有此角色的用户可以读取 |
|
拥有此角色的用户具有管理记录规则的管理员级访问权限。此集群角色授予在 |
|
拥有此角色的用户可以查看与 |
|
拥有此角色的用户有权创建、更新和删除 |
|
拥有此角色的用户可以读取 |
要为用户应用集群角色,必须将现有集群角色绑定到特定用户名。
集群角色可以是集群范围或命名空间范围,具体取决于您使用哪种类型的角色绑定。当使用RoleBinding
对象时(例如使用oc adm policy add-role-to-user
命令时),集群角色仅应用于指定的命名空间。当使用ClusterRoleBinding
对象时(例如使用oc adm policy add-cluster-role-to-user
命令时),集群角色应用于集群中的所有命名空间。
以下示例命令为指定用户提供在集群中特定命名空间内创建、读取、更新和删除 (CRUD) 警报规则的权限
$ oc adm policy add-role-to-user alertingrules.loki.grafana.com-v1-admin -n <namespace> <username>
以下命令为指定用户提供所有命名空间中警报规则的管理员权限
$ oc adm policy add-cluster-role-to-user alertingrules.loki.grafana.com-v1-admin <username>
AlertingRule
CR 包含一组规范和 webhook 验证定义,用于声明单个 LokiStack
实例的告警规则组。此外,webhook 验证定义还支持规则验证条件。
如果 AlertingRule
CR 包含无效的 interval
周期,则它是一个无效的告警规则。
如果 AlertingRule
CR 包含无效的 for
周期,则它是一个无效的告警规则。
如果 AlertingRule
CR 包含无效的 LogQL expr
,则它是一个无效的告警规则。
如果 AlertingRule
CR 包含两个同名的组,则它是一个无效的告警规则。
如果上述情况均不适用,则告警规则被认为有效。
租户类型 | AlertingRule CR 的有效命名空间 |
---|---|
application |
|
audit |
|
infrastructure |
|
创建一个 AlertingRule
自定义资源 (CR)
AlertingRule
CR 示例 apiVersion: loki.grafana.com/v1
kind: AlertingRule
metadata:
name: loki-operator-alerts
namespace: openshift-operators-redhat (1)
labels: (2)
openshift.io/<label_name>: "true"
spec:
tenantID: "infrastructure" (3)
groups:
- name: LokiOperatorHighReconciliationError
rules:
- alert: HighPercentageError
expr: | (4)
sum(rate({kubernetes_namespace_name="openshift-operators-redhat", kubernetes_pod_name=~"loki-operator-controller-manager.*"} |= "error" [1m])) by (job)
/
sum(rate({kubernetes_namespace_name="openshift-operators-redhat", kubernetes_pod_name=~"loki-operator-controller-manager.*"}[1m])) by (job)
> 0.01
for: 10s
labels:
severity: critical (5)
annotations:
summary: High Loki Operator Reconciliation Errors (6)
description: High Loki Operator Reconciliation Errors (7)
1 | 创建此 AlertingRule CR 的命名空间必须具有与 LokiStack spec.rules.namespaceSelector 定义匹配的标签。 |
2 | labels 块必须与 LokiStack spec.rules.selector 定义匹配。 |
3 | infrastructure 租户的 AlertingRule CR 仅在 openshift-* 、kube-\* 或 default 命名空间中受支持。 |
4 | kubernetes_namespace_name: 的值必须与 metadata.namespace 的值匹配。 |
5 | 此必填字段的值必须是 critical 、warning 或 info 。 |
6 | 此字段是必填字段。 |
7 | 此字段是必填字段。 |
AlertingRule
CR 示例 apiVersion: loki.grafana.com/v1
kind: AlertingRule
metadata:
name: app-user-workload
namespace: app-ns (1)
labels: (2)
openshift.io/<label_name>: "true"
spec:
tenantID: "application"
groups:
- name: AppUserWorkloadHighError
rules:
- alert:
expr: | (3)
sum(rate({kubernetes_namespace_name="app-ns", kubernetes_pod_name=~"podName.*"} |= "error" [1m])) by (job)
for: 10s
labels:
severity: critical (4)
annotations:
summary: (5)
description: (6)
1 | 创建此 AlertingRule CR 的命名空间必须具有与 LokiStack spec.rules.namespaceSelector 定义匹配的标签。 |
2 | labels 块必须与 LokiStack spec.rules.selector 定义匹配。 |
3 | kubernetes_namespace_name: 的值必须与 metadata.namespace 的值匹配。 |
4 | 此必填字段的值必须是 critical 、warning 或 info 。 |
5 | 此必填字段的值是规则的摘要。 |
6 | 此必填字段的值是规则的详细描述。 |
应用 AlertingRule
CR
$ oc apply -f <filename>.yaml
在 OpenShift Container Platform 集群中,管理员通常使用非私有 IP 网络范围。因此,LokiStack memberlist 配置会失败,因为默认情况下它只使用私有 IP 网络。
作为管理员,您可以为 memberlist 配置选择 pod 网络。您可以修改 LokiStack
自定义资源 (CR) 以在 hashRing
规范中使用 podIP
地址。要配置 LokiStack
CR,请使用以下命令
$ oc patch LokiStack logging-loki -n openshift-logging --type=merge -p '{"spec": {"hashRing":{"memberlist":{"instanceAddrType":"podIP"},"type":"memberlist"}}}'
podIP
的 LokiStack 示例apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
# ...
hashRing:
type: memberlist
memberlist:
instanceAddrType: podIP
# ...
您可以根据日志流配置保留策略。这些规则可以在全局、每个租户或两者同时设置。如果同时配置两者,则租户规则优先于全局规则。
如果在 s3 bucket 或 LokiStack 自定义资源 (CR) 中未定义保留期限,则日志不会被修剪,它们将永远保留在 s3 bucket 中,这可能会填满 s3 存储。 |
推荐使用 Schema v13。 |
创建一个 LokiStack
CR
按以下示例所示全局启用基于流的保留
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
limits:
global: (1)
retention: (2)
days: 20
streams:
- days: 4
priority: 1
selector: '{kubernetes_namespace_name=~"test.+"}' (3)
- days: 1
priority: 1
selector: '{log_type="infrastructure"}'
managementState: Managed
replicationFactor: 1
size: 1x.small
storage:
schemas:
- effectiveDate: "2020-10-11"
version: v13
secret:
name: logging-loki-s3
type: aws
storageClassName: gp3-csi
tenants:
mode: openshift-logging
1 | 设置所有日志流的保留策略。**注意:此字段不会影响对象存储中存储日志的保留期限。** |
2 | 将此块添加到 CR 时,将在集群中启用保留。 |
3 | 包含用于定义日志流的 LogQL 查询。spec: limits |
按以下示例所示启用基于每个租户的流保留
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
limits:
global:
retention:
days: 20
tenants: (1)
application:
retention:
days: 1
streams:
- days: 4
selector: '{kubernetes_namespace_name=~"test.+"}' (2)
infrastructure:
retention:
days: 5
streams:
- days: 1
selector: '{kubernetes_namespace_name=~"openshift-cluster.+"}'
managementState: Managed
replicationFactor: 1
size: 1x.small
storage:
schemas:
- effectiveDate: "2020-10-11"
version: v13
secret:
name: logging-loki-s3
type: aws
storageClassName: gp3-csi
tenants:
mode: openshift-logging
1 | 按租户设置保留策略。有效的租户类型为 application 、audit 和 infrastructure 。 |
2 | 包含用于定义日志流的 LogQL 查询。 |
应用 LokiStack
CR
$ oc apply -f <filename>.yaml
您可以使用 Pod 上的容忍度或节点选择器来控制 Loki Pod 运行的节点,并阻止其他工作负载使用这些节点。
您可以使用 LokiStack 自定义资源 (CR) 将容忍度应用于日志存储 Pod,并使用节点规范将污点应用于节点。节点上的污点是一个 key:value
对,它指示节点排斥所有不允许该污点的 Pod。使用其他 Pod 上不存在的特定 key:value
对可确保只有日志存储 Pod 才能在该节点上运行。
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
# ...
template:
compactor: (1)
nodeSelector:
node-role.kubernetes.io/infra: "" (2)
distributor:
nodeSelector:
node-role.kubernetes.io/infra: ""
gateway:
nodeSelector:
node-role.kubernetes.io/infra: ""
indexGateway:
nodeSelector:
node-role.kubernetes.io/infra: ""
ingester:
nodeSelector:
node-role.kubernetes.io/infra: ""
querier:
nodeSelector:
node-role.kubernetes.io/infra: ""
queryFrontend:
nodeSelector:
node-role.kubernetes.io/infra: ""
ruler:
nodeSelector:
node-role.kubernetes.io/infra: ""
# ...
1 | 指定适用于节点选择器的组件 Pod 类型。 |
2 | 指定移动到包含已定义标签的节点的 Pod。 |
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
# ...
template:
compactor:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
distributor:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
indexGateway:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
ingester:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
querier:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
queryFrontend:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
ruler:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
gateway:
nodeSelector:
node-role.kubernetes.io/infra: ""
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/infra
value: reserved
- effect: NoExecute
key: node-role.kubernetes.io/infra
value: reserved
# ...
要配置 LokiStack (CR) 的 nodeSelector
和 tolerations
字段,您可以使用 oc explain
命令查看特定资源的描述和字段。
$ oc explain lokistack.spec.template
KIND: LokiStack
VERSION: loki.grafana.com/v1
RESOURCE: template <Object>
DESCRIPTION:
Template defines the resource/limits/tolerations/nodeselectors per
component
FIELDS:
compactor <Object>
Compactor defines the compaction component spec.
distributor <Object>
Distributor defines the distributor component spec.
...
有关更详细的信息,您可以添加特定字段
$ oc explain lokistack.spec.template.compactor
KIND: LokiStack
VERSION: loki.grafana.com/v1
RESOURCE: compactor <Object>
DESCRIPTION:
Compactor defines the compaction component spec.
FIELDS:
nodeSelector <map[string]string>
NodeSelector defines the labels required by a node to schedule the
component onto it.
...
工作负载身份联合使用短期令牌启用对基于云的日志存储的认证。
使用以下选项之一启用身份验证
如果您使用 OpenShift Container Platform Web 控制台安装 Loki Operator,则会自动检测使用短期令牌的集群。系统会提示您创建角色并提供 Loki Operator 创建 CredentialsRequest
对象所需的数据,该对象会填充一个密钥。
如果您使用 OpenShift CLI (oc
) 安装 Loki Operator,则必须使用适合您的存储提供商的模板手动创建一个 Subscription
对象,如下例所示。此身份验证策略仅支持指示的存储提供商。
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: loki-operator
namespace: openshift-operators-redhat
spec:
channel: "stable-6.0"
installPlanApproval: Manual
name: loki-operator
source: redhat-operators
sourceNamespace: openshift-marketplace
config:
env:
- name: CLIENTID
value: <your_client_id>
- name: TENANTID
value: <your_tenant_id>
- name: SUBSCRIPTIONID
value: <your_subscription_id>
- name: REGION
value: <your_region>
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: loki-operator
namespace: openshift-operators-redhat
spec:
channel: "stable-6.0"
installPlanApproval: Manual
name: loki-operator
source: redhat-operators
sourceNamespace: openshift-marketplace
config:
env:
- name: ROLEARN
value: <role_ARN>
Loki Operator 支持设置 Pod 反亲和性规则,以请求将相同组件的 Pod 调度到集群中不同的可用节点上。
亲和性是 Pod 的一个属性,它控制 Pod 首选在其上调度的节点。反亲和性是 Pod 的一个属性,它阻止 Pod 调度到某个节点上。
在 OpenShift Container Platform 中,Pod 亲和性和Pod 反亲和性允许您根据其他 Pod 上的键值标签来约束 Pod 可调度到的节点。
Operator 为所有 Loki 组件设置默认的、首选的 podAntiAffinity
规则,其中包括 compactor
、distributor
、gateway
、indexGateway
、ingester
、querier
、queryFrontend
和 ruler
组件。
您可以通过在 requiredDuringSchedulingIgnoredDuringExecution
字段中配置必需的设置来覆盖 Loki 组件的首选 podAntiAffinity
设置。
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
# ...
template:
ingester:
podAntiAffinity:
# ...
requiredDuringSchedulingIgnoredDuringExecution: (1)
- labelSelector:
matchLabels: (2)
app.kubernetes.io/component: ingester
topologyKey: kubernetes.io/hostname
# ...
1 | 定义必需规则的节。 |
2 | 必须匹配的键值对(标签)才能应用该规则。 |
当 OpenShift Container Platform 集群重启时,LokiStack 数据摄取和查询路径将继续在节点可用的 CPU 和内存资源内运行。这意味着在 OpenShift Container Platform 集群更新期间,LokiStack 没有停机时间。此行为是通过使用 PodDisruptionBudget
资源实现的。Loki Operator 为 Loki 提供 PodDisruptionBudget
资源,这些资源确定在特定条件下每个组件必须可用的 Pod 最小数量,以确保正常运行。
Loki Operator 通过 Pod topology spread constraints 提供对区域感知数据复制的支持。启用此功能可以增强可靠性并防止在单个区域发生故障时丢失日志。当将部署大小配置为 1x.extra-small
、1x.small
或 1x.medium
时,replication.factor
字段会自动设置为 2。
为了确保正确的复制,您至少需要与复制因子指定的可用区数量一样多的可用区。虽然可用区的数量可以多于复制因子,但可用区的数量少于复制因子会导致写入失败。为了获得最佳操作效果,每个区域应托管相同数量的实例。
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
replicationFactor: 2 (1)
replication:
factor: 2 (2)
zones:
- maxSkew: 1 (3)
topologyKey: topology.kubernetes.io/zone (4)
1 | 已弃用的字段,输入的值将被 replication.factor 覆盖。 |
2 | 此值在安装时选择部署大小后自动设置。 |
3 | 任何两个拓扑域之间 Pod 数量的最大差异。默认值为 1,您不能指定值为 0。 |
4 | 定义拓扑键形式的区域,该键对应于节点标签。 |
在 OpenShift Container Platform 中,区域故障是指特定可用区资源变得不可访问的情况。可用区是云提供商数据中心内的隔离区域,旨在增强冗余性和容错能力。如果您的 OpenShift Container Platform 集群未配置为处理此问题,则区域故障可能导致服务或数据丢失。
Loki Pod 是 StatefulSet 的一部分,它们带有由 StorageClass
对象提供的持久卷声明 (PVC)。每个 Loki Pod 及其 PVC 都位于同一区域。当集群中发生区域故障时,StatefulSet 控制器会自动尝试恢复故障区域中受影响的 Pod。
以下过程将删除故障区域中的 PVC 及其包含的所有数据。为了避免完全丢失数据,应始终将 |
验证您的 LokiStack
CR 的复制因子是否大于 1。
控制平面检测到区域故障,并且云提供商集成会标记故障区域中的节点。
StatefulSet 控制器会自动尝试重新调度故障区域中的 Pod。由于关联的 PVC 也在故障区域中,因此无法自动重新调度到其他区域。您必须手动删除故障区域中的 PVC,才能成功在新的区域中重新创建有状态的 Loki Pod 及其提供的 PVC。
运行以下命令列出状态为 Pending
的 Pod
$ oc get pods --field-selector status.phase==Pending -n openshift-logging
oc get pods
输出示例NAME READY STATUS RESTARTS AGE (1)
logging-loki-index-gateway-1 0/1 Pending 0 17m
logging-loki-ingester-1 0/1 Pending 0 16m
logging-loki-ruler-1 0/1 Pending 0 16m
1 | 这些 Pod 的状态为 Pending ,因为它们对应的 PVC 位于故障区域。 |
运行以下命令列出状态为 Pending
的 PVC
$ oc get pvc -o=json -n openshift-logging | jq '.items[] | select(.status.phase == "Pending") | .metadata.name' -r
oc get pvc
输出示例storage-logging-loki-index-gateway-1
storage-logging-loki-ingester-1
wal-logging-loki-ingester-1
storage-logging-loki-ruler-1
wal-logging-loki-ruler-1
运行以下命令删除 Pod 的 PVC
$ oc delete pvc <pvc_name> -n openshift-logging
运行以下命令删除 Pod
$ oc delete pod <pod_name> -n openshift-logging
成功删除这些对象后,它们应该会自动重新调度到可用的区域。
如果日志转发器 API 转发的大量消息块超过 Loki 的速率限制,Loki 将生成速率限制 (429
) 错误。
这些错误可能在正常运行期间发生。例如,当向已有一些日志的集群添加日志时,在日志尝试摄取所有现有日志条目时可能会发生速率限制错误。在这种情况下,如果新日志添加的速率小于总速率限制,则最终会摄取历史数据,并且无需用户干预即可解决速率限制错误。
如果速率限制错误持续发生,您可以通过修改 LokiStack
自定义资源 (CR) 来解决此问题。
Grafana 托管的 Loki 上不提供 |
日志转发器 API 配置为将日志转发到 Loki。
您的系统向 Loki 发送大于 2 MB 的消息块。例如
"values":[["1630410392689800468","{\"kind\":\"Event\",\"apiVersion\":\
.......
......
......
......
\"received_at\":\"2021-08-31T11:46:32.800278+00:00\",\"version\":\"1.7.4 1.6.0\"}},\"@timestamp\":\"2021-08-31T11:46:32.799692+00:00\",\"viaq_index_name\":\"audit-write\",\"viaq_msg_id\":\"MzFjYjJkZjItNjY0MC00YWU4LWIwMTEtNGNmM2E5ZmViMGU4\",\"log_type\":\"audit\"}"]]}]}
输入 oc logs -n openshift-logging -l component=collector
后,集群中的收集器日志显示包含以下错误消息之一的行
429 Too Many Requests Ingestion rate limit exceeded
2023-08-25T16:08:49.301780Z WARN sink{component_kind="sink" component_id=default_loki_infra component_type=loki component_name=default_loki_infra}: vector::sinks::util::retries: Retrying after error. error=Server responded with an error: 429 Too Many Requests internal_log_rate_limit=true
2023-08-30 14:52:15 +0000 [warn]: [default_loki_infra] failed to flush the buffer. retry_times=2 next_retry_time=2023-08-30 14:52:19 +0000 chunk="604251225bf5378ed1567231a1c03b8b" error_class=Fluent::Plugin::LokiOutput::LogPostError error="429 Too Many Requests Ingestion rate limit exceeded for user infrastructure (limit: 4194304 bytes/sec) while attempting to ingest '4082' lines totaling '7820025' bytes, reduce log volume or contact your Loki administrator to see if the limit can be increased\n"
错误在接收端也可见。例如,在 LokiStack ingester Pod 中
level=warn ts=2023-08-30T14:57:34.155592243Z caller=grpc_logging.go:43 duration=1.434942ms method=/logproto.Pusher/Push err="rpc error: code = Code(429) desc = entry with timestamp 2023-08-30 14:57:32.012778399 +0000 UTC ignored, reason: 'Per stream rate limit exceeded (limit: 3MB/sec) while attempting to ingest for stream
更新 LokiStack
CR 中的 ingestionBurstSize
和 ingestionRate
字段
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
name: logging-loki
namespace: openshift-logging
spec:
limits:
global:
ingestion:
ingestionBurstSize: 16 (1)
ingestionRate: 8 (2)
# ...
1 | ingestionBurstSize 字段定义每个分发器副本的本地速率限制样本大小(以 MB 为单位)的最大值。此值是硬限制。将此值至少设置为单个推送请求中预期的最大日志大小。不允许大小大于 ingestionBurstSize 值的单个请求。 |
2 | ingestionRate 字段是每秒摄入样本量的最大值(以 MB 为单位)的软限制。如果日志速率超过此限制,则会发生速率限制错误,但收集器会重试发送日志。只要总平均值低于限制,系统就会恢复,并且错误会在无需用户干预的情况下解决。 |