一、k8s安全管理:认证、授权、准入控制概述

1.1、认证

认证基本介绍:

kubernetes主要通过APIserver对外提供服务,那么就需要对访问apiserver的用户做认证,如果任何人都能访问apiserver,那么就可以随意在k8s集群部署资源,这是非常危险的,所以需要我们对访问k8s系统的apiserver的用户进行认证,确保是合法的符合要求的用户。

授权基本介绍:

认证通过后仅代表它是一个被apiserver信任的用户,能访问apiserver,但是用户是否拥有删除资源的权限, 需要进行授权操作,常见的授权方式有rbac授权。

准入控制基本介绍:

当用户经过认证和授权之后,最后一步就是准入控制了,k8s提供了多种准入控制机制,它有点类似"插件",为apiserver提供了很好的"可扩展性"。请求apiserver时,通过认证、鉴权后、持久化("api对象"保存到etcd)前,会经过"准入控制器",让它可以做"变更和验证"。

为什么需要准入控制器呢?

如果我们创建pod时定义了资源上下限,但不满足LimitRange规则中定义的资源上下限,此时LimitRanger就会拒绝我们创建此pod。

假如我们定义了一个名称空间叫做test,这个名称空间做下资源限制:限制最多可以使用10vCPU、10Gi内存,在这个名称空间test下创建的所有pod,定义limit的时候,所有pod的limit值不能超过test这个名称空间设置的limit上限。

1.1.1、k8s客户端访问apiserver的几种认证方式

1.1.1.1、客户端认证

客户端认证也称为双向TLS认证, kubectl在访问apiserver的时候,apiserver也要认证kubectl是否是合法的,他们都会通过ca根证书来进行验证。

1.1.1.2、Bearertoken认证

Bearertoken认证的方式,可以理解为apiserver将一个密码通过了非对称加密的方式告诉了kubectl,然后通过该密码进行相互访问。

1.1.1.3、Serviceaccount认证

  上面客户端证书认证和Bearertoken的两种认证方式,都是外部访问apiserver的时候使用的方式,那么我们这次说的Serviceaccount是内部访问pod和apiserver交互时候采用的一种方式。Serviceaccount包括了namespace、token、ca,且通过目录挂载的方式给予pod,当pod运行起来的时候,就会读取到这些信息,从而使用该方式和apiserver进行通信。

1.1.2、kubeconfig文件 

官方地址:https://kubernetes.io/zh-cn/docs/concepts/configuration/organize-cluster-access-kubeconfig/

在K8S集群当中,当我们使用kubectl操作k8s资源时候,需要确定我们用哪个用户访问哪个k8s集群,kubectl操作k8s集群资源会去/root/.kube目录下找config文件,可以通过kubectl config查看config文件配置,如下:

在Master下执行命令:kubectl config view

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.60.140:6443	#apiserver的地址
  name: kubernetes	#集群的名字
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes	#上下文的名字
current-context: kubernetes-admin@kubernetes	#当前上下文的名字
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

在上面的配置文件当中,定义了集群、上下文以及用户。其中Config也是K8S的标准资源之一,在该配置文件当中定义了一个集群列表,指定的集群可以有多个;用户列表也可以有多个,指明集群中的用户;而在上下文列表当中,是进行定义可以使用哪个用户对哪个集群进行访问,以及当前使用的上下文是什么。

1.2、授权

用户通过认证之后,什么权限都没有,需要一些后续的授权操作,如对资源的增删改查等,kubernetes1.6之后开始有RBAC(基于角色的访问控制机制)授权检查机制。

1.2.1、Kubernetes的授权是基于插件形成的,其常用的授权插件有以下几种:

  • Node(节点认证)
  • ABAC(基于属性的访问控制)
  • RBAC(基于角色的访问控制)***
  • Webhook(基于http回调机制的访问控制)

1.2.2、什么是RBAC(基于角色的授权)?

 让一个用户(Users)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在授权机制当中,只需要将权限授予某个角色,此时用户将获取对应角色的权限,从而实现角色的访问控制。

在k8s的授权机制当中,采用RBAC的方式进行授权,其工作逻辑是,把对对象的操作权限定义到一个角色当中,再将用户绑定到该角色,从而使用户得到对应角色的权限。如果通过rolebinding绑定role,只能对rolebingding所在的名称空间的资源有权限,user1这个用户绑定到role1上,只对role1这个名称空间的资源有权限,对其他名称空间资源没有权限,属于名称空间级别的。

另外,k8s为此还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有可操作的权限,从而将User2通过ClusterRoleBinding到ClusterRole,从而使User2拥有集群的操作权限。

1.2.3、Role、RoleBinding、ClusterRole和ClusterRoleBinding的关系

关系如下:

1、用户基于rolebinding绑定到role,限定在rolebinding所在的名称空间。

2、用户基于rolebinding绑定到clusterrole,拥有集群的操作权限。

上面我们说了两个角色绑定:

  • 用户通过rolebinding绑定role
  • 用户通过rolebinding绑定clusterrole

rolebinding绑定clusterrole的好处:

假如有6个名称空间,每个名称空间的用户都需要对自己的名称空间有管理员权限,那么需要定义6个role和rolebinding,然后依次绑定,如果名称空间更多,我们需要定义更多的role,这个是很麻烦的,所以我们引入clusterrole,定义一个clusterrole,对clusterrole授予所有权限,然后用户通过rolebinding绑定到clusterrole,就会拥有自己名称空间的管理员权限了

注:RoleBinding仅仅对当前名称空间有对应的权限。

3、用户基于clusterrolebinding绑定到clusterrole

用户基于rbac授权有几种方案:

基于rolebinding绑定到role上

基于rolebinding绑定到clusterrole上

