写点什么

k8s- 权限管理

作者:EquatorCoco
  • 2024-02-21
    福建
  • 本文字数:10102 字

    阅读完需:约 33 分钟

1. 身份认证


我们在目前的 k8s 集群环境里面,只能在 master 节点上执行 kubectl 的一些命令,在其他节点上执行就会报错


# 看一下是不是[root@node1 ~]# kubectl get nodesE0220 12:50:15.695133    6091 memcache.go:238] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refusedE0220 12:50:15.695771    6091 memcache.go:238] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refusedE0220 12:50:15.697555    6091 memcache.go:238] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refusedE0220 12:50:15.699191    6091 memcache.go:238] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refusedE0220 12:50:15.700655    6091 memcache.go:238] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refusedThe connection to the server localhost:8080 was refused - did you specify the right host or port?
复制代码


我们可以看到在 node1 上执行 kubectl get nodes 都会报错,那就更不谈创建 pod 之类的操作了,那为什么 master 可以而其他节点不行呢?这是因为在 master 节点上是有一个 kubeconfig 的


[root@master ~]# env |grep -i kubeconfigKUBECONFIG=/etc/kubernetes/admin.conf
复制代码


我们可以看到在 master 节点上是有一个环境变量加载了这个 admin.conf 这个文件的,这个文件就是 k8s 集群默认的管理员文件,换一种说法,只要你有本事偷走这个文件并且保障你的网络跟这个集群的网络是通的,那么恭喜你,得到了一个 k8s 集群


node 节点操作


我们现在来将这个 admin.conf 传到 node1 上,再来看看 node1 能不能去执行命令


# 传文件[root@master ~]# scp /etc/kubernetes/admin.conf node1:~admin.conf                                                                    100% 5669     6.2MB/s   00:00  # 在node1上执行命令看看效果[root@node1 ~]# kubectl get node --kubeconfig=admin.confNAME     STATUS   ROLES                  AGE   VERSIONmaster   Ready    control-plane,master   43d   v1.26.0node1    Ready    node1                  43d   v1.26.0node2    Ready    node2                  43d   v1.26.0
复制代码


我们通过这个小实验看到,node1 节点确实是可以获取到节点信息了,但是他执行的命令跟 master 上有所不同,在 node1 上执行的时候他是需要执行配置文件的,如果你不想执行的话可以将这个注册到环境变量里面


[root@node1 ~]# echo "export KUBECONFIG=/root/admin.conf" >> /etc/profile[root@node1 ~]# tail -1 /etc/profileexport KUBECONFIG=/root/admin.conf
复制代码


只需要这样就好了


但是这样存在一个问题,他们用的都是管理员的配置文件,那么就相当于他们都是管理员,对集群有全部权限,我们追求是的最小权限原则,就是我给你的权限正好能够让你完成属于你自己的任务,多的权限不应该有,那么我们能不能像 Linux 一样创建普通用户,给普通用户定制权限呢?当然是可以的


创建普通用户并授权


我们现在来创建一个普通用户 zhangsan 并授权


1. 生成私钥


# 使用openssl生成一个rsa类型的私钥,私钥文件名是client.key 2048位[root@master ca]# openssl genrsa -out client.key 2048Generating RSA private key, 2048 bit long modulus (2 primes)........................+++++...............................................................................................................................................................................................................................................+++++e is 65537 (0x010001)[root@master ca]# lsclient.key
复制代码


2. 生成 zhangsan 用户证书请求文件


# 使用client.key 生成一个新的文件叫做client.csr[root@master ca]# openssl req -new -key client.key -subj "/CN=zhangsan" -out client.csr[root@master ca]# lsclient.csr  client.key
复制代码


3. 为 zhangsan 用户颁发证书


zhangsan 用户如何将请求发送给 k8s 的 ca 进行证书颁发呢?这个时候我们可以使用 k8s 自带的 ca 来颁发证书


# k8s的ca在/etc/kubernetes/pki下[root@master ca]# openssl x509 -req -in client.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out client.crt -days 3650Signature oksubject=CN = zhangsanGetting CA Private Key# 拷贝ca到当前目录[root@master ca]# cp /etc/kubernetes/pki/ca.crt .[root@master ca]# lsca.crt  client.crt  client.csr  client.key
复制代码


4. 创建命名空间及 pod


[root@master ca]# kubectl create ns zhangsannamespace/zhangsan created# 切到这个命名空间[root@master ca]# kubectl config set-context --current --namespace zhangsanContext "kubernetes-admin@kubernetes" modified.# 创建一个pod[root@master ca]# kubectl run test01 --image nginx --image-pull-policy IfNotPresentpod/test01 created[root@master ca]# kubectl get podsNAME     READY   STATUS    RESTARTS   AGEtest01   1/1     Running   0          13s
复制代码


