接着上一个K8s认证的笔记:https://blog.csdn.net/tushanpeipei/article/details/121877797?spm=1001.2014.3001.5501

在这里插入图片描述
上一笔记中涵盖了K8s认证的相关操作,但是我们也能看到,无论我们使用token或者kubeconfig文件认证成功后,都没有K8s操作的权限。所以,我们需要对于对应的用户进行授权操作,保证他们能够完成权限内的操作。

本章节中将对于授权行实验,准入控制将在后续的笔记中涉及到。

一、授权方式

  1. AlwaysAllow:允许所有请求(无论管理的用户是否被赋予对应的权限);
  2. AlwaysDeny:拒绝所有请求(即使用户被赋予了对应的权限,也无法进行任何操作),对本身的管理员无效;
  3. ABAC:Attribute-Based Access Control 不够灵活放弃(基于属性的控制,非常不灵活,基本已经被放弃,本笔记不涉及);
    5.RBAC:Role Based Access Control 基于角色的访问控制(最推荐);
  4. Node:Node授权器主要用于各个worker node上的kubelet访问apiserver时使用的,其他一般均由RBAC授权器来授权;
  5. Webhook。 部署webhook后端服务器,可以与K8s通过http传输数据。这样的话能够在webhook服务器中更加精确的做授权操作。(在后面的比较中会专门涉及到)

授权方式可以在/etc/kubernetes/manifests/kube-apiserver.yaml文件下进行查看和更改。默认在此文件下的command中设置了:

–authorization-mode=Node,RBAC

也就是启用了RBAC和Node的授权。下面我们来详细看看RBAC和Node授权是怎么实现的。

二、RBAC授权

1.RBAC基础
在这里插入图片描述
create、delete、list、watch等权限(具体可以使用命令 kubectl describe clusterrole admin查看资源类型和管理员的权限,也就是所有的权限)是绑定在一个role上,而不同的用户想要获取到这些权限,则需要与对应的role进行绑定。

注意,role和role building是基于Namespace的,当用户通过role binding绑定了这个role,则仅仅能在role所在的Namespace中获取对应的权限,如果在另外一个Namespace中,则没有权限。

如果想要在不同的命名空间中调用同一个role。这时,我们可以将role修改为cluster role。cluster role是全局的,可以通过绑定多个命名空间的role binding实现用户在多个命名空间内都有该cluster role的权限。

如果想直接赋予某个用户所有Namespace都具有相同的权限,可以使用cluster role和 cluster role building来实现。所以,RBAC的实现方式有如下三种:

  1. role --> role building <— K8s user
  2. cluster role --> 多个role building <— K8s user
  3. cluster role --> cluster role building <— K8s user

2.测试1,使用role和role building测试

目标:让testuser拥有default命名空间内对于pod的create、delete、list的权限。目前所在的Namespace为default,后续创建的role和role building都存在于当前的Namespace中。

首先在master上创建一个role的yaml文件(易于后续修改),然后再通过次yaml文件创建对应的role1。

root@vms71:~/authority# kubectl create role role1 --verb=get,delete,list --resource=pod --dry-run=client -o yaml > role1.yaml                            
root@vms71:~/authority# cat role1.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: role1
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - delete
  - list
root@vms71:~/authority# kubectl apply -f role1.yaml
role.rbac.authorization.k8s.io/role1.yaml created
root@vms71:~/authentication# kubectl describe role role1
Name:         role1.yaml
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get delete list]

使用rolebinding连接role1和testuser:

root@vms71:~/authority# kubectl create rolebinding rbind1 --role=role1 --user=testuser
rolebinding.rbac.authorization.k8s.io/rbind1 created

然后再使用testuser的kc1文件进行登陆验证:

root@vms71:~/authority# kubectl get pods -n default --kubeconfig=../authentication/kc1
NAME       READY   STATUS    RESTARTS        AGE
pod1       1/1     Running   3 (5h56m ago)   2d3h
pod2       1/1     Running   3 (5h56m ago)   2d3h
testpod1   1/1     Running   3 (5h56m ago)   2d1h
root@vms71:~/authority# kubectl get pods -n kube-system --kubeconfig=../authentication/kc1
Error from server (Forbidden): pods is forbidden: User "testuser" cannot list resource "pods" in API group "" in the namespace "kube-system"

可以看到,当我们查看default中的pods时,则可以查看到信息;然后,当查看-n kube-system时则权限不够。同样的,由于我们只赋予了testuser对于pods操作的相关信息,如果想要对deployments、service资源操作,一样会被拒绝:

root@vms71:~/authority# kubectl get deployments -n default --kubeconfig=../authentication/kc1
Error from server (Forbidden): deployments.apps is forbidden: User "testuser" cannot list resource "deployments" in API group "apps" in the namespace "default"
root@vms71:~/authority# kubectl get svc -n default --kubeconfig=../authentication/kc1
Error from server (Forbidden): services is forbidden: User "testuser" cannot list resource "services" in API group "" in the namespace "default"

