一、K8s 多租户管理
多租户是指在同一集群中隔离多个用户或团队,以避免他们之间的资源冲突和误操作。在K8s
中,多租户管理的核心目标是在保证安全性的同时,提高资源利用率和运营效率。
在K8s
中,该操作可以通过命名空间(Namespaces
)+ RBAC
角色权限控制实现资源的隔离。每个租户都可以拥有自己的命名空间,从而避免资源名称的冲突。此外,通过资源配额(Resource Quotas
)和限制范围(Limit Ranges
),进一步确保每个租户只能使用一定量的计算资源,如CPU
、内存,以及API
对象的数量等。通过RBAC
,为每个租户或用户组分配不同的角色和权限,从而确保他们只能访问和操作他们有权管理的资源。
例如下图所示,这是一个简单的多租户案例,租户A
仅能操控命名空间 ns1
中的资源,而租户B
也只能操控命名空间 ns2
中的资源,对于对方的的资源均无法操作。并且每个租户的资源也不是无限使用的,通过资源配额为每个命名空间限制了使用额度,这样就不会因为某一个租户资源使用过大影响其他租户的应用。
下面开始实践下上图中的结构。
二、创建租户
1. 创建租户的命名空间
这里创建两个命名空间,下面分配给租户A
和租户B
使用:
kubectl create ns ns1
kubectl create ns ns2
2. 对两个命名空间进行资源配额
vi ns_rq.yml
apiVersion: v1
kind: ResourceQuota
metadata:
name: ns1-rq
namespace: ns1
spec:
hard:
requests.cpu: "2"
requests.memory: 2Gi
limits.cpu: "4"
limits.memory: 4Gi
pods: "200"
services: "50"
persistentvolumeclaims: "30"
secrets: "100"
configmaps: "100"
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: ns2-rq
namespace: ns2
spec:
hard:
requests.cpu: "2"
requests.memory: 2Gi
limits.cpu: "4"
limits.memory: 4Gi
pods: "200"
services: "50"
persistentvolumeclaims: "30"
secrets: "100"
configmaps: "100"
上面控制了cpu
和内存的请求总和大小,以及一些资源的数量。
注意:这里为了方便后续的测试 cpu
和 内存 都给的比较少,根据你实际的情况进行配置。
kubectl apply -f ns_rq.yml
3. 创建租户A和租户B,指定命名空间,并分配权限
vi user.yml
# 创建租户
apiVersion: v1
kind: ServiceAccount
metadata:
name: user-a
namespace: ns1
---
# 分配操作权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: user-a-role
namespace: ns1
rules:
- apiGroups:
- apps
- ''
resources:
- deployments
- replicasets
- statefulsets
- daemonsets
- services
- pods
- pods/log
- pods/exec
- namespaces
- configmaps
- secrets
- endpoints
- storageclasss
- persistentvolumes
- persistentvolumeclaims
- jobs
- daemonsets
- cronjobs
verbs:
- list
- get
- watch
- create
- update
- delete
- patch
- edit
- view
---
# 绑定用户
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: user-a-role-bd
namespace: ns1
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: user-a-role
subjects:
- kind: ServiceAccount
name: user-a
namespace: ns1
---
# 创建租户
apiVersion: v1
kind: ServiceAccount
metadata:
name: user-b
namespace: ns2
---
# 分配操作权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: user-b-role
namespace: ns2
rules:
- apiGroups:
- apps
- ''
resources:
- deployments
- replicasets
- statefulsets
- daemonsets
- services
- pods
- pods/log
- pods/exec
- namespaces
- configmaps
- secrets
- endpoints
- storageclasss
- persistentvolumes
- persistentvolumeclaims
- jobs
- daemonsets
- cronjobs
verbs:
- list
- get
- watch
- create
- update
- delete
- patch
- edit
- view
---
# 绑定用户
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: user-b-role-bd
namespace: ns2
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: user-b-role
subjects:
- kind: ServiceAccount
name: user-b
namespace: ns2
kubectl apply -f user.yml
3. 查看租户 A 和 租户B 的 Token
查看租户A:
echo $(kubectl -n ns1 get secret $(kubectl -n ns1 get secret | grep user-a | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d)
查看租户B:
echo $(kubectl -n ns2 get secret $(kubectl -n ns2 get secret | grep user-b | awk '{print $1}') -o go-template='{{.data.token}}' | base64 -d)
下面就可以将用户名、token
、master
的地址给到具体租户去使用了,例如:
租户:user-a
token:eyJhbGciOiJSUzI1NiIsImtpZCI6IlA5SnRxTkVjcGV3bVdmeWV5SHo0VFBSaXdWVVYwWGMzNmYtY1NZMVRwYkUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJuczEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoidXNlci1hLXRva2VuLWx3Yjc4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InVzZXItYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRhZTUwZWI4LThhMTEtNDQ2Yy05NTEyLWE1MmI3NzMxNDNlMSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpuczE6dXNlci1hIn0.LI72bJeJERegwnwkAp8AKlvplcJMrhhYvr6K70dtQ02MXepbhVtouB_1yUiZODQZvyaRgrbgFUhEzVFB6YunB7cm2WH2blOaj_3hvuLw9FZRQ7IWmeKV7a07aviUg58ZGlrdOzUXYKNBT-A3y1zb6XrHOXNSiOZjHwQob1ft1GOM04bu7GnO6docgDXjQ0h6knpiwNFUqG-I9tI9I52dUOsUbxnhyrCzxUIJsfa2eoHOP-mz3m8ud-WLFwaOmH0G49STZnmkWs2pJJqBqP0LRJ_fs2gmgS6kMITwxraR81kBXywmVi6szNReX74fHhNVyNa-kE0gZSG6S9C-uqEJUw
master-server:https://11.0.1.144:6443
三、租户使用测试
使用 kubectl
指向提供的集群,如果已经指定可不设置:
kubectl config set-cluster cluster --insecure-skip-tls-verify=true --server=https://11.0.1.144:6443
设置租户的 token
:
格式:kubectl config set-credentials {租户名} --token={token}
kubectl config set-credentials user-a --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IlA5SnRxTkVjcGV3bVdmeWV5SHo0VFBSaXdWVVYwWGMzNmYtY1NZMVRwYkUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJuczEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlY3JldC5uYW1lIjoidXNlci1hLXRva2VuLWx3Yjc4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InVzZXItYSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRhZTUwZWI4LThhMTEtNDQ2Yy05NTEyLWE1MmI3NzMxNDNlMSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpuczE6dXNlci1hIn0.LI72bJeJERegwnwkAp8AKlvplcJMrhhYvr6K70dtQ02MXepbhVtouB_1yUiZODQZvyaRgrbgFUhEzVFB6YunB7cm2WH2blOaj_3hvuLw9FZRQ7IWmeKV7a07aviUg58ZGlrdOzUXYKNBT-A3y1zb6XrHOXNSiOZjHwQob1ft1GOM04bu7GnO6docgDXjQ0h6knpiwNFUqG-I9tI9I52dUOsUbxnhyrCzxUIJsfa2eoHOP-mz3m8ud-WLFwaOmH0G49STZnmkWs2pJJqBqP0LRJ_fs2gmgS6kMITwxraR81kBXywmVi6szNReX74fHhNVyNa-kE0gZSG6S9C-uqEJUw
设置 context
,指定默认的命名空间名称:
kubectl config set-context user-context --cluster=cluster --user user-a --namespace=ns1
切换到上面的 context
中:
kubectl config use-context user-context
测试访问其他命名空间的资源
查看 ns2
下有哪些 pod
:
kubectl get pods -n ns2
可以看出无法访问。
测试创建资源,申请配额大于限制时
vi test-nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- image: nginx:1.20.1
name: nginx
ports:
- containerPort: 80
protocol: TCP
resources:
limits:
cpu: "2"
memory: "2Gi"
requests:
cpu: "1"
memory: "1Gi"
kubectl apply -f test-nginx.yml
查看 pod
:
kubectl get pods
可以看到仅创建成功了两个 pod
,因为资源已经使用完了。
可以通过管理员查看 ns
空间的配额情况:
kubectl get quota -n ns1
可以看到都已经使用满了。
如果此时管理员给 ns1
空间提高配额:
kubectl edit resourcequota ns1-rq -n ns1
更新服务:
kubectl apply -f test-nginx.yml
等待片刻后,使用租户A
再次查看pod
:
pod
已经全部起来了