1、概述

  kube-rbac-proxy 是 Kubernetes 生态中一个专注于“基于角色的访问控制(RBAC)”的轻量级代理组件,通常以 Sidecar 容器的形式部署在 Pod 中,为服务提供细粒度的请求鉴权能力。它尤其适用于保护 /metrics、/debug 等敏感端点,通过将 RBAC 策略直接应用到应用层,弥补了 Kubernetes 原生网络策略的不足,成为服务安全的关键防线。
  在使用 Prometheus 监控 Kubernetes 集群时,一个常见的问题是 Prometheus 检索的指标可能包含敏感信息(例如,Prometheus 节点导出器暴露了主机的内核版本),这些信息可能被潜在入侵者利用。虽然 Prometheus 中验证和授权指标端点的默认方法是使用 TLS 客户端证书,但由于发行、验证和轮换客户端证书的复杂性,Prometheus 请求在大多数情况下并未经过验证和授权。为了解决这一问题,kube-rbac-proxy 应运而生,它是一个针对单一上游的小型 HTTP 代理,能够使用 SubjectAccessReviews 对 Kubernetes API 执行 RBAC 鉴权,从而确保只有经过授权的请求(如来自 Prometheus 的请求)能够从 Pod 中运行的应用程序中检索指标。本文将详细解释 kube-rbac-proxy 如何利用 Kubernetes RBAC 实现这一功能。

  项目地址:https://github.com/brancz/kube-rbac-proxy

2、RBAC是如何在幕后工作的

  Kubernetes基于角色的访问控制(RBAC)本身只解决了一半的问题。顾名思义,它只涉及访问控制,意味着授权,而不是认证。在一个请求能够被授权之前,它需要被认证。简单地说:我们需要找出谁在执行这个请求。在Kubernetes中,服务自我认证的机制是ServiceAccount令牌。
  Kubernetes API公开了验证ServiceAccount令牌的能力,使用所谓的TokenReview。TokenReview的响应仅仅是ServiceAccount令牌是否被成功验证,以及指定的令牌与哪个用户有关。kube-rbac-proxy期望ServiceAccount令牌在Authorization HTTP头中被指定,然后使用TokenReview对其进行验证。
  在这一点上,一个请求已经被验证,但还没有被授权。与TokenReview平行,Kuberenetes有一个SubjectAccessReview,它是授权API的一部分。在SubjectAccessReview中,指定了一个预期的行动以及想要执行该行动的用户。在Prometheus请求度量的具体案例中,/metrics HTTP端点被请求。不幸的是,在Kubernetes中这不是一个完全指定的资源,然而,SubjectAccessReview资源也能够授权所谓的 "非资源请求"。
  当用Prometheus监控Kubernetes时,那么Prometheus服务器可能已经拥有访问/metrics非资源url的权限,因为从Kubernetes apiserver检索指标需要同样的RBAC角色。

注意 1:TokenReview详解参见《Kubernetes身份认证资源 —— TokenReview详解》这篇博文,SubjectAccessReview详解参见《Kubernetes鉴权资源 —— SubjectAccessReview详解》这篇博文。

3、kube-rbac-proxy原理及示例

3.1 原理

  现在已经解释了所有必要的部分,让我们看看kube-rbac-proxy是如何具体地验证和授权一个请求的,案例在本博文的开头就已经说明了。普罗米修斯从节点输出器中请求度量。

  当Prometheus对node-exporter执行请求时,kube-rbac-proxy在它前面,kube-rbac-proxy用提供的ServiceAccount令牌执行TokenReview,如果TokenReview成功,它继续使用SubjectAccessReview来验证,ServiceAccount被授权访问/metrics HTTP端点。

  可见,从Prometheus验证和授权请求的整个流程是这样的:

3.2 示例

通过node-exporter的servicemonitors资源对象配置可知,prometheus访问node-expoter指标用的是/var/run/secrets/kubernetes.io/serviceaccount/token。

