k8s~ServiceAccount_ClusterRole_ClusterRoleBinding
apisix的k8s服務發現配置
命名空(kong)間權(quan)限(xian)是基于Kubernetes RBAC能力的授權(quan),通過(guo)權(quan)限(xian)設置可以讓不(bu)同的用(yong)戶(hu)或(huo)用(yong)戶(hu)組擁有操作不(bu)同Kubernetes資(zi)源(yuan)的權(quan)限(xian)。Kubernetes RBAC API定義了四種類型:Role、ClusterRole、RoleBinding與ClusterRoleBinding,這四種類型之間的關系(xi)和簡要說明如下:
- Role:角色,其實是定義一組對Kubernetes資源(命名空間級別)的訪問規則。
- RoleBinding:角色綁定,定義了用戶和角色的關系。
- ClusterRole:集群角色,其實是定義一組對Kubernetes資源(集群級別,包含全部命名空間)的訪問規則。
- ClusterRoleBinding:集群角色綁定,定義了用戶和集群角色的關系。
Role和(he)(he)ClusterRole指(zhi)定(ding)了可以對哪些資源(yuan)做哪些動作,RoleBinding和(he)(he)ClusterRoleBinding將角色綁(bang)定(ding)到(dao)特定(ding)的用戶、用戶組或ServiceAccount上。如下圖所示。

實踐部分
1 為了讓 APISIX 能查(cha)詢和監聽(ting) Kubernetes 的 Endpoints 資源變動,我們(men)需要創建一個 ServiceAccount:
kind: ServiceAccount
apiVersion: v1
metadata:
name: apisix-test
namespace: default
2 以及一個(ge)具(ju)有集(ji)群級(ji)查詢和監聽(ting) Endpoints 資(zi)源(yuan)權限(xian)的 ClusterRole:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: apisix-test
rules:
- apiGroups: [ "" ]
resources: [ endpoints ]
verbs: [ get,list,watch ]
3 再將這個 ServiceAccount 和(he) ClusterRole 關聯起來(lai):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: apisix-test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: apisix-test
subjects:
- kind: ServiceAccount
name: apisix-test
namespace: default
4 然后我們需要(yao)獲(huo)取這個 ServiceAccount 的(de) token 值(zhi),如果 Kubernetes 是 v1.24 之前(qian)的(de)版本(ben),可以通過下面的(de)方(fang)法獲(huo)取 token 值(zhi):
$ kubectl get secrets | grep apisix-test
$ kubectl get secret apisix-test-token-879xv -o jsonpath={.data.token} | base64 -d
5 Kubernetes 從 v1.24 版本開始,不能(neng)再(zai)通過(guo) kubectl get secret 獲取 token 了,需要(yao)使用 TokenRequest API 來獲取,首(shou)先(xian)開啟代理:
$ kubectl proxy --port=8001
Starting to serve on 127.0.0.1:8001
6 然后(hou)調用 TokenRequest API 生成一個 token:
$ curl '//127.0.0.1:8001/api/v1/namespaces/default/serviceaccounts/apisix-test/token' \
-H "Content-Type:application/json" -X POST -d '{}'
{
"kind": "TokenRequest",
"apiVersion": "authentication.k8s.io/v1",
...
"status": {
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImtLdHRyVzFmNTRHWGFVUjVRS3hrLVJMSElNaXM4aENLMnpfSGk1SUJhbVkifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjc5NTMzMDQwLCJpYXQiOjE2Nzk1Mjk0NDAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0Iiwic2VydmljZWFjY291bnQiOnsibmFtZSI6ImFwaXNpeC10ZXN0IiwidWlkIjoiMzVjZWJkYTEtNGZjNC00N2JlLWIxN2QtZDA4NWJlNzU5ODRlIn19LCJuYmYiOjE2Nzk1Mjk0NDAsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmFwaXNpeC10ZXN0In0.YexM_VoumpdwZNbSkwh6IbEu59PCtZrG1lkTnCqG24G-TC0U1sGxgbXf6AnUQ5ybh-CHWbJ7oewhkg_J4j7FiSAnV_yCcEygLkaCveGIQbWldB3phDlcJ52f8YDpHFtN2vdyVTm79ECwEInDsqKhn4n9tPY4pgTodI6D9j-lcK0ywUdbdlL5VHiOw9jlnS7b60fKWBwCPyW2uohX5X43gnUr3E1Wekgpo47vx8lahTZQqnORahTdl7bsPsu_apf7LMw40FLpspVO6wih-30Ke8CNBxjpORtX2n3oteE1fi2vxYHoyJSeh1Pro_Oykauch0InFUNyEVI4kJQ720glOw",
"expirationTimestamp": "2023-03-23T00:57:20Z"
}
}
7 默認的(de) token 有(you)效期只有(you)一個小時,可以通過參數(shu)改為一年:
$ curl '//127.0.0.1:8001/api/v1/namespaces/default/serviceaccounts/apisix-test/token' \
-H "Content-Type:application/json" -X POST \
-d '{"kind":"TokenRequest","apiVersion":"authentication.k8s.io/v1","metadata":{"name":"apisix-test","namespace":"default"},"spec":{"audiences":["//kubernetes.default.svc.cluster.local"],"expirationSeconds":31536000}}'
8 我們(men)在 APISIX 的配置文件 config.yaml 中添加如(ru)下內容( 將上面生成的 token 填寫(xie)到 token 字段 ):
discovery:
kubernetes:
service:
schema: https
host: 127.0.0.1
port: "6443"
client:
token: ...
這里有一個比較坑的地方,port 必須是字符串,否則會導致 APISIX 啟動報錯
invalid discovery kubernetes configuration: object matches none of the required
大功告成!
參考: