指标认证与授权
介绍
从 Kubebuilder v4 开始,Shifu 的控制器暴露了一个带有内置认证和授权功能的 /metrics
端点。此端点提供与 Prometheus 兼容的指标,用于监控控制器的健康状况和性能。
主要特性:
- 认证: 所有请求都使用 Kubernetes TokenReview 进行认证
- 授权: 通 过 RBAC 使用 SubjectAccessReview 控制访问
- 默认使用 HTTP: 指标通过 HTTP(端口 8080)提供服务,以避免证书问题
- 可选 HTTPS: 可以通过 cert-manager 启用加密传输
无论您使用 HTTP 还是 HTTPS,认证和授权始终启用。这确保只有授权的用户和服务账户才能访问指标。
默认配置(HTTP)
默认情况下,Shifu 在 HTTP 端口 8080 上提供指标服务,并启用认证。此配置无需额外设置即可开箱即用,适用于大多数在受信任集群网络内进行指标采集的部署。
为什么默认使用 HTTP?
在不使用 cert-manager 的情况下使用 HTTPS 时,controller-runtime 会生成自签名证书,这些证书仅包含 localhost
和 127.0.0.1
作为主体备用名称(SAN)。当 Prometheus 或其他工具尝试使用服务 DNS 名称(例如 shifu-crd-controller-manager-metrics-service.shifu-crd-system.svc.cluster.local
)采集指标时,这会导致 x509 验证错误。
HTTP 避免了这些证书问题,同时仍然通过认证和授权保持安全性。
认证工作原理
指标端点使用 Kubernetes 的内置认证机制:
- TokenReview: 验证客户端发送的 bearer token 是否有效
- SubjectAccessReview: 检查已认证的身份是否有权限访问
/metrics
这意味着每个请求都必须包含有效的 Kubernetes ServiceAccount token,并且 ServiceAccount 必须具有适当的 RBAC 权限。
未授权的访问
如果您尝试在没有适当授权的情况下访问指标:
$ kubectl exec -it deploy/prometheus -n monitoring -- \
curl -k http://shifu-crd-controller-manager-metrics-service.shifu-crd-system.svc.cluster.local:8080/metrics
Unauthorized
授予指标访问权限
要允许 ServiceAccount 访问指标,您需要将其绑定到 shifu-crd-metrics-reader
ClusterRole。
步骤 1: 创建 ServiceAccount
在您的监控工具运行的命名空间中创建 ServiceAccount:
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitoring
步骤 2: 创建 ClusterRoleBinding
将 ServiceAccount 绑定到 shifu-crd-metrics-reader
ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-metrics-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: shifu-crd-metrics-reader
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
应用这两个资源:
kubectl apply -f prometheus-sa.yaml
kubectl apply -f prometheus-metrics-binding.yaml
步骤 3: 配置 Prometheus 使用 ServiceAccount
更新您的 Prometheus 部署以使用 ServiceAccount:
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
template:
spec:
serviceAccountName: prometheus # 使用我们创建的 ServiceAccount
containers:
- name: prometheus
image: prom/prometheus:latest
# ... 其余配置
步骤 4: 添加采集配置
配置 Prometheus 采集 Shifu 控制器指标:
scrape_configs:
- job_name: 'shifu-controller'
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- shifu-crd-system
relabel_configs:
- source_labels: [__meta_kubernetes_service_name]
regex: shifu-crd-controller-manager-metrics-service
action: keep
- source_labels: [__meta_kubernetes_endpoint_port_name]
regex: http
action: keep
scheme: http
验证
测试 ServiceAccount 现在可以访问指标:
$ kubectl exec -it deploy/prometheus -n monitoring -- \
curl -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
http://shifu-crd-controller-manager-metrics-service.shifu-crd-system.svc.cluster.local:8080/metrics
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 2.5875e-05
...
可选: 使用 Cert-Manager 启用 HTTPS
对于需要加密指标的生产环境,您可以使用 cert-manager 启用 HTTPS。此配置:
- 在端口 8443 上通过 TLS 提供指标服务
- 生成具有正确 DNS 名称作为 SAN 的有效证书
- 保持认证和授权
前提条件
在集群中安装 cert-manager:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.yaml
等待 cert-manager 准备就绪:
kubectl wait --for=condition=Available --timeout=300s \
deployment/cert-manager -n cert-manager
在 Shifu 中启用 HTTPS
编辑 pkg/k8s/crd/config/default/kustomization.yaml
并取消注释 cert-manager 部分:
resources:
# 取消注释以下行
- ../certmanager
patches:
# 取消注释以下补丁
- path: cert_metrics_manager_patch.yaml
target:
kind: Deployment
- path: cert_metrics_service_patch.yaml
target:
kind: Service
name: controller-manager-metrics-service
# 取消注释 replacements 部分
replacements:
- source:
kind: Service
version: v1
name: controller-manager-metrics-service
fieldPath: metadata.name
targets:
- select:
kind: Certificate
group: cert-manager.io
version: v1
name: metrics-certs
fieldPaths:
- spec.dnsNames.0
- spec.dnsNames.1
options:
delimiter: '.'
index: 0
create: true
# ... (其余 replacements)
重新部署 Shifu
应用更新的配置:
cd pkg/k8s/crd
make deploy IMG=edgehub/shifu-controller:nightly
更新 Prometheus 配置
更新采集配置以使用 HTTPS:
scrape_configs:
- job_name: 'shifu-controller'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: false # 证书现在有效!
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- shifu-crd-system
relabel_configs:
- source_labels: [__meta_kubernetes_service_name]
regex: shifu-crd-controller-manager-metrics-service
action: keep
- source_labels: [__meta_kubernetes_endpoint_port_name]
regex: https # 从 'http' 改为 'https'
action: keep
故障排除
"Unauthorized" 错误
问题: 指标端点返回 Unauthorized
解决方案: 这意味着认证失败。确保您的请求包含有效的 bearer token:
# 在请求中包含 ServiceAccount token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -H "Authorization: Bearer $TOKEN" http://metrics-service:8080/metrics
"Forbidden" 错误
问题: 指标端点返回 Forbidden
解决方案: 这意味着认证成功,但授权失败。ServiceAccount 没有访问 /metrics
的权限。创建 ClusterRoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-app-metrics-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: shifu-crd-metrics-reader
subjects:
- kind: ServiceAccount
name: my-app
namespace: my-namespace
x509 证书错误(HTTPS)
问题: x509: certificate is valid for localhost, not shifu-crd-controller-manager-metrics-service.shifu-crd-system.svc.cluster.local
解决方案: 这发生在不使用 cert-manager 的情况下启用 --metrics-secure=true
时。您可以:
- 使用 HTTP(大多数情况下推荐): 保持默认配置
- 启用 cert-manager: 按照上面的 HTTPS 设置指南操作
连接被拒绝
问题: 尝试访问指标时出现 Connection refused
解决方案: 检查 Shifu 控制器是否正在运行:
kubectl get pods -n shifu-crd-system
kubectl logs -n shifu-crd-system deploy/shifu-crd-controller-manager
检查服务是否存在:
kubectl get svc -n shifu-crd-system shifu-crd-controller-manager-metrics-service
完整示例: 具有指标访问权限的 Prometheus
以下是部署具有指标访问权限的 Prometheus 的完整示例:
1. 创建监控命名空间
kubectl create namespace monitoring
2. 创建 ServiceAccount 和 RBAC
# prometheus-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-metrics-reader
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: shifu-crd-metrics-reader
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
3. 创建 Prometheus ConfigMap
# prometheus-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'shifu-controller'
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- shifu-crd-system
relabel_configs:
- source_labels: [__meta_kubernetes_service_name]
regex: shifu-crd-controller-manager-metrics-service
action: keep
- source_labels: [__meta_kubernetes_endpoint_port_name]
regex: http
action: keep
scheme: http
4. 部署 Prometheus
# prometheus-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
serviceAccountName: prometheus
containers:
- name: prometheus
image: prom/prometheus:latest
ports:
- containerPort: 9090
volumeMounts:
- name: config
mountPath: /etc/prometheus
volumes:
- name: config
configMap:
name: prometheus-config
5. 应用所有资源
kubectl apply -f prometheus-rbac.yaml
kubectl apply -f prometheus-config.yaml
kubectl apply -f prometheus-deployment.yaml
6. 验证指标收集
端口转发到 Prometheus:
kubectl port-forward -n monitoring deploy/prometheus 9090:9090
打开 http://localhost:9090 并检查 shifu-controller
目标是否正常运行并成功采集指标。
总结
- 指标始终经过认证和授权,无论是 HTTP 还是 HTTPS
- 默认配置使用 HTTP(端口 8080) 以避免证书问题
- 授予访问权限需要将 ServiceAccount 绑定到
shifu-crd-metrics-reader
ClusterRole - HTTPS 是可选的,需要 cert-manager 来生成有效证书
- 认证错误(
Unauthorized
)表示 token 缺失或无效 - 授权错误(
Forbidden
)表示 ServiceAccount 缺少权限
有关指标系统的更多信息,请参阅 controller-runtime 指标文档。