08K8S之k8s认证和serviceaccount

k8s认证和serviceaccount

客户端-->API server
	user:username,uid
	group:
	extra:

	API
	Request path
		http://192.168.1.130:6443/apis/apps/v1/namespaces/default/deployments/myapp-deploy/
	HTTP request verb:
		get,post,put,delete
	API Request verb:
		get,list,create,update,patch,watch,proxy,redirect,delete,deletecollection
         watch: kubectl get pod -w
	Resource:
	Subresource:
	Namespace:
	API group

Object URL:
    /apis/<GROUP>/<VERSION>/namespaces/<NAMESPACE_NAME>/<KIND>[/OBJECT_DI]/
kubernetes集群有两类认证时的用户账号,一类是useraccount,叫用户账号,通常对应现实中的人使用的账号;另一类叫serviceaccount,叫服务账号,它是指pod中一种应用程序运行托管在k8s集群上,想访问k8s集群上的apiserver时,需要的认证信息,包括:用户名、账号、密码等等。。
kubectl get pod myapp-deploy-controll-55555dd47b-vsf8p -o yaml > myapp-deploy-controll.yaml # 根据一个已知pod的定义格式,生成一份yaml文件,然后修改之后即可使用,不用从头开始编辑。
kubectl create sa mysa --dry-run=none/client/server -o yaml > mysa.yaml # 创建一个serviceaccount并重定向到yaml文件中。
每创建要给serviceaccount账号就会自动生成一个secret:
    kubectl get secret 

kubectl explain pod.spec
	serviceAccountName:指定此字段,相当于指定一个sa账号,可以附带认证到私有registry 云上的secret信息的。
 
kubectl describe secret admin
'''
Name:                admin
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>  # 
Mountable secrets:   admin-token-f9mk6
Tokens:              admin-token-f9mk6
Events:              <none>
'''

所以以后创建的secret对象不要定义在pod上,可以定义在sa上,然后把sa定义在pod上,然后pod通过sa的Image pull secrets 也能完成私有仓库镜像下载的认证。这样在pod资源文件清单中就不被泄露出去secret使用的是哪些相关信息了。对于sa的细节我们可以认为是获取不到的。

我们为pod获取私有仓库镜像认证的两种方式为:
1.直接使用imagePullSecret字段指定能完成认证时的secret对象;
2.在pod上自定义一个serviceaccout,在serviceaccount上附加pod获取镜像时使用的secret对象。
kubectl config view # 查看客户端通过kubeconfig配置文件连接apiserver的配置信息
配置文件也是一个标准的k8s资源
'''
[root@master01 static-pod]# kubectl config view
apiVersion: v1
clusters: # 集群列表,cluster1、cluster2、cluster3、cluster4.....
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.1.130:6443
  name: kubernetes
contexts: # 上下文列表
- context: # 表示用哪个账号访问哪个集群
    cluster: kubernetes  # 哪个集群
    user: kubernetes-admin # 被哪个用户账号访问
  name: kubernetes-admin@kubernetes # 给context的取名
current-context: kubernetes-admin@kubernetes  # 当前上下文,表示当前用哪个账号访问哪个集群:用kubernetes-admin账号访问cluster集群为kubernetes的k8s集群。
kind: Config
preferences: {}
users: # 用户账号名称列表,user1、user2、user3、user4......
- name: kubernetes-admin # kubernetes-admin表示整个集群的管理员
  user: # 用户自己也需要被服务器端apiserver所认证。
    client-certificate-data: REDACTED
    client-key-data: REDACTED
'''
上下文是什么?kubeconfig配置文件不单单让我们访问一个k8s集群的,如果有多个k8s集群,我们只有一台可访问远端k8s集群的主机,我们一会儿想控制A集群,一会儿想控制B集群,一会儿想控制C集群,难道还要换用户账号(控制台上的系统用户账号)?为了一个kubectl能控制多个k8s集群
cd /etc/kubernetes/pki
(umask 077;openssl genrsa -out xiaochao.key 2048) # 创建私钥
openssl req -new -key xiaochao.key -out xiaochao.csr -subj "/CN=xiaochao" # 创建证书签名 /CN=xiaochao 就是创建的的认证apiserver的用户,一定不能写错。
openssl x509 -req -in xiaochao.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out xiaochao.crt -days 3650  # 根据签名和集群私钥和证书签发用户证书
openssl x509 -in xiaochao.crt -text -noout # 以文本格式输出颁发的证书 如下图

