[Kubernetes]基於角色的權限控制之RBAC

Kubernetes中有不少種內置的編排對象,此外還能夠自定義API資源類型和控制器的編寫方式.那麼,我能不能本身寫一個編排對象呢?答案是確定的.而這,也正是Kubernetes項目最具吸引力的地方.
畢竟在互聯網級別的大規模集羣裏,Kubernetes內置的編排對象,很難作到徹底知足全部需求,因此不少實際的容器化工做,都會要求設計一個本身的編排對象,實現本身的控制器模式.
因此,咱們能夠基於插件機制來完成這些工做,而不須要修改任何一行代碼.可是,若是要經過外部插件,在Kubernetes中實現新增和操做API對象,那麼就必須先了解一個很是重要的知識:RBAC.
什麼是RBAC呢?咱們知道,Kubernetes中全部的API對象,都保存在Etcd裏,可是呢,對這些API對象的操做,卻必定都是經過訪問kube-apiserver來實現的.其中一個很是重要的緣由,就是你須要APIServer來幫助你作受權工做.而在Kubernetes項目中,負責完成受權(Authorization)工做的機制,就是RABC:基於角色的訪問控制(Role-Based Access Control).
web

  • 經過這篇文章,能明確三個基本的概念,就能夠說收穫很多了:
    • Role:角色.它實際上是一組規則,定義了一組對Kubernetes API對象的操做權限
    • Subject:被做用者.既能夠是"人",也能夠是"機器",也能夠是你在Kubernetes裏定義的"用戶"
    • RoleBinding:定義了"被做用者"和"角色"的綁定關係.
  • 這三個概念,能夠說是整個RABC體系的核心所在.因此接下來詳細講解一下.
    Role

    Role自己就是一個Kubernetes的API對象,定義以下所示:api

    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      namespace: mynamespace
      name: example-role
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "watch", "list"]

    若是對這個格式比較熟悉的話,應該可以一眼看出來:首先,這個Role對象指定了它能產生做用的Namespace是:mynamespace.
    Namespace是Kubernetes項目裏的一個邏輯管理單位,不一樣Namespace的API對象,在經過kubectl命令進行操做的時候,是互相隔離開的.這只是邏輯上的"隔離".Namespace並不會提供任何實際的隔離或者多租戶能力.
    Role對象的rules字段,就是它所定義的權限規則.在這裏規則的意思就是:容許"被做用者",對mynamespace下面的Pod對象,進行GET,WATCH和LIST操做.
    那麼,這個具體的"被做用者"又是如何指定的呢?這就須要經過RoleBinding來實現了.
    svg

    Subject與RoleBinding

    RoleBinding自己也是Kubernetes的API對象.定義以下:學習

    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: example-rolebinding
      namespace: mynamespace
    subjects:
    - kind: User
      name: example-user
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: example-role
      apiGroup: rbac.authorization.k8s.io

    由上,咱們可以看到,這個RoleBinding對象裏定義了一個subjects字段,即"被做用者".它的類型是User,即Kubernetes中的用戶,這個用戶的名字是example-user.可是,在Kubernetes中,並無一個叫作"User"的API對象,這個User究竟是從哪兒來的呢?
    實際上,Kubernetes中的"User"就是"用戶",只是一個受權系統裏的邏輯概念.它須要經過外部認證服務來提供,或者也能夠直接給APIServer指定一個用戶名,密碼文件.那麼Kubernetes的受權系統,就能夠從這個文件裏找到對應的"用戶".其實在大多數私有的使用環境中,只要使用Kubernetes提供的內置"用戶",就足夠了.
    好像有點兒扯遠了.這個等下再詳細說吧.
    spa

    再往下看,可以看到roleRef字段.正是經過這個字段,RoleBinding對象就能夠直接經過名字,來引用咱們前面定義的Role對象(example-role),從而定義了"被做用者(Subject)"和"角色(Role)"之間的綁定關係.
    在這裏須要強調一下:Role和RoleBinding對象都是Namespaced對象,它們對權限的限制規則僅在它們本身的Namespace內有效,roleRef也只能引用當前Namespace中的Role對象.
    那麼,對於非Namespaced(Non-namespaced)對象(好比:Node),或者某一個Role想要做用於全部的Namespace時,咱們又該怎麼去作受權呢?
    這時,就必需要使用ClusterRole和ClusterRoleBinding這兩個組合了.這兩個API對象的用法和Role與RoleBinding徹底同樣,只不過它們的定義裏,沒有了Namespace字段.
    具體以下所示:
    插件

    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: example-clusterrole
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "watch", "list"]
    kind: ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: example-clusterrolebinding
    subjects:
    - kind: User
      name: example-user
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: example-clusterrole
      apiGroup: rbac.authorization.k8s.io

    上面的例子中,意味着名叫example-user用戶,擁有對全部Namespace裏的Pod進行GET,WATCH和LIST操做的權限.更進一步的說,在Role或者ClusterRole裏面,若是要賦予用戶example-user全部權限,那麼就能夠給它指定一個verbs字段的全集,以下所示:設計

    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

    固然,也能夠根據本身的需求,只針對某一個具體的對象進行權限設置.好比:code

    rules:
    - apiGroups: [""]
      resources: ["configmaps"]
      resourceNames: ["my-config"]
      verbs: ["get"]

    這個例子就表示,這條規則的"被做用者",只對名叫"my-config"的ConfigMap對象,有進行GET操做權限.
    在上面提了一下,大多數時候,咱們其實都不太使用"用戶"這個功能,而是直接使用Kubernetes中的"內置用戶",而這個"內置用戶"就是:ServiceAccount.
    server

    ServiceAccount分配權限的過程

    經過一個實例,來說解一下爲ServiceAccount分配權限的過程.
    首先,須要定義一個ServiceAccount.它的API對象很是簡單,以下所示:
    xml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      namespace: mynamespace
      name: example-sa

    能夠看到,一個最簡單的ServiceAccount對象,只須要Name和Namespace這兩個最基本的字段.
    而後咱們經過編寫RoleBinding的YAML文件,來爲這個ServiceAccount分配權限:

    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: example-rolebinding
      namespace: mynamespace
    subjects:
    - kind: ServiceAccount
      name: example-sa
      namespace: mynamespace
    roleRef:
      kind: Role
      name: example-role
      apiGroup: rbac.authorization.k8s.io

    接下來,咱們用kubectl命令建立這三個對象:

    $ kubectl create -f svc-account.yaml
    $ kubectl create -f role-binding.yaml
    $ kubectl create -f role.yaml

    而後,來查看一下ServiceAccount的詳細信息:

    $ kubectl get sa -n mynamespace -o yaml
    - apiVersion: v1
      kind: ServiceAccount
      metadata:
        creationTimestamp: 2018-09-08T12:59:17Z
        name: example-sa
        namespace: mynamespace
        resourceVersion: "409327"
        ...
      secrets:
      - name: example-sa-token-vmfg6

    能夠看到,Kubernetes會爲一個ServiceAccount自動建立並分配一個Secret對象.這個Secret就是這個ServiceAccount對應的,用來和APIServer進行交互的受權文件,通常稱它爲:Token.
    Token文件的內容通常是證書或者密碼,它以一個Secret對象的方式,保存在Etcd當中.
    此時,用戶的Pod就能夠聲明使用這個ServiceAccount了.

    對以上內容的總結

    上面內容有些多,最後來一個總結:
    所謂角色(Role),其實就是一組權限規則列表.分配這些權限的方式,就是經過建立RoleBinding對象,將被做用者(Subject)和權限列表進行綁定.
    另外,與之對應的ClusterRole和ClusterRoleBinding,則是Kubernetes集羣級別的Role和RoleBinding,它們的做用範圍不受Namespace限制.
    儘管權限的被做用者能夠用不少種(好比,User,Group等),但在咱們日常的使用中,最廣泛的用法仍是ServiceAccount.因此,Role+RoleBinding+ServiceAccount的權限分配方式,是最應該掌握的內容.

    以上內容來自我學習<深刻剖析Kubernetes>專欄文章以後的一些看法,有偏頗之處,還望指出. 感謝您的閱讀~

    相關文章
    相關標籤/搜索