基于clusterrolebinding绑定到clusterrole上

1.3、准入控制

在k8s上准入控制器的模块有很多,其中比较常用的有LimitRanger、ResourceQuota、ServiceAccount、PodSecurityPolicy(k8s1.25废弃了)等等,对于前面三种准入控制器系统默认是启用的,我们只需要定义对应的规则即可;对于PodSecurityPolicy(k8s1.25废弃了)这种准入控制器,系统默认没有启用,如果我们要使用,就必需启用以后,对应规则才会正常生效;这里需要注意一点,对应psp准入控制器,一定要先写好对应的规则,把规则和权限绑定好以后,在启用对应的准入控制器,否则先启用准入控制器,没有对应的规则,默认情况它是拒绝操作,这可能导致现有的k8s系统跑的系统级pod无法正常工作;所以对于psp准入控制器要慎用,如果规则和权限做的足够精细,它会给我们的k8s系统安全带来大幅度的提升,反之,可能导致整个k8s系统不可用。

1.3.1、查看apiserver启用的准入控制器有哪些?

root@k8s-master:~/K8sStudy/Chapter2-16# grep enable-admission-plugins /etc/kubernetes/manifests/kube-apiserver.yaml 
    - --enable-admission-plugins=NodeRestriction
root@k8s-master:~/K8sStudy/Chapter2-16# 

提示:

apiserver启用准入控制插件需要使用--enable-admission-plugins选项来指定,该选项可以使用多个值,用逗号隔开表示启用指定的准入控制插件;这里配置文件中显式启用了NodeRestrication这个插件;默认没有写在这上面的内置准入控制器,它也是启用了的,比如LimitRanger、ResourceQuota、ServiceAccount等等;对于不同的k8s版本,内置的准入控制器和启用与否请查看相关版本的官方文档;对于那些没有启动的准入控制器,我们可以在上面选项中直接启用,分别用逗号隔开即可。

对应的官网地址:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/admission-controllers/

1.3.2、Useraccount和ServiceAccount介绍

kubernetes中账户分为:UserAccounts(用户账户) 和 ServiceAccounts(服务账户)两种:

UserAccount:是给kubernetes集群外部用户使用的,如kubectl访问k8s集群要用useraccount用户, kubeadm安装的k8s,默认的useraccount用户是kubernetes-admin;用以下命令可以查看:kubectl config view

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.60.140:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin	# kubeadm用的useraccount账号
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED
root@k8s-master:~/K8sStudy/Chapter2-16# 

k8s客户端(一般用:kubectl) ------>API Server

APIServer需要对客户端做认证,使用kubeadm安装的K8s,会在用户家目录下创建一个认证配置文件k8s时,它就会自动读取该配置文件,向API Server发起认证,然后完成操作请求。

ServiceAccount:是Pod使用的账号,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户;ServiceAccount仅局限它所在的namespace,每个namespace创建时都会自动创建一个default service account;创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。

1.3.3、ServiceAccount使用案例介绍

创建sa资源,并绑定到pod

1、创建sa资源sa-test

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl create serviceaccount sa-test
serviceaccount/sa-test created
root@k8s-master:~/K8sStudy/Chapter2-16# kubectl get sa 
NAME              SECRETS   AGE
default           0         67d
nfs-provisioner   0         5d20h
sa-test           0         5s

2、创建pod资源

查看pod资源清单文件:Eg-Pod-ServiceAccount.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Pod-ServiceAccount.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: sa-test
  namespace: default
  labels:
    app: sa
spec:
  serviceAccountName: sa-test
  containers:
  - name:  web
    ports:
    - containerPort: 80
    image: nginx:latest
    imagePullPolicy: IfNotPresent

应用/更新pod资源清单文件:Eg-Pod-ServiceAccount.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Pod-ServiceAccount.yaml 
pod/sa-test created

登入Pod验证pod访问apiserver的权限

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl exec -it sa-test -- /bin/bash
root@sa-test:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@sa-test:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)"  https://kubernetes/api/v1/namespaces/kube-system
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "namespaces \"kube-system\" is forbidden: User \"system:serviceaccount:default:sa-test\" cannot get resource \"namespaces\" in API group \"\" in the namespace \"kube-system\"",
  "reason": "Forbidden",
  "details": {
    "name": "kube-system",
    "kind": "namespaces"
  },
  "code": 403

上面结果能看到sa能通过https方式成功认证API,但是没有权限访问k8s资源,所以code状态码是403,表示没有权限操作k8s资源

3、对sa做授权,通过clusterrolebinding绑定到clusterrole集群角色cluster-admin

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl create clusterrolebinding sa-test-clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:sa-test
clusterrolebinding.rbac.authorization.k8s.io/sa-test-clusterrolebinding created
root@k8s-master:~/K8sStudy/Chapter2-16#
root@k8s-master:~/K8sStudy/Chapter2-16# kubectl get clusterrolebinding |grep sa-test
sa-test-clusterrolebinding                             ClusterRole/cluster-admin                                                          26s
root@k8s-master:~/K8sStudy/Chapter2-16# 

