ShokaX

k8s-Kubernetes用户和访问控制

发布于 字数统计 7.1k 字 阅读时长 24 分钟

k8s-Kubernetes用户和访问控制

发布于 字数统计 7,096 阅读时长 36 分钟

简介

K8S中有两种用户(User)——服务账号(ServiceAccount)和普通意义上的用户(User)
ServiceAccount是由K8S管理的,相当于系统账号。而User通常是在我们添加的,但K8S不存储用户列表——也就是说,添加/编辑/删除用户都是在外部进行,无需与K8S API交互,虽然K8S并不管理用户,但是在K8S接收API请求时,是可以认知到发出请求的用户的。

而这里我主要介绍的是User普通用户。
通过以上介绍,我们知道了普通用户是不需要api-server存储的,那api-server是怎么判断用户是否为合法用户和它具有的权限的呢?我们带着这个问题往下看。

api-service用户验证(用户识别)

尽管K8S认知用户靠的只是用户的名字,但是只需要一个名字就能请求K8S的API显然是不合理的,所以依然需要验证此用户的身份

而api-server去验证用户主要通过以下几种情况:
这三种认证资料的生成都是和证书密不可分的。
• X509客户端证书
客户端证书验证通过为API Server指定—client-ca-file=xxx选项启用,API Server通过此ca文件来验证API请求携带的客户端证书的有效性,一旦验证成功,API Server就会将客户端证书Subject里的CN属性作为此次请求的用户名
• 静态token文件
通过指定—token-auth-file=SOMEFILE选项来启用bearer token验证方式,引用的文件是一个包含了 token,用户名,用户ID 的csv文件 请求时,带上Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269头信息即可通过bearer token验证
• 静态密码文件
通过指定—basic-auth-file=SOMEFILE选项启用密码验证,类似的,引用的文件时一个包含 密码,用户名,用户ID 的csv文件 请求时需要将Authorization头设置为Basic BASE64ENCODED(USER

)

这里我们已经解答了前面的api-server是怎么识别用户的,但是这里又诞生了一个问题,api-server怎么通过证书或者说token、密钥文件来识别出用户是合法用户而不是假冒的用户?毕竟api-server理论上没保存用户的列表。
这里就涉及到用户的生成方式了。

用户的创建

为了让api-server能够准确的识别到用户为合法用户而不是假冒的,用户的证书在创建时需要经过api-server的ca进行签发。也就是说api-server签发过的证书就是合法用户。
其实就是api-server是第三方证书颁发机构的同时也是服务端。

生成一个私钥(RSA算法私钥,我们访问k8s的凭证)

openssl genrsa -out test.key 2048

image-20220303155034528

创建证书签名请求文件(预签发)

使用上述得到的私钥创建一个csr(证书签名请求)文件,其中我们需要在subject里带上用户信息(CN为用户名,O为用户组)
这个用户名就是我们要创建的用户。用户组其实不重要,只是我们给这个证书分的组而已,在集群中没有任何意义。

openssl req -new -key test.key -out test.csr -subj "/CN=test/O=RUYUE" # 生成crt,并使用我们的私钥进行签名

使用ca证书进行签发(给用户颁发证书)

这里主要就是使用api-server的ca证书去签发用户证书。
找到api-server的证书文件,在api-server的安装节点的/etc/kubernetes/pki/路径下,会有两个文件,一个是CA证书(ca.crt),一个是CA私钥(ca.key)

image-20220303155042234

openssl x509 -req -in test.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out test.crt -days 365 #提取用户信息,并加上其他信息(比如颁发者等信息),用CA的私钥签发数字证书。

image-20220303155047446

k8s用户的权限控制(RBAC)介绍

至此,我们已经解决了最初的两个问题之一(api-server是怎么识别用户的),还剩下一个权限问题。

RBAC(Role-Based Access Control,基于角色的访问控制)在Kubernetes的1.5版本中引入,在1.6版本时升级为Beta版本,在1.8版本时升级为GA。作为kubeadm安装方式的默认选项,足见其重要程度。

RBAC的概念

RBAC引入了4个新的顶级资源对象: Role, ClusterRole,RoleBinding和ClusterRoleBinding. 同其他API资源对象一样,用户可以使用kubectl 或者API调用等方式操作这些资源对象.

• Role: 角色,它定义了一组规则,定义了一组对Kubernetes API对象的操作权限
• Subject: 被作用者,既可以是”人”,也可以是机器,当然也可以是我们Kubernetes中定义的用户
• RoleBinding: 定义了”被作用者”和”角色”的绑定关系

角色(Role)

其实就相当于我给这个资源定义了一个组(角色),然后后续可以通过用户绑定实现这个组内的用户(subject)可以对这个资源做什么操作(还需要绑定)。

