概覽文章中提到了k8s的鑒權(quán)模式,簡(jiǎn)單回顧下:
- RBAC: Role-based access control 是基于角色的訪問控制
- ABAC: Atrribute-based access control 是基于屬性的訪問控制
- Node Authorization: 節(jié)點(diǎn)鑒權(quán),專門用于kubelet發(fā)出的api請(qǐng)求進(jìn)行鑒權(quán)
- Webhook Authorization: webhook是一種http回調(diào),kube-apiserver配置webhook時(shí), 會(huì)設(shè)置回調(diào)webhook的規(guī)則,這些規(guī)則中包含了調(diào)用的api
group、version、operation、scope等信息。
有細(xì)心的小伙伴指出,RBAC的角色可以作為ABAC的屬性來配置。 感謝小伙伴指正,ABAC可以更細(xì)粒度的控制權(quán)限,相應(yīng)配置起來也更復(fù)雜。
kubernetes 鑒權(quán)
選定RBAC模式后,關(guān)于角色,有Role和ClusterRole,對(duì)應(yīng)對(duì)象的綁定分別為: RoleBinding 和 ClusterRoleBinding。
Role創(chuàng)建后歸屬于特定的namespace,一般與特定namespace的權(quán)限綁定,而ClusterRole 不屬于任何namespace,通常與一組權(quán)限綁定。
ClusterRole通常用于
- 定義指定namespace資源的訪問權(quán)限,并在某個(gè)namespace范圍內(nèi)授予訪問權(quán)限;
- 定義指定namespace資源的訪問權(quán)限,并在跨namespace范圍內(nèi)授予訪問權(quán)限;
- 定義集群范圍內(nèi)的資源訪問權(quán)限。
官方文檔推薦,如果在單個(gè)namespace內(nèi)定義角色則使用Role,如果是定義集群范圍的角色,則使用ClusterRole。
要監(jiān)控kubernetes組件和集群范圍內(nèi)業(yè)務(wù)以及為了通用性,所以我們選擇ClusterRole 和 ClusterRoleBinding。
權(quán)限盤點(diǎn)
我們來盤點(diǎn)需要監(jiān)控的對(duì)象。
- 組件監(jiān)控,訪問組件metrics接口,需要非資源對(duì)象的
get/list權(quán)限。訪問/api/v1/xxx /apis/<group>/<version>/xxx都屬于非資源對(duì)象請(qǐng)求。 - node、pod對(duì)象的資源監(jiān)控, 需要訪問kubelet metrics接口,權(quán)限同上。
- serverless場(chǎng)景下,如果不能直接訪問kubelet,還需要
node/proxy的get權(quán)限。 - node、pod對(duì)象的數(shù)量監(jiān)控, 需要資源對(duì)象的
get/list權(quán)限。 - 自動(dòng)發(fā)現(xiàn), 需要service、endpoint的
get/list+watch權(quán)限。 - 如果要從metrics server 拿數(shù)據(jù),還需要metrics.k8s.io 的訪問權(quán)限。
不論需要多少權(quán)限, 一個(gè)原則就是按需申請(qǐng),最小化申請(qǐng)。 指標(biāo)采集都是讀權(quán)限,基本都是get、list。自動(dòng)發(fā)現(xiàn)要達(dá)到發(fā)現(xiàn)及時(shí),需要watch endpoints變化。
如何確定資源對(duì)象的api groups和version呢? 可以使用kubectl api-resources -o wide 來查看。 新版本的APIVERSION包含了api groups和version信息。

