目录
1.2 允许读写 apps API 组中的 deployment 资源
1.4 允许读取一个名为 my-config 的 ConfigMap(必须绑定到一个 RoleBinding 来限制到一个Namespace 下的 ConfigMap):
1.5 读取核心组的 Node 资源(Node 属于集群级的资源,所以必须存在于 ClusterRole 中,并使用ClusterRoleBinding 进行绑定):
1.6 允许对非资源端点“/healthz”及其所有子路径进行 GET 和 POST 操作(必须使用ClusterRole 和 ClusterRoleBinding):
2.3 kube-system 命名空间中默认 Service Account
3.2 将角色授予某名字空间中的 “default” 服务账户
3.4 在集群范围内为所有服务账户授予一个受限角色(不鼓励)
3.5 授予超级用户访问权限给集群范围内的所有服务帐户(强烈不鼓励)
4.1 在命名空间 rbac 中为用户 es 授权 admin ClusterRole:
4.2 在命名空间 rbac 中为名为 myapp 的 Service Account 授予 view ClusterRole:
4.3 在全集群范围内为用户 root 授予 cluster-admin ClusterRole:
4.4 在全集群范围内为名为 myapp 的 Service Account 授予 view ClusterRole:
六、授权 kubectl 用户只能查看所有名称空间下的 pods 权限
8.1 在 limit 名称空间创建 pod,不指定资源,看看是否会被 limitrange 规则自动附加其资源限制?
8.2 创建 pod 指定 cpu 请求是 100m,看看是否允许创建
只有在符合下列条件之一的情况下,你才能创建/更新角色:
rbac.authorization.k8s.io
API 组中的 roles
或 clusterroles
资源使用 escalate
动词。例如,如果 user-1
没有列举集群范围所有 Secret 的权限,他将不能创建包含该权限的 ClusterRole。 若要允许用户创建/更新角色:
escalate
动作显式完成授权。 这里的 roles
和 clusterroles
资源包含在 rbac.authorization.k8s.io
API 组中。rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get","list","watch","create","update","patch","delete"]
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["jobs"]
verbs: ["get","list","watch","create","update","patch","delete"]
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["get"]
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get","list","watch"]
rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
verbs: ["get","post"]
对角色创建或更新的限制:使用 RBAC 鉴权 | Kubernetes
只有你已经具有了所引用的角色中包含的全部权限时,或者 你被授权在所引用的角色上执行 bind
动词时,你才可以创建或更新角色绑定。这里的权限与角色绑定的作用域相同。 例如,如果用户 user-1
没有列举集群范围所有 Secret 的能力,则他不可以创建 ClusterRoleBinding 引用授予该许可权限的角色。 如要允许用户创建或更新角色绑定:
bind
动词的权限。subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: alice
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
对角色绑定创建或更新的限制:使用 RBAC 鉴权 | Kubernetes
Service Account 也是一种账号,是给运行在 Pod 里的进程提供了必要的身份证明。需要在Pod 定义中指明引用的 Service Account,这样就可以对 Pod 的进行赋权操作。
这要求应用在其 Pod 规约中指定 serviceAccountName
, 并额外创建服务账户(包括通过 API、应用程序清单、kubectl create serviceaccount
等)。
例如,在名字空间 “my-namespace” 中授予服务账户 “my-sa” 只读权限:
kubectl create rolebinding my-sa-view \
--clusterrole=view \
--serviceaccount=my-namespace:my-sa \
--namespace=my-namespace
如果某应用没有指定 serviceAccountName
,那么它将使用 “default” 服务账户。说明:"default" 服务账户所具有的权限会被授予给名字空间中所有未指定 serviceAccountName
的 Pod。
例如,在名字空间 "my-namespace" 中授予服务账户 "default" 只读权限:
kubectl create rolebinding default-view \
--clusterrole=view \
--serviceaccount=my-namespace:default \
--namespace=my-namespace
如果你想要名字空间中所有应用都具有某角色,无论它们使用的什么服务账户, 可以将角色授予该名字空间的服务账户组。
例如,在名字空间 “my-namespace” 中的只读权限授予该名字空间中的所有服务账户:
kubectl create rolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts:my-namespace \
--namespace=my-namespace
如果你不想管理每一个名字空间的权限,你可以向所有的服务账户授予集群范围的角色。
例如,为集群范围的所有服务账户授予跨所有名字空间的只读权限:
kubectl create clusterrolebinding serviceaccounts-view \
--clusterrole=view \
--group=system:serviceaccounts
如果你不在乎如何区分权限,你可以将超级用户访问权限授予所有服务账户。
警告:
这样做会允许所有应用都对你的集群拥有完全的访问权限,并将允许所有能够读取 Secret(或创建 Pod)的用户对你的集群有完全的访问权限。
kubectl create clusterrolebinding serviceaccounts-cluster-admin \
--clusterrole=cluster-admin \
--group=system:serviceaccounts
服务账户权限:使用 RBAC 鉴权 | Kubernetes
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac
kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac
kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root
kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp
一些命令行工具:使用 RBAC 鉴权 | Kubernetes
#1. 生成一个私钥 lucky.key
[root@k8s-master01 ~]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# (umask 077; openssl genrsa -out lucky.key 2048)
#2. 对用户 lucky 生成一个证书请求
[root@k8s-master01 pki]# openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky"
#3. 生成一个证书
[root@k8s-master01 pki]# openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650
openssl 支持以手工方式为你的集群生成证书:手动生成证书 | Kubernetes
#1. 把 lucky 这个用户添加到 kubernetes 集群中,可以用来认证 apiserver 的连接
[root@k8s-master01 pki]# kubectl config set-credentials lucky --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true
#2. 在 kubeconfig 下新增加一个 lucky 上下文
[root@k8s-master01 pki]# kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky
#3. 切换账号到 lucky,默认是没有任何权限
[root@k8s-master01 ~]# kubectl config use-context lucky@kubernetes
Switched to context "lucky@kubernetes".
[root@k8s-master01 ~]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"
#4. 切换回 admin 账户,这个是集群用户,有任何权限
[root@k8s-master01 ~]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
#5. 查看新增用户信息
[root@k8s-master01 ~]# kubectl config view
把 lucky 这个用户通过 rolebinding 绑定到 clusterrole 上,授予权限,权限只是在 rolebinding 这个名称空间下有效。
#1. 把 lucky 这个用户通过 rolebinding 绑定到 clusterrole上
[root@k8s-master01 ~]# kubectl create ns lucky-test
[root@k8s-master01 ~]# kubectl create rolebinding lucky -n lucky-test --clusterrole=cluster-admin --user=lucky
#2. 切换到 lucky 用户
[root@k8s-master01 ~]# kubectl config use-context lucky@kubernetes
#3. 测试是否有权限
[root@k8s-master01 ~]# kubectl get pods -n lucky-test
No resources found in lucky-test namespace.
[root@k8s-master01 ~]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"
测试发现,lucky 是有权限操作 lucky-test 这个名称空间,其他名称空间不行。
[root@k8s-master01 ~]# useradd lucky
[root@k8s-master01 ~]# cp -ar /root/.kube /home/lucky/
[root@k8s-master01 ~]# cd /home/lucky/
# 修改 /home/lucky/.kube/config 文件,把 kubernetes-admin 相关的删除,只留 lucky 信息
[root@k8s-master01 lucky]# vim .kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ······
server: https://192.168.78.133:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: lucky
name: lucky@kubernetes
current-context: lucky@kubernetes
kind: Config
preferences: {}
users:
- name: lucky
user:
client-certificate-data: ······
client-key-data: ······
# 设置密码
[root@k8s-master01 lucky]# passwd lucky
[root@k8s-master01 lucky]# chown -R lucky.lucky /home/lucky
# 登录 lucky 账户
[root@k8s-master01 lucky]# su - lucky
# 访问不了默认空间
[lucky@k8s-master01 ~]$ kubectl get pods
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"
# 可以访问 lucky-test 空间
[lucky@k8s-master01 ~]$ kubectl get pods -n lucky-test
No resources found in lucky-test namespace.
# 最后退出 lucky 用户,需要在把集群环境切换成管理员权限
[lucky@k8s-master01 ~]$ exit
登出
[root@k8s-master01 lucky]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
#1. 生成一个私钥 lucky66.key
[root@k8s-master01 ~]# cd /etc/kubernetes/pki/
[root@k8s-master01 pki]# (umask 077; openssl genrsa -out lucky66.key 2048)
#2. 对用户 lucky66 生成一个证书请求
[root@k8s-master01 pki]# openssl req -new -key lucky66.key -out lucky66.csr -subj "/CN=lucky66"
#3. 生成一个证书
[root@k8s-master01 pki]# openssl x509 -req -in lucky66.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky66.crt -days 3650
openssl 支持以手工方式为你的集群生成证书:手动生成证书 | Kubernetes
#1. 把 lucky 这个用户添加到 kubernetes 集群中,可以用来认证 apiserver 的连接
[root@k8s-master01 pki]# kubectl config set-credentials lucky66 --client-certificate=./lucky66.crt --client-key=./lucky66.key --embed-certs=true
#2. 在 kubeconfig 下新增加一个 lucky 上下文
[root@k8s-master01 pki]# kubectl config set-context lucky66@kubernetes --cluster=kubernetes --user=lucky66
把 lucky66 这个用户通过 clusterrolebinding 绑定到 clusterrole 上,授予权限,权限是只能查看所有名称空间下的 pods。
#1. 创建一个 clusterrole
[root@k8s-master01 ~]# vim lucky66-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: lucky66-get-pod
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
[root@k8s-master01 ~]# kubectl apply -f lucky66-clusterrole.yaml
#2. 创建一个 clusterrolebinding
[root@k8s-master01 ~]# kubectl create clusterrolebinding lucky66-get-pods --clusterrole=lucky66-get-pod --user=lucky66
[root@k8s-master01 ~]# useradd lucky66
[root@k8s-master01 ~]# cp -ar /root/.kube/ /home/lucky66/
[root@k8s-master01 ~]# cd /home/lucky66/
# 修改 /home/lucky66/.kube/config 文件,把 kubernetes-admin 和 lucky 相关的删除,只留 lucky66 信息,并修改当前上下文为 current-context: lucky66@kubernetes
[root@k8s-master01 lucky]# vim .kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ······
server: https://192.168.78.133:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: lucky66
name: lucky66@kubernetes
current-context: lucky66@kubernetes
kind: Config
preferences: {}
users:
- name: lucky66
user:
client-certificate-data: ······
client-key-data: ······
# 设置密码
[root@k8s-master01 lucky]# passwd lucky66
[root@k8s-master01 lucky]# chown -R lucky66.lucky66 /home/lucky66
# 登录 lucky66 账户
[root@k8s-master01 lucky]# su - lucky66
# 可以访问默认空间
[lucky@k8s-master01 ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nfs-provisioner-6fc44b8b68-r8r8d 1/1 Running 12 (10h ago) 12d
# 可以访问 lucky-test 空间
[lucky@k8s-master01 ~]$ kubectl get pods -n lucky-test
No resources found in lucky-test namespace.
[lucky66@k8s-master01 ~]$ kubectl get pods -n kube-system
# 最后退出 lucky66 用户
[lucky@k8s-master01 ~]$ exit
登出
ResourceQuota 准入控制器是 k8s 上内置的准入控制器,默认该控制器是启用的状态,它主要作用是用来限制一个名称空间下的资源的使用,它能防止在一个名称空间下的 pod 被过多创建时,导致过多占用 k8s 资源,简单讲它是用来在名称空间级别限制用户的资源使用。
本次主要介绍如何在命名空间中设置限制 cpu、内存、pod、deployment 数量。 你可以通过使用 ResourceQuota 对象来配置配额。
#1. 创建一个命名空间
[root@k8s-master01 serviceaccount]# kubectl create ns quota
#2. 创建 ResourceQuota
[root@k8s-master01 serviceaccount]# vim resourcequota-1.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota-test
namespace: quota
spec:
hard:
pods: "6"
requests.cpu: "2"
requests.memory: 2Gi
limits.cpu: "4"
limits.memory: 10Gi
count/deployments.apps: "6"
persistentvolumeclaims: "6"
[root@k8s-master01 serviceaccount]# kubectl apply -f resourcequota-1.yaml
spec.hard 字段是用来定义对应名称空间下的资源限制规则;pods 用来限制在对应名称空间下的 pod 数量,requests.cpu 字段用来限制对应名称空间下所有 pod 的 cpu 资源的下限总和;requests.memory 用来限制对应名称空间下 pod 的内存资源的下限总和;limits.cpu 用来限制对应名称空间下的 pod cpu 资源的上限总和,limits.memory 用来限制对应名称空间下 pod 内存资源上限总和;count/deployments.apps 用来限制对应名称空间下 apps 群组下的 deployments 的个数;
以上配置清单表示,在 quota 名称空间下运行的 pod 数量不能超过6个,所有 pod 的 cpu 资源下限总和不能大于 2 个核心,内存资源下限总和不能大于 2G,cpu 上限资源总和不能大于 4 个核心,内存上限总和不能超过 10 G,apps 群组下的 deployments 控制器不能超过 6 个, pvc 个数不能超过 6 个。
#3. 创建 pod 进行测试
[root@k8s-master01 serviceaccount]# vim quota-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: quota
namespace: quota
spec:
replicas: 7
selector:
matchLabels:
app: quota
template:
metadata:
labels:
app: quota
spec:
containers:
- name: myapp
image: janakiramm/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
cpu: 10m
memory: 10Mi
limits:
cpu: 10m
memory: 10Mi
[root@k8s-master01 serviceaccount]# kubectl apply -f quota-deployment.yaml
[root@k8s-master01 serviceaccount]# kubectl get pods -n quota
NAME READY STATUS RESTARTS AGE
quota-6d5c459f69-dfq2j 1/1 Running 0 27s
quota-6d5c459f69-gkhrb 1/1 Running 0 27s
quota-6d5c459f69-k9s4z 1/1 Running 0 27s
quota-6d5c459f69-msbfw 1/1 Running 0 27s
quota-6d5c459f69-qxc79 1/1 Running 0 27s
quota-6d5c459f69-r9xm4 1/1 Running 0 27s
# 查看 quota 空间信息
[root@k8s-master01 serviceaccount]# kubectl describe ns quota
Name: quota
Labels: kubernetes.io/metadata.name=quota
Annotations: <none>
Status: Active
Resource Quotas
Name: quota-test
Resource Used Hard
-------- --- ---
count/deployments.apps 1 6
limits.cpu 60m 4
limits.memory 60Mi 10Gi
persistentvolumeclaims 0 6
pods 6 6
requests.cpu 60m 2
requests.memory 60Mi 2Gi
配置命名空间下 Pod 配额:配置命名空间下 Pod 配额 | Kubernetes
为命名空间配置内存和 CPU 配额:为命名空间配置内存和 CPU 配额 | Kubernetes
[root@k8s-master01 serviceaccount]# vim resourcequota-2.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota-storage-test
namespace: quota
spec:
hard:
requests.storage: "5Gi"
persistentvolumeclaims: "5"
requests.ephemeral-storage: "1Gi"
limits.ephemeral-storage: "2Gi"
[root@k8s-master01 serviceaccount]# kubectl apply -f resourcequota-2.yaml
requests.storage 用来限制对应名称空间下的存储下限总和,persistenvolumeclaims 用来限制 pvc 总数量,requests.ephemeral-storage 用来现在使用本地临时存储的下限总容量;limits.ephemeral-storage 用来限制使用本地临时存储上限总容量;以上配置表示在 default 名称空间下非停止状态的容器存储下限总容量不能超过 5G,pvc 的数量不能超过 5 个,本地临时存储下限容量不能超过 1G,上限不能超过 2G。
限制存储使用量:限制存储使用量 | Kubernetes
LimitRanger 准入控制器是 k8s 上一个内置的准入控制器,LimitRange 是 k8s 上的一个标准资源,它主要用来定义在某个名称空间下限制 pod 或 pod 里的容器对 k8s 上的 cpu 和内存资源使用;它能够定义我们在某个名称空间下创建 pod 时使用的 cpu 和内存的上限和下限以及默认 cpu、内存的上下限。
如果我们创建 pod 时定义了资源上下限,但不满足 LimitRange 规则中定义的资源上下限,此时 LimitRanger 就会拒绝我们创建此 pod;如果我们在 LimitRange 规则中定义了默认的资源上下限制,我们创建资源没有指定其资源限制,它默认会使用 LimitRange 规则中的默认资源限制;同样的逻辑 LimitRanger 可以限制一个 pod 使用资源的上下限,它还可以限制 pod 中的容器的资源上下限,比限制 pod 更加精准;不管是针对 pod 还是 pod 里的容器,它始终只是限制单个 pod 资源使用。
[root@k8s-master01 serviceaccount]# vim limitrange.yaml
apiVersion: v1
kind: Namespace
metadata:
name: limit
---
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-memory
namespace: limit
spec:
limits:
- default:
cpu: 1000m
memory: 1000Mi
defaultRequest:
cpu: 500m
memory: 500Mi
min:
cpu: 500m
memory: 500Mi
max:
cpu: 2000m
memory: 2000Mi
maxLimitRequestRatio:
cpu: 4
memory: 4
type: Container
[root@k8s-master01 serviceaccount]# kubectl apply -f limitrange.yaml
以上清单主要定义了两个资源,一个创建 limit 名称空间,一个是在对应 limit 名称空间下定义了 LimitRange资源;其中 LimitRange 资源的名称为 cpu-memory,default 字段用来指定默认容器资源上限值;defaultRequest 用来指定默认容器资源下限值;min 字段用来指定限制用户指定的资源下限不能小于对应资源的值;max 是用来限制用户指定资源上限值不能大于该值;maxLimitRequestRatio 字段用来指定资源的上限和下限的比值;即上限是下限的多少倍;type 是用来描述对应资源限制的级别,该字段有两个值 pod 和 container。
上述资源清单表示在该名称空间下创建 pod 时,默认不指定其容器的资源限制,就限制对应容器最少要有 0.5 个核心的 cpu 和 500M 的内存;最大为 1 个核心 cpu、1g 内存;如果我们手动定义了容器的资源限制,那么对应资源限制最小不能小于 cpu 为 0.5 个核心,内存为 500M,最大不能超过 cpu 为 2 个核心,内存为 2000M;
如果我们在创建 pod 时,只指定了容器的资源上限或下限,那么上限最大是下限的的 4 倍,如果指定 cpu 上限为 2000m 那么下限一定不会小于 500m,如果只指定了 cpu 下限为 500m 那么上限最大不会超过 2000m,对于内存也是同样的逻辑。
[root@k8s-master01 serviceaccount]# vim pod-limit.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-demo
namespace: limit
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
[root@k8s-master01 serviceaccount]# kubectl apply -f pod-limit.yaml
[root@k8s-master01 serviceaccount]# kubectl describe pods -n limit nginx-pod-demo
······
Limits:
cpu: 1
memory: 1000Mi
Requests:
cpu: 500m
memory: 500Mi
······
通过上面结果可以看到我们在 limit 名称空间下创建的 pod 没有指定其容器资源限制,创建pod 后,其内部容器自动就有了默认的资源限制;其大小就是我们在定义 LimitRange 规则中的default 和 defaultRequest 字段中指定的资源限制。
[root@k8s-master01 serviceaccount]# vim pod-request.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-request
namespace: limit
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
requests:
cpu: 100m
[root@k8s-master01 serviceaccount]# kubectl apply -f pod-request.yaml
Error from server (Forbidden): error when creating "pod-request.yaml": pods "pod-request" is forbidden: [minimum cpu usage per Container is 500m, but request is 100m, cpu max limit to request ratio per Container is 4, but provided ratio is 10.000000]
创建失败,cup 太小,至少要大于 500m。
关于使用限值的例子,可参阅:
上一篇文章:【云原生 | Kubernetes 实战】18、K8s 安全实战篇之 RBAC 认证授权(上)_Stars.Sky的博客-CSDN博客
下一篇文章:【云原生 | Kubernetes 实战】19、K8s Ingress-Controller 高可用方案_Stars.Sky的博客-CSDN博客