RBAC
RBAC模型(Role-Based Access Control:基于角色的访问控制),k8s集群中的身份有两种:用户(User)和服务账号(Service Account),其中service account是k8s为pod内部的进程访问apiserver创建的一种用户。我们可以通过sa中的token与apierver进行通信,也可以基于用户的kubeconfig与apierver进行通信。
用户user
对于User账户,主要分为系统管理员账户和普通账户,系统管理员账户为创造集群时自带,权限很高,普通账户也是由系统管理员账户创建并赋予期对应的访问操作权限。
创建用户
对于User账户,我们可以通过创建k8s集群时自带的证书对我们(admin)权限(几乎)手动管理master中的凭证文件,并且将每个凭证文件和一个字符串对应起来,只要用户请求中有信息(一般来自本地保存的.kube/config文件中)能够证明自己有任意一个凭证文件的授权,那么这个请求就被认为是一个合法用户发出的,同时,在证书中还可以加入用户所在的组(group)的信息,k8s可以据此认为user在一个组中或者后期通过rolebinding等赋予操作权限。
通过CSR创建为例,(参考官方文档https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests)
1.生成一个 2048 位的 morece.key 文件
openssl genrsa -out morece.key 2048
2.在 morece.key 文件的基础上,生成 morece.crt 文件(用参数 -days 设置证书有效期)
这里注意两个字段Common Name输入的是用户名。
Organization Name 是用户组,如果写system:masters则归属于系统组获取系统管理权限,这块可以写一个新的,后边我们通过role或clusterrole来限制账号的权限。
openssl req -new -key morece.key -out morece.csr
创建 CertificateSigningRequest
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: morece
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ2p6Q0NBWGNDQVFBd1NqRUxNQWtHQTFVRUJoTUNRMDR4RlRBVEJnTlZCQWNNREVSbFptRjFiSFFnUTJsMAplVEVUTUJFR0ExVUVDZ3dLYTNWaVpYSnVaWFJsY3pFUE1BMEdBMVVFQXd3R2JXOXlaV05sTUlJQklqQU5CZ2txCmhraUc5dzBCQVFFRkFBT0NBUThBT==..
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400 # one day
usages:
- client auth
EOF
-
usage
字段必须是 ‘client auth
’ -
expirationSeconds
可以设置为更长(例如864000
是十天)或者更短(例如3600
是一个小时) -
request
字段是 CSR 文件内容的 base64 编码值。 要得到该值,可以执行命令cat morece.csr | base64 | tr -d "\n"
批准证书kubectl certificate approve morece
取得证书
从 CSR 取得证书:
kubectl get csr/morece -o yaml
证书的内容使用 base64 编码,存放在字段 status.certificate
。
从 CertificateSigningRequest 导出颁发的证书。
kubectl get csr morece -o jsonpath='{.status.certificate}'| base64 -d > morece.crt
添加到 kubeconfig
最后一步是将这个用户添加到 kubeconfig 文件。
首先,你需要添加新的凭据:
kubectl config set-credentials morece --client-key=morece.key --client-certificate=morece.crt --embed-certs=true
然后,你需要添加上下文:
kubectl config set-context morece --cluster=kubernetes --user=morece
这里也推荐个工具看用户,切换context很方便https://github.com/sunny0826/kubecm.git
来测试一下,把上下文切换为 morece
:
kubectl config use-context morece
这里可以看到报错了,错误原因是more测用户并没有权限去访问default空间下的pod,这时候就要引入RBAC来分配权限了
RBAC来分配权限
RBAC API 声明了四种 Kubernetes 对象:Role、ClusterRole、RoleBinding 和 ClusterRoleBinding。
创建角色Role和ClusterRole
Role 总是用来在某个名字空间内设置访问权限; 在你创建 Role 时,你必须指定该 Role 所属的名字空间。
与之相对,ClusterRole 则是一个集群作用域的资源
接下来创建个读取default pod的权限(注意要切换为管理员context再进行资源创建)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: morecepod-reader
rules:
- apiGroups: [""] # "" 标明 core API 组
resources: ["pods"]
verbs: ["get", "watch", "list"]//允许的操作行为
//get和list区别在于如果是get可以查看详情kubectl describe这在secret时获取详情中的token很好用,list只能获取列表不能查看详情
RoleBinding 和 ClusterRoleBinding
简单来说RoleBinding 和 ClusterRoleBinding就是将Role和ClusterRole规则作用效果绑定到用户或serveraccount,使其拥有与Role和ClusterRole一样的权限。
一个 RoleBinding 可以引用同一的名字空间中的任何 Role。 或者,一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。 如果你希望将某 ClusterRole 绑定到集群中所有名字空间,你要使用 ClusterRoleBinding。
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "jane" 读取 "default" 名字空间中的 Pod
# 你需要在该命名空间中有一个名为 “pod-reader” 的 Role
kind: RoleBinding
metadata:
name: moreceread-pods
namespace: default
subjects:
# 你可以指定不止一个“subject(主体)”
- kind: User
name: morece # "morece" 是区分大小写的
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
kind: Role # 此字段必须是 Role 或 ClusterRole
name: morecepod-reader # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
apiGroup: rbac.authorization.k8s.io
然后再把上下文切换为 morece
看下default空间下pod可以了:
权限划分
Role和ClusterRole的权限控制主要通过rules下字段
apiGroups:设定资源组"" 标明 core API 组,“" 标明所有组
resource内容为常见资源类(crontabs、jobs、pods、pods/log、configmaps、deployments等)
同时也支持nonResourceURLs通过api url加载
nonResourceURLs: [“/healthz”, "/healthz/”] # nonResourceURL 中的 ‘*’ 是一个全局通配符
verbs主要控制对资源的行为[“get”, “list”, “watch”, “create”, “update”, “patch”, “delete”]
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: morecepod-reader
rules:
- apiGroups: [""] # "" 标明 core API 组
resources: ["pods"]
verbs: ["get", "watch", "list"]//允许的操作行为
//get和list区别在于如果是get可以查看详情kubectl describe这在secret时获取详情中的token很好用,list只能获取列表不能查看详情
手动创建证书方法
利用手动创建证书创建用户,前面生成密钥部分都相同,但是签名通过利用集群中CA自带的CA证书进行签名即可。详细在http://blog.itpub.net/69955379/viewspace-2778141
创建用户server account
服务账号对象主体更多为pod,比如当有pod需要运行时,必须以一个service account的身份去运行他。一个pod不需要区分是那个用户的,只需要对service account权限进行控制即可。
我们在创建 Pod 时,如果没有指定服务账号,Pod 会被指定给命名空间中的 default
服务账号。
角色role和roleBinding
下面我们在namespace为ceshi下创建一个service account,接着在pod中使用这个账户
kubectl create serviceaccount morece -n ceshi //创建sa
挂载sa起pod
apiVersion: v1
kind: Pod
metadata:
name: morecewithsa
namespace: ceshi
spec:
serviceAccount: morece
containers:
- name: morece
image: nginx
imagePullPolicy: IfNotPresent
将kubectl cp进去测试用
kubectl cp /usr/bin/kubectl ceshi/morecewithsa:/
find / -name "*token"找一下pod里挂载的token,也可以直接用kubectl
kubectl get pod
可以看到我们光是创建一个service account,在pod内是没什么权限的,现在创建个role,通过rolebinding绑定在我们的sa上
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: ceshi
name: morecepod-create
rules:
- apiGroups: ["*"]
# 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
resources: ["secrets","pods","nodes","services"]
verbs: ["get", "watch", "list","create"]
EOF
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 service account 读取 "ceshi" 名字空间中的 Pod
# 你需要在该命名空间中有一个名为 “morecepod-create” 的 Role
kind: RoleBinding
metadata:
name: morececreate-pods
namespace: ceshi
subjects:
# 你可以指定不止一个“subject(主体)”
- kind: ServiceAccount
name: morece # "morece" 是区分大小写的
roleRef:
# "roleRef" 指定与某 Role 或 ClusterRole 的绑定关系
kind: Role # 此字段必须是 Role 或 ClusterRole
name: morecepod-create # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
apiGroup: rbac.authorization.k8s.io
EOF
在里边试试创建个pod,可以了
cat <<EOF | ./kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: createinmorecewithsa
namespace: ceshi
spec:
containers:
- name: createinmorecewithsacon
image: nginx
imagePullPolicy: IfNotPresent
EOF
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zmpCoF6c-1678978192710)(https://prefect12.oss-cn-beijing.aliyuncs.com/8.png?Expires=1676567430&OSSAccessKeyId=TMP.3Kk4pSrSmBFm96NfgY6GZKm1qhse1DffMaig8NhGPYR9RcQ4j74QAFhCvmGWDyXkr2E7wtHv71FS2rrVZhzZTQXAJUXuCo&Signature=iOG9FI4viDa8002eio23AIw0dw0%3D)]
我们再试试在别的命名空间创建pod,失败了。于是现在创建个clusterrole,通过clusterrolebinding绑定在我们的sa上
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: pod-create
rules:
- apiGroups: ["*"]
# 在 HTTP 层面,用来访问 Secret 资源的名称为 "secrets"
resources: ["secrets","pods","nodes","services"]
verbs: ["get", "watch", "list","create"]
EOF
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
# 此集群角色绑定允许 “manager” 组中的任何人访问任何名字空间中的 Secret 资源
kind: ClusterRoleBinding
metadata:
name: create-pod-glob
subjects:
- kind: ServiceAccount
namespace: ceshi
name: morece # 'name' 是区分大小写的
roleRef:
kind: ClusterRole
name: pod-create
apiGroup: rbac.authorization.k8s.io
EOF