kubectl config --help
	current-context:显示当前上下文
	set-cluster:
	set-context:创建一个新的上下文
	set-credentials:创建一个新的用户
	use-context:切换当前上下文
	view:查看./kubeconfig文件
	--embed-certs=true:隐藏客户端证书和私钥
# 创建一个集群外部的客户端
kubectl config set-credentials xiaochao --client-certificate=./xiaochao.crt --client-key=./xiaochao.key --embed-certs=true

# 创建一个集群上下文
kubectl config set-context xiaochao@kubernetes --cluster=kubernetes --user=xiaochao

# 切换当前上下文
kubectl config use-context xiaochao@kubernetes

在访问集群用户为xiaochao时,如下图:

xiaochao用户虽然是已经是认证的用户,但是没有授权,没有操作集群的权限。。。

# 切换到kubernetes-admin用户
kubectl config use-context kubernetes-admin@kubernetes
# 创建一个集群
kubectl config set-cluster mycluster --kubeconfig=/tmp/test.conf --server="https://192.168.1.130:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true

授权

授权插件:
    Node
    ABAC(attribution based access control):基于属性的访问控制;在RBAC启用之前用到的授权控制插件的算法
    RBAC:Role based access control,基于角色的访问控制。
    Webhook:基于http回调机制的访问控制

        
k8s上的所有组件或者说是所有内容可分为3类,绝大部分是对象和对象列表:
	对象
	对象列表
	虚拟路径(url):非对象资源,占有比例很少
什么是RBAC(基于角色的访问控制)?
  让一个用户(Users)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在授权机制当中,只需要将权限授予某个角色,此时用户将获取对应角色的权限,从而实现角色的访问控制。如图:

把对一个Object(对象)的Operation(操作)叫做许可权限(Permissions),授予Role拥有某种被许可的权限(Permissions),就拥有了某些对象上的某种操作权限。

在k8s的授权机制当中,采用RBAC的方式进行授权,其工作逻辑是,把对对象的操作权限定义到一个角色当中,再将用户(user account or service account)绑定到该角色,从而使用户(user account or service account)得到对应角色的权限。如果通过rolebinding绑定role,只能对rolebinding所在的名称空间的资源有权限,上图user1这个用户(user account or service account)绑定到role1上,只对role1这个名称空间的资源有权限,对其他名称空间资源没有权限,属于名称空间级别的;
role 和role binding授予名称空间级别的权限,对某个名称空间的操作权限
role:
    operations
    objects
rolebinding:
    user account or service account
    role

clusterrole 和 clusterrolebinding授予集群级别的权限,对所有名称空间都有操作权限

另外,k8s为此还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有可操作的权限,从而将User2(user account or service account)通过ClusterRoleBinding到ClusterRole,从而使User2(user account or service account)拥有集群的操作权限。Role、RoleBinding、ClusterRole和ClusterRoleBinding的关系如下图:

通过上图可以看到,可以通过rolebinding绑定role,**rolebinding绑定clusterrole**,clusterrolebinding绑定clusterrole。

上面我们说了两个角色绑定:

(1)用户通过rolebinding绑定role

(2)用户通过clusterrolebinding绑定clusterrole

还有一种:rolebinding绑定clusterrole

假如有6个名称空间,每个名称空间的用户都需要对自己的名称空间有管理员权限,那么需要定义6个role和rolebinding,然后依次绑定,如果名称空间更多,我们需要定义更多的role,这个是很麻烦的,所以我们引入clusterrole,定义一个clusterrole,对clusterrole授予所有权限,然后用户通过rolebinding绑定到clusterrole,就会拥有自己名称空间的管理员权限了

注:RoleBinding仅仅对当前名称空间有对应的权限。

Role

kubectl explain role --help
kubectl create role pod-reader --verb=get,list,watch --resource=pods --dry-run -o yaml
'''
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: null
  name: pod-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
'''
创建一个role角色pod-reader,--verb 可以执行get,list,watch操作,--resource 可以对pod资源进行操作。

kubectl create role pod-reader --verb=get,list,watch --resource=pods --dry-run -o yaml > pod-reader-role.yaml
vim pod-reader-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs: ["get","list","watch"]


kubectl apply -f pod-reader-role.yaml 
kubectl get role
kubectl describe role pod-reader

Resources:资源类别
Resource Names:资源名称,对某一类别资源的某个或某些个资源进行限制操作
Non-Resource URLs:在k8s上不能被定义成对象的资源,通常表示是来定义对某些资源的一种操作