[root@xxx]# kubectl get servicemonitors.monitoring.coreos.com -n=xxxx node-exporter -o yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
.....
spec:
endpoints:
- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
interval: 1m
metricRelabelings:
- action: keep
regex: node_(uname|network)_info|node_cpu_.+|node_memory_Mem.+_bytes|node_memory_SReclaimable_bytes|node_memory_Cached_bytes|node_memory_Buffers_bytes|node_network_(.+_bytes_total|up)|node_network_.+_errs_total|node_nf_conntrack_entries.*|node_disk_.+_completed_total|node_disk_.+_bytes_total|node_filesystem_files|node_filesystem_files_free|node_filesystem_avail_bytes|node_filesystem_size_bytes|node_filesystem_free_bytes|node_filesystem_readonly|node_load.+|node_timex_offset_seconds
sourceLabels:
- __name__
port: https
relabelings:
- action: labeldrop
regex: (service|endpoint)
- action: replace
regex: (.*)
replacement: $1
sourceLabels:
- __meta_kubernetes_pod_node_name
targetLabel: instance
scheme: https
tlsConfig:
insecureSkipVerify: true
jobLabel: app.kubernetes.io/name
selector:
matchLabels:
app.kubernetes.io/name: node-exporter

进入prometheus容器内部获取并解析token。

[root@x]# kubectl exec -it -n=xxxx prometheus-k8s-0 /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "prometheus" out of: prometheus, config-reloader
/prometheus # cd /var/run/secrets/kubernetes.io/serviceaccount/
/var/run/secrets/kubernetes.io/serviceaccount # ls
ca.crt namespace token
/var/run/secrets/kubernetes.io/serviceaccount # cat token
eyJhbGciOiJSUzI1NiIsImtpZCI6ImpyaFRNMDRFR0h5a2JpSUY2Vk5jM2lZYnRYY2Fwcl9yTmhDV04tTkdzdnMifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNzczMTA4NDgwLCJpYXQiOjE3NDE1NzI0ODAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJjbG91ZGJhc2VzLW1vbml0b3Jpbmctc3lzdGVtIiwicG9kIjp7Im5hbWUiOiJwcm9tZXRoZXVzLWs4cy0wIiwidWlkIjoiZDhmMDJmZDgtNGVjNS00M2VlLWIyYzQtMzY3MWViMTEyOWViIn0sInNlcnZpY2VhY2NvdW50Ijp7Im5hbWUiOiJwcm9tZXRoZXVzLWs4cyIsInVpZCI6IjE4NDRjNzcxLTkyMjctNDYzOS1iY2FlLTQ3NTQ0NmU5MDU0OCJ9LCJ3YXJuYWZ0ZXIiOjE3NDE1NzYwODd9LCJuYmYiOjE3NDE1NzI0ODAsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpjbG91ZGJhc2VzLW1vbml0b3Jpbmctc3lzdGVtOnByb21ldGhldXMtazhzIn0.lBPR2j1Ad_zzRH98nk35DFIKhBXPCLN4KcnqzZA1i8tOwVEkMY4nGUIXT8par1AWDKNm2S6wpJUH7WPh3VM4k-KOrD-gFC8lovPj67NEY__6cW0X6VHTSBC2euAr4uVYSoL4tCW0EzPoDajoXrqmcOAqwzNSZb7ecLaN5yv5VyEUK79zbJvZ2-n-T0y2nYBe3qP1wH2XIrhcWB2Vam4_9YICeJ6WmGwc16rH_phQu8Zu58EJ7CDt_oiQ7Iz/var/run/secrets/kubernetes.io/serviceaccount #

查看node-exporter服务配置:

apiVersion: v1
kind: Service
metadata:
......
spec:
clusterIP: None
clusterIPs:
- None
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: https
port: 9100
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/name: node-exporter
sessionAffinity: None
type: ClusterIP