修改并应用role1的yaml文件,增加对应于services和deployments操作的权限。

root@vms71:~/authority#  cat role1.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: role1
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - services
  verbs:
  - get
  - delete
  - list
- apiGroups:
  - "apps"
  resources:
  - deployments
  verbs:
  - get
  - delete
  - list

注意,deployments与 pods和services需要分开写。这是因为pods、services的apiversion=v1,所以父级apiGroups为空。而deployments的apiversion=apps/v1,所以父级apiGroups为apps。

更改role之后,再对deployments、service资源操作时,则可以实现:

root@vms71:~/authority# kubectl get deployments -n default --kubeconfig=../authentication/kc1
No resources found in default namespace.
root@vms71:~/authority# kubectl get svc -n default --kubeconfig=../authentication/kc1
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
kubernetes   ClusterIP      10.96.0.1       <none>           443/TCP        12d
svc1         LoadBalancer   10.103.222.93   192.168.26.240   80:31604/TCP   44h
svc2         LoadBalancer   10.98.110.109   192.168.26.241   80:31459/TCP   44h

2.测试2,使用cluster role和role building测试

在删除第一步测试的role和role building后,创建一个cluster role,同样是对pods有list、get、delete权限。

root@vms71:~/authority# kubectl create clusterrole clusterrole1 --verb=get,delete,list --resource=pod --dry-run=client -o yaml > clusterrole1.yaml
root@vms71:~/authority# kubectl apply -f clusterrole1.yaml
clusterrole.rbac.authorization.k8s.io/clusterrole1 created

分别在default和kube-system这两个Namespace中创建role building,绑定k8s用户testuser:

root@vms71:~/authority# kubectl create rolebinding rbind1 --clusterrole=clusterrole1--user=testuser
root@vms71:~/authority# kubens kube-system
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "kube-system".
root@vms71:~/authority#  kubectl create rolebinding rbind2 --clusterrole=clusterrole1--user=testuser

然后继续在master上使用testuser查看default和kube-system下的pod信息,发现可以正常查看:

root@vms71:~/authority# kubectl get pods -n kube-system --kubeconfig=../authentication/kc1
NAME                                       READY   STATUS    RESTARTS       AGE
calico-kube-controllers-78d6f96c7b-pdf9d   1/1     Running   7 (8h ago)     12d
calico-node-g52b9                          1/1     Running   6 (8h ago)     12d
calico-node-j6wgm                          1/1     Running   5 (8h ago)     12d
calico-node-pmn6t                          1/1     Running   5 (8h ago)     12d
coredns-7f6cbbb7b8-cl4nw                   1/1     Running   5 (8h ago)     12d
coredns-7f6cbbb7b8-pvnw6                   1/1     Running   5 (8h ago)     12d
etcd-vms71.rhce.cc                         1/1     Running   6 (8h ago)     12d
kube-apiserver-vms71.rhce.cc               1/1     Running   1 (8h ago)     9h
kube-controller-manager-vms71.rhce.cc      1/1     Running   13 (48m ago)   12d
kube-proxy-476jg                           1/1     Running   5 (8h ago)     12d
kube-proxy-l8jhq                           1/1     Running   6 (8h ago)     12d
kube-proxy-v6cdb                           1/1     Running   5 (8h ago)     12d
kube-scheduler-vms71.rhce.cc               1/1     Running   14 (48m ago)   12d
root@vms71:~/authority# kubectl get pods -n default --kubeconfig=../authentication/kc1
NAME       READY   STATUS    RESTARTS     AGE
pod1       1/1     Running   3 (8h ago)   2d6h
pod2       1/1     Running   3 (8h ago)   2d6h
testpod1   1/1     Running   3 (8h ago)   2d3h

3.测试3,使用cluster role和clusterrolebinding测试
删除掉rbind1和rbind2,重新创建clusterrolebind:

root@vms71:~/authority# kubectl create clusterrolebinding crbind1 --clusterrole=clusterrole1 --user=testuser
clusterrolebinding.rbac.authorization.k8s.io/crbind1 created

目前,使用testuser可以在任意的Namespace中查看pod的信息:

root@vms71:~/authority# kubectl get pods --kubeconfig=../authentication/kc1 -n cert-manager
NAME                                       READY   STATUS    RESTARTS       AGE
cert-manager-7c6f78c46d-gdc5k              1/1     Running   5 (8h ago)     11d
cert-manager-cainjector-668d9c86df-k4jnk   1/1     Running   19 (55m ago)   11d
cert-manager-webhook-764b556954-c64tk      1/1     Running   5 (8h ago)     11d
root@vms71:~/authority# kubectl get pods --kubeconfig=../authentication/kc1 -n testns
NAME       READY   STATUS    RESTARTS     AGE
testpod2   1/1     Running   3 (8h ago)   2d3h
root@vms71:~/authority# kubectl get pods --kubeconfig=../authentication/kc1 -n kube-system
NAME                                       READY   STATUS    RESTARTS       AGE
calico-kube-controllers-78d6f96c7b-pdf9d   1/1     Running   7 (8h ago)     12d
calico-node-g52b9                          1/1     Running   6 (8h ago)     12d
calico-node-j6wgm                          1/1     Running   5 (8h ago)     12d
calico-node-pmn6t                          1/1     Running   5 (8h ago)     12d
coredns-7f6cbbb7b8-cl4nw                   1/1     Running   5 (8h ago)     12d
coredns-7f6cbbb7b8-pvnw6                   1/1     Running   5 (8h ago)     12d
etcd-vms71.rhce.cc                         1/1     Running   6 (8h ago)     12d
kube-apiserver-vms71.rhce.cc               1/1     Running   1 (8h ago)     9h
kube-controller-manager-vms71.rhce.cc      1/1     Running   13 (56m ago)   12d
kube-proxy-476jg                           1/1     Running   5 (8h ago)     12d
kube-proxy-l8jhq                           1/1     Running   6 (8h ago)     12d
kube-proxy-v6cdb                           1/1     Running   5 (8h ago)     12d
kube-scheduler-vms71.rhce.cc               1/1     Running   14 (56m ago)   12d

三、对SA授权

RBAC分为2种账户:

  1. user account 用户账号(UA):用于远程登陆系统,也就是我们在刚刚实验所使用的账号
  2. service account 服务账户(SA):Service account是为了方便Pod里面的进程(而非人工)调用Kubernetes API或其他外部服务而设计的。例如使用web来管理k8s环境时,需要调用相关的程序(pod中)有对K8s管理,当时此程序需要有相关的权限,这时候就可以创建一个SA,赋予相关的权限,并且与管理K8s的环境程序进行绑定,那么这个程序就有了SA的对应权限,可以对K8s进行管理。

首先我们需要创建一个SA:

root@vms71:~/authority# kubectl create sa sa1
serviceaccount/sa1 created

每创建一个sa,就会创建一个secret,名称为sa名-token-xxxx。而每个secret中有一个token:

root@vms71:~/authority# kubectl get secrets | grep sa1
sa1-token-pnrmf       kubernetes.io/service-account-token   3      39s
root@vms71:~/authority# kubectl describe secrets sa1-token-pnrmf
Name:         sa1-token-pnrmf
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: sa1
              kubernetes.io/service-account.uid: bb4b5b84-5499-4c37-98b8-52bfc3ed6ca3

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1099 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IkhEUXVaUEVObi1ubmZxV1NFTk5PdUMwZThubHZPZDZXUEtJWmJMOXFGN1kifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNhMS10b2tlbi1wbnJtZiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJzYTEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJiYjRiNWI4NC01NDk5LTRjMzctOThiOC01MmJmYzNlZDZjYTMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpzYTEifQ.AT5MEmvjYU-I48JES63U8xG2Gs3zSFNSxdQQGAa5Ny6f_sm_rBZFdiV3ghK7E2r6ANRG43U4dJikfL3PATGugXNP7AslTw6LPDR6E001j8P3GXv1MDDfD5QglaOsbyqGglPwB_adRJbiqycrsGozyepCdspuJfcRnbNjP9zat6EkAaXsrUZ9Bk4IyoOWtTAKG2P6vG4ol36sObaOJMmW-4qlYphmrO-1ZNb0coz_y050J4bO3Y-LGqZwCDxCO4YGROwiecjbJoEPJbC0r1W7P-qHRP9_p7KYYg8lf98VBJQM28y-4ejMz2RZ2q5Zz9Y5sRBCAZ6lVf9GYVocyflIhg

当我们给SA授权时,其实也就是在跟其token授权。当我们创建pod时,绑定授权了的SA,其实也就是把token挂在了pod里面的/run/secrets/kubernetes.io/serviceaccount目录里面,也就有了对应token的权限。

给SA授权的语法如下:

kubectl create clusterrolebinding(绑定方式) sabind1(绑定名) --clusterrole=cluster-admin(角色名) --serviceaccount=security:sa1(命名空间:sa名)

例如我们在这里授权cluster-admin(K8s自带,拥有所有权限)的权限给sa1:

root@vms71:~/authority# kubectl create clusterrolebinding sabind1 --clusterrole=cluster-admin --serviceaccount=default:sa1
clusterrolebinding.rbac.authorization.k8s.io/sabind1 created

注意,如果一个pod没有手动添加SA,则默认使用的是default这个SA。当然也就是挂在了default sa的token。