一个角色就是一组权限的集合,这里的权限都是许可形式的,不存在拒绝的规则,在一个命名空间中,可以用角色来定义一个角色,如果是集群级别的,就需要使用ClusterRole了.

角色只能对命名空间内的资源进行授权,在下面例子中定义的角色具备读取Pod的权限:
实际上, Role 本身就是一个kubernetes的API对象,定义文件如下:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: test #这个Role作用的命名空间
  name: test-role 
rules:
- apiGroups: [""]  # ""空字符串,表示核心API群,支持的API组列表,例如"“apiVersion: batch/v1”“apiVersion: extensions:v1beta1”“apiVersion: apps/v1beta1”等”

  resources: ["pods"] #支持的资源对象列表,例如Pods,deployments,jobs等
  verbs: ["get", "watch", "list"]  #对资源对象的操作方法列表,例如get,watch,list,delete,replace,patch等

集群角色(ClusterRole)

本质上也是角色,只是它相当于更加广泛的角色,是集群级别的,不再是命名空间那么细了。
集群角色除了具有和角色一致的命名空间内资源的管理能力,因其集群级别的范围,还可以用于以下特殊元素的授权.
主要用来绑定以下资源:

  • 集群范围的资源,例如Node.
  • 非资源型的路径, 例如”/ealthz”
  • 包含全部命名空间的资源,例如Pods(用于kubectl get pods —all-namespaces这样的操作授权)
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  # ClusterRole 不受限于命名空间,所以无需设置namespace的名称
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

角色绑定(Rolebinding)和集群角色绑定(ClusterRolebinding)

其实就是将指定的角色给绑定到一个目标上,绑定目标可以是User(用户)、Group(组)或者Service Account,相当于给一个或一组对象进行赋予权限。

使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。
RoleBinding可以引用Role进行授权。下面的例子中的RoleBinding将在default命名空间中把pod-reader角色授予用户jane,这一操作可以让jane读取default命名空间中的Pod:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: example-rolebinding
  namespace: default
subjects:
- kind: User
  name: youmen
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: example-role
  apiGroup: rbac.authorization.k8s.io

在Rolebinding中定义了一个subject字段,即”被作用者”。它的类型是User,即Kubernetes里的用户,名称为youmen
在kubernetes里的User,也就是用户,只是一个授权系统里的逻辑概念。它需要通过外部认证服务,比如Keystone,来提供。或者直接给APIServer指定一个用户名、密码文件。那么kubernetes的授权系统就能够从这个文件里找到对象的用户.
Rolebinding对象通过roleRef字段可以直接通过名字,来引用前面定义的Role对象(example-role),从而定义了”被作用者(Subject)”和”角色(Role)”之间的绑定关系
Role和RoleBinding 他们的权限限制规则仅仅在他们自己的namespace内有效,roleRef也只能引用当前namespace里的Role对象
“RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。一种常见的做法是集群管理员为集群范围预先定义好一组ClusterRole,然后在多个命名空间中重复使用这些ClusterRole。

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-secrets
  namespace: development
  # 集群角色中,只有development命名空间的权限才能赋予davesubjects
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

给test用户授权(绑定资源组)

前面我们已经学习了k8s的权限控制,这里我们可以实践下,这里我们目标是让我们新建的test用户有php这个命名空间的所有权限。构造如下role和rolebinding即可。

赋予指定命名空间权限

创建如下role和RoleBinding,则赋予了test这个账号对php这个命名空间的管理权限。

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: php
  name: test_role
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: test_rolebinding
  namespace: php
subjects:
- kind: User
  name: test
roleRef:
  kind: Role
  name: test_role
  apiGroup: rbac.authorization.k8s.io

赋予所有命名空间权限(相当于让test变成超管)

k8s中存在很多默认的role,cluster-admin就是其中一个。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: eviltest
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: test
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin

image-20220303155729464

使用test用户访问指定资源

前面我们创建了一个用户,并为该用户分配了权限,接着我们就能使用这个用户去访问指定资源了。这里我们将这个用户绑定到kubectl配置文件中。

创建用户配置

告诉kubectl test用户的证书,此时。kube/config文件内容如下

kubectl config set-credentials test --client-certificate=/home/momo/桌面/unhiden/test.crt --client-key=/home/momo/桌面/unhiden/test.key   

image-20220303155823937

创建api-server配置

kubectl config set-cluster kubernetes --server=https://192.168.5.174:6443 --certificate-authority=/home/momo/桌面/unhiden/ca.crt

此时,kube/config文件内容如下

image-20220303155933323

设置环境项中默认上下文

kubectl config  set-context default --cluster=kubernetes --user=test

设定使用kubernetes 集群,使用用户test进行验证

image-20220303155938489

设置默认环境项为default

kubectl config use-context default

image-20220303155948297

访问指定资源

可以看到,由于我们前面设置的rbac规则,我们只能管控php的资源。

image-20220303155952545