查看node-exporter守护进程集配置,可以看到node-exporter应用容器本身是没有开放容器端口的,所有外部进入流量都走kube-rbac-proxy,进入流量kube-rbac-proxy先认证(TokenReview),认证并获取用户信息prometheus-k8s,然后再鉴权(SubjectAccessReview,查看是否有/metrics访问权限),鉴权通过后再把流量代理到node-exporter容器(http://127.0.0.1:9100/):

apiVersion: apps/v1
kind: DaemonSet
metadata:
......
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/name: node-exporter
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/name: node-exporter
app.kubernetes.io/version: v0.18.1
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/edge
operator: DoesNotExist
containers:
- args:
- --web.listen-address=127.0.0.1:9100
- --path.procfs=/host/proc
- --path.sysfs=/host/sys
- --path.rootfs=/host/root
- --no-collector.wifi
- --no-collector.hwmon
- --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/)
- --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$
image: 192.168.137.94:80/cscec_big_data-cloudbases/node-exporter:v0.18.1
imagePullPolicy: IfNotPresent
name: node-exporter
resources:
limits:
cpu: "1"
memory: 500Mi
requests:
cpu: 102m
memory: 180Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /host/proc
name: proc
readOnly: true
- mountPath: /host/sys
name: sys
readOnly: true
- mountPath: /host/root
mountPropagation: HostToContainer
name: root
readOnly: true
- args:
- --logtostderr
- --secure-listen-address=[$(IP)]:9100
- --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- --upstream=http://127.0.0.1:9100/
env:
- name: IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
image: 192.168.137.94:80/cscec_big_data-cloudbases/kube-rbac-proxy:v0.8.0
imagePullPolicy: IfNotPresent
name: kube-rbac-proxy
ports:
- containerPort: 9100
hostPort: 9100
name: https
protocol: TCP
resources:
limits:
cpu: "1"
memory: 100Mi
requests:
cpu: 10m
memory: 20Mi
securityContext:
runAsGroup: 65532
runAsNonRoot: true
runAsUser: 65532
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
hostNetwork: true
hostPID: true
nodeSelector:
kubernetes.io/os: linux
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
runAsNonRoot: true
runAsUser: 65534
serviceAccount: node-exporter
serviceAccountName: node-exporter
terminationGracePeriodSeconds: 30
tolerations:
- operator: Exists
volumes:
- hostPath:
path: /proc
type: ""
name: proc
- hostPath:
path: /sys
type: ""
name: sys
- hostPath:
path: /
type: ""
name: root
updateStrategy:
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
type: RollingUpdate
status:
currentNumberScheduled: 1
desiredNumberScheduled: 1
numberAvailable: 1
numberMisscheduled: 0
numberReady: 1
observedGeneration: 1
updatedNumberScheduled: 1

注意 1: clusterrolebinding:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
......
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: xxxx-prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: xxxxx

clusterrole:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
......
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
- nodes
- services
- endpoints
- pods
verbs:
- get
- list
- watch
- nonResourceURLs:
- /metrics
verbs:
- get

5、总结

 kube-rbac-proxy 作为 Kubernetes RBAC 的扩展组件,通过将权限控制能力延伸至应用层,为服务端点提供细粒度权限控制。特别适用于敏感接口防护、多租户资源隔离等场景(如 Prometheus 安全采集 node-exporter/kube-state-metrics 指标)。尽管会增加少量部署复杂度,但通过强化 API 访问审计、身份验证和权限校验,显著提升集群安全防护能力,已成为云原生环境中保障关键业务安全的核心组件。

主要参考:https://juejin.cn/post/7217644586868801596

