Grafana Alloy Discovery.kubernetes 配置故障排查指南

概述

Grafana Alloy 是新一代的可观测性数据收集器,用于替代 Grafana Agent。在使用 discovery.kubernetes 组件进行 Kubernetes 服务发现时,经常会遇到配置语法错误。本文将详细介绍常见的配置问题和解决方案。

常见错误:missing required attribute “role”

错误现象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Error: /etc/alloy/alloy.yaml:1:1: Failed to build component: decoding configuration: missing required attribute "role"

1 |   discovery.kubernetes "pods" {
  |  _^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2 | |   role = "pod"
3 | |   selectors {
4 | |     label = "app.kubernetes.io/name=flog"
5 | |   }
6 | | }
  | |_^
7 |
interrupt received
Error: could not perform the initial load successfully

问题分析

这个错误通常出现在 discovery.kubernetes 组件的 selectors 块配置不正确时。根据 Grafana Alloy 官方文档,selectors 块需要包含 role 属性来指定要发现的 Kubernetes 资源类型。

错误配置示例

1
2
3
4
5
6
7
# ❌ 错误配置 - selectors 块中缺少 role 属性
discovery.kubernetes "pods" {
  role = "pod"
  selectors {
    label = "app.kubernetes.io/name=flog"
  }
}

正确配置示例

1
2
3
4
5
6
7
8
# ✅ 正确配置 - selectors 块中包含 role 属性
discovery.kubernetes "pods" {
  role = "pod"
  selectors {
    role = "pod"
    label = "app.kubernetes.io/name=flog"
  }
}

discovery.kubernetes 组件详解

基本语法结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
discovery.kubernetes "<LABEL>" {
  role = "<ROLE>"
  
  // 可选配置
  api_server = "<API_SERVER_URL>"
  kubeconfig_file = "<KUBECONFIG_PATH>"
  
  selectors {
    role = "<ROLE>"
    field = "<FIELD_SELECTOR>"
    label = "<LABEL_SELECTOR>"
  }
  
  namespaces {
    own_namespace = <BOOLEAN>
    names = ["<NAMESPACE1>", "<NAMESPACE2>"]
  }
}

支持的 role 类型

  • node - 发现 Kubernetes 节点
  • pod - 发现 Pod
  • service - 发现 Service
  • endpoints - 发现 Endpoints
  • endpointslice - 发现 EndpointSlice
  • ingress - 发现 Ingress

selectors 块配置

selectors 块用于过滤要发现的资源,支持以下属性:

  • role - 必需,指定资源类型
  • field - 字段选择器,如 metadata.name=my-pod
  • label - 标签选择器,如 app=nginx

完整配置示例

基础 Pod 发现配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
discovery.kubernetes "pods" {
  role = "pod"
  selectors {
    role = "pod"
    label = "app.kubernetes.io/name=flog"
  }
}

loki.source.kubernetes "pods" {
  targets    = discovery.kubernetes.pods.targets
  forward_to = [loki.write.grafana_loki.receiver]
}

loki.write "grafana_loki" {
  endpoint {
    url = "http://loki:3100/loki/api/v1/push"
  }
}

多命名空间配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
discovery.kubernetes "pods" {
  role = "pod"
  selectors {
    role = "pod"
    label = "app.kubernetes.io/name=flog"
  }
  namespaces {
    names = ["default", "kube-system", "monitoring"]
  }
}

字段选择器配置

1
2
3
4
5
6
7
8
discovery.kubernetes "running_pods" {
  role = "pod"
  selectors {
    role = "pod"
    field = "status.phase=Running"
    label = "app=nginx"
  }
}

故障排查步骤

1. 检查配置文件语法

1
2
3
4
5
# 验证 Alloy 配置文件语法
alloy fmt /etc/alloy/alloy.yaml

# 检查配置文件是否有语法错误
alloy run --config.file=/etc/alloy/alloy.yaml --dry-run

2. 验证 Kubernetes 连接

