zoukankan      html  css  js  c++  java
  • 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
    

  • 相关阅读:
    软件开发流程
    开心一笑 项目的开发和升级(转载知乎)
    转载编程之美
    etc/hosts文件详解
    自己centos7成功的修改了主机名(记录了该改哪些文件)
    CentOS7修改主机名的三种方法
    /etc/hosts文件修改后如何生效
    如何在Linux中显示和设置主机名(适用ubantu、centos等版本)
    Linux centos7 shell 介绍、 命令历史、命令补全和别名、通配符、输入输出重定向
    hadoop学习笔记(四):HDFS文件权限,安全模式,以及整体注意点总结
  • 原文地址:https://www.cnblogs.com/zhangchaocoming/p/15728640.html
Copyright © 2011-2022 走看看