通过Kube-rbac-proxy保护 Kubernetes 工作负载中的应用容器的更多相关文章

  1. (译)Kubernetes中的多容器Pod和Pod内容器间通信

    原文:https://www.mirantis.com/blog/multi-container-pods-and-container-communication-in-kubernetes/Pave ...

  2. 重定向Kubernetes pod中的tcpdump输出

    重定向Kubernetes pod中的tcpdump输出 最新发现一个比较有意思的库ksniff,它是一个kubectl 插件,使用tcpdump来远程捕获Kubernetes集群中的pod流量并保存 ...

  3. windows7下系统保护中出现错误“文件名、目录名或卷标语法不正确。(0x8007007B)“ 以及保护设置列表中出现“Windows7_os(c:)(找不到)”选项时的解决方法

    windows7下系统保护功能很是鸡肋,有事会出现一下两个问题: 1.出现错误“文件名.目录名或卷标语法不正确.(0x8007007B) 2.保护设置列表中出现“Windows7_os(c:)(找不到 ...

  4. ASP.NET Core在Azure Kubernetes Service中的部署和管理

    目录 ASP.NET Core在Azure Kubernetes Service中的部署和管理 目标 准备工作 注册 Azure 账户 AKS文档 进入Azure门户(控制台) 安装 Azure Cl ...

  5. kubernetes中的Pause容器如何理解?

    前几篇文章都是讲的Kubernetes集群和相关组件的部署,但是部署只是入门的第一步,得理解其中的一些知识才行.今天给大家分享下Kubernets的pause容器的作用. Pause容器 全称infr ...

  6. kubernetes集群中的pause容器

    昨天晚上搭建好了k8s多主集群,启动了一个nginx的pod,然而每启动一个pod就伴随这一个pause容器,考虑到之前在做kubelet的systemd unit文件时有见到: 1 2 3 4 5 ...

  7. Kubernetes 平台中的日志收集

    准备 关于容器日志 Docker 的日志分为两类,一类是 Docker 引擎日志:另一类是容器日志.引擎日志一般都交给了系统日志,不同的操作系统会放在不同的位置. 本文主要介绍容器日志,容器日志可以理 ...

  8. K8s中的多容器Pod和Pod内容器间通信

    容器(Container)常被用来解决比如微服务的单个问题,但在实际场景中,问题的解决往往需要多容器方案.本文会讨论将多个容器整合进单个Kubernetes Pod 中,以及Pod中的容器之间是如何通 ...

  9. 《两地书》--Kubernetes(K8s)基础知识(docker容器技术)

    大家都知道历史上有段佳话叫“司马相如和卓文君”.“皑如山上雪,皎若云间月”.卓文君这么美,却也抵不过多情女儿薄情郎. 司马相如因一首<子虚赋>得汉武帝赏识,飞黄腾达之后便要与卓文君“故来相 ...

  10. Spring管理Filter和Servlet(在servlet中注入spring容器中的bean)

    在使用spring容器的web应用中,业务对象间的依赖关系都可以用context.xml文件来配置,并且由spring容器来负责依赖对象 的创建.如果要在servlet中使用spring容器管理业务对 ...

随机推荐

  1. java判断反射的Field是不是用final修饰

    今天调用Field.set方法报错: Caused by: java.lang.IllegalAccessException: Can not set static final long field ...

  2. 2024-12-28:求出出现两次数字的 XOR 值。用go语言,给定一个数组 nums,其中的数字出现的频率要么是一次,要么是两次。 请找出所有出现两次的数字,并计算它们的按位 XOR 值。 如果没

    2024-12-28:求出出现两次数字的 XOR 值.用go语言,给定一个数组 nums,其中的数字出现的频率要么是一次,要么是两次. 请找出所有出现两次的数字,并计算它们的按位 XOR 值. 如果没 ...

  3. 在Node.js环境下使用npm命令安装OpenLayers6.4.3时,提示错误“rollbackFailedOptional: verb npm-session”的解决办法

    该问题一般情况是因为npm源问题. 更换为淘宝的源: npm config set registry http://registry.npm.taobao.org 使用  npm info expre ...

  4. IM跨平台技术学习(九):全面解密新QQ桌面版的Electron内存优化实践

    本文由QQ技术团队分享,本文收录时有内容修订和大量排版优化. 1.引言 QQ 作为国民级应用,从互联网兴起就一直陪伴着大家,是很多用户刚接触互联网就开始使用的应用. 而 QQ 桌面版最近一次技术架构升 ...

  5. SpringBoot进阶教程(八十四)spring-retry

    在日常的一些场景中, 很多需要进行重试的操作.而spring-retry是spring提供的一个基于spring的重试框架,某些场景需要对一些异常情况下的方法进行重试就会用到spring-retry. ...

  6. 分析基于ASP.NET Core Kernel的gRPC服务在不同.NET版本的不同部署方式的不同线程池下的性能表现

    分析基于ASP.NET Core Kernel的gRPC服务在不同.NET版本的不同部署方式的不同线程池下的性能表现 使用默认的 gRPC 项目模板创建,垃圾回收器类型为 ServerGC(Serve ...

  7. JS 实现在指定的时间点播放列表中的视频

    为了实现在指定的时间点播放列表中的视频,你可以使用JavaScript中的setTimeout或setInterval结合HTML5的<video>元素.但是,由于你需要处理多个时间点,并 ...

  8. biancheng-Spring Cloud Alibaba Sentinel

    http://c.biancheng.net/springcloud/sentinel.html Sentinel 是由阿里巴巴中间件团队开发的开源项目,是一种面向分布式微服务架构的轻量级高可用流量控 ...

  9. 基于Pamion的流实数仓架构

    目录 1. 背景 2. 目标 3. Pamion 的概念和设计 3.1 架构 3.2 统一存储 3.3 基础概念 3.3.1 文件布局 3.3.2 Snapshot 3.3.3 Manifest 文件 ...

  10. MPC收藏

    收集有关MPC的优秀文章,方便查阅. 同态加密 原理 介绍 程序员的干货!核心理论之同态加密 https://mp.weixin.qq.com/s/1uH0UjnS_Mo8ShXJ-16UXw BGV ...