root@vms71:~/authority# kubectl get sa
NAME      SECRETS   AGE
default   1         12d
sa1       1         13m

现在,我们来创建一个pod,并且使用sa1作为SA。yaml文件如下:

root@vms71:~/authority# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: podsa
  name: podsa
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: podsa
    resources: {}
  serviceAccount: sa1
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

进入podsa后,查看/run/secrets/kubernetes.io/serviceaccount目录:

root@podsa:/# root@podsa:/# ls /run/secrets/kubernetes.io/serviceaccount
ca.crt  namespace  token

其中,ca.crt为集群ca的证书;namespace记录了pod所在的Namespace;token则是sa1对应的token值。

root@podsa:/run/secrets/kubernetes.io/serviceaccount# cat token
eyJhbGciOiJSUzI1NiIsImtpZCI6IkhEUXVaUEVObi1ubmZxV1NFTk5PdUMwZThubHZPZDZXUEtJWmJ                                                                               MOXFGN1kifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9                                                                               jYWwiXSwiZXhwIjoxNjcwODc5NzI1LCJpYXQiOjE2MzkzNDM3MjUsImlzcyI6Imh0dHBzOi8va3ViZX                                                                               JuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY                                                                               2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJwb2RzYSIsInVpZCI6ImMzZTRkOTM5LWUyODctNDUy                                                                               ZS05MTU5LWU3Y2Y3ZDUyOTNmNCJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoic2ExIiwidWlkIjo                                                                               iYmI0YjViODQtNTQ5OS00YzM3LTk4YjgtNTJiZmMzZWQ2Y2EzIn0sIndhcm5hZnRlciI6MTYzOTM0Nz                                                                               MzMn0sIm5iZiI6MTYzOTM0MzcyNSwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6c                                                                               2ExIn0.3n9Ke1WPqPB2X-q-90ZmgnMn4OPyoJ9Vz5-CrOeNw74V-HkAtfRTyhTqOrgPeK8iXe9frQ9J                                                                               8d2-62BYD1o9WVGbnrnooNlg5hI8ALz-1LRxhsIVDgY5h_VBR0RLcoM6vW2_0VcT9XU8QGDfogCPub9                                                                               Vly_dC8hzyr-p--s_EmBbOnmqdOIVvm-nGU9w_3KpYP_l9IkpRT6XRzeWiwmOzEW2Wx0VAd-x3D0E-c                                                                               23us1GJaQG46rLdqAHpqa4V4gMdem6DmDLPmNOMHOOjYQ-x4RkJtTxDA2CCgAX2WT33wCqRBzP9r9oF                                                                               h1H-5ZPXKtbk4zyqa7UeFJ8Cc7STxI5Fg

接下来,我们在pod内对访问k8s的资源,首先先设置几个环境变量:

root@podsa:/run/secrets/kubernetes.io/serviceaccount# CA_CERT=ca.crt
root@podsa:/run/secrets/kubernetes.io/serviceaccount# TOKEN=$(cat token)
root@podsa:/run/secrets/kubernetes.io/serviceaccount# NAMESPACE=$(cat namespace)    

使用如下命令访问k8s资源,查看是否能够访问成功:

curl --cacert $CA_CERT -H "Authorization: Bearer $TOKEN" "https://kubernetes.default/api/v1/namespaces/$NAMESPACE/services/"

curl --cacert $CA_CERT -H "Authorization: Bearer $TOKN" "https://192.168.26.71:6443/api/v1/namespaces/$NAMESPACE/services/"

由于本次实验中使用的是cluster-admin这个角色的权限,所以可以访问成功。也可以在master上直接使用如下命令进行测试:

root@vms71:~/authority# kubectl --as=system:serviceaccount:default:sa1 auth can-i get svc
yes

此命令使用了sa1这个账号验证师傅能够获取svc信息,返回的结果是yes。

需要注意的是,在实际环境中,我们不能给一个pod如此大的权限的SA,如果pod中存在恶意代码,又拥有对应的操作权限,会危及到我们整个K8s集群环境。同时如果没有什么特别的操作,可以不用在pod中挂载SA。有两个实现方式:

  1. 在创建pod时,在spec下设置automountServiceAccountToken值为false,这个值默认为ture。
  2. 在创建SAt时,在在外层添加automountServiceAccountToken值为false。

设置了如上两个方式的任何一个方式,就算是在pod中挂载了

四、Node认证方式

Node权限是Worker向Master的API发送各种查询请求(例如在Worker上使用kubelet)所需要的权限。
在这里插入图片描述
想要启用Node授权,先要在/etc/kubernetes/manifests/kube-apiserver.yaml中的command下设置如同两条语句。启用认证模式为Node,并开启准入控制器。

   - --authorization-mode=Node
   - --enable-admission-plugins=NodeRestriction

整理资料来源:
《老段CKS课程》

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