一、认证

访问k8s时,主要是通过访问apiserver进行操作,所以需要对访问apiserver的用户做认证。如果不做认证那么任何人都可以进行访问k8s,这种情况是非常危险的,所以需要对访问k8s的apiserver的用户进行认证,确保是符合要求的用户。

1.1 访问apiserver的集中认证方式

1.1.1~1.1.2 两种认证方式就是kubectl访问k8s集群,要找一个kubeconfig的文件,基于该文件里的用户访问apiserver,属于是外部访问apiserver的时候使用的方式。

1.1.3 认证方式属于是内部访问pod和apiserver交互时候采用的一种方式。

1.1.1 方式一:客户端认证

可称为双向TSL认证,kubectl访问apiserver的时候,apiserver需要认证kubectl是否符合要求,通常是通过ca根证书进行验证

1.1.2 方式二:Bearertoken

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

1.1.3 方式三:ServiceAccount

ServiceAccount(服务账号),创建一个pod,该pod访问k8s集群apiserver时用到的一个用户(就是pod想要访问apiserver时创建的一个ServiceAccount用户并将这个用户绑定到pod中),ServiceAccount包括了namespace、token、ca,他是通过目录的方式挂载给pod的,当pod运行起来的时候就会读取到这些信息,从而使用这种方式和apiserver进行通信。

1.2 kubeconfig文件

在K8S集群当中,当我们使用kubectl操作k8s资源时候,需要确定我们用哪个用户访问哪个k8s集群,kubectl操作k8s集群资源会去/root/.kube目录下找config文件。

可以通过kubectl config view 命令查看config文件配置,如下:

kubeconfig 文件官方地址解释说明

k8s 安全管理:认证、授权、准入控制_Linux

users:                                        //用户信息
- name: kubernetes-admin                      //用户名称(该用户拥有证书和私钥,说明已经被ca证书签发,可被apiserver信任)
  user:                                       
    client-certificate-data: DATA+OMITTED     //用户证书
    client-key-data: DATA+OMITTED             //用户私钥

#在使用kubectl时默认找的就是/root/.kube/config文件,该文件中的kubernetes-admin用户就具有k8s集群中的访问和操作资源的权限,
#因为使用kubeadm安装的k8s集权,安装时就默认就对该用户做了rbac授权,拥有了管理员的权限,因此它有操作k8s集群中的权限

clusters:
- cluster:                                    //定义的集群信息
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.57.131:6443       //apiserver的地址(maser节点的地址)
  name: kubernetes                            //该集群对应的名称

contexts:                                     //上下文(环境)
- context:
    cluster: kubernetes                       //上下文中定义的集群
    user: kubernetes-admin                    //上下文中定义的用户(users则定义了该用户的权限)
  name: kubernetes-admin@kubernetes           //上下文的名称
current-context: kubernetes-admin@kubernetes  //current-context(定义当前上下文):冒号后面定义了上下问的名称,表示当前使用的是哪个上下文。

#上下文(环境)中定义集群的信息即用户的信息,该集群及用户又分别定义了集群的信息及用户的权限。

#总结:使用kubectl时默认找到config配置文件中定义的kubernetes-admin用户,
#该用户通过当前上下文中定义的集群找到192.168.57.131:6443这个apiserver,然后进行操作。


#通过使用 --kubeconfig=“file” 也可以访问当前集群的pod
[root@k8s-master ~]# kubectl get pods --kubeconfig=/root/.kube/config 
NAME     READY   STATUS    RESTARTS   AGE
pod-05   1/1     Running   0          20h

#将文件拷贝迁移之后验证
[root@k8s-master ~]# cp /root/.kube/config  /tmp/

[root@k8s-master ~]# kubectl get pods --kubeconfig=/tmp/config 
NAME     READY   STATUS    RESTARTS   AGE
pod-05   1/1     Running   0          20h

二、授权

用户经过认证之后,只能仅代表它是一个被apiserver信任的用户,能否访问apiserver,但是用户能否拥有在k8s集权内自由操作资源的权限,还需要进行授权的操作,常见的授权方式有rbac授权。

2.1 授权方式:RBAC

RBAC(基于角色的访问控制机制)将一个用户绑定到一个角色上,授权的时候给角色进行授权,该角色拥有权限,从而让绑定的用户也拥有权限

用户可以是useraccount或者是serviceaccount

2.1.1 绑定方式:用户基于rolebinding绑定到role

用户通过rolebinding绑定到role之后,只需要给role设置权限,那么绑定到role的用户也会有相同的权限,该方式只能限制在一个名称空间中,就是rolebinding和role在哪个名称空间,那么绑定的用户就只对哪个名称空间有权限。创建role有名称空间的限制,需要和rolebinding在一起。

2.2.2 绑定方式:用户基于rolebinding绑定到clusterrole

与role不同的是,创建clusterrole没有名称空间的限制,比如在a和b两个名称空间创建了rolebinding,这两个名称空间都可以绑定clusterrole,然后用户绑定clusterrole之后,用户就可以对a和b两个名称空间都具有操作权限。

