• 普通程序员看k8s基于角色的访问控制(RBAC)


    一、知识准备

    ● 上一节描述了k8s的账户管理,本文描述基于角色的访问控制
    ● 网上RBAC的文章非常多,具体概念大神们也解释得很详细,本文没有站在高屋建瓴的角度去描述RBAC,而是站在一个普通程序员的视角,去看待RBAC
    ● 我理解的基于角色的访问控制,如图:

                                            +------------+
                              +------------>|all:resource|-+
                              |             +------------+ |       +----------------+
                         +----+---+                        |       |                |
    +------+             |role:   |                        +------>+  namespaces    |
    |user1 |------------>|admin   |                                |                |
    +------+             +--------+         +------------+         |  pod           |
                                      +---->|get:pod     |-------->+                |
                                      |     +------------+         |  service       |
                                      |                            |                |
    +------+             +--------+   |                            |  deployment    |
    |user2 |------------>|role:   |---+                            |                |
    +------+             |guest   |         ....                   |  daemonsets    |
                         +--------+                                |                |
                                                                   |  ...           |
                                            +------------+         |                |
                                            |list:service|         +----------------+
                                            +------------+
    
    

    账户:请求kube-api必要的身份验证。身份验证之后只是被允许进入集群,但是不一定有访问资源的权限
    角色:账户登录之后扮演的角色
    规则:在k8s集群内允许的操作。比如get namespace、get pod等
    资源:k8s各种各样的资源
    角色绑定:资源与规则组成访问权限,将角色绑定在访问权限上,最后账户登录之后扮演不同的角色


    二、环境准备

    组件 版本
    OS Ubuntu 18.04.1 LTS
    docker 18.06.0-ce
    k8s v1.10.1

    三、创建角色

    角色分为role与clusterrole,区别在于前者是namespace级别,后者是整个k8s cluster级别

    (1)创建role

    创建一个default namespace的普通角色,权限是对pod的get、list、watch

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: po_r
      namespace: default
    rules:
    - apiGroups:
      - ""
      resources:
      - pods
      verbs:
      - get
      - list
      - watch
    

    (2)创建clusterrole

    创建一个具有pod的get、list、watch的clusterrole,这个角色是cluster级别的,也就是所有的namespace

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: cluster_po_r
    rules:
    - apiGroups:
      - ""
      resources:
      - pods
      verbs:
      - get
      - list
      - watch
    

    四、userAccount角色绑定

    (1)role绑定

    先将上一节的mrvolleyball账号绑定一个namespace级别的role,使用rolebinding

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: mrvolleyball
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: po_r
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: mrvolleyball
    

    再看mrvolleyball的账户,已经拥有了对default namespace的get pod权限

    root@k8s-master:~# kubectl get pod
    NAME                                      READY     STATUS    RESTARTS   AGE
    busybox                                   1/1       Running   89         3d
    nginx-deployment-77d7f55978-lvfkf         1/1       Running   0          21h
    
    

    不过他既没有service的访问权限,更没有别的namespace的访问权限

    root@k8s-master:~# kubectl get svc
    Error from server (Forbidden): services is forbidden: User "mrvolleyball" cannot list services in the namespace "default"
    root@k8s-master:~# kubectl get pod -n kube-system
    Error from server (Forbidden): pods is forbidden: User "mrvolleyball" cannot list pods in the namespace "kube-system"
    

    (2)clusterrole绑定

    绑定clusterrole,让mrvollerball能够读取所有namespace的pod

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: mrvolleyball
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster_po_r
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: mrvolleyball
    

    这时候mrvolleyball也可以读取其他namespace的pod

    root@k8s-master:~# kubectl get pod -n kube-system
    NAME                                        READY     STATUS             RESTARTS   AGE
    calico-kube-controllers-55c94797d7-vr9k6    1/1       Running            0          15d
    calico-node-86xgg                           1/1       Running            0          7d
    calico-node-drsl2                           1/1       Running            0          7d
    calico-node-l67h4                           1/1       Running            0          7d
    coredns-794b5f8589-vgclz                    1/1       Running            4809       15d
    coredns-794b5f8589-xzpxd                    1/1       Running            0          130d
    default-http-backend-6cb5c56987-tcx92       1/1       Running            0          139d
    kubernetes-dashboard-77c46fc984-djdd4       1/1       Running            0          139d
    nginx-ingress-controller-6d95468cc8-ft6nn   1/1       Running            0          140d
    

    这里需要注意几种资源的绑定:

    rolebinding --> role
    clusterrolebinding --> clusterrole
    rolebinding --> clusterrole

    ● 第一种是namespace级别的绑定,只对role所在的namespace生效
    ● 第二种是cluster级别的绑定,对于集群所有的namespace都生效
    ● 第三种是namespace级别的绑定,只对role所在的namespace生效

    有同学要问,第一种和第三种有什么区别:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: mrvolleyball
      namespace: default
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster_po_r
    subjects:
    - apiGroup: rbac.authorization.k8s.io
      kind: User
      name: mrvolleyball
    

    区别主要是为了方便管理:
    ● 比如有10个namespace,分配给了10个不同的团队,那每个团队都需要使用自己的userAccount操作自己所在的namespace
    ● 最简单的做法,就是在10个不同namespace创建10个role,然后通过rolebinding将role绑定userAccount。如果需要添加userAccount,那这个管理成本就会升高
    ● 这时候创建一个clusterrole,由于他们对各自的namespace的行为都是一样的,那就只需要通过rolebinding将clusterrole绑定在userAccount,只需要创建1次clusterrole

    五、serviceAccount角色绑定

    serviceAccount要提供给pod内访问,或者是外部服务的访问。为了验证serviceAccount,我们来模拟pod去访问api

    首先先创建一个serviceAccount

    root@k8s-master:/etc/kubernetes/ssl# kubectl create serviceaccount helloworld
    serviceaccount "helloworld" created
    root@k8s-master:/etc/kubernetes/ssl# kubectl get sa helloworld -o yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      creationTimestamp: 2019-03-12T06:36:00Z
      name: helloworld
      namespace: default
      resourceVersion: "24381027"
      selfLink: /api/v1/namespaces/default/serviceaccounts/helloworld
      uid: 1987b4e6-4491-11e9-96bc-525400c34cf1
    secrets:
    - name: helloworld-token-sr9xb
    

    serviceAccount获取默认生成一个token,该token是用于pod访问kube-api的身份验证(详情访问上一篇文章)

    root@k8s-master:/etc/kubernetes/ssl# kubectl get secret helloworld-token-sr9xb -o yaml
    apiVersion: v1
    data:
    ...
      token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklpSjkuZXlKcGMzTWlPaUpyZFdKbGNtNWxkR1Z6TDNObGNuWnBZMlZoWTJOdmRXNTBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5dVlXMWxjM0JoWTJVaU9pSmtaV1poZFd4MElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WldOeVpYUXVibUZ0WlNJNkltaGxiR3h2ZDI5eWJHUXRkRzlyWlc0dGMzSTVlR0lpTENKcmRXSmxjbTVsZEdWekxtbHZMM05sY25acFkyVmhZMk52ZFc1MEwzTmxjblpwWTJVdFlXTmpiM1Z1ZEM1dVlXMWxJam9pYUdWc2JHOTNiM0pzWkNJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExuVnBaQ0k2SWpFNU9EZGlOR1UyTFRRME9URXRNVEZsT1MwNU5tSmpMVFV5TlRRd01HTXpOR05tTVNJc0luTjFZaUk2SW5ONWMzUmxiVHB6WlhKMmFXTmxZV05qYjNWdWREcGtaV1poZFd4ME9taGxiR3h2ZDI5eWJHUWlmUS5zTTQ3dnBMV25nVmZ1Q2c3RGRfNWlVSGFCa0loeHNvNXY1ZHotRzh3X3ctZUNaS05pZlRyUE9xd3R3QjR4MnZnS3dPaExXX2c0UWxtRDNXS3QyejhlNHVJeFV0cHZkc0lRYkdrYjVrUUdsV1p4cnZwTUZHbTF0eVRsU1lVc3gxa25GdnViWTV0bWU5Y2JkNExOc2RQQ1IxTXBBYnBkYjlqZFh6OWRxMVAyb1Z1LVVuYmVBTkFMcE5tSGJHZjFSdVRPUEJBcUNPNlI3Zm0zUUxpZFZOSDBjRUkwX1Joa0NKR2xPUi1rUlZ5bE5GYXJOVWhvQnJGSEJpTWJyOHd6UHpRNk42Z0hpblctWUc1ekFCY2JNaUR1QUZrRDBCXzBNbDlJandHaDgtbHlrSUZBTU1sbTktUS1hTjJTUjkwSnJyelRYcUtUV3NJU0ZQWHhCTUItX3BXTTlEMEhiZTU4TURCQ1VlSlp0SUcyNno4alBiU0Y1aHRuTy1YSFJRWm1CUzJoaXFLelE2aG9TMkxEa045WUdwcFRETkJUY0dySjg2U0ZQaDlkRWtaYWw0QU9XLWlfTHdEYnY0V2luQjBDOG1Pc3c1WkhDdEVxTVNUTE90aXFyOWZ3bEYzb2lldERqV3FSSXhKeG5rY1NRYTBOTHR4cENiQjFvOGRDTjlqaE1WLVRZMDdidUVNNUpJUGhzeERBMVpqTjNJenVpc3VTVWZMRjd5NkgwZ1JxaGdITzdyMVZvdU5ubGFybjNhSmxMYmF3NUk3RnIwM1ZrQ0pqSmotX0FFRmpSWGlNVmRtenM0el9nWVRfUGR0TXR4YnFfd1p5ZXJHWXpuUk9NQ3p0b2gtRlRCWktOT2dfZjBmTEN3c29rd2NJaEtWWFh2YXMtcjN0YXFBcXZEbWtOOA==
    kind: Secret
    metadata:
      annotations:
        kubernetes.io/service-account.name: helloworld
        kubernetes.io/service-account.uid: 1987b4e6-4491-11e9-96bc-525400c34cf1
      creationTimestamp: 2019-03-12T06:36:00Z
      name: helloworld-token-sr9xb
      namespace: default
      resourceVersion: "24381026"
      selfLink: /api/v1/namespaces/default/secrets/helloworld-token-sr9xb
      uid: 198c824f-4491-11e9-96bc-525400c34cf1
    type: kubernetes.io/service-account-token
    

    拿到该token,将其转码之后作为连接kube-api的身份验证

    root@k8s-master:/etc/kubernetes/ssl# token=`kubectl get secret helloworld-token-sr9xb -o yaml | grep "token:" | awk '{print $2}' | base64 -d`
    root@k8s-master:/etc/kubernetes/ssl# kubectl config set-credentials helloworld --token=$token
    User "helloworld" set.
    

    配置rolebinding,po_r这个role只能对default namespace的pod有读权限

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: helloworld-role-binding
      namespace: default
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: po_r
    subjects:
    - kind: ServiceAccount
      name: helloworld
      namespace: default
    

    尝试访问一下:

    root@k8s-master:~# kubectl config use-context context@helloworld
    Switched to context "context@helloworld".
    root@k8s-master:~# kubectl get pod
    NAME                                      READY     STATUS    RESTARTS   AGE
    busybox                                   1/1       Running   187        7d
    

    该serviceAccount也只有default namespace的访问权限

    root@k8s-master:~# kubectl get pod -n kube-system
    Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:helloworld" cannot list pods in the namespace "kube-system"
    

    六、小结

    ● 本文介绍了k8s基于权限的访问,详细k8s当中role、clusterrole与rolebinding、clusterrolebinding
    ● 并且模拟了不同类型的账户访问kube-api时不同的认证方式



    至此,本文结束
    在下才疏学浅,有撒汤漏水的,请各位不吝赐教...

  • 相关阅读:
    推荐一些学习软件编程的网站
    Git总结笔记2-克隆远程仓库到本地
    Git总结笔记3-把本地仓库推送到github
    Git总结笔记1-搭建和使用30条简明笔记
    【师兄笔记】Java记录生活
    【师兄笔记】Java入门
    学习软件技术的那些事?
    Java编程基础
    献给还不知道怎么坚持的你
    GIT 检查、撤销修改简明教程
  • 原文地址:https://www.cnblogs.com/MrVolleyball/p/10709142.html
Copyright © 2020-2023  润新知