4、再次请求

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl exec -it sa-test -- /bin/bash
root@sa-test:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@sa-test:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)"  https://kubernetes/api/v1/namespaces/kube-system
{
  "kind": "Namespace",
  "apiVersion": "v1",
  "metadata": {
    "name": "kube-system",
    "uid": "16d731cc-f018-46e4-99c9-2f74831c489f",
    "resourceVersion": "5",
    "creationTimestamp": "2024-03-21T02:11:34Z",
    "labels": {
      "kubernetes.io/metadata.name": "kube-system"
    },
    "managedFields": [
      {
        "manager": "kube-apiserver",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2024-03-21T02:11:34Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {
          "f:metadata": {
            "f:labels": {
              ".": {},
              "f:kubernetes.io/metadata.name": {}
            }
          }
        }
      }
    ]
  },
  "spec": {
    "finalizers": [
      "kubernetes"
    ]
  },
  "status": {
    "phase": "Active"
  }

   通过上面可以看到,对sa做授权之后就有权限访问k8s资源了。

1.4、RBAC认证授权策略

RBAC介绍:

在Kubernetes中,所有资源对象都是通过API进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。

RBAC有四个资源对象,分别是Role、ClusterRole、RoleBinding、ClusterRoleBinding

1.4.1 、Role:角色

一组权限的集合,在一个命名空间中,可以用其来定义一个角色,只能对命名空间内的资源进行授权。如果是集群级别的资源,则需要使用ClusterRole。

1.4.1.1、查看Role资源有哪些字段?

帮助命令: kubectl explain role

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl explain role |grep -E '^[A-Z]|<*>'
GROUP:      rbac.authorization.k8s.io
KIND:       Role
VERSION:    v1
DESCRIPTION:
FIELDS:
  apiVersion    <string>	# API版本,与GROUP/VERSION保持一致,即rbac.authorization.k8s.io/v1
  kind  <string>	# 资源类型,与KIND保持一致,即Role
  metadata      <ObjectMeta>	# 元数据,定义资源名称、所在名称空间
  rules <[]PolicyRule>	# 定义访问权限规则
1.4.1.2、查看role.rules有哪些字段?

帮助命令: kubectl explain role.rules

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl explain role.rules |grep -E '^[A-Z]|<*>'
GROUP:      rbac.authorization.k8s.io
KIND:       Role
VERSION:    v1
FIELD: rules <[]PolicyRule>
DESCRIPTION:
FIELDS:
  apiGroups     <[]string>	# 支持的API组列表
  nonResourceURLs       <[]string>
  resourceNames <[]string>	# 指定resource的名称
  resources     <[]string>	# 支持的资源对象列表
  verbs <[]string> -required-	# 对资源对象的操作方法列表

rules中的参数说明:

1、apiGroups:支持的API组列表,例如:"apiVersion: apps/v1"等

2、resources:支持的资源对象列表,例如pods、deployments、jobs等

3、resourceNames: 指定resource的名称

4、verbs:对资源对象的操作方法列表。

1.4.1.3、实例:定义一个角色用来读取Pod的权限

查看Role资源清单文件:Eg-Role.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Role.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: rbac	# 创建一个namespace资源rbac
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role	
metadata:
  namespace: rbac	# 名称空间rbac
  name: pod-read	# role名称
rules:	# role的规则
- apiGroups: [""]
  resources: ["pods"]	# 授权的资源对象
  resourceNames: []	# 资源名称
  verbs: ["get","watch","list"]	# 对象资源可操作的方法

应用/更新Role资源清单文件:Eg-Role.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Role.yaml 
namespace/rbac created
role.rbac.authorization.k8s.io/pod-read created
root@k8s-master:~/K8sStudy/Chapter2-16# 

产看创建的namespace资源和Role资源状态:

k8s安全管理RBAC认证授权_认证

1.4.2 、ClusterRole:集群角色

具有和角色一致的命名空间资源的管理能力,还可用于以下特殊元素的授权:

1、集群范围的资源,例如Node

2、非资源型的路径,例如:/healthz

3、包含全部命名空间的资源,例如Pods

1.4.2.1、查看ClusterRole资源有哪些字段?

帮助命令: kubectl explain clusterrole

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl explain clusterrole |grep -E '^[A-Z]|<*>'
GROUP:      rbac.authorization.k8s.io
KIND:       ClusterRole
VERSION:    v1
DESCRIPTION:
FIELDS:
  aggregationRule       <AggregationRule>
  apiVersion    <string>	# api版本
  kind  <string>	# 资源类型
  metadata      <ObjectMeta>	# 元数据
  rules <[]PolicyRule>	# 规则策略
1.4.2.2、查看clusterrole.rules有哪些字段?

帮助命令: kubectl explain clusterrole.rules

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl explain clusterrole.rules |grep -E '^[A-Z]|<*>'
GROUP:      rbac.authorization.k8s.io
KIND:       ClusterRole
VERSION:    v1
FIELD: rules <[]PolicyRule>
DESCRIPTION:
FIELDS:
  apiGroups     <[]string>	# 支持的API组列表
  nonResourceURLs       <[]string>
  resourceNames <[]string>	# 指定resource的名称
  resources     <[]string>	# 支持的资源对象列表
  verbs <[]string> -required-	# 对资源对象的操作方法列表
1.4.2.3、例如:定义一个集群角色可让用户访问任意secrets

查看ClusterRole资源清单文件:Eg-ClusterRole.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-ClusterRole.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secrets-clusterrole	# clusterrole名称
rules:	# 规则策略
- apiGroups: [""]	# 授权的api组列表
  resources: ["secrets"]	# 对secrets资源授权
  verbs: ["get","watch","list"]	# 对secrets有get、watch、list操作方法

应用/更新ClusterRole资源清单文件:Eg-ClusterRole.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-ClusterRole.yaml
clusterrole.rbac.authorization.k8s.io/secrets-clusterrole created

查看创建的ClusterRole资源状态

k8s安全管理RBAC认证授权_RBAC_02

1.4.3 、RoleBinding:角色绑定、ClusterRolebinding:集群角色绑定

角色绑定和集群角色绑定用于把一个角色绑定在一个目标上,可以是User,Group,Service Account,使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。

1.4.3.1、查看ClusterRolebinding和Rolebunding资源有哪些字段?

帮助命令: kubectl explain clusterrolebinding

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl explain clusterrolebinding |grep -E '^[A-Z]|<*>'
GROUP:      rbac.authorization.k8s.io
KIND:       ClusterRoleBinding
VERSION:    v1
DESCRIPTION:
FIELDS:
  apiVersion    <string>	# api版本与GROUP/VERSION保持一致,即rbac.authorization.k8s.io/v1
  kind  <string>	# 资源类型,与KIND的值保持一致,即ClusterRoleBinding
  metadata      <ObjectMeta>	# 元数据
  roleRef       <RoleRef> -required-
  subjects      <[]Subject>

帮助命令: kubectl explain rolebinding

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl explain rolebinding |grep -E '^[A-Z]|<*>'
GROUP:      rbac.authorization.k8s.io
KIND:       RoleBinding
VERSION:    v1
DESCRIPTION:
FIELDS:
  apiVersion    <string>	# api版本与GROUP/VERSION保持一致,即rbac.authorization.k8s.io/v1
  kind  <string>	# 资源类型,与KIND的值保持一致,即RoleBinding
  metadata      <ObjectMeta>	# 元数据
  roleRef       <RoleRef> -required-
  subjects      <[]Subject>
1.4.3.2、实例一:将在rbac命名空间中把pod-read角色授予用户es

查看Rolebinding资源清单文件:Eg-Rolebinding.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Rolebinding.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-read-bind
  namespace: rbac
subjects:
- kind: User
  name: es
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-read
  apiGroup: rbac.authorization.k8s.io

应用/更新Rolebinding资源清单文件:Eg-Rolebinding.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Rolebinding.yaml
rolebinding.rbac.authorization.k8s.io/pod-read-bind created
root@k8s-master:~/K8sStudy/Chapter2-16# 

查看创建的Rolebinding资源状态

k8s安全管理RBAC认证授权_RBAC_03

RoleBinding也可以引用ClusterRole,对属于同一命名空间内的ClusterRole定义的资源主体进行授权。

1.4.3.3、实例二:es能获取到集群中所有的资源信息

查看Rolebinding资源清单文件:Eg-Rolebinding-clusterrole.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Rolebinding-clusterrole.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: es-allresource
  namespace: rbac
subjects:
- kind: User
  name: es
  apiGroup: rbac.authorization.k8s.io
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin

应用/更新Rolebinding资源清单文件:Eg-Rolebinding-clusterrole.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Rolebinding-clusterrole.yaml
rolebinding.rbac.authorization.k8s.io/es-allresource created
root@k8s-master:~/K8sStudy/Chapter2-16#

查看创建的Rolebinding资源状态

k8s安全管理RBAC认证授权_k8s_04

1.5、资源的引用方式

多数资源可以用其名称的字符串表示,也就是Endpoint中的URL相对路径,例如pod中的日志是GET /api/v1/namaspaces/{namespace}/pods/{podname}/log

如果需要在一个RBAC对象中体现上下级资源,就需要使用“/”分割资源和下级资源。

1.5.1、实例一:若想授权让某个主体同时能够读取Pod和Pod log,则可以配置 resources为一个数组

查看Role资源清单文件:Eg-Role-Multi-resources.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Role-Multi-resources.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: test	# 创建名称空间:test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: test
  name: pod_logs_read_role
rules:
- apiGroups: [""]
  resources: ["pods","pods/log"]	# 授权资源对象pods和pods/log
  resourceNames: []
  verbs: ["get","watch","list"]	# 可操作权限

应用/更新Role资源清单文件:Eg-Role-Multi-resources.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Role-Multi-resources.yaml
namespace/test created
role.rbac.authorization.k8s.io/pod_logs_read_role created
root@k8s-master:~/K8sStudy/Chapter2-16# 

查看创建的Role资源状态

k8s安全管理RBAC认证授权_RBAC_05

在名称空间test下创建一个Serviceaccount账号sa-test:kubectl create sa sa-test -n test

将sa账号通过rolebinding绑定到role角色pod_logs_read_role上。kubectl create rolebinding sa-test-rolebinding -n test --role=pod_logs_read_role --serviceaccount=test:sa-test

创建一个Pod资源引用serviceAccount用户

查看Pod资源清单文件:Eg-Pod-rolebinding-role.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Pod-rolebinding-role.yaml
apiVersion: v1
kind: Pod
metadata:
  name: rolebinding-role-sa-test-pod
  namespace: test
  labels:
    app: sa
spec:
  serviceAccountName: sa-test
  containers:
  - name:  nginx
    ports:
    - containerPort: 80
    image: nginx:latest
    imagePullPolicy: IfNotPresent

应用/更新Pod资源清单文件:Eg-Pod-rolebinding-role.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Pod-rolebinding-role.yaml
pod/rolebinding-role-sa-test-pod created
root@k8s-master:~/K8sStudy/Chapter2-16#

验证权限,登入到pod中请求logs

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl exec -n test -it rolebinding-role-sa-test-pod -- /bin/bash
root@rolebinding-role-sa-test-pod:/# cd /var/run/secrets/kubernetes.io/serviceaccount
root@rolebinding-role-sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# 
root@rolebinding-role-sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# 
root@rolebinding-role-sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# 
root@rolebinding-role-sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt  -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test/pods/rolebinding-role-sa-test-pod/log
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "pods \"rolebinding-role-sa-test-pod\" is forbidden: User \"system:serviceaccount:test:sa-test\" cannot get resource \"pods/log\" in API group \"\" in the namespace \"test\"",
  "reason": "Forbidden",
  "details": {
    "name": "rolebinding-role-sa-test-pod",
    "kind": "pods"
  },
  "code": 403

如上所示报403错误。因为User system:serviceaccount:test:sa-test没有获取pods/logs资源的权限。

解决上述报错需要做授权:

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl create rolebinding sa-test-rolebinding2 -n test --role=pod_logs_read_role --user=system:serviceaccount:test:sa-test
rolebinding.rbac.authorization.k8s.io/sa-test-rolebinding2 created
root@k8s-master:~/K8sStudy/Chapter2-16# 

重新验证权限,登入到pod中请求logs

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl exec -n test -it rolebinding-role-sa-test-pod -- /bin/bash
root@rolebinding-role-sa-test-pod:/# 
root@rolebinding-role-sa-test-pod:/# cd /var/run/secrets/kubernetes.io/serviceaccount
root@rolebinding-role-sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt  -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/test/pods/rolebinding-role-sa-test-pod/log
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2024/05/28 07:24:34 [notice] 1#1: using the "epoll" event method
2024/05/28 07:24:34 [notice] 1#1: nginx/1.25.5
2024/05/28 07:24:34 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14) 
2024/05/28 07:24:34 [notice] 1#1: OS: Linux 5.15.0-107-generic
2024/05/28 07:24:34 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/05/28 07:24:34 [notice] 1#1: start worker processes
2024/05/28 07:24:34 [notice] 1#1: start worker process 29
2024/05/28 07:24:34 [notice] 1#1: start worker process 30
root@rolebinding-role-sa-test-pod:/var/run/secrets/kubernetes.io/serviceaccount# 

