k8s安全管理

百度网盘链接:https://pan.baidu.com/s/15t_TSH5RRpCFXV-93JHpNw?pwd=8od3  提取码:8od3

17 k8s安全管理

17.1 安全管理

17.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上线。

 

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

1)客户端认证:

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

 

2)Bearertoken:

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

 

Kubectl访问k8s集群,要找一个kubeconfig文件,基于kubeconfig文件里的用户访问apiserver

3)Serviceaccount

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

 

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文件配置,如下:

[root@master1 ~]# kubectl config view

apiVersion: v1

clusters:

- cluster:

    certificate-authority-data: DATA+OMITTED

    server: https://192.168.40.180: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: REDACTED

    client-key-data: REDACTED

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

[root@master1 ~]# kubectl get pods --kubeconfig=/root/.kube/config

17.1.2 授权

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

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

1)Node(节点认证)

2)ABAC (基于属性的访问控制)

3)RBAC(基于角色的访问控制)

4)Webhook(基于http回调机制的访问控制)

 

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

 

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

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

 

Role、RoleBinding、ClusterRole和ClusterRoleBinding的关系如下:

1、用户基于rolebinding绑定到role:

限定在rolebinding所在的名称空间。

 

2、用户基于rolebinding绑定到clusterrole:

 

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

(1)用户通过rolebinding绑定role

(2)用户通过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上

17.1.3 准入控制

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

[root@master1 ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml   //查看apiserver启用的准入控制器

apiVersion: v1

kind: Pod

metadata:

  annotations:

    kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint: 192.168.40.63:6443

  creationTimestamp: null

  labels:

    component: kube-apiserver

    tier: control-plane

  name: kube-apiserver

  namespace: kube-system

spec:

  containers:

  - command:

    - kube-apiserver

    - --advertise-address=192.168.40.180

    …

- --enable-admission-plugins=NodeRestriction

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

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

17.2 Useraccount和ServiceAccount介绍

17.2.1 Useraccount和ServiceAccount概述

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

UserAccount是给kubernetes集群外部用户使用的,如kubectl访问k8s集群要用useraccount用户, kubeadm安装的k8s,默认的useraccount用户是kubernetes-admin。

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

APIServer需要对客户端做认证,使用kubeadm安装的K8s,会在用户家目录下创建一个认证配置文件 .kube/config 这里面保存了客户端访问API Server的密钥相关信息,这样当用kubectl访问k8s时,它就会自动读取该配置文件,向API Server发起认证,然后完成操作请求。

[root@master1~]# cat ~/.kube/config    //用户名称可以在kubeconfig中查看

...

users:

- name: kubernetes-admin

...

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

17.2.2 ServiceAccount使用案例

1、创建sa

[root@master1 ~]# kubectl create sa sa-test

2、创建pod

[root@master1 ~]# vim pod.yaml

apiVersion: v1

kind: Pod

metadata:

  name: sa-test

  namespace: default

  labels:

    app: sa

spec:

  serviceAccountName: sa-test

  containers:

  - name: sa-tomcat

    ports:

    - containerPort: 80

    image: nginx

    imagePullPolicy: IfNotPresent   

[root@master1 ~]# kubectl apply -f pod.yaml

[root@master1 ~]# 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做授权

[root@master1 ~]# kubectl create clusterrolebinding sa-test-admin --clusterrole=cluster-admin  --serviceaccount=default:sa-test

4、再次请求

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": "c392fcb2-12da-4419-b5de-6e2fe2ca626a",

    "resourceVersion": "28",

    "creationTimestamp": "2022-09-18T06:19:42Z",

    "labels": {

      "kubernetes.io/metadata.name": "kube-system"

    },

    "managedFields": [

      {

        "manager": "kube-apiserver",

        "operation": "Update",

        "apiVersion": "v1",

        "time": "2022-09-18T06:19:42Z",

        "fieldsType": "FieldsV1",

        "fieldsV1": {

          "f:metadata": {

            "f:labels": {

              ".": {},

              "f:kubernetes.io/metadata.name": {}

            }

          }

        }

      }

    ]

  },

  "spec": {

    "finalizers": [

      "kubernetes"

    ]

  },

  "status": {

    "phase": "Active"

  }

}

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