rolebinding

rolebinding 既可以绑定到role,有可以绑定到clusterrole;而clusterrolebinding只能绑定到clusterrole。

将用户绑定(rolebinding)到role

在上面创建的xiaochao用户,是没有读取pod资源权限的,现在我们通过rolebinding,将xiaochao用户绑定到pod-reader角色上。

kubectl create rolebinding --help
 kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname]
[--serviceaccount=namespace:serviceaccountname] [--dry-run=server|client|none] [options]

kubectl create rolebinding xiaochao-read-pods --role=pod-reader --user=xiaochao --dry-run -o yaml
'''
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: xiaochao-read-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xiaochao
'''

kubectl create rolebinding xiaochao-read-pods --role=pod-reader --user=xiaochao --dry-run -o yaml > xiaochao-read-pods.yaml

vim xiaochao-read-pods.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
# creationTimestamp: null
  name: xiaochao-read-pods
roleRef: # roleRef:roleReference,role引用
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User  # 并不是单独存在的一种资源,但是在绑定用户时,我们需要这样来定义
  name: xiaochao

kubectl apply -f xiaochao-read-pods.yaml
kubectl get rolebinding -o wide
kubectl describe rolebinding xiaochao-read-pods

kubectl explain rolebinding
apiVersion	<string>
kind	<string>
metadata  <Object>
roleRef	<Object> -required-
  apiGroup	<string> -required-
  kind	<string> -required-
  name	<string> -required-

subjects	<[]Object>
  apiGroup	<string>
  kind	<string> -required- #  "User", "Group", and "ServiceAccount". 
  name	<string> -required-
  namespace	<string>  # 指明sa是哪个名称空间中的sa,因为sa是名称空间级别的资源,不同名称空间sa名称可能重名。

切换集群上下文到xiaochao用户,操作role定义资源的动作

# 切换集群上下文到xiaochao用户
kubectl config use-context xiaochao@kubernetes
kubectl get pods  # 现在能对pod资源进行get list watch操作了,但如果create,delete,edit还是不行,因为我们rolebinding role对象pod-reader中没定义此操作的--verb

kubectl get svc # 通过rolebinding 绑定的用户xiaochao到role资源操作对象的pod-reader,只有对pod的操作get list watch的权限,其他资源无法操作.

kubectl get po -n kube-system # 没有权限,因为定义的role和rolebinding属于名称空间级别的资源,都只对当前名称空间(当前是default名称空间)有效,所以不能访问kube-system名称空间下的资源。

clusterrole

clusterrole和role的定义方式是一样的。。。
kubectl create clusterrole --help

创建clusterrole:

kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=pods --dry-run -o yaml
'''
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  creationTimestamp: null
  name: cluster-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
'''
# 切换系统上下文,
kubectl config use-context kubernetes-admin@kubernetes

kubectl create clusterrole cluster-reader --verb=get,list,watch --resource=pods --dry-run -o yaml > clusterrole-reader.yaml
vim clusterrole-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
#  creationTimestamp: null
  name: cluster-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

kubectl apply -f clusterrole-reader.yaml

clusterrolebinding

kubectl create clusterrolebinding --help

创建clusterrolebinding

创建一个linux系统用户,并使用此用户将kubernetes集群的上下文切换为xiaochao,使用k8s的xiaochao账号去操作集群,就和liunx root用户在k8s的admin账号操作就分开了,互不干涉。
[root@master01 authority]# useradd ik8s
[root@master01 authority]# cp -rp /root/.kube/ /home/ik8s/
[root@master01 authority]# chown -R ik8s.ik8s /home/ik8s/
[root@master01 authority]# ls -ld /home/ik8s/
drwx------. 3 ik8s ik8s 75 Dec 23 09:57 /home/ik8s/

[root@master01 authority]# su - ik8s    
kubectl config use-context xiaochao@kubernetes
kubectl get po 

先删除之前创建的rolebinding-->xiaochao-read-pods,为了接下来将xiaochao账号绑定到clusterrolebinding。
kubectl delete rolebinding xiaochao-read-pods
kubectl create clusterrolebinding xiaochao-read-all-pods --clusterrole=cluster-reader --user=xiaochao --dry-run -o yaml
kubectl create clusterrolebinding xiaochao-read-all-pods --clusterrole=cluster-reader --user=xiaochao --dry-run -o yaml > clusterrolebinding-xiaochao-read-all-pods-cluster-reader.yaml

