×

在日志记录文档中,LokiStack 指的是 Loki 和 Web 代理与 AWS 上的 Red Hat OpenShift 服务身份验证集成所支持的日志记录组合。LokiStack 的代理使用 AWS 上的 Red Hat OpenShift 服务身份验证来强制实施多租户。Loki 指的是日志存储,可以是单个组件或外部存储。

为集群管理员用户角色创建新组

作为cluster-admin用户查询多个命名空间的应用程序日志时,如果集群中所有命名空间字符总数超过 5120,则会返回错误Parse error: input size too long (XXXX > 5120)。为了更好地控制对 LokiStack 中日志的访问,请将cluster-admin用户添加到cluster-admin组。如果cluster-admin组不存在,请创建它并将所需用户添加到其中。

使用以下步骤为具有cluster-admin权限的用户创建一个新组。

步骤
  1. 输入以下命令以创建新组

    $ oc adm groups new cluster-admin
  2. 输入以下命令将所需用户添加到cluster-admin

    $ oc adm groups add-users cluster-admin <username>
  3. 输入以下命令将cluster-admin用户角色添加到该组

    $ oc adm policy add-cluster-role-to-group cluster-admin cluster-admin

集群重启期间 LokiStack 的行为

在 5.8 及更高版本的日志记录中,当 AWS 上的 Red Hat OpenShift 服务集群重启时,LokiStack 数据摄取和查询路径将继续在节点可用的 CPU 和内存资源内运行。这意味着在 AWS 上的 Red Hat OpenShift 服务集群更新期间,LokiStack 没有停机时间。此行为是通过使用PodDisruptionBudget资源实现的。Loki 运算符为 Loki 提供PodDisruptionBudget资源,这些资源确定在某些条件下每个组件必须可用的最小 Pod 数量,以确保正常运行。

配置 Loki 以容忍节点故障

在 5.8 及更高版本的日志记录中,Loki 运算符支持设置 Pod 反亲和性规则,以请求将相同组件的 Pod 调度到集群中不同的可用节点上。

亲和性是 Pod 的一个属性,它控制 Pod 优先在哪些节点上进行调度。反亲和性是 Pod 的一个属性,它阻止 Pod 在节点上进行调度。

在 AWS 上的 Red Hat OpenShift 服务中,Pod 亲和性Pod 反亲和性允许您根据其他 Pod 上的键值标签来限制 Pod 可以调度的节点。

运算符为所有 Loki 组件设置默认的、首选的podAntiAffinity规则,其中包括compactordistributorgatewayindexGatewayingesterquerierqueryFrontendruler组件。

您可以通过在requiredDuringSchedulingIgnoredDuringExecution字段中配置必需的设置来覆盖 Loki 组件的首选podAntiAffinity设置。

ingester 组件的用户设置示例
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 必须匹配以应用规则的键值对(标签)。

区域感知数据复制

在 5.8 及更高版本的日志记录中,Loki 运算符通过 Pod 拓扑分布约束提供对区域感知数据复制的支持。启用此功能可以提高可靠性,并在单个区域发生故障时防止日志丢失。当将部署大小配置为1x.extra.small1x.small1x.medium时,replication.factor字段将自动设置为 2。

为了确保正确的复制,您至少需要与复制因子指定的可用区域数量相同的可用区域数量。虽然可以拥有比复制因子更多的可用区域,但是拥有较少的区域会导致写入失败。为了获得最佳操作,每个区域应该托管相同数量的实例。

启用区域复制的 LokiStack CR 示例
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 定义拓扑键形式的区域,该键对应于节点标签。

从故障区域恢复 Loki Pod

在 AWS 上的 Red Hat OpenShift 服务中,区域故障发生在特定可用区域资源变得不可访问时。可用区域是云提供商数据中心内的隔离区域,旨在增强冗余性和容错能力。如果您的 AWS 上的 Red Hat OpenShift 服务集群未配置为处理此问题,则区域故障可能导致服务或数据丢失。

Loki Pod 是 StatefulSet 的一部分,它们带有由StorageClass对象提供的持久卷声明 (PVC)。每个 Loki Pod 及其 PVC 都位于同一区域。当集群中发生区域故障时,StatefulSet 控制器会自动尝试恢复故障区域中受影响的 Pod。

以下步骤将删除故障区域中的 PVC 及其中包含的所有数据。为避免完全丢失数据,应始终将LokiStack CR 的复制因子字段设置为大于 1 的值,以确保 Loki 正在进行复制。

先决条件
  • 5.8 或更高版本的日志记录。

  • 验证您的LokiStack CR 的复制因子是否大于 1。

  • 控制平面检测到区域故障,并且云提供商集成标记了故障区域中的节点。

StatefulSet 控制器会自动尝试重新调度故障区域中的 Pod。由于关联的 PVC 也位于故障区域,因此无法自动重新调度到其他区域。您必须手动删除故障区域中的 PVC,才能成功在新的区域中重新创建有状态的 Loki Pod 及其提供的 PVC。

步骤
  1. 通过运行以下命令列出状态为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 位于故障区域。
  2. 运行以下命令列出处于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
  3. 运行以下命令删除 Pod 的 PVC:

    oc delete pvc __<pvc_name>__  -n openshift-logging
  4. 然后运行以下命令删除 Pod:

    oc delete pod __<pod_name>__  -n openshift-logging

成功删除这些对象后,它们应该会自动重新调度到可用的区域。

排查终止状态下的 PVC