2.2.3 绑定方式:clusterrolebindbing绑定到clusterrole

由于clusterrolebinding与clusterrole一样没有名称空间限制,如果用户通过clusterrolebinding绑定到clusterrole上,那么这个用户将对任何名称空间都具有clusterrole授予的权限

2.2.4 绑定方式总结

 上面2.2.1绑定方式如果有多个名称空间,每个名称空间的用户都要对自己的名称空间具有管理员的权限,那么需要定义多个role和rolebinding,然后依次绑定,这种方法过于麻烦,所以引入了clusterrole 即2.2.2绑定方式,该方式直接定义一个clusterrole,然后对其授权,用户通过rolebinding绑定clusterrole就能拥有自己名称空间的权限。


PS: rolebinding 仅对当前名称空间具有对应的权限。

 

而2.2.3绑定方式则用户对任何名称空间都具有授予的管理员权限。

2.2 useraccount及serviceaccount的区别

k8s中账户分为useraccount(用户账号)和serviceaccount(服务账号)两种


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

 

serviceaccount是创建pod时候pod里面所使用的账号,pod容器中的进程如果想要访问k8s中的apiserver那么就需要有一个serviceaccount账号,该账号创建的时候仅局限于所在的名称空间,创建的每一个名称空间都会自动创建一个default service account,如果创建pod的时候没有指定serviceaccount,那么pod则会使用pod所在的那个名称空间中自动生成的serviceaccount账号。

下面则是查看名称空间中自动生成的serviceaccount账号信息。

#创建一个名称空间
[root@k8s-master ~]# kubectl create ns test
namespace/test created

#查看该名称空间的sa账号  (sa是 serviceaccount的缩写)
[root@k8s-master ~]# kubectl get sa -n test 
NAME      SECRETS   AGE
default   0         28s

#测试创建pod时使用的sa账号,创建一个pod的yaml文件
[root@k8s-master ~]# vim pod-01.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-01
  namespace: test    #指定创建pod所在名称空间
spec:
  containers:
  - name: my-nginx
    image: nginx
    imagePullPolicy: IfNotPresent


#创建
[root@k8s-master ~]# kubectl apply -f pod-01.yaml 
pod/pod-01 created

[root@k8s-master ~]# kubectl get pods -n test
NAME     READY   STATUS    RESTARTS   AGE
pod-01   1/1     Running   0          8s

#查看pod详细信息挂载的sa账号信息
[root@k8s-master ~]# kubectl describe pod pod-01 -n test 
Name:             pod-01
Namespace:        test
Priority:         0
Service Account:  default      //账号信息见左侧

2.3 serviceaccoun RBAC授权方式

(1)对my-namespace中的my-sa账号授予只读权限(view是系统自带的)
kubectl create rolebinding my-name --clusterrole=view --serviceaccount=my-namespace:my-sa --namespace=my-namespace

(2)为一个命名空间中名为default的Service Account授权
#如果一个应用没有指定 serviceAccount的名称,则会使用名为default的Service Account。注意,赋予Service Account “default”的权限会让所有没有指定serviceAccountName的Pod都具有这些权限
#例如,在my-namespace命名空间中为Service Account“default”授予只读权限:
kubectl create rolebinding my-name --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace

(3)为命名空间中所有Service Account都授予一个角色
#如果希望在一个命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权
kubectl create rolebinding my-name --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace

(4)为集群范围内所有Service Account都授予一个低权限角色
#如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。
kubectl create clusterrolebinding my-name --clusterrole=view --group=system:serviceaccounts

(5)为所有Service Account授予超级用户权限
kubectl create clusterrolebinding my-name --clusterrole=cluster-admin --group=system:serviceaccounts

(6)在命名空间rbac中为用户es授权admin ClusterRole:
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac

(7)在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:
kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac
 
(8)在全集群范围内为用户root授予cluster-admin ClusterRole:
kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root
  
(9)在全集群范围内为名为myapp的Service Account授予view ClusterRole:
kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp


#rbac授权yaml文件官方文档使用方式:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/

2.4 serviceaccount 使用方法

需要创建一个 serviceaccount (缩写 sa)并将其绑定到pod中,并给账号赋予权限,使pod能够有权限访问k8s集群

2.4.1 创建sa及pod

#创建sa
[root@k8s-master ~]# kubectl create sa  sa-01
serviceaccount/sa-01 created

[root@k8s-master ~]# kubectl get sa | grep -Ei "sa|name"
NAME              SECRETS   AGE
sa-01             0         32s

#创建pod 将sa账号绑定到pod中
[root@k8s-master ~]# vim pod-001.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-001
spec:
  serviceAccount: sa-01  #指定sa的账号
  containers:
  - name: mynginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80


#创建
[root@k8s-master ~]# kubectl apply -f pod-001.yaml 
pod/pod-001 created

[root@k8s-master ~]# kubectl get pods 
NAME      READY   STATUS    RESTARTS   AGE
pod-001   1/1     Running   0          3s