5. 创建角色

角色是什么呢?我们可以这样想,假如我们现在有增删改查 4 个权限,用户用张三,李四,王五,那我们现在给他们授权的话只能是一个权限一个权限的去给,万一后面又新增了用户我们依旧是一个个去指定,过于麻烦,而角色就是介于权限与用户之间的一个模板,就像这样我们指定了一个角色是管理员,拥有增删改查 4 个权限一个是开发的角色,拥有增改查的权限一个是普通用户角色,只有查的权限我们指定好这 3 个模板之后,后面新来的用户只需要知道他的作用是什么,比如他就是一个普通用户,那我们直接把这个模板给他套上,那他就只有查的权限,来了一个开发者,那我们就给他开发的这个角色模板,他就自然而然的拥有增改查的权限

# 这里的pod-reader是role的名字 后面的--verb就是这个角色所包含哪些权限,并且这个角色所能操作的资源对象仅仅只有pod[root@master ca]# kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=podsrole.rbac.authorization.k8s.io/pod-reader created
复制代码

6. 绑定角色给用户


# 创建一个rolebinding名字叫zhangsan,这个zhangsan并不是用户张三,而是这个rolebinding的名字,后面--user这个才是用户张三[root@master ca]# kubectl create rolebinding zhangsan --role pod-reader --user zhangsanrolebinding.rbac.authorization.k8s.io/zhangsan created[root@master ca]# kubectl get rolebindings.rbac.authorization.k8s.io NAME       ROLE              AGEzhangsan   Role/pod-reader   4s
复制代码


7. 编辑 kubeconfig 文件


关于这个文件的框架,我们可以到官网去找到


地址 https://kubernetes.io/zh-cn/docs/concepts/configuration/organize-cluster-access-kubeconfig/在官网找到之后我们只需要做一些修改就行,改成这样就可以,直接复制这个去改也行


apiVersion: v1kind: Config
clusters:- cluster: name: cluster-zs
users:- name: zhangsan
contexts:- context: name: context-zs namespace: zhangsancurrent-context: "context-zs"
复制代码


这个文件就写好了,但是目前来看他与管理员的那个 admin.conf 好像不一样,那个文件里面内容很多,这个很少这是因为我们还没有将刚刚创建出来的那些密钥文件嵌入进去


8. 嵌入密钥文件


# 1. 嵌入ca文件# set-cluster与刚刚文件里的一样就好了 server地址就是master的ip加上6443端口 [root@master ca]# kubectl config --kubeconfig=kube-zhangsan set-cluster cluster-zs --server=https://192.168.200.200:6443 --certificate-authority=ca.crt --embed-certs=trueCluster "cluster-zs" set.# 2. 嵌入client[root@master ca]# kubectl config --kubeconfig=kube-zhangsan set-credentials zhangsan --client-certificate=client.crt --client-key=client.key --embed-certs=trueUser "zhangsan" set.# 3. 设置上下文信息[root@master ca]# kubectl config --kubeconfig=kube-zhangsan set-context context-zs --cluster=cluster-zs --namespace=zhangsan --user=zhangsanContext "context-zs" modified.
复制代码


这 3 个操作搞定之后,你再去看看这个文件,你会发现他跟 admin.conf 是一样一样的了


9. 验证权限


这个文件我们就算搞定了,我们来看看使用这个文件所拥有的权限是否是与我们预期的一样


[root@node1 ~]# kubectl get pods --kubeconfig=kube-zhangsanNAME     READY   STATUS    RESTARTS   AGEtest01   1/1     Running   0          9m# 可以看到pod,我们尝试一下能否创建pod[root@node1 ~]# kubectl run test02 --image nginx --kubeconfig=kube-zhangsanError from server (Forbidden): pods is forbidden: User "zhangsan" cannot create resource "pods" in API group "" in the namespace "zhangsan"# 我们看报错信息,用户zhangsan是不能创建的,我们来看看除了pod之外的其他资源是否可见[root@node1 ~]# kubectl get ns --kubeconfig=kube-zhangsanError from server (Forbidden): namespaces is forbidden: User "zhangsan" cannot list resource "namespaces" in API group "" at the cluster scope
复制代码


现在这个文件符合我们预期的权限,那么这就是创建一个用户并授权的过程


静态 token 登录


这个方法用人话来讲就是,账号密码登录静态的方式就是创建一个 csv 文件,csv 文件的格式是 token,user,idtoken 这一栏我们可以使用 openssl 生成


1. 生成 token