k8s安全管理RBAC认证授权_k8s_06

请求正常返回结果。

资源还可以通过名称(ResourceName)进行引用,在指定ResourceName后,使用get、delete、update、patch请求,就会被限制在这个资源实例范围内

例如,下面的声明让一个主体只能对名为my-configmap的Configmap进行get和update操作:

apiVersion: rabc.authorization.k8s.io/v1
kind: Role
metadata:
  namaspace: default
  name: configmap-update
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["get","update"]

1.6、常见角色(role)授权的案例

1.6.1、允许读取核心API组的Pod资源

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]

1.6.2、允许读写apps API组中的deployment资源

rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get","list","watch","create","update","patch","delete"]

1.6.3、允许读取Pod以及读写job信息

rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["jobs"]
  verbs: ["get","list","watch","create","update","patch","delete"]

1.6.4、允许读取一个名为my-config的ConfigMap

rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["get"]

1.6.5、读取核心组的Node资源

Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定。

rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get","list","watch"]

1.6.6、允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作

必须使用ClusterRole和ClusterRoleBinding。

rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
  verbs: ["get","post"]

1.7、常见的角色绑定示例

1、用户名rshine

subjects:
- kind: User
  name: rshine
  apiGroup: rbac.authorization.k8s.io

2、组名rshine