如果 PVC 元数据最终器设置为kubernetes.io/pv-protection,则 PVC 可能会挂起在终止状态而未被删除。删除最终器应该允许 PVC 成功删除。

  1. 运行以下命令删除每个 PVC 的最终器,然后重试删除操作:

    oc patch pvc __<pvc_name>__ -p '{"metadata":{"finalizers":null}}' -n openshift-logging

Loki 日志的细粒度访问控制

在 Logging 5.8 及更高版本中,Red Hat OpenShift Logging Operator 默认情况下不会授予所有用户访问日志的权限。作为管理员,您必须配置用户的访问权限,除非 Operator 已升级并且之前的配置已到位。根据您的配置和需求,您可以使用以下方法配置对日志的细粒度访问:

  • 集群范围策略

  • 命名空间范围策略

  • 创建自定义管理员组

作为管理员,您需要创建适合您部署的适当角色绑定和集群角色绑定。Red Hat OpenShift Logging Operator 提供以下集群角色:

  • cluster-logging-application-view 授予读取应用程序日志的权限。

  • cluster-logging-infrastructure-view 授予读取基础设施日志的权限。

  • cluster-logging-audit-view 授予读取审计日志的权限。

如果您从早期版本升级,则附加的集群角色logging-application-logs-reader和关联的集群角色绑定logging-all-authenticated-application-logs-reader提供向后兼容性,允许任何已认证的用户在其命名空间中读取访问权限。

按命名空间访问的用户必须在查询应用程序日志时提供命名空间。

集群范围访问

集群角色绑定资源引用集群角色,并设置集群范围的权限。

集群角色绑定示例
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: logging-all-application-logs-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-logging-application-view (1)
subjects: (2)
- kind: Group
  name: system:authenticated
  apiGroup: rbac.authorization.k8s.io
1 其他ClusterRoles包括cluster-logging-infrastructure-viewcluster-logging-audit-view
2 指定此对象适用的用户或组。

命名空间访问

RoleBinding资源可以与ClusterRole对象一起使用,以定义用户或组可以访问日志的命名空间。

RoleBinding 示例
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: allow-read-logs
  namespace: log-test-0 (1)
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-logging-application-view
subjects:
- kind: User
  apiGroup: rbac.authorization.k8s.io
  name: testuser-0
1 指定此RoleBinding适用的命名空间。

自定义管理员组访问

如果您有一个大型部署,其中有多个用户需要更广泛的权限,您可以使用adminGroup字段创建一个自定义组。LokiStack CR 的adminGroups字段中指定的任何组的成员都被视为管理员。

如果管理员用户也被分配了cluster-logging-application-view角色,则他们可以访问所有命名空间中的所有应用程序日志。

LokiStack CR 示例
apiVersion: loki.grafana.com/v1
kind: LokiStack
metadata:
  name: logging-loki
  namespace: openshift-logging
spec:
  tenants:
    mode: openshift-logging (1)
    openshift:
      adminGroups: (2)
      - cluster-admin
      - custom-admin-group (3)
1 自定义管理员组仅在此模式下可用。
2 为此字段输入空列表[]值将禁用管理员组。
3 覆盖默认组(system:cluster-adminscluster-admindedicated-admin

启用 Loki 的基于流的保留策略

其他资源

在 Logging 5.6 及更高版本中,您可以基于日志流配置保留策略。这些规则可以在全局、每个租户或两者同时设置。如果同时配置两者,则租户规则优先于全局规则。

如果在 s3 bucket 或 LokiStack 自定义资源 (CR) 中未定义保留期,则日志不会被修剪,它们会永久保留在 s3 bucket 中,这可能会填满 s3 存储。

尽管 Logging 5.9 及更高版本支持 schema v12,但建议使用 v13。

  1. 要启用基于流的保留策略,请创建一个LokiStack CR

    AWS 的全局基于流的保留策略示例
    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: v11
        secret:
          name: logging-loki-s3
          type: aws
      storageClassName: gp3-csi
      tenants:
        mode: openshift-logging
    1 设置所有日志流的保留策略。**注意:此字段不影响对象存储中存储日志的保留期。**
    2 将此块添加到 CR 中时,将在集群中启用保留策略。
    3 包含用于定义日志流的LogQL 查询。spec: limits
AWS 的每个租户基于流的保留策略示例
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: v11
    secret:
      name: logging-loki-s3
      type: aws
  storageClassName: gp3-csi
  tenants:
    mode: openshift-logging
1 按租户设置保留策略。有效的租户类型为applicationauditinfrastructure
2 包含用于定义日志流的LogQL 查询

2 应用LokiStack CR

$ oc apply -f <filename>.yaml

排查 Loki 速率限制错误

如果日志转发器 API 转发的大量消息块超过 Loki 的速率限制,Loki 会生成速率限制 (429) 错误。

这些错误可能在正常运行期间发生。例如,当向已经包含一些日志的集群添加日志记录时,在日志记录尝试摄取所有现有日志条目时可能会发生速率限制错误。在这种情况下,如果新日志的添加速率低于总速率限制,则最终会摄取历史数据,并且无需用户干预即可解决速率限制错误。

如果速率限制错误持续发生,您可以通过修改LokiStack自定义资源 (CR) 来解决此问题。

Grafana 托管的 Loki 上没有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
    Vector 错误消息示例
    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
    Fluentd 错误消息示例
    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 中

    Loki ingester 错误消息示例
    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 中的ingestionBurstSizeingestionRate字段

    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 为单位)的软限制。如果日志速率超过限制,则会发生速率限制错误,但收集器会重试发送日志。只要总平均值低于限制,系统就会恢复,并且无需用户干预即可解决错误。

配置 Loki 以容忍 memberlist 创建失败

在 OpenShift 集群中,管理员通常使用非专用 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
# ...