zoukankan      html  css  js  c++  java
  • Kubernetes权限说明

    转载于: https://www.jianshu.com/p/1be126cdaf1c

    Kubernetes对外只暴露了api-server一个入口,对Kubernetes所有资源的操作都需要通过调用api-server的方式来实现,api-server一般都是通过RBAC的方式来实现权限的控制,大部分人可能对api-server如何对用户进行授权和鉴权一知半解,没有搞清楚用户和组以及ServiceAccount的概念,因此做一个相对简单的说明。由于个人能力有限,如有错误还望不吝指出。

    RBAC API声明了四种对象,分别是Role、ClusterRole、RoleBinding、ClusterRoleBinding,下面就对这几个对象进行详细的说明。

    Role--角色

    用于在限定的命名空间中设定资源的操作权限,下面是一个示例的role,在default命名空间限定了pod的只读权限。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      namespace: default
      name: pod-reader
    rules:
    - apiGroups: [""] 
      resources: ["pods"]
    # 可以通过resourceNames:[] 来指定仅获取某些特定名称pod的资源,从而实现更细粒度的权限控制
      verbs: ["get", "watch", "list"]
    

    ClusterRole--集群角色

    用于在整个集群中设定资源的操作权限,不知局限于具体命名空间,下面是一个示例的clusterrole,在整个集群中限定了pod的只读权限。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: pod-reader
    rules:
    - apiGroups: [""]
      resources: ["pods"]
    # 可以通过resourceNames:[] 来指定仅获取某些特定名称pod的资源,从而实现更细粒度的权限控制
      verbs: ["get", "watch", "list"]
    

    Kubernetes内置的Role和ClusterRole

    kubernetes实际上内置很多使用的Role以及ClusterRole来方便我们对集群做权限的管理,具体有哪些内置的角色可以参考官方文档,本文只举例几个常用的ClusterRole进行说明。可以通过 kubectl get clusterrole来获取对应的列表。

    view

    具有只读权限的ClusterRole

    edit

    具有操作部分资源的ClusterRole,包括pod、configmap等,但是无法操作secret以及创建rule和rolebinding的权限,通常可以作为指定命名空间下的普通用户权限来对处理。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: admin-binding
      namespace: test
    subjects:
      - kind: User
        name: test
        apiGroup: rbac.authorization.k8s.io
    roleRef:
        kind: ClusterRole
        name: edit
        apiGroup: rbac.authorization.k8s.io
    

    admin

    具有edit的所有权限,同时可以操作secret、rule、rulebinding等资源,通常通过rolebinding将其与指定命名空间下的user或者group进行绑定,从而赋予用户或组在指定命名空间中的管理员权限。可以以下面的示例为参考,赋予一个用户指定命名空间中的管理员权限。

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: admin-binding
      namespace: test
    subjects:
      - kind: User
        name: test
        apiGroup: rbac.authorization.k8s.io
    roleRef:
        kind: ClusterRole
        name: admin
        apiGroup: rbac.authorization.k8s.io
    

    cluster-admin

    集群管理员,拥有集群的所有权限,此权限不应该随意给到用户。

    RoleBinding--角色绑定

    用于在限定的命名空间中绑定Role(ClusterRule)的权限到指定的用户或者组上,从而赋予用户或组操作资源的权限。

    ClusterRoleBinding--集群角色绑定

    用于在限定的明明空间中绑定ClusterRule的权限到指定的用户或者组上,从而赋予用户或组操作资源的权限。ClusterRoleBinding不需要指定具体的命名空间,而是在所有的命名空间都有权限。

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

    User、Group

    User和Group是无法通过kubectl get user(group)来获得的,大部分刚接触kubernetes的人可能会对此比较迷惑,既然无法获得,那怎么来判断这个用户或者组是否存在的呢?api-server又怎么知道客户端是的用户是谁呢,属于哪个组呢?接下来就详细说明一下其中的原理。

    首先我们要先了解一下kubectl是如何调用api-server,我们都知道有config文件的存在,下面是一个config文件的组成部分,出于所见篇幅的原因,将其中的一些参数值以X替代。

    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: XXXX
        server: https://XXX.XXX.XXX.XXX:443
      name: local
    contexts:
    - context:
        cluster: local
        user: test
      name: test
    - context:
        cluster: local
        user: kube-admin-local
      name: local
    current-context: local
    kind: Config
    preferences: {}
    users:
    - name: test
      user:
        client-certificate-data: XXXX
        client-key-data: XXXX
    - name: kube-admin-local
      user:
        client-certificate-data: XXXXX
        client-key-data: XXXXXXXX
    

    主要包含一下这几个部分clusters、context、current-context以及users,下面稍微解释一下。

    • clusters---集群的信息,其中包含集群的crt证书信息,以及api-server接口的地址,可以包含多个cluster。

    • context---上下文,这个说的更直白一点就是cluster和user的配对。

    • current-context---当前上下文

    • users---用户信息,包含用户的名称、组以及经过api-server认证过的crt证书信息,但具体的内容已经被加密处理,api-server经过解密就可以得出来。

    User和Group信息其实就是从user的内容中解析出来的,那这些信息又是如何生成的呢,那这就又要简单的提一下如何创建一个用户以及kubernetes复杂的tls认证过程了。

    一般添加一个用户的流程如下所示:

    # 生成一个客户端的key
    openssl genrsa -out test.key 2048
    
    # 通过key生成一个客户端的csr证书,并指定用户命和组名
    # 其中CN表示用户命,而O表示组名,一个组可以有多个用户,组名可以根据实际需要填写,也可以不填写,仅使用用户名
    openssl req -new -key test.key -out test.csr -subj "/CN=test/O=apps"
    
    # 创建一个csr请求,要求kube-controller对这个生成的客户端证书进行认证并通过ca来进行签名
    cat <<EOF | kubectl apply -f -
    apiVersion: certificates.k8s.io/v1
    kind: CertificateSigningRequest
    metadata:
      name: test
    spec:
      groups:
      - system:authenticated
      request: $(cat test.csr | base64 | tr -d "
    ")
      signerName: kubernetes.io/kube-apiserver-client
      usages:
      - client auth
    EOF
    
    # 批准客户端的认证请求
    kubectl certificate approve test
    
    # 将该用户与内置的admin ClusterRole进行绑定,授予其管理员权限,到这一步,用户test实际上已经获得了访问test命名空间下大部分资源的操作权限,接下来就是如何让客户端调用的时候带上用户信息
    cat <<EOF | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: test-binding
      namespace: test
    subjects:
      - kind: User
        name: test
        apiGroup: rbac.authorization.k8s.io
    roleRef:
        kind: ClusterRole
        name: admin
        apiGroup: rbac.authorization.k8s.io
    EOF
    
    # 获取签发完成的crt证书信息并将其写到本地文件
    kubectl get csr test-o jsonpath='{.status.certificate}' | base64 -d > test.crt
    
    # 将获取到的crt信息以及客户端的key写入到config文件的users中,为了方便起见,通过将embed-certs=true来将文件内容直接写入进去
    kubectl config set-credentials test --client-key=./test.key --client-certificate=./test.crt --embed-certs=true
    
    # 添加一个上下文,并将已有的cluster与刚才写入的user作为一对
    kubectl config set-context test --cluster=local --user=test
    
    # 将当前的上下文切换到刚才生成的上下文
    kubectl config use-context test
    
    # 完成这些操作之后,当我们再通过kubectl指令调用的api-server的时候就会使用test这个用户了,并且权限也会与之前设定的对应,只能用于操作test命名空间下的资源了。
    

    连接完用户是怎么来的以后就可以了解一下Group的概念了。

    Group就是对User的一个分组,比如我们想要一个Group都拥有test命名空间下的管理员权限,如果没有Group的情况下我们就需要一个用户添加一个RoleBinding,这样非常的不变,所以就可以通过将RoleBinding,将管理员权限直接绑定到一个Group上就可以让指定Group下的所有用户全部获得管理员权限。

    # 创建指定group的用户
    openssl req -new -key test.key -out test.csr -subj "/CN=test/O=test"
    
    # 创建rolebinding
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: test-group-binding
      namespace: test
    subjects:
      - kind: Group
        name: test
        apiGroup: rbac.authorization.k8s.io
    roleRef:
        kind: ClusterRole
        name: admin
        apiGroup: rbac.authorization.k8s.io
    
    # 后续再创建用户的时候,只要指定group为test即可
    

    ServiceAccount

    既然谈到了User和Group,就避免不了谈一下ServiceAccount,首先要谈一下Servcie和User的区别。

    最简单的理解方式就是,User和Group主要是给外部客户端(如kubectl)调用api-server时做权限控制的,而ServiceAccount是给运行在kubernetes内部的服务调用api-server的时候做权限控制的。

    实际上每个运行的pod,如果没有指定serviceaccount的话都会生成一个default的serviceaccount,并且会作为一个文件挂载到/var/run/secrets/kubernetes.io/serviceaccount目录下,默认的ServiceAccount是没有权限调用api-server接口的。

    当一个pod需要访问api-server资源的时候就需要额外的权限了,这时候就可以先通过RoleBinding将ServiceAccount与具有权限的Role进行绑定,然后为pod指定ServiceAccount来获取调用的权限。

    # ServiceAccount
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: admin-serviceaccount
    
    # RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: admin-binding
    subjects:
      - kind: ServiceAccount
        name: admin-serviceaccount
        apiGroup: rbac.authorization.k8s.io
    roleRef:
        kind: ClusterRole
        name: admin
        apiGroup: rbac.authorization.k8s.io
    
    # Pod
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
      serviceAccountName: admin-serviceaccount
    

    生产环境的注意点

    1、 一定要严格管控生产环境下的权限,不要随意给予超级管理员权限给到普通用于,要严格把控各个命名空间的权限,切勿直接把超级管理员的config文件给到开发人员直接使用。

    2、 建议平时使用时多用rolebinding,不要为了方便就使用clusterrolebinding而造成权限管控混乱。

    RBAC:https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/
    ServiceAccount:https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-service-account/

  • 相关阅读:
    x01.os.17: 换心术
    x01.os.16: 添加功能
    x01.os.15: 看上去很美
    JVM 栈帧之操作数栈与局部变量表
    IDEA字节码学习查看神器jclasslib bytecode viewer介绍
    java上下文Context类
    UML ——区分类图中的几种关系.md
    UML ——六种依赖关系.md
    JDK动态代理[1]----代理模式实现方式的概要介绍
    java方法句柄-----5.Method Handles in Java
  • 原文地址:https://www.cnblogs.com/LiuChang-blog/p/15203855.html
Copyright © 2011-2022 走看看