subjects:
- kind: Group
  name: alice
  apiGroup: rbac.authorization.k8s.io

3、kube-system命名空间中默认Service Account

subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

1.8、对Service Account的授权管理

Service Account也是一种账号,是给运行在Pod里的进程提供了必要的身份证明。需要在Pod定义中指明引用的Service Account,这样就可以对Pod的进行赋权操作。

1.8.1、实例:pod内可获取rbac命名空间的所有Pod资源,sa-rshine的Service Account是绑定了名为pod-read的Role

1、创建ns资源rbac:kubectl create ns rbac

2、名称空间rbac下创建Service Account资源sa-rshine:kubectl create sa sa-rshine -n rbac

3、名称空间rbac创建Role资源pod-read:

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Role.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: rbac
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: rbac
  name: pod-read
rules:
- apiGroups: [""]
  resources: ["pods"]
  resourceNames: []
  verbs: ["get","watch","list"]

4、创建Rolebinding资源rolebinding-sa-rshine,将Service Account sa-rshine绑定到了Role资源pod-read上:kubectl create rolebinding rolebinding-sa-rshine -n rbac --role=pod-read --serviceaccount=rbac:sa-rshine

5、创建Pod资源引用ServiceAccount,查看Pod资源清单文件:Eg-Pod-rbac.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Pod-rbac.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-rbac
  namespace: rbac
spec:
  serviceAccountName: sa-rshine
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80

6、应用/更新Pod资源清单文件:Eg-Pod-rbac.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Pod-rbac.yaml
pod/pod-rbac created
root@k8s-master:~/K8sStudy/Chapter2-16#

7、查看Pod资源状态和详细信息

k8s安全管理RBAC认证授权_k8s_07

1.8.2、常见Service Account授权示例

1、my-namespace中的my-sa Service Account授予只读权限

kubectl create rolebinding my-sa-view --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace

2、为一个命名空间中名为default的Service Account授权

如果一个应用没有指定 serviceAccountName,则会使用名为default的Service Account。注意,赋予Service Account “default”的权限会让所有没有指定serviceAccountName的Pod都具有这些权限

例如,在my-namespace命名空间中为Service Account“default”授予只读权限:

kubectl create rolebinding default-view --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace

3、为命名空间中所有Service Account都授予一个角色

如果希望在一个命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权

kubectl create rolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace

4、为集群范围内所有Service Account都授予一个低权限角色

如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。

kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts

5、为所有Service Account授予超级用户权限

kubectl create clusterrolebinding serviceaccounts-view --clusterrole=cluster-admin --group=system:serviceaccounts

1.9、使用kubectl命令行工具创建资源对象

1、在命名空间rbac中为用户es授权admin ClusterRole:

kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac

2、在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:

kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac

3、在全集群范围内为用户root授予cluster-admin ClusterRole:

kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root

4、在全集群范围内为名为myapp的Service Account授予view ClusterRole:

kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp

yaml文件进行rbac授权:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/

1.10、案例一:限制不同的用户操作k8s集群

1、ssl认证,生成一个证书