# 注意文件位置,最好放在/etc/kubernetes/pki下,因为k8s默认只对/etc/kubernetes这个目录有权限操作,放在其他位置可能会产生权限错误[root@master pki]# openssl rand -hex 10 > jerry.csv[root@master pki]# cat jerry.csv# 这里的用户名和id可以自己改动3127c2e2b863d4c23878a,jerry,2000
复制代码


在 apiserver 加入参数


# 默认情况下你刚刚写的文件与集群是没有任何关联的,如果想要产生作用需要在kube-apiserver文件加入参数[root@master manifests]# vim /etc/kubernetes/manifests/kube-apiserver.yamlspec:  containers:  - command:    - kube-apiserver# 在这里加上 --token-auth-file后面就是你刚刚的那个文件    - --token-auth-file=/etc/kubernetes/pki/jerry.csv    - --advertise-address=192.168.200.200    - --allow-privileged=true# 然后重启kubelet[root@master pki]# systemctl restart kubelet
复制代码


2. 尝试登录集群


[root@node1 pki]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a" get pod -n defaultUnable to connect to the server: x509: certificate signed by unknown authority
复制代码


他会有一个报错,但是我们现在没有使用 x509 的证书啊,所以我们需要让他跳过安全认证

3. 带上参数再次尝试


[root@node1 pki]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a" get pod  --insecure-skip-tls-verify=true -n zhangsanError from server (Forbidden): pods is forbidden: User "jerry" cannot list resource "pods" in API group "" in the namespace "zhangsan"
复制代码


现在我们再来看,他报的错是不是跟刚刚不一样了,这个报错说的是 jerry 这个用户没有权限能看到这个其实就说明我们已经可以登录了,只是没有权限看到一些信息罢了


2. 角色授权


上面我们提到了用户的登录,提到了一点点授权,现在开始聊授权的那些事默认情况下 k8s 采用的是 Node 和 RBAC 的鉴权模式 RBAC 就是基于角色的访问控制 R 就是 role 嘛我们可以在 kube-apiserver 文件里面看到


spec:  containers:  - command:    - kube-apiserver    - --token-auth-file=/etc/kubernetes/pki/jerry.csv    - --advertise-address=192.168.200.200    - --allow-privileged=true# 就是这一行    - --authorization-mode=Node,RBAC
复制代码


刚刚我们不是使用 jerry 用户登录但是没有任何权限吗?我们现在将这一行参数改掉


# 将之前的注释掉,然后写一行新的   # - --authorization-mode=Node,RBAC# 这个是总是允许,不会鉴权,你能登录就有权限,这个模式仅用于测试    - --authorization-mode=AlwaysAllow# 重启kubelet[root@master manifests]# systemctl restart kubelet
复制代码


然后我们来到 node 节点再尝试一下 jerry 用户