root@sa-test:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt  -H "Authorization: Bearer $(cat ./token)"  https://kubernetes/api/v1/pods

17.3 RBAC认证授权策略

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

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

17.3.1 Role:角色

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

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

  namespace: rbac

  name: pod-read

rules:

- apiGroups: [""]

  resources: ["pods"]

  resourceNames: []

  verbs: ["get","watch","list"]

rules中的参数说明:

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

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

3、resourceNames: 指定resource的名称

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

17.3.2 ClusterRole:集群角色

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

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

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

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

 

例如:定义一个集群角色可让用户访问任意secrets

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRole

metadata:

  name: secrets-clusterrole

rules:

- apiGroups: [""]

  resources: ["secrets"]

  verbs: ["get","watch","list"]

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

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

例如:将在rbac命名空间中把pod-read角色授予用户

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.authorizatioin.k8s.io

 

RoleBinding也可以引用ClusterRole,对属于同一命名空间内的ClusterRole定义的资源主体进行授权,例如:es能获取到集群中所有的资源信息。

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

17.4 资源的引用方式

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

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

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

[root@master1 ~]# kubectl create ns test

[root@master1 ~]# vim role-test.yaml

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

  name: logs-reader

  namespace: test

rules:

- apiGroups: [""]

  resources: ["pods","pods/log"]

  verbs: ["get","list","watch"]

[root@master1 ~]# kubectl apply -f role-test.yaml

[root@master1 ~]# kubectl create sa sa-test -n test

[root@master1 ~]# kubectl create rolebinding sa-test-1 -n test --role=logs-reader --serviceaccount=test:sa-test

[root@master1]# vim pod-test.yaml

apiVersion: v1

kind: Pod

metadata:

  name: sa-test-pod

  namespace: test

  labels:

    app: sa

spec:

  serviceAccountName: sa-test

  containers:

  - name:  sa-tomcat

    ports:

    - containerPort: 80

    image: nginx

imagePullPolicy: IfNotPresent

[root@master1 ~]# kubectl apply -f pod-test.yaml

[root@master1 ~]# kubectl exec -it sa-test-pod -n test -- /bin/bash

root@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/sa-test-pod/log

 

资源还可以通过名称(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"]

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

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

rules:

- apiGroups: [""]

  resources: ["pods"]

  verbs: ["get","list","watch"]

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

rules:

- apiGroups: ["apps"]

  resources: ["deployments"]

  verbs: ["get","list","watch","create","update","patch","delete"]

17.5.3 允许读取Pod以及读写job信息

rules:

- apiGroups: [""]

  resources: ["pods"]

  verbs: ["get","list","watch"]

- apiGroups: [""]

  resources: ["jobs"]

  verbs: ["get","list","watch","create","update","patch","delete"]

17.5.4 允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):

rules:

- apiGroups: [""]

  resources: ["configmaps"]

  resourceNames: ["my-configmap"]

  verbs: ["get"]

17.5.5 读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):

rules:

- apiGroups: [""]

  resources: ["nodes"]

  verbs: ["get","list","watch"]

17.5.6 允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding):

rules:

- nonResourceURLs: ["/healthz","/healthz/*"]

  verbs: ["get","post"]

17.6 常见的角色绑定示例

17.6.1 用户名alice    

subjects:

- kind: User

  name: alice

  apiGroup: rbac.authorization.k8s.io

17.6.2 组名alice 

subjects:

- kind: Group

  name: alice

  apiGroup: rbac.authorization.k8s.io

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

subjects:

- kind: ServiceAccount

  name: default

  namespace: kube-system

17.7 对Service Account的授权管理