# 生成一个私钥
root@k8s-master:~/K8sStudy/Chapter2-16# cd /etc/kubernetes/pki/
root@k8s-master:/etc/kubernetes/pki# umask 077
root@k8s-master:/etc/kubernetes/pki# openssl genrsa -out rshine.key 2048
root@k8s-master:/etc/kubernetes/pki#
# 生成一个证书请求
root@k8s-master:/etc/kubernetes/pki# openssl req -new -key rshine.key -out rshine.csr -subj "/CN=rshine"
# 生成一个证书
root@k8s-master:/etc/kubernetes/pki# openssl x509 -req -in rshine.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out rshine.crt -days 3650
Certificate request self-signature ok
subject=CN = rshine

2、在kubeconfig下新增加一个rshine这个用户

# 把rshine这个用户添加到kubernetes集群中,可以用来认证apiserver的连接
root@k8s-master:/etc/kubernetes/pki# kubectl config set-credentials rshine --client-certificate=./rshine.crt --client-key=./rshine.key --embed-certs=true 
 
User "rshine" set.
root@k8s-master:/etc/kubernetes/pki#
# 在kubeconfig下新增加一个这个账号
root@k8s-master:/etc/kubernetes/pki# kubectl config set-context rshine@kubernetes --cluster=kubernetes --user=rshine
Context "rshine@kubernetes" created.
root@k8s-master:/etc/kubernetes/pki#

查看新增的用户rshine:kubectl config view

k8s安全管理RBAC认证授权_授权_08

3、切换账号到rshine,默认没有任何权限:kubectl config use-context rshine@kubernetes

# 切换到账号rshine
root@k8s-master:/etc/kubernetes/pki# kubectl config use-context rshine@kubernetes
Switched to context "rshine@kubernetes".
root@k8s-master:/etc/kubernetes/pki# 

查看当前集群用户:  kubectl config view

k8s安全管理RBAC认证授权_RBAC_09

4、切换kubernetes-admin@kubernetes账号,这个是集群用户,有任何权限:kubectl config use-context kubernetes-admin@kubernetes

root@k8s-master:/etc/kubernetes/pki# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
root@k8s-master:/etc/kubernetes/pki#

查看当前集群用户:  kubectl config view

k8s安全管理RBAC认证授权_k8s_10

5、把rshine这个用户通过rolebinding绑定到clusterrole角色cluster-admin上,授予权限,权限只是在rshine这个名称空间有效

# 创建名称空间rshine
root@k8s-master:~/K8sStudy/Chapter2-16# kubectl create ns rshine
namespace/rshine created
# 把这个用户rshine通过rolebinding绑定到clusterrole集群角色cluster-admin上
root@k8s-master:~/K8sStudy/Chapter2-16# kubectl create rolebinding rshine-rolebinding -n rshine --clusterrole=cluster-admin --user=rshine
rolebinding.rbac.authorization.k8s.io/rshine-rolebinding created
root@k8s-master:~/K8sStudy/Chapter2-16# 
# 将k8s用户切换到rshine@kubernetes
root@k8s-master:~/K8sStudy/Chapter2-16# kubectl config use-context rshine@kubernetes
Switched to context "rshine@kubernetes".

6、测试rshine用户是否有权限

k8s安全管理RBAC认证授权_k8s_11

7、Linux系统添加一个rshine的普通用户,并配置普通用户管理k8s集群。

root@k8s-master:~/K8sStudy/Chapter2-16# useradd -m rshine
root@k8s-master:~/K8sStudy/Chapter2-16# cp -ar /root/.kube /mnt
# 修改/mnt/.kube/config文件,把kubernetes-admin相关的删除,只留rshine用户
root@k8s-master:~/K8sStudy/Chapter2-16# vim /mnt/.kube/config
root@k8s-master:~/K8sStudy/Chapter2-16# cp -ar /mnt/.kube /home/rshine
root@k8s-master:~/K8sStudy/Chapter2-16# chown -R rshine:rshine /home/rshine/.kube
root@k8s-master:~/K8sStudy/Chapter2-16# vim /home/rshine/.kube/config 	# 修改current-context: rshine@kubernetes

8、Linux系统切换普通用户rshine,验证k8s中rhsine用户在rshine名称空间是否有权限

k8s安全管理RBAC认证授权_授权_12

9、退出rshine用户,需要在把集群环境切换成管理员权限:kubectl config use-context kubernetes-admin@kubernetes

k8s安全管理RBAC认证授权_RBAC_13

1.11、案例二:授权kubectl用户能查看所有名称空间的pod的权限

1、ssl认证,生成一个证书

# 生成一个私钥
root@k8s-master:~/K8sStudy/Chapter2-16# cd /etc/kubernetes/pki/
root@k8s-master:/etc/kubernetes/pki# umask 077
root@k8s-master:/etc/kubernetes/pki# openssl genrsa -out kakaluote.key 2048
# 生成一个证书请求
root@k8s-master:/etc/kubernetes/pki# openssl req -new -key kakaluote.key -out kakaluote.csr -subj "/CN=kakaluote"
# 生成一个证书
root@k8s-master:/etc/kubernetes/pki# openssl x509 -req -in kakaluote.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kakaluote.crt -days 3650
Certificate request self-signature ok
subject=CN = kakaluote

2、在kubeconfig下新增加一个kakaluote这个用户

# 把kakaluote这个用户添加到kubernetes集群中,可以用来认证apiserver的连接
root@k8s-master:/etc/kubernetes/pki# kubectl config set-credentials kakaluote --client-certificate=./kakaluote.crt --client-key=./kakaluote.key --embed-certs=true
User "kakaluote" set.
# 在kubeconfig下新增加一个kakaluote这个账号
root@k8s-master:/etc/kubernetes/pki# kubectl config set-context kakaluote@kubernetes --cluster=kubernetes --user=kakaluote
Context "kakaluote@kubernetes" created.