2.4.2 对sa账号授权

进入pod中给sa账号授权

#进入pod容器
[root@k8s-master ~]# kubectl exec -it pod-001 -- /bin/bash
root@pod-001:/# ls /var/run/secrets/kubernetes.io/serviceaccount/
ca.crt	namespace  token
#创建pod时不管有没有指定sa账号,默认都会在pod中生成这个目录及目录下的这些文件, ca证书及token等。


#测试还未对sa账号授权时pod访问k8s集群
root@pod-001:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@pod-001:/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-01\" cannot get resource \"namespaces\" in API group \"\" in the namespace \"kube-system\"",
  "reason": "Forbidden",
  "details": {
    "name": "kube-system",
    "kind": "namespaces"
  },
  "code": 403                 //403  未授权无法请求k8s集权


ps: #使用ca.crt证书获取token中的内容去请求访问k8s集群
    #kubernetes/api/v1/       //kubernetes是apiserver pod前端的四层代理(kubectl get svc  可以查看到),访问的是api  namespace的版本是v1
    #namespaces/kube-system   //表示访问的是kube-system名称空间


#对sa账号进行rbac授权
#退出容器
root@pod-001:/var/run/secrets/kubernetes.io/serviceaccount# exit 
exit

#授权(将sa账号通过clusterrolebinding绑定到clusterrole)
[root@k8s-master ~]# kubectl create clusterrolebinding sa-01-admin --clusterrole=cluster-admin  --serviceaccount=default:sa-01
clusterrolebinding.rbac.authorization.k8s.io/sa-01-admin created

ps: #kubectl create clusterrolebinding sa-01-admin  //创建的资源类型为 clusterrolebinding,并且给这个绑定起了一个名字 sa-01-admin
    #--clusterrole=cluster-admin                    //指定了要绑定的 ClusterRole 名称为 cluster-admin
    #-serviceaccount=default:sa-01                  //指定了要授权的 sa账号名称,default 是 sa账号所在的命名空间,sa-01 是 ServiceAccount 的名称。
    
    
#授权之后再次测试pod访问k8s集群
[root@k8s-master ~]# kubectl exec -it pod-001 -- /bin/bash
root@pod-001:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@pod-001:/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": "0cbb283a-249c-4177-a5a8-6e6921ce7b97",
    "resourceVersion": "3",
    "creationTimestamp": "2024-03-20T07:09:36Z",
    "labels": {
      "kubernetes.io/metadata.name": "kube-system"
    },
    "managedFields": [
      {
        "manager": "kube-apiserver",
        "operation": "Update",
        "apiVersion": "v1",
        "time": "2024-03-20T07:09:36Z",
        "fieldsType": "FieldsV1",
        "fieldsV1": {
          "f:metadata": {
            "f:labels": {
              ".": {},
              "f:kubernetes.io/metadata.name": {}
            }
          }
        }
      }
    ]
  },
  "spec": {
    "finalizers": [
      "kubernetes"
    ]
  },
  "status": {
    "phase": "Active"              //Active 表示能够访问
  }