[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a" get pod  --insecure-skip-tls-verify=true -n zhangsanNAME     READY   STATUS    RESTARTS   AGEtest01   1/1     Running   0          56m
复制代码


我们发现他确实有权限查看了,好了但是我们的重点并不是这个,我们将他改回来


role 与 rolebinding


是通过命名空间来授权的,你在哪个命名空间创建的角色,那么这个角色只有这个命名空间下的权限 rolebinding 就是将角色与用户进行绑定


1. 创建角色


刚刚我们不是有一个 Jerry 用户可以登录集群,但是没有任何权限吗?那我们现在来授权


# 不知道参数是怎么来的可以使用kubectl create role --help 里面有示例[root@master role]# kubectl create role jerry --verb=get --verb=list --verb=watch --resource=pods --dry-run=client -o yaml > jerry.yaml[root@master role]# kubectl apply -f jerry.yaml role.rbac.authorization.k8s.io/jerry created[root@master role]# kubectl get roleNAME         CREATED ATjerry        2024-02-20T09:31:35Zpod-reader   2024-02-20T05:23:30Z
复制代码


我们现在有 2 个 role 一个是之前的,一个 jerry 就是刚刚我们创建出来的现在我们角色有了,但是 jerry 用户依旧是查不到任何信息的,因为我们没有对他进行绑定


2. rolebinding


# 注意一个坑,当这个用户是token登录的时候必须指定他的token,老版本不会有这个问题,新版本不指定的话依然是没有权限的,注意一下[root@master role]#  kubectl create rolebinding jerry --role=jerry --user=jerry --token="3127c2e2b863d4c23878a" --dry-run=client -o yaml > rolebinding.yaml[root@master role]# kubectl apply -f rolebinding.yaml rolebinding.rbac.authorization.k8s.io/jerry created[root@master role]# kubectl get rolebindings.rbac.authorization.k8s.io NAME       ROLE              AGEjerry      Role/jerry        5szhangsan   Role/pod-reader   4h3m
复制代码


这里的每一步操作都应该能看懂吧,然后我们回到 node 节点上使用 jerry 来查一下 zhangsan 命名空间下的 pod


3. 验证权限


[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a" get pod  --insecure-skip-tls-verify=true -n zhangsanNAME     READY   STATUS    RESTARTS   AGEtest01   1/1     Running   0          4h24m
复制代码


我们可以看到,他现在就可以看到 pod 的信息了,但是我们在指定权限的时候是没有给他创建的权限的,那么他肯定不能创建 pod,但是我们现在想要他可以创建 pod 怎么办呢?也是很简单,只需要给角色加上一个权限就可以了


4. 修改权限


修改权限我们只需要修改 jerry.yaml


apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  creationTimestamp: null  name: jerryrules:- apiGroups:  - ""  resources:  - pods  verbs:  - get  - list  - watch# 加上这个他就可以创建pod了,如果加上delete那么他就可以删除  - create
复制代码


然后我们再 apply 这个文件


[root@master role]# kubectl apply -f jerry.yaml role.rbac.authorization.k8s.io/jerry configured
复制代码


5. 验证是否成功增加权限


[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a"   --insecure-skip-tls-verify=true -n zhangsan run test02 --image nginxpod/test02 created
复制代码


我们可以看到 pod 被创建出来了,说明刚刚的权限已经增加上了这里我们仅仅只是针对 pod 的操作,如果我要创建一个 deployment 控制器呢?上操作


6. deploymentde 的操作


我们仔细观察一下 jerry.yaml 这个文件,发现里面有一行写的是 pods,那我们是不是直接在这里加上 deployments 就好了呢?我们来试试


# 修改yaml文件apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  creationTimestamp: null  name: jerryrules:- apiGroups:  - ""  resources:  - pods  - deployments  verbs:  - get  - list  - watch  - create
复制代码


然后我们 apply 这个文件


[root@master role]# kubectl apply -f jerry.yaml role.rbac.authorization.k8s.io/jerry configured
复制代码


我们来看看是不是能够创建 deployment 了


[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a"   --insecure-skip-tls-verify=true -n zhangsan create deployment test03 --image nginxerror: failed to create deployment: deployments.apps is forbidden: User "jerry" cannot create resource "deployments" in API group "apps" in the namespace "zhangsan"
复制代码


喔嚯,报错了,我们不是加上了 deployment 吗?这其实是因为我们还需要给他指定 apiGroup,光指定资源是不行的,能创建 pod 是因为 pod 他的 apiVersion 就是 v1,而 deployment 的 apiVersion 是 apps/v1 所以他会报错,那我们再来修改一下文件


apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  creationTimestamp: null  name: jerryrules:- apiGroups:  - ""# 加上这个,如果你想要创建其他的资源,那么你也要在这里写上# 查询apiVersion很简单,你可以使用kubectl create xxx --dry-run 的方式,也可以直接 kubectl api-version去查,查到之后填到这里  - "apps"  resources:  - pods  - deployments  verbs:  - get  - list  - watch  - create
复制代码


然后我们 apply 之后再来创建


[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a"   --insecure-skip-tls-verify=true -n zhangsan create deployment test03 --image nginxdeployment.apps/test03 created
复制代码


我们现在是可以创建 deployment 了,那我们想更新他的副本数量也是可以的嘛?来看看


[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a"   --insecure-skip-tls-verify=true -n zhangsan scale deployment test03 --replicas 3Error from server (Forbidden): deployments.apps "test03" is forbidden: User "jerry" cannot patch resource "deployments/scale" in API group "apps" in the namespace "zhangsan"
复制代码


他又报错了,他说不能 patch,那我们在 verb 里面加上个试试看呢,等一下,注意看完报错,他说 resource 里面是 deployments/scale 我们好像也没有给他这个资源,一并加上最终的 yaml 文件是这样的


apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  creationTimestamp: null  name: jerryrules:- apiGroups:  - ""  - "apps"  resources:  - pods  - deployments/scale  - deployments  verbs:  - get  - patch  - list  - watch  - create
复制代码


我们 apply 之后再来试试看呢


[root@master role]# kubectl apply -f jerry.yaml role.rbac.authorization.k8s.io/jerry configured# 修改副本数[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="3127c2e2b863d4c23878a"   --insecure-skip-tls-verify=true -n zhangsan scale deployment test03 --replicas 3deployment.apps/test03 scaled
复制代码


我们可以看到现在他可以了这个 yaml 文件还可以有另外一种格式


apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:  creationTimestamp: null  name: jerryrules:- apiGroups: ["","apps"]  resources: ["pods","deployments"]  verbs: ["get","delete","watch"]
复制代码


这种方式也可以,喜欢用哪种就用哪种,无所谓的嘛这个就是 role 和 rolebinding

clusterrole 和 clusterrolebinding


clusterrole 对于 role 来说,role 是属于某个命名空间的,而 clusterrole 是属于整个集群的,clusterrole 可以进行 clusterrolebinding,也可以进行 rolebinding,rolebinding 的时候指定一下命名空间就可以了使用 rolebinding 的时候它就相当于是将 clusterrole 的权限模板给了某个命名空间下的某个用户,也就是说在你进行 rolebinding 的时候你就当这个 clusterrole 就是一个普通的没有指定特定命名空间的 role 我们可以这样想一下,我们有很多个命名空间,然后每个命名空间里的用户权限其实都是差不多的,那么如果我要是使用 role 的话,我就需要每个命名空间下都要去创建 role,费时费力但是我们使用 clusterrole 的话,所有命名空间都可以看到这个 clusterrole,那么就无需每个命名空间都去创建 role 了,直接 rolebingding 就好了


1. 创建一个新的用户,使用 token


[root@master pki]# openssl rand -hex 10 >> /etc/kubernetes/pki/jerry.csv[root@master pki]# cat jerry.csv# 这里的token不一样长可能是因为我按a插入的时候多按了一下,没什么太大的问题,token是可以自己写的3127c2e2b863d4c23878a,jerry,2000958a15cfa9431e088e0b,tom,2001
复制代码


2. 创建 clusterrole


这个创建方法与 role 是一样的


[root@master role]# kubectl create clusterrole cluster-pod --verb=get,list,watch --resource=pods --dry-run=client -o yaml > clusterrole.yaml[root@master role]# cat clusterrole.yamlapiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  creationTimestamp: null  name: cluster-podrules:- apiGroups:  - ""  resources:  - pods  verbs:  - get  - list  - watch
复制代码


3. clusterrolebinding


[root@master role]# kubectl create clusterrolebinding cluster-tom --clusterrole=cluster-pod --user=tom --token="958a15cfa9431e088e0b"
复制代码


4. 验证权限


在验证权限之前我建议退出 shell 重新登录一下,或者重启一下节点,因为你直接登录的话他可能会报错 error: You must be logged in to the server (Unauthorized)我就遇到这个问题了,我的解决方式是将 kube-system 里面的 apiserver 这个 pod 重启了


# 查看pod[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="958a15cfa9431e088e0bb"   --insecure-skip-tls-verify=true -n zhangsan get podsNAME                      READY   STATUS    RESTARTS   AGEtest01                    1/1     Running   0          6h29mtest03-6484c64bb6-88xlr   1/1     Running   0          81mtest03-6484c64bb6-9hf4l   1/1     Running   0          75mtest03-6484c64bb6-w4zwk   1/1     Running   0          75m# 查看其他命名空间的pod[root@node1 manifests]# kubectl --server="https://192.168.200.200:6443" --token="958a15cfa9431e088e0bb"   --insecure-skip-tls-verify=true -n kube-system get podsNAME                             READY   STATUS    RESTARTS        AGEcoredns-5bbd96d687-9tsbb         1/1     Running   38 (7h6m ago)   42dcoredns-5bbd96d687-q6dl8         1/1     Running   38 (7h6m ago)   42detcd-master                      1/1     Running   42 (7h6m ago)   44dkube-apiserver-master            1/1     Running   0               13mkube-controller-manager-master   1/1     Running   63 (3h1m ago)   44dkube-proxy-mp98s                 1/1     Running   40 (7h6m ago)   44dkube-proxy-snk8k                 1/1     Running   46 (7h6m ago)   44dkube-proxy-xmxpj                 1/1     Running   38 (7h6m ago)   44dkube-scheduler-master            1/1     Running   61 (3h1m ago)   44dmetrics-server-54b5b8fb6-v4cqx   1/1     Running   29 (7h4m ago)   7d1h
复制代码


我们可以看到,他可以看到其他命名空间下的 pod,这就是 role 和 clusterrole 的区别了至于他能不能创建 pod,能不能创建 deployment,这些东西就是跟 role 是一样的了


文章转载自:FuShudi

原文链接:https://www.cnblogs.com/fsdstudy/p/18023589

体验地址:http://www.jnpfsoft.com/?from=001

用户头像

EquatorCoco

关注

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
k8s-权限管理_Kubernetes_EquatorCoco_InfoQ写作社区