1
2
3
4
5
# 检查 Alloy 是否能连接到 Kubernetes API
kubectl auth can-i get pods --as=system:serviceaccount:default:alloy

# 检查 ServiceAccount 权限
kubectl describe clusterrolebinding alloy

3. 查看 Alloy 日志

1
2
3
4
5
# 查看 Alloy 容器日志
kubectl logs -f deployment/alloy -n monitoring

# 查看详细调试日志
alloy run --config.file=/etc/alloy/alloy.yaml --log.level=debug

4. 测试服务发现

1
2
3
4
5
# 检查发现的目标
curl -s http://alloy:12345/api/v0/component/discovery.kubernetes.pods/targets | jq .

# 验证标签选择器
kubectl get pods -l app.kubernetes.io/name=flog --all-namespaces

最佳实践

1. 使用明确的标签选择器

1
2
3
4
5
# 推荐:使用具体的标签选择器
selectors {
  role = "pod"
  label = "app.kubernetes.io/name=flog,app.kubernetes.io/component=logger"
}

2. 限制命名空间范围

1
2
3
4
# 推荐:限制发现范围以提高性能
namespaces {
  names = ["production", "staging"]
}

3. 使用字段选择器过滤

1
2
3
4
5
6
# 推荐:只发现运行中的 Pod
selectors {
  role = "pod"
  field = "status.phase=Running"
  label = "app=myapp"
}

4. 配置适当的权限

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: alloy
rules:
- apiGroups: [""]
  resources: ["nodes", "nodes/proxy", "services", "endpoints", "pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["extensions", "networking.k8s.io"]
  resources: ["ingresses"]
  verbs: ["get", "list", "watch"]

常见问题解答

Q: 为什么 selectors 块中需要重复指定 role?

A: 这是 Grafana Alloy 的设计要求。外层的 role 定义了组件的主要发现类型,而 selectors 块中的 role 用于过滤特定类型的资源。

Q: 如何发现多种类型的资源?

A: 需要创建多个 discovery.kubernetes 组件实例,每个实例负责一种资源类型:

1
2
3
4
5
6
7
8
9
discovery.kubernetes "pods" {
  role = "pod"
  // ...
}

discovery.kubernetes "services" {
  role = "service"
  // ...
}

Q: 如何调试服务发现不工作的问题?

A: 1. 检查 RBAC 权限;2. 验证标签选择器;3. 查看 Alloy 日志;4. 使用 /api/v0/component 端点检查发现的目标。

实时调试服务配置

启用 Live Debugging

如果在使用 Alloy UI 时遇到 “the live debugging service is disabled” 错误,需要在配置文件中启用实时调试功能:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 在配置文件顶部添加 livedebugging 块
livedebugging {
  enabled = true
}

discovery.kubernetes "pods" {
  role = "pod"
  selectors {
    role = "pod"
    label = "app.kubernetes.io/name=flog"
  }
}

安全注意事项

1 实时调试功能默认被禁用,以避免意外显示敏感的遥测数据。启用时请确保:

  1. 配置 TLS 加密:在生产环境中使用 http 块配置 TLS
  2. 限制访问权限:确保只有授权用户能访问 Alloy UI
  3. 网络隔离:在非容器化平台上,Alloy 默认监听 localhost

访问 Alloy UI

1 Alloy UI 默认在 http://localhost:12345 提供服务,包含以下功能:

  • 组件健康状态:查看所有组件的运行状态
  • 实时数据流:观察组件间的数据流动
  • 配置验证:检查组件参数和导出值
  • 调试信息:获取详细的组件调试数据

参考资料

总结

通过正确配置 discovery.kubernetes 组件的 selectors 块,可以有效避免 “missing required attribute ‘role’” 错误。记住在 selectors 块中始终包含 role 属性,并根据实际需求配置适当的标签和字段选择器。

定期检查配置文件语法、验证 Kubernetes 权限、监控 Alloy 日志是确保服务发现正常工作的关键步骤。

0%