Service Account也是一种账号,是给运行在Pod里的进程提供了必要的身份证明。需要在Pod定义中指明引用的Service Account,这样就可以对Pod的进行赋权操作。例如:pod内可获取rbac命名空间的所有Pod资源,pod-reader-sc的Service Account是绑定了名为pod-read的Role   

[root@master1 ~]# kubectl create ns rbac

[root@master1 ~]# kubectl create sa pod-reader-sc -n rbac

[root@master1 ~]# vim pod-rbac.yaml

apiVersion: v1

kind: Pod

metadata:

  name: nginx

  namespace: rbac

spec:

  serviceAccountName: pod-reader-sc

  containers:

  - name: nginx

    image: nginx

    imagePullPolicy: IfNotPresent

    ports:

    - containerPort: 80

[root@master1 ~]# kubectl apply -f pod-rbac.yaml

 

(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

17.8 使用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/

17.9 限制不同的用户操作k8s集群

17.9.1 授权kubectl用户能查看lucky-test名称空间资源的权限

生成一个证书:

(1)生成一个私钥

# cd /etc/kubernetes/pki/

# umask 077; openssl genrsa -out lucky.key 2048

(2)生成一个证书请求

openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky"

(3)生成一个证书

openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650

在kubeconfig下新增加一个lucky这个用户

(1)把lucky这个用户添加到kubernetes集群中,可以用来认证apiserver的连接

# kubectl config set-credentials lucky --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true 

(2)在kubeconfig下新增加一个lucky这个账号

# kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky

(3)切换账号到lucky,默认没有任何权限

# kubectl config use-context lucky@kubernetes    #切换后执行命令没有权限

# kubectl config use-context kubernetes-admin@kubernetes   #这个是集群用户,有任何权限

把user这个用户通过rolebinding绑定到clusterrole上,授予权限,权限只是在lucky这个名称空间有效

(1)把lucky这个用户通过rolebinding绑定到clusterrole上

# kubectl create ns lucky-test

# kubectl create rolebinding lucky -n lucky-test --clusterrole=cluster-admin --user=lucky

(2)切换到lucky这个用户

# kubectl config use-context lucky@kubernetes

(3)测试是否有权限

# kubectl get pods -n lucky-test

添加一个lucky的普通用户

# useradd lucky

# cp -ar /root/.kube /tmp/

修改/tmp/.kube/config文件,把kubernetes-admin相关的删除,只留lucky用户

# cp -ar /tmp/.kube/ /home/lucky/

# chown -R lucky.lucky /home/lucky/

# su - lucky

# kubectl get pods -n lucky-test

退出test用户,需要在把集群环境切换成管理员权限

kubectl config use-context kubernetes-admin@kubernetes

17.9.2 授权kubectl用户能查看所有名称空间的pod的权限

生成一个证书:

(1)生成一个私钥

cd /etc/kubernetes/pki/

umask 077; openssl genrsa -out kubectl.key 2048

(2)生成一个证书请求

openssl req -new -key kubectl.key -out kubectl.csr -subj "/CN=kubectl"

(3)生成一个证书

openssl x509 -req -in kubectl.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kubectl.crt -days 3650

在kubeconfig下新增加一个kubectl这个用户:

(1)把lucky这个用户添加到kubernetes集群中,可以用来认证apiserver的连接

kubectl config set-credentials kubectl --client-certificate=./kubectl.crt --client-key=./kubectl.key --embed-certs=true

(2)在kubeconfig下新增加一个lucky这个账号

kubectl config set-context kubectl@kubernetes --cluster=kubernetes --user=kubectl

(3)创建一个clusterrole

# vim kubectl-clusterrole.yaml

apiVersion: rbac.authorization.k8s.io/v1

kind: ClusterRole

metadata:

  name: kubectl-get-pod

rules:

- apiGroups: [""]

  resources: ["pods"]

  verbs: ["get", "list", "watch"]

[root@master1 ~]# kubectl apply -f kubectl-clusterrole.yaml

(4)创建一个clusterrolebinding

kubectl create clusterrolebinding kubectl-get-pods --clusterrole=kubectl-get-pod  --user=kubectl

添加一个kubectl的普通用户:

# useradd kubectl

# cp -ar /root/.kube /home/kubectl/

# vim /home/kubectl/.kube/config

把kubernetes-admin和lucky相关的删除,只留kubectl用户。

把current-context变成如下:current-context: kubectl@kubernetes

apiVersion: v1

clusters:

- cluster:

    certificate-authority-data:

RTczc1BKL0xaT3RqOU5PR1U5tRmlXSzk1RjNTUTJVN0ZGREJOSWgyZE1ZNnlFPQotCBDVJUSUZJQ0FURS0tLS0tCg==

    server: https://192.168.40.180:6443

  name: kubernetes

contexts:

- context:

    cluster: kubernetes

    user: kubectl

  name: kubectl@kubernetes

current-context: kubectl@kubernetes

kind: Config

preferences: {}

users:

- name: kubectl

  user:

    client-certificate-data:

AKak83NHNzeWxYZzltOVBTUVVmN3TcDl3NwpGQ09aUTZNakJBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=

# chown -R kubectl.kubectl /home/kubectl/

# su - kubectl

$ kubectl get pods

$ kubectl get pods -n kube-system

17.10 准入控制

17.10.1 ResourceQuota准入控制器

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

限制cpu、内存、pod、deployment数量:

[root@master1 ~]# kubectl create ns quota

[root@master1 ~]# vim resourcequota.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@master1 ~]# kubectl apply -f resourcequota.yaml

资源清单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个核心,内存上限总和不能超过10G,apps群组下的deployments控制器不能超过6个, pvc个数不能超过6个;以上条件中任意一个条目不满足,都将无法在对应名称空间创建对应的资源。

[root@master1 ~]# 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: nginx

        imagePullPolicy: IfNotPresent

        ports:

        - containerPort: 80

        resources:

         requests:

            cpu: 10m

            memory: 10Mi

         limits:

            cpu: 10m

            memory: 10Mi

[root@master1 ~]# kubectl apply -f quota-deployment.yaml

[root@master1 ~]# kubectl get pods -n quota

NAME                     READY   STATUS    RESTARTS   AGE

quota-6d5c459f69-4q86p   1/1     Running   0          8s

quota-6d5c459f69-7kchv   1/1     Running   0          8s

quota-6d5c459f69-dgzl7   1/1     Running   0          8s

quota-6d5c459f69-g6c8j   1/1     Running   0          9s

quota-6d5c459f69-hfdng   1/1     Running   0          9s

quota-6d5c459f69-nfb7p   1/1     Running   0          9s

限制存储空间大小:

[root@master1 ~]# 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@master1 ~]# kubectl apply -f resourcequota-2.yaml

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

17.10.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资源使用。

[root@master1 ~]# 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@master1 ~]# 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,对于内存也是同样的逻辑。

 

limitrange使用案例:

(1)在limit名称空间创建pod,不指定资源,看看是否会被limitrange规则自动附加其资源限制?

[root@master1 ~]# vim pod-limit.yaml

apiVersion: v1

kind: Pod

metadata:

  name: nginx-pod-demo

  namespace: limit

spec:

  containers:

  - image: nginx

    imagePullPolicy: IfNotPresent

    name: nginx

[root@master1 ~]# kubectl apply -f pod-limit.yaml

[root@master1 ~]# kubectl describe pods nginx-pod-demo -n limit

显示如下:

    Limits:

      cpu:     1

      memory:  1000Mi

    Requests:

      cpu:        500m

      memory:     500Mi

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

 

(2)创建pod,指定cpu请求是100m,看看是否允许创建

[root@master1 ~]# 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@master1 ~]# 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]

posted @ 2022-12-27 00:59  Krill_ss  阅读(322)  评论(0编辑  收藏  举报