權(quán)限配置
基本的權(quán)限配置如下
- apiGroups: [""]
resources:
- pods
- nodes
- nodes/stats
- nodes/metrics
- nodes/proxy
- services
- endpoints
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
將權(quán)限填充到ClusterRole中
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations: {}
labels:
app: n9e
component: categraf
name: categraf-role
rules:
- apiGroups: [""]
resources:
- nodes
- nodes/stats
- nodes/metrics
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
有了ClusterRole, 創(chuàng)建ClusterRoleBinding之前,還需要一個(gè)ServiceAccount,用于存儲(chǔ)api的訪問憑據(jù),這個(gè)憑據(jù)可以以token形式掛載到Pod內(nèi)。
也可以直接解析用于Pod外部使用。
apiVersion: v1
kind: ServiceAccount
metadata:
annotations: {}
labels:
app: n9e
component: categraf
name: categraf-serviceaccount
namespace: ${NAMESPACE}
注意,ServiceAccount需要指定namespace,需要跟categraf即將部署的namespace保持一致。
利用ClusterRoleBinding 將ClusterRole和ServiceAccount關(guān)聯(lián)起來
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations: {}
labels:
app: n9e
component: categraf
name: categraf-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: categraf-role
subjects:
- kind: ServiceAccount
name: categraf-serviceaccount
namespace: ${NAMESPACE}
現(xiàn)在ClusterRoleBinding 已經(jīng)將權(quán)限和票據(jù)關(guān)聯(lián)起來了。
備注:創(chuàng)建完成后,ServiceAccount會(huì)自動(dòng)創(chuàng)建一個(gè)secret,這個(gè)secret 會(huì)自動(dòng)掛載到后續(xù)創(chuàng)建的categraf pod內(nèi)。
可以通過 kubectl get secrets -n monitoring categraf-serviceaccount-token-frqc5 -o jsonpath={.data.token} | base64 -d
獲得token內(nèi)容,這樣通過curl -s -k -H "Authorization: Bearer $TOKEN" 即可訪問apiserver,用來調(diào)試。
kubernetes 組件的服務(wù)發(fā)現(xiàn)
1. 監(jiān)控對(duì)象部署在pod內(nèi)
當(dāng)創(chuàng)建service(帶選擇符)時(shí),k8s會(huì)自動(dòng)為pod創(chuàng)建endpoint,這樣service和pod就關(guān)聯(lián)起來了。利用這個(gè)特性,我們可以及時(shí)發(fā)現(xiàn)pod的變化。
如果組件是部署在pod內(nèi),我們就可以直接利用這個(gè)特性進(jìn)行采集。比如kubeadm部署的集群,apiserver 本身就已經(jīng)創(chuàng)建了對(duì)應(yīng)的service。
...
- job_name: "apiserver"
metrics_path: "/metrics"
kubernetes_sd_configs:
- role: endpoints # 看這里
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels:
[
__meta_kubernetes_namespace,
__meta_kubernetes_service_name,
__meta_kubernetes_endpoint_port_name,
]
action: keep
regex: default;kubernetes;https
...
2. 監(jiān)控對(duì)象部署在物理機(jī) (文件服務(wù)發(fā)現(xiàn))
如果組件是以二進(jìn)制方式部署在物理機(jī),又沒有其他服務(wù)發(fā)現(xiàn)的手段。那可以利用prometheus類似的文件服務(wù)發(fā)現(xiàn),當(dāng)組件有變更時(shí),直接在目錄中添加刪除包含目標(biāo)信息的文件就好了。
這里多提一點(diǎn),之前有小伙伴提出,categraf提供一個(gè)注冊(cè)接口,服務(wù)向categraf注冊(cè),然后categraf去拉注冊(cè)目標(biāo)指標(biāo)。categraf本身的定位是一個(gè)采集器,沒有服務(wù)發(fā)現(xiàn)的功能。
提一個(gè)最簡(jiǎn)單的問題,如果categraf掛了重啟,但是采集目標(biāo)沒有發(fā)現(xiàn),這里就會(huì)有很多數(shù)據(jù)不能被采集了。再有就是集中式拉取方式,提供push接口,會(huì)把業(yè)務(wù)和采集器耦合更深了。
這種方式 并不可取。
....
- job_name: 'coredns'
file_sd_configs:
- files:
- /home/work/prometheus/file_sd_config/*.json
...
在file_sd_config目錄下放一個(gè)json文件,如下:
[
{
"labels": {
"job": "coredns"
},
"targets": [
"172.16.6.160:9153"
]
}
]
等增加新的coredns后,只需要再增加一份json配置(這里只是為了舉例說明,直接修改coredns.json效果一樣)。不需要再做任何其他操作
[
{
"labels": {
"job": "coredns"
},
"targets": [
"172.16.0.85:9153"
]
}
]
3. 其他服務(wù)發(fā)現(xiàn)方式
采集器categraf集成了prometheus的agent mode模式, 如果你使用了其他服務(wù)發(fā)現(xiàn)方式, 例如consul,則可以和categraf無縫對(duì)接了。
除此之外,還支持docker_swarm_sd_configs,docker_sd_config, dns_sd_configs, http_sd_configs等prometheus所支持的服務(wù)發(fā)現(xiàn)方式。
本次主要介紹kubernete權(quán)限和服務(wù)自動(dòng)發(fā)現(xiàn)。感謝大家持續(xù)關(guān)注,歡迎各位批評(píng)指正, 歡迎各位點(diǎn)贊 轉(zhuǎn)發(fā)和收藏。
關(guān)于作者
本文作者是孔飛,來自快貓星云( https://flashcat.cloud )是Kubernetes和Prometheus專家,快貓團(tuán)隊(duì)致力于讓監(jiān)控更簡(jiǎn)單,為企業(yè)提供穩(wěn)定性保障的產(chǎn)品,也提供夜鶯監(jiān)控的技術(shù)支持服務(wù),性價(jià)比極高,有興趣的小伙伴歡迎聯(lián)系我們
關(guān)于夜鶯監(jiān)控
夜鶯監(jiān)控是一款開源云原生監(jiān)控分析系統(tǒng),姑且可以看做是 Prometheus 的企業(yè)級(jí)版本。Kubernetes 監(jiān)控系列文章都是基于夜鶯監(jiān)控來梳理,歡迎關(guān)注
- 夜鶯站點(diǎn):https://n9e.github.io/
- 倉(cāng)庫(kù)地址:https://github.com/ccfos/nightingale