apisix的k8s服务发现配置
命名空间权限是基于Kubernetes RBAC能力的授权,通过权限设置可以让不同的用户或用户组拥有操作不同Kubernetes资源的权限。Kubernetes RBAC API定义了四种类型:Role、ClusterRole、RoleBinding与ClusterRoleBinding,这四种类型之间的关系和简要说明如下:
- Role:角色,其实是定义一组对Kubernetes资源(命名空间级别)的访问规则。
- RoleBinding:角色绑定,定义了用户和角色的关系。
- ClusterRole:集群角色,其实是定义一组对Kubernetes资源(集群级别,包含全部命名空间)的访问规则。
- ClusterRoleBinding:集群角色绑定,定义了用户和集群角色的关系。
Role和ClusterRole指定了可以对哪些资源做哪些动作,RoleBinding和ClusterRoleBinding将角色绑定到特定的用户、用户组或ServiceAccount上。如下图所示。
实践部分
1 为了让 APISIX 能查询和监听 Kubernetes 的 Endpoints 资源变动,我们需要创建一个 ServiceAccount:
kind: ServiceAccount
apiVersion: v1
metadata:name: apisix-testnamespace: default
2 以及一个具有集群级查询和监听 Endpoints 资源权限的 ClusterRole:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: apisix-test
rules:
- apiGroups: [ "" ]resources: [ endpoints ]verbs: [ get,list,watch ]
3 再将这个 ServiceAccount 和 ClusterRole 关联起来:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: apisix-test
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: apisix-test
subjects:- kind: ServiceAccountname: apisix-testnamespace: default
4 然后我们需要获取这个 ServiceAccount 的 token 值,如果 Kubernetes 是 v1.24 之前的版本,可以通过下面的方法获取 token 值:
$ kubectl get secrets | grep apisix-test
$ kubectl get secret apisix-test-token-879xv -o jsonpath={.data.token} | base64 -d
5 Kubernetes 从 v1.24 版本开始,不能再通过 kubectl get secret 获取 token 了,需要使用 TokenRequest API 来获取,首先开启代理:
$ kubectl proxy --port=8001
Starting to serve on 127.0.0.1:8001
6 然后调用 TokenRequest API 生成一个 token:
$ curl 'http://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 默认的 token 有效期只有一个小时,可以通过参数改为一年:
$ curl 'http://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":["https://kubernetes.default.svc.cluster.local"],"expirationSeconds":31536000}}'
8 我们在 APISIX 的配置文件 config.yaml 中添加如下内容( 将上面生成的 token 填写到 token 字段 ):
discovery:kubernetes:service:schema: httpshost: 127.0.0.1port: "6443"client:token: ...
这里有一个比较坑的地方,port 必须是字符串,否则会导致 APISIX 启动报错
invalid discovery kubernetes configuration: object matches none of the required
大功告成!
参考:https://www.aneasystone.com/archives/2023/03/apisix-service-discovery.html