查看新增的用户kakaluote:kubectl config view

k8s安全管理RBAC认证授权_RBAC_14

3、创建一个clusterrole资源kakaluote-get-pod,拥有pods资源的get,list,watch权限

查看ClusterRole资源清单文件:Eg-ClusterRole-kakaluote-get-pod.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-ClusterRole-kakaluote-get-pod.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kakaluote-get-pod
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]

应用/更新ClusterRole资源清单文件:Eg-ClusterRole-kakaluote-get-pod.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-ClusterRole-kakaluote-get-pod.yaml
clusterrole.rbac.authorization.k8s.io/kakaluote-get-pod created
root@k8s-master:~/K8sStudy/Chapter2-16# 

查看创建的ClusterRole的详细信息:

k8s安全管理RBAC认证授权_授权_15

4、创建一个clusterrolebinding资源kakaluote-get-pods-rolebinding:kubectl create rolebinding kakaluote-get-pods-rolebinding --clusterrole=kakaluote-get-pod --user=kakaluote

5、Linux系统添加一个kakaluote的普通用户

root@k8s-master:~/K8sStudy/Chapter2-16# useradd -m kakaluote
root@k8s-master:~/K8sStudy/Chapter2-16# cp -ar /root/.kube /mnt
# 修改/mnt/.kube/config文件,把kubernetes-admin和rshine相关的删除,只留kakaluote用户
root@k8s-master:~/K8sStudy/Chapter2-16# vim /mnt/.kube/config
root@k8s-master:~/K8sStudy/Chapter2-16# cp -ar /mnt/.kube /home/kakaluote
root@k8s-master:~/K8sStudy/Chapter2-16# chown -R kakaluote:kakaluote /home/kakaluote/.kube
root@k8s-master:~/K8sStudy/Chapter2-16# vim /home/kakaluote/.kube/config 	# 修改current-context: kakaluote@kubernetes

6、Linux系统切换普通用户kakaluote,验证k8s中kakaluote用户是否有pods的get权限

k8s安全管理RBAC认证授权_k8s_16

由上结果可见,rolebinding即使是绑定到clusterrole上也只能在名称空间下生效。

1.12、准入控制

1.12.1、ResourceQuota准入控制器

ResourceQuota准入控制器是k8s上内置的准入控制器,默认该控制器是启用的状态,它主要作用是用来限制一个名称空间下的资源的使用,它能防止在一个名称空间下的pod被过多创建时,导致过多占用k8s资源,简单讲它是用来在名称空间级别限制用户的资源使用。

1.12.1.1、实例一:ResourceQuota限制cpu、内存、pod、deployment数量

1、创建resourcequota资源,查看resourcequota资源清单文件:Eg-ResourceQuota-cpu-mem-pod-deployment.yaml 

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-ResourceQuota-cpu-mem-pod-deployment.yaml 
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-test
  namespace: rshine
spec:
  hard:
    pods: "6"
    requests.cpu: "1"
    requests.memory: 20M
    limits.cpu: "4"
    limits.memory: 25M
    count/deployments.apps: "2"
    persistentvolumeclaims: "2"

spec.hard字段是用来定义对应名称空间下的资源限制规则;pods用来限制在对应名称空间下的pod数量,requests.cpu字段用来限制对应名称空间下所有pod的cpu资源的下限总和;requests.memory用来限制对应名称空间下pod的内存资源的下限总和;limits.cpu用来限制对应名称空间下的podcpu资源的上限总和,limits.memory用来限制对应名称空间下pod内存资源上限总和;count/deployments.apps用来限制对应名称空间下apps群组下的deployments的个数;

以上配置清单表示,在quota名称空间下运行的pod数量不能超过6个,所有pod的cpu资源下限总和不能大于1个核心,内存资源下限总和不能大于20M,cpu上限资源总和不能大于4个核心,内存上限总和不能超过25M,apps群组下的deployments控制器不能超过2个, pvc个数不能超过2个;以上条件中任意一个条目不满足,都将无法在对应名称空间创建对应的资源。

2、应用/更新resourcequota资源清单文件:Eg-ResourceQuota-cpu-mem-pod-deployment.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-ResourceQuota-cpu-mem-pod-deployment.yaml
resourcequota/quota-test created

3、查看resourcequota资源详细信息

k8s安全管理RBAC认证授权_认证_17

4、创建pod进行测试验证

创建一个Deployment资源,超过了名称空间资源限制,看看是否能创还能Deployment资源。

查看Deployment资源清单文件:Eg-deployment-quota.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-deployment-quota.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-quota-test
  namespace: rshine
spec:
  replicas: 2
  selector:
    matchLabels:
      app: quota
  template:
    metadata:
      labels:
         app: quota
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
         requests:
            cpu: 10m
            memory: 9Mi
         limits:
            cpu: 10m
            memory: 10Mi

这里创建两个pod副本,每个pod的requests.memory是9Mi,两个加起来就是18Mi。看看是否能正常创建Deployment,和对应数量的Pod。

应用/更新Deployment资源清单文件:Eg-deployment-quota.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-deployment-quota.yaml 
deployment.apps/pod-quota-test created
root@k8s-master:~/K8sStudy/Chapter2-16# 

查看Deployment资源状态。

k8s安全管理RBAC认证授权_认证_18

可以看到Deployment状态正常。

查看Pod的状态

k8s安全管理RBAC认证授权_认证_19

两个副本状态正常。

修改Deployment的副本为3,这时requests.memory的综合为27Mi,超过了名称空间rshine的ResourceQuota的requests.memory资源的20Mi限制了,看是否能正常创建第3个副本了。