vim clusterrolebinding-xiaochao-read-all-pods-cluster-reader.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
# creationTimestamp: null
  name: xiaochao-read-all-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xiaochao

kubectl apply -f clusterrolebinding-xiaochao-read-all-pods-cluster-reader.yaml

在之前创建的linux用户上,在集群上下文为xiaochao的账号上:

kubectl get pod
kubectl get pod -kube-system

将rolebinding绑定到clusterrole

**1.将xiaochao通过rolebinding绑定到clusterrole cluster-reader **

xiaochao -> rolebinding -> clusterrole

先将之间xiaochao账号 clusterrolebinding xiaochao-read-all-pods删除:
kubectl delete clusterrolebinding xiaochao-read-all-pods

kubectl create rolebinding xiaochao-by-clusterrole-read-pods --clusterrole=cluster-reader --user=xiaochao --dry-run -o yaml
'''
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: null
  name: xiaochao-by-clusterrole-read-pods
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xiaochao
'''
kubectl create rolebinding xiaochao-by-clusterrole-read-pods --clusterrole=cluster-reader --user=xiaochao --dry-run -o yaml > rolebinding-clusterrole-read_pods.yaml
kubectl apply -f rolebinding-clusterrole-read_pods.yaml 

kubectl get pods
kubectl get pod -n kube-system  # 只能读取自己名称空间的pods。。。

2.将xiaochao通过rolebinding绑定到clusterrole admin

将xiaochao通过rolebinding绑定到clusterrole admin,则xiaochao 在rolebinding所在名称空间下的所有资源均能执行各类操作,类似管理员的权限。。。
kubectl create rolebinding default-ns-admin --clusterrole=admin --user=xiaochao --dry-run -o yaml > rolebinding-cluster_admin-ops_all-resource.yaml 

vim rolebinding-cluster_admin-ops_all-resource.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
#  creationTimestamp: null
  name: default-ns-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: xiaochao

kubectl apply -f rolebinding-cluster_admin-ops_all-resource.yaml

在k8s集群搭建完之后,默认的账号就有操作所有名称空间下的所有资源,这是为什么呢?

kubectl get clusterrolebinding 

kubectl get clusterrolebinding cluster-admin -o yaml

clusterrolebinding cluster-admin定义了一个组(Group:不是系统上常见资源,不能创建)system:masters,而这个组内定义了集群初始化完成之后的用户kubernetes-admin:
        kubectl config view
那为什么 kubernetes-admin会属于system:masters 组呢?这是在kubernetes证书中定义的:
cd /etc/kubernetes/pki
openssl x509 -in apiserver-kubelet-client.crt -text -noout

RBAC三类组件绑定到role或者clusterrole

在RBAC上授权时,RBAC允许3类组件:
user:绑定到roelbding或者clusterolebinding,表示只授权一个用户来扮演相关角色
group:绑定到组上,表示授权组上所有用户都能扮演角色。如果想一次授权多个用户,在一个名称空间中,拥有同样的权限,可以把多个用户定义成组,授权时做总的授权。。如何定义成组?在创建xiaochao 证书签名的时候将xiaochao添加到组中即可:
    openssl req -new -key xiaochao.key -out xiaochao.csr -subj "/CN=xiaochao/O=admin"
以后再授权的时候,绑定到system:masters组上,xiaochao就有权限
serviceaccount:

serviceaccount绑定rolebinding或者clusterrolebinding

当serviceaccount做了rolebinding或者clusterrolebinding,则serviceaccount拥有了rolebinding或者clusterrolebinding,任何一个pod启动时如果以这个serviceAccountName作为它使用的serviceaccount的话,这个pod中运行的应用程序就拥有了serviceaccouont授予的权限。
pod中,pod.spec.serviceAccountName以serviceaccount来连接apiserver获取访问资源。比如把serviceAccountName指定的账号(serivceaccount)授予admin权限,那么间接就让pod拥有了管理员权限,拥有了管理集群资源的权限。
以flannel网络插件为例:
https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
rules:
- apiGroups: ['extensions']
  resources: ['podsecuritypolicies']
  verbs: ['use']
  resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: flannel
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: flannel
subjects:
- kind: ServiceAccount  # flannel pod就有了serviceAccount(flannel)的所有权限
  name: flannel
  namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: flannel
  namespace: kube-system
kubectl get po -n kube-system
kubectl get po kube-flannel-ds-hjhgr -o yaml -n kube-system

原文地址:https://www.cnblogs.com/zhangchaocoming/p/15728640.html