#也可以访问所有名称空间中的pod
root@pod-001:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt  -H "Authorization: Bearer $(cat ./token)"  https://kubernetes/api/v1/pods | more
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "21323"
  },
  "items": [
    {
      "metadata": {
        "name": "pod-001",
        "namespace": "default",
        "uid": "956798c4-61d4-4318-b3c1-8ed130819dd8",
        "resourceVersion": "16924",
        "creationTimestamp": "2024-07-12T02:01:20Z",
         ..............
         .............
         .........
         ....
         ..
         .      (内容省略)

2.5 资源定义及角色(role)绑定

2.5.1 常用的角色(role)资源定义方式

rules:               //定义角色信息

- apiGroups:    //定义api组  [""] 什么都不写,表示对所有

   resources:    //定义pod或者控制器

   verbs:          //定义权限

 

  • get: 读取。
  • list: 列出。
  • watch: 监听。
  • create: 创建。
  • update: 更新。
  • patch: 类似于 update,允许使用补丁操作来部分更新资源。
  • delete: 删除。
(1)允许读取核心API组的Pod资源
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]

(2)允许读写apps API组中的deployment资源
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get","list","watch","create","update","patch","delete"]


(3)允许读取Pod以及读写job信息
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["jobs"]
  verbs: ["get","list","watch","create","update","patch","delete"]


(4)允许读取一个名为my-config的ConfigMap(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["my-configmap"]
  verbs: ["get"]

(5)读取核心组的Node资源(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get","list","watch"]

(6)允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作(必须使用ClusterRole和ClusterRoleBinding):
rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
  verbs: ["get","post"]

2.5.2 常用的角色(role)绑定方式

(1)用户名 A
subjects:
- kind: User
  name: A
  apiGroup: rbac.authorization.k8s.io
  
(2)组名B	
subjects:
- kind: Group
  name: B
  apiGroup: rbac.authorization.k8s.io

(3)kube-system命名空间中默认Service Account	
subjects:
- kind: ServiceAccount
  name: default
  namespace: kube-system

2.6 pod资源引用方式

如上方2.4~2.4.2. 所示,创建一个完成的pod引用资源过程

#创建名称空间
[root@k8s-master ~]# kubectl create ns test-01
namespace/test-01 created

#在创建的名称空间下创建角色(role)
[root@k8s-master ~]# vim role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: test-01
  name: role-01
rules:                           #定义角色信息
- apiGroups: [""]                #定义api的组,空字符串表示核心 API 组
  resources: ["pods","pods/log"] #定义对该名称空间中的pod及pod下的log拥有下面verbs字段定义的权限。
  verbs: ["get","list","watch"]  #读取(get)、监听(watch)和列表(list)权限
#role-01 角色对test-01名称空间下的所有pod及pod的log具有读取(get)、监听(watch)和列表(list)权限

[root@k8s-master ~]# kubectl apply -f role.yaml 
role.rbac.authorization.k8s.io/role-01 created

[root@k8s-master ~]# kubectl get role -n test-01
NAME      CREATED AT
role-01   2024-07-12T03:23:52Z

#在test-01名称空间下创建sa账号
[root@k8s-master ~]# kubectl create sa sa-01-test -n test-01
serviceaccount/sa-01-test created

#创建rolebonding并将sa账号绑定到role下(对sa账号做rbac授权)
[root@k8s-master ~]# kubectl create rolebinding name-sa  -n test-01 --role=role-01 --serviceaccount=test-01:sa-01-test
rolebinding.rbac.authorization.k8s.io/name-sa created

PS: #kubectl create rolebinding name-sa -n test-01 //创建rolebinding并其名称为 name-sa 且指定在test-01名称空间下
     #--role=role-01                                //指定role的名称(上面创建好的)
     #--serviceaccount=test-01:sa-01-test           //指定test-01名称空间下sa的账号
     
     
#创建pod将sa账号绑定到pod中
[root@k8s-master ~]# cat pod-002.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-002
  namespace: test-01
spec:
  serviceAccount: sa-01-test       #指定sa的账号
  containers:
  - name: mynginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80


[root@k8s-master ~]# kubectl apply -f pod-002.yaml 
pod/pod-002 created

[root@k8s-master ~]# kubectl get pods -n test-01
NAME      READY   STATUS    RESTARTS   AGE
pod-002   1/1     Running   0          15s

#进入到pod容器中验证权限
[root@k8s-master ~]# kubectl exec -it pod-002 -n test-01 -- /bin/bash
root@pod-002:/# cd /var/run/secrets/kubernetes.io/serviceaccount/
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount# ls 
ca.crt	namespace  token

#查看test-01 名称空间下的pod信息
ps:#https://kubernetes.default/    //这里因为这个sa的账号在test-01名称空间下并绑定了test-01空间下的rolebonding和role,
                                    //所以只能访问该名称空间的role所拥有的权限,因为该名称空间下的kebernetes的servic在default下,
                                    //通过kubectl describe svc kubernetes | grep -i namespace 进行查看,所以需要加上defuts
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt  -H "Authorization: Bearer $(cat ./token)"  https://kubernetes.default/api/v1/namespaces/test-01/pods/
{
  "kind": "PodList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "16516"
  },
  "items": [
    {
      "metadata": {
        "name": "pod-002",
        "namespace": "test-01",
        "uid": "1842b180-02b7-423a-b367-9cbb2caed97e",
        "resourceVersion": "16240",
        "creationTimestamp": "2024-07-12T05:18:44Z",
        "annotations": {
          "cni.projectcalico.org/podIP": "10.244.126.2/32",
          "cni.projectcalico.org/podIPs": "10.244.126.2/32",
          ......
          ....
          ...
          ..
          .    (内容省略)


#查看pod日志
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount# curl --cacert ./ca.crt  -H "Authorization: Bearer $(cat ./token)"  https://kubernetes.default/api/v1/namespaces/test-01/pods/pod-002/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: 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/07/12 05:18:45 [notice] 1#1: using the "epoll" event method
2024/07/12 05:18:45 [notice] 1#1: nginx/1.21.5
2024/07/12 05:18:45 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2024/07/12 05:18:45 [notice] 1#1: OS: Linux 3.10.0-1160.el7.x86_64
2024/07/12 05:18:45 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2024/07/12 05:18:45 [notice] 1#1: start worker processes
2024/07/12 05:18:45 [notice] 1#1: start worker process 31
2024/07/12 05:18:45 [notice] 1#1: start worker process 32
2024/07/12 05:18:45 [notice] 1#1: start worker process 33
2024/07/12 05:18:45 [notice] 1#1: start worker process 34
root@pod-002:/var/run/secrets/kubernetes.io/serviceaccount# 



PS:如上过程所示,创建了role 指定了role可以对test-01名称空间下的pod及pod/log 拥有读取(get)、监听(watch)和列表(list)权限
    创建的sa账号通过创建的rolebinding绑定到了role上,然后通过创建pod将具有role权限的sa账号绑定到了pod中,
    故,进入该pod容器中可以访问test-01名称空间中的pod及pod/log信息。

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

2.7.1 限制系统中普通用户操作k8s集群其中一个名称空间

在k8s集群中创建一个名为lucky的用户,让该用户只拥有对k8s集群中的lucky-test名称空间具有操作权限,并创建普通系统账户使之拥有这个lucky用户对k8s集群中的lucky-test名称空间的操作权限

[root@k8s-master ~]# cd /etc/kubernetes/pki/

#生成私钥
[root@k8s-master pki]# (umask 077; openssl genrsa -out lucky.key 2048)
Generating RSA private key, 2048 bit long modulus
......................+++
..........................................................................+++
e is 65537 (0x10001)

#生成证书请求
[root@k8s-master pki]# openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky"

#生成证书
[root@k8s-master pki]# openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650
Signature ok
subject=/CN=lucky
Getting CA Private Key

#备份kubecofig文件
[root@k8s-master pki]# cp /root/.kube/config /root/.kube/config.bak

#在kubeconfig文件中添加用户lucky
#创建一个用户lucky并指定lucky.crt证书及lucky.key,创建之后这个用户lucky就会加入到kubeconfig文件中
[root@k8s-master pki]# kubectl config set-credentials lucky  --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true
User "lucky" set.

#验证kubeconfig文件中的lucky
[root@k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.57.131: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
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED
- name: lucky                                    //用户已添加并指定了证书及key
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

#在kubeconfig文件中添加上下文
[root@k8s-master ~]# kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky
Context "lucky@kubernetes" created.

#验证文件中的上下文
[root@k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.57.131:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
- context:                                       //已添加
    cluster: kubernetes
    user: lucky
  name: lucky@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED
- name: lucky
  user:
    client-certificate-data: DATA+OMITTED
    client-key-data: DATA+OMITTED

#切换账号到lucky,默认没有任何权限
[root@k8s-master ~]# kubectl config use-context lucky@kubernetes
Switched to context "lucky@kubernetes".

#然后kubeconfig文件中的current-context指定的用户就变成了lucky@kubernetes
[root@k8s-master ~]# kubectl config view | grep -i curren
current-context: lucky@kubernetes

#验证权限(切换用户后,只是被api信任,但没有授权所以没有权限无法访问k8s集群)
[root@k8s-master ~]# kubectl get pods 
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"

#切换回去
[root@k8s-master ~]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".

[root@k8s-master ~]# kubectl config view | grep -i curren
current-context: kubernetes-admin@kubernetes

[root@k8s-master ~]# kubectl get ns
NAME              STATUS   AGE
default           Active   114d
kube-node-lease   Active   114d
kube-public       Active   114d
kube-system       Active   114d

#切回之后为lucky用户授权
#在lucky-test名称空间下创建 rolebinding 将lucky用户通过创建lucky-test名称空间下的rolebinding绑定到cluster-admin(clusterrole)上
#lucky绑定到 cluster-admin之后就拥有了对lucky-test名称空间下的权限。
[root@k8s-master ~]# kubectl create ns lucky-test
namespace/lucky-test created

[root@k8s-master ~]# kubectl create rolebinding lucky -n lucky-test --clusterrole=cluster-admin --user=lucky
rolebinding.rbac.authorization.k8s.io/lucky created

#再次切换用户到lucky下,使用kubectl命令时需要指定名称空间,看其他空间没权限
[root@k8s-master ~]# kubectl config use-context lucky@kubernetes
Switched to context "lucky@kubernetes".

[root@k8s-master ~]# kubectl config view | grep -i curren
current-context: lucky@kubernetes

[root@k8s-master ~]# kubectl get pods 
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"

[root@k8s-master ~]# kubectl get pods -n lucky-test
No resources found in lucky-test namespace.

#验证在lucky-test名称空间下创建测试的sa账号
[root@k8s-master ~]# kubectl create sa sa-test -n lucky-test
serviceaccount/sa-test created

[root@k8s-master ~]# kubectl get sa -n lucky-test 
NAME      SECRETS   AGE
default   0         6m50s
sa-test   0         11s

#创建系统普通账户test,使之拥有lucky的权限
#创建普通账户 设置密码
[root@k8s-master ~]# useradd test
[root@k8s-master ~]# echo test:'123456' | chpasswd 

#修改k8s集群中的kubeconfig文件,使文件中只保留lucky账户的信息
[root@k8s-master ~]# mkdir test
[root@k8s-master ~]# cp -ar /root/.kube /root/test/

#进入到拷贝的新文件中修改文件,将kubernetes-admin相关的删除,只留lucky用户
#删除后大概保留内容如下图所示:
[root@k8s-master ~]# vim /root/test/.kube/config

#将修改后的文件连同整个kube目录传到普通用户test的家路径下并修改权限
[root@k8s-master ~]# cp -ar /root/test/.kube  /home/test/
[root@k8s-master ~]# chown -R test:test /home/test/

#切换到test用户上进行访问k8s集群
[root@k8s-master ~]# su - test 
[test@k8s-master ~]$ kubectl get pods 
Error from server (Forbidden): pods is forbidden: User "lucky" cannot list resource "pods" in API group "" in the namespace "default"

[test@k8s-master ~]$ kubectl get pods -n lucky-test
No resources found in lucky-test namespace.

[test@k8s-master ~]$ kubectl get sa -n lucky-test
NAME      SECRETS   AGE
default   0         37m
sa-test   0         30m

#这样系统中的普通用户就能使用k8s集群中只对某一名称空间有操作权限的用户进行使用了。

PS: 关于kubeconfig文件内容详情说明可参考上面标题 1.2

k8s 安全管理:认证、授权、准入控制_k8s_02

2.7.2 限制系统中普通用户查看k8s集群所有名称空间的pod权限

#切换回k8s用户
[root@k8s-master pki]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".

[root@k8s-master ~]# cd /etc/kubernetes/pki/

#生成私钥 lucky01.key
[root@k8s-master pki]# (umask 077; openssl genrsa -out lucky01.key 2048)
Generating RSA private key, 2048 bit long modulus
...................................................................................................................................................................+++
............................+++
e is 65537 (0x10001)

#基于lucky01.key生成证书请求文件lucky01.csr,用户是lucky0002
[root@k8s-master pki]# openssl req -new -key lucky01.key -out lucky01.csr -subj "/CN=lucky0002"

#基于lucky01.csr ca.crt  ca.key生成证书lucky01.crt
[root@k8s-master pki]# openssl x509 -req -in lucky01.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky01.crt -days 3650
Signature ok
subject=/CN=lucky0002
Getting CA Private Key

#在kubeconfig文件中添加用户lucky0002
#创建set-credentials并指定用户lucky0002使用生成的lucky01.crt lucky01.key使该用户被apiserver信任
[root@k8s-master pki]# kubectl config set-credentials lucky0002  --client-certificate=./lucky01.crt --client-key=./lucky01.key --embed-certs=true
User "lucky0002" set.

#在kubeconfig文件中添加用户lucky0002上下文
[root@k8s-master pki]#  kubectl config set-context lucky0002@kubernetes --cluster=kubernetes --user=lucky0002
Context "lucky222@kubernetes" created.

#创建clusterrole 
[root@k8s-master pki]# vi /root/clusterrole.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: lucky0002-pod-01
rules:                 #定义权限,对所有名称空前的pod具有查看权限
- apiGroups: [""]      #所有名称空间  
  resources: ["pods"]  #目标pod
  verbs: ["get", "list", "watch"]  #查看权限


[root@k8s-master pki]# kubectl apply -f /root/clusterrole.yaml 
clusterrole.rbac.authorization.k8s.io/lucky0002-pod-01 created

[root@k8s-master pki]# kubectl get clusterrole | grep 0002
lucky0002-pod-01  

#创建clusterrolebinding并将lucky0002用户通过clusterrolebinding绑定到clusterrole上
#绑定之后已被apiserver信任的lucky0002用户就拥有了clusterrole这个lucky0002-pod-01用户的权限,可以对集群内所有名称空间的pod拥有查看权限
[root@k8s-master pki]# kubectl create clusterrolebinding lucky0002-pod-02 --clusterrole=lucky0002-pod-01 --user=lucky0002
clusterrolebinding.rbac.authorization.k8s.io/lucky0002-pod-02 created

#创建一个普通用户进行切换测试
[root@k8s-master pki]# useradd test001
[root@k8s-master pki]# echo test001:'123456'|chpasswd 

#拷贝kubeconfig配置文件并修改文件中删除所有用户相关信息,只保留lucky0002的信息
[root@k8s-master pki]# mkdir /root/test001
[root@k8s-master pki]# cp -ar /root/.kube/ /root/test001/

#修改文件中删除所有用户相关信息,只保留lucky0002的信息,参考上方图片
[root@k8s-master pki]# vim /root/test001/.kube/config

#还需要修改配置文件的current-context用户
[root@k8s-master pki]# cat /root/test001/.kube/config | grep current
current-context: lucky0002@kubernetes

#拷贝修改好的kubeconfig文件至test001用户的家目录下并赋予权限
[root@k8s-master pki]# cp -ar /root/test001/.kube  /home/test001/
[root@k8s-master pki]# chown -R test001:test001 /home/test001/

#切换到 test001 用户
[root@k8s-master pki]# su - test001

#验证集群名称空间pod查看权限(只能查看pod,查看名称空间或这servic都没有权限)
[test001@k8s-master ~]$ kubectl get ns
Error from server (Forbidden): namespaces is forbidden: User "lucky0002" cannot list resource "namespaces" in API group "" at the cluster scope

[test001@k8s-master ~]$ kubectl get svc
Error from server (Forbidden): services is forbidden: User "lucky0002" cannot list resource "services" in API group "" in the namespace "default"

[test001@k8s-master ~]$ kubectl get pods -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS
kube-system   calico-kube-controllers-6744f6b6d5-2p7nh   1/1     Running   0       
kube-system   calico-node-cjx7d                          1/1     Running   0       
kube-system   calico-node-j4f5g                          1/1     Running   0       
kube-system   calico-node-qtbn6                          1/1     Running   0       
kube-system   coredns-7f8cbcb969-9h9b2                   1/1     Running   0       
kube-system   coredns-7f8cbcb969-wklp5                   1/1     Running   0       
kube-system   etcd-k8s-master                            1/1     Running   0       
kube-system   kube-apiserver-k8s-master                  1/1     Running   0       
kube-system   kube-controller-manager-k8s-master         1/1     Running   0       
kube-system   kube-proxy-2rntj                           1/1     Running   0       
kube-system   kube-proxy-7pphs                           1/1     Running   0       
kube-system   kube-proxy-s2fb6                           1/1     Running   0       
kube-system   kube-scheduler-k8s-master                  1/1     Running   0

三、准入控制

当用户经过了认证和授权之后,最后一步就是准入控制,也就是准入控制器,经过准入控制器之后可以让它做变更和验证,之所以要使用准入控制器是因为,如果创建pod时定义了资源的上下限,但是不满足LimitRange(名称空间的资源上下限),那么LimitRange就会拒绝创建pod。比如名称空间设置了cpu使用是4核,内存是100G,创建pod时定义使用的是cpu5核,120G内存,那么超出了名称空间定义的上下限,pod将无法创建。

3.1 准入控制插件介绍


--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction


在k8s上准入控制器的模块有很多,其中比较常用的有LimitRanger、ResourceQuota、ServiceAccount

如果使用的是kubeadm安装的k8s可以通过/etc/kubernetes/manifests/kube-apiserver.yaml 该文件查看或修改当前k8s使用的准入控制器


如下图所示,当前使用的的是NodeRestriction,如果什么都不写的话,默认启用的是LimitRanger、ResourceQuota、ServiceAccount,当前虽然没有指定这三个插件,但是也默认是开启的。

 

如果定义多个的话可以使用逗号进行分割如下:

--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,ResourceQuota,NodeRestriction

 

修改配置文件之后 需要重启kubelet   (systemctl restart kubelet)

准入控制器官方介绍链接地址

k8s 安全管理:认证、授权、准入控制_Linux_03

3.2 ResourceQuota准入控制器

它是k8s集群中内置的准入控制器,默认是启用状态,主要作用是用来限制一个名称空间下的资源使用,能防止在一个空间下创建的pod过多时,导致过多的占用k8s资源。

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

#创建名称空间
[root@k8s-master ~]# kubectl create ns test
namespace/test created

#创建ResourceQuota资源
[root@k8s-master ~]# vim rq.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: rq-01
  namespace: test
spec:
  hard:
    pods: "4"                      #定义创建pod不能超过4个
    requests.cpu: "2"              #所有Pods请求的CPU总和不能超过2个单位(假设是2核)
    requests.memory: 2Gi           #所有Pods请求的memory总和不能超过2GiB
    limits.cpu: "4"                #所有Pods的CPU限制总和不能超过4个单位
    limits.memory: 10Gi            #所有Pods的memory限制总和不能超过10GiB
    count/deployments.apps: "4"    #定义创建的deploymen资源不能超过4个
    persistentvolumeclaims: "4"    #定义创建的pvc不能超过4个


[root@k8s-master ~]# kubectl apply -f rq.yaml 
resourcequota/rq-01 created

#查看详细配置
[root@k8s-master ~]# kubectl describe  quota -n test
Name:                   rq-01
Namespace:              test
Resource                Used  Hard
--------                ----  ----
count/deployments.apps  0     4
limits.cpu              0     4
limits.memory           0     10Gi
persistentvolumeclaims  0     4
pods                    0     4
requests.cpu            0     2
requests.memory         0     2Gi

#测试在test名称空间下创建超过定义数量的deploymen资源
[root@k8s-master ~]# vim dep.yaml 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: dep
  namespace: test
spec:
  replicas: 5       #创建5个pod
  selector:
    matchLabels:
      a01: b01
  template:
    metadata:
      labels:
         a01: b01
    spec:
      containers:
      - name: mynginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 1
            memory: 1G
          limits:
            cpu: 1
            memory: 1G

[root@k8s-master ~]# kubectl apply -f dep.yaml 
deployment.apps/dep created

#由于限制了请求上限为两个cpu 定义的是创建5个pod,每个pod1个cpu,所以只创建完成了俩个pod
[root@k8s-master ~]# kubectl get deploy -n test
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
dep    2/5     2            2           10s

[root@k8s-master ~]# kubectl get pods -n test 
NAME                   READY   STATUS    RESTARTS   AGE
dep-5454f6b78d-qs7k2   1/1     Running   0          2m11s
dep-5454f6b78d-rjs49   1/1     Running   0          2m11s

PS:定义的规则只要有一个不满足就无法创建完成。

3.2.2 限制存储空间的yaml文件配置方式

[root@k8s-master ~]# vim rq-2.yaml 

apiVersion: v1
kind: ResourceQuota
metadata:
  name: rq-02
  namespace: test
spec:
  hard:
    requests.storage: "5Gi"             #(PVC)请求的存储总量不能超过5GiB
    persistentvolumeclaims: "5"         #在test命名空间中,最多允许存在5个PersistentVolumeClaim对象
    requests.ephemeral-storage: "1Gi"   #所有Pod请求的临时存储(Ephemeral Storage)总量不能超过1GiB
    limits.ephemeral-storage: "2Gi"     #所有Pod设置的临时存储(Ephemeral Storage)限制总量不能超过2GiB
    
    
[root@k8s-master ~]# kubectl apply -f rq-2.yaml 
resourcequota/rq-02 created
    
[root@k8s-master ~]# kubectl describe quota rq-02 -n test
Name:                       rq-02
Namespace:                  test
Resource                    Used  Hard
--------                    ----  ----
limits.ephemeral-storage    0     2Gi
persistentvolumeclaims      0     5
requests.ephemeral-storage  0     1Gi
requests.storage            0     5Gi

3.3 LimitRanger准入控制器

它是k8s集群中内置的准入控制器,是k8s上的一个标准资源,主要用来定义某个名称空间下限制pod或pod里容器对k8s上的cpu和内存的资源使用。

它不仅可以定义pod及pod容器中创建时的使用资源上下限,还能定义默认上下限,默认上下限是指,在创建pod时,如没有定义使用的资源上下限,那么将会使用LimitRanger定义的默认上下限,而不会像ResourceQuota一样在不定义pod的上下限时,无法进行创建pod。它还可以限制单独的一个pod的资源上下限。

#创建名称空间lr
[root@k8s-master ~]# kubectl create ns lr
namespace/lr created

#创建LimitRanger的yaml文件
[root@k8s-master ~]# vim lr.yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: lr-01
  namespace: lr
spec:
  limits:
  - default:          #定义默认限制 cpu 1核 1000兆内存(在创建pod时没有定义限制默认使用改值)
      cpu: 1000m
      memory: 1000Mi
    defaultRequest:   #定义默认限制 cpu 0.5核 500兆内存(在创建pod时没有定义限制默认使用改值)
      cpu: 500m
      memory: 500Mi
    min:              #不能小于0.5核cpu 500兆内存 (创建pod时定义了限制时使用该值)
      cpu: 500m
      memory: 500Mi
    max:              #不能大于2核cpu 2000兆内存  (创建pod时定义了限制时使用该值)
      cpu: 2000m
      memory: 2000Mi
    maxLimitRequestRatio:  #定义资源限制和请求之间的最大比例关系
      cpu: 4               #设置为4,那么容器的CPU上下限制不能超过其CPU请求的4倍,内存上下限制也不能超过其内存请求的4倍
      memory: 4
    type: Container        #限制的容器的层级
    
    
[root@k8s-master ~]# kubectl apply -f lr.yaml 
limitrange/lr-01 created

#创建pod(这里不定义资源限制,那么该pod就会使用LimitRange定义的默认的资源限制)
[root@k8s-master ~]# vim pod-01.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-01
  namespace: lr
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    	
    
[root@k8s-master ~]# kubectl apply -f pod-01.yaml 
pod/pod-01 created

#验证查看使用的资源限制(如上方LimitRange定义的默认的资源限制一致)
[root@k8s-master ~]# kubectl describe pods pod-01 -n lr | grep -A 5 Limits
    Limits:
      cpu:     1
      memory:  1000Mi
    Requests:
      cpu:        500m
      memory:     500Mi

    
#创建第二个pod yaml文件中指定资源使用低于限制看是否能创建
[root@k8s-master ~]# vim pod-02.yaml

apiVersion: v1
kind: Pod
metadata:
  name: pod-02
  namespace: lr
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources:
      requests:
        cpu: 100m    #指定使用cpu 100豪核(定义的最小要使用500豪核)
        
        
#创建失败
[root@k8s-master ~]# kubectl apply -f pod-02.yaml 
Error from server (Forbidden): error when creating "pod-02.yaml": pods "pod-02" 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]

#修改为范围内的使用资源  (定义的范围内的cpu: 500m -- 2000m)
[root@k8s-master ~]# cat pod-02.yaml | grep cpu
        cpu: 1000m 

#再次创建(创建成功)
[root@k8s-master ~]# kubectl apply -f pod-02.yaml 
pod/pod-02 created

[root@k8s-master ~]# kubectl describe pod pod-02 -n lr | grep -A 5 Limits
    Limits:
      cpu:     1
      memory:  1000Mi      //指定的是1000m  其他未指定的还是使用的默认的。
    Requests:
      cpu:        1
      memory:     500Mi