修改Eg-deployment-quota.yaml中副本数为3,然后应用/更新Eg-deployment-quota.yaml清单文件:

root@k8s-master:~/K8sStudy/Chapter2-16# vim Eg-deployment-quota.yaml
root@k8s-master:~/K8sStudy/Chapter2-16# 
root@k8s-master:~/K8sStudy/Chapter2-16# grep replicas Eg-deployment-quota.yaml
  replicas: 3
root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-deployment-quota.yaml
deployment.apps/pod-quota-test configured
root@k8s-master:~/K8sStudy/Chapter2-16#

查看Deployment和Pod资源状态:

k8s安全管理RBAC认证授权_kubernetes_20

可以看到当名称空间下资源配比超过ResourceQuota的资源限制时,不会创建超出的资源。

1.12.1.2、ResourceQuota限制存储空间大小

查看ResourceQuota资源清单文件:Eg-ResourceQuota-storage.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-ResourceQuota-storage.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-storage-test
  namespace: rshine
spec:
  hard:
    requests.storage: "5Gi"
    persistentvolumeclaims: "2"
    requests.ephemeral-storage: "1Gi"
    limits.ephemeral-storage: "2Gi"

备注:requests.storage用来限制对应名称空间下的存储下限总和,persistenvolumeclaims用来限制pvc总数量,requests.ephemeral-storage用来现在使用本地临时存储的下限总容量;limits.ephemeral-storage用来限制使用本地临时存储上限总容量;以上配置表示在rshine名称空间下非停止状态的容器存储下限总容量不能超过5G,pvc的数量不能超过2个,本地临时存储下限容量不能超过1G,上限不能超过2G。

应用/更新ResourceQuota资源清单文件:Eg-ResourceQuota-storage.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-ResourceQuota-storage.yaml
resourcequota/quota-storage-test created
root@k8s-master:~/K8sStudy/Chapter2-16#

查看ResourceQuota资源详细信息

k8s安全管理RBAC认证授权_RBAC_21

1.12.2 LimitRanger准入控制器

LimitRanger准入控制器是k8s上一个内置的准入控制器,LimitRange是k8s上的一个标准资源,它主要用来定义在某个名称空间下限制pod或pod里的容器对k8s上的cpu和内存资源使用;它能够定义我们在某个名称空间下创建pod时使用的cpu和内存的上限和下限以及默认cpu、内存的上下限。

如果我们创建pod时定义了资源上下限,但不满足LimitRange规则中定义的资源上下限,此时LimitRanger就会拒绝我们创建此pod;如果我们在LimitRange规则中定义了默认的资源上下限制,我们创建资源没有指定其资源限制,它默认会使用LimitRange规则中的默认资源限制;同样的逻辑LimitRanger可以限制一个pod使用资源的上下限,它还可以限制pod中的容器的资源上下限,比限制pod更加精准;不管是针对pod还是pod里的容器,它始终只是限制单个pod资源使用。

1、创建一个LimitRanger资源:Eg-LimitRanger.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-LimitRanger.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: 1000m
      memory: 1000Mi
    maxLimitRequestRatio:
      cpu: 2
      memory: 2
    type: Container

备注:以上清单主要定义了两个资源,一个创建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为1个核心,内存为1G;

如果我们在创建pod时,只指定了容器的资源上限或下限,那么上限最大是下限的的2倍,如果指定cpu上限为2000m那么下限一定不会小于1000m,如果只指定了cpu下限为500m那么上限最大不会超过1000m,对于内存也是同样的逻辑。

2、应用/更新LimitRanger资源:Eg-LimitRanger.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-LimitRanger.yaml
namespace/limit unchanged
limitrange/cpu-memory created
root@k8s-master:~/K8sStudy/Chapter2-16# 

3、查看LimitRanger资源

k8s安全管理RBAC认证授权_认证_22

1.12.2.1、实例一:在limit名称空间创建pod,不指定资源,验证是否会被limitrange规则自动附加其资源限制?

查看Pod资源文件:Eg-Pod-limitrange.yaml 

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Pod-limitrange.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-test-limitrange
  namespace: limit
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx

应用/更新Pod资源文件:Eg-Pod-limitrange.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Pod-limitrange.yaml
pod/pod-test-limitrange created
root@k8s-master:~/K8sStudy/Chapter2-16#

查看创建的Pod详细信息:

k8s安全管理RBAC认证授权_k8s_23

通过上面结果可以看到我们在limit名称空间下创建的pod没有指定其容器资源限制,创建pod后,其内部容器自动就有了默认的资源限制;其大小就是我们在定义LimitRange规则中的default和defaultRequest字段中指定的资源限制。

1.12.2.2、创建pod,指定cpu请求是100m,看看是否允许创建

创建一个Pod资源:Eg-Pod-limitrange-request.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# cat Eg-Pod-limitrange-request.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-test-limitrange-request
  namespace: limit
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources:
      requests:
        cpu: 100m

应用/更新Pod资源:Eg-Pod-limitrange-request.yaml

root@k8s-master:~/K8sStudy/Chapter2-16# kubectl apply -f Eg-Pod-limitrange-request.yaml
Error from server (Forbidden): error when creating "Eg-Pod-limitrange-request.yaml": pods "pod-test-limitrange-request" is forbidden: [minimum cpu usage per Container is 500m, but request is 100m, cpu max limit to request ratio per Container is 2, but provided ratio is 10.000000]
root@k8s-master:~/K8sStudy/Chapter2-16#

更新Pod资源时报错,创建的Pod资源的requests.cpu的值是100m,而limit名称空间下限制容器最小cpu是500m,不满足要求,不允许创建。