共計 9876 個字符,預計需要花費 25 分鐘才能閱讀完成。
今天就跟大家聊聊有關怎么實現 TKE 及 Kubernetes 訪問權限控制,可能很多人都不太了解,為了讓大家更加了解,丸趣 TV 小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
下面將會向你介紹騰訊云 TKE 平臺側的訪問控制、Kubernetes 訪問控制鏈路,以及演示如何將平臺側賬號對接到 Kubernetes 內。
當你在使用騰訊云容器服務 TKE(Tencent Kubernetes Engine)的時候,如果多人共用一個賬號的情況下,是否有遇到以下問題呢?
密鑰由多人共享,泄密風險高。
無法限制其他人的訪問權限,其他人誤操作易造成安全風險。
為了解決以上問題,騰訊云 CAM(Cloud Access Management)提供了主賬號和子賬號的認證體系以及基于角色的權限控制。
而不同的子賬號對于 TKE 平臺側資源的控制粒度比較粗(cluster 實例級別),又會遇到以下問題:
同一個集群由多子賬號可訪問,無法保證集群資源級別、命名空間級別的讀寫控制。
集群的高權限子賬戶無法對低權限子賬戶進行授權管理。
為了解決以上兩個問題,TKE 針對平臺側資源、Kubernetes 資源分別進行相應的訪問控制管理。
平臺側訪問控制
首先介紹下什么是平臺側資源,平臺側資源即 Cluster 資源、CVM 資源、CLB 資源、VPC 資源等騰訊云資源,而訪問的用戶主要分為用戶和服務角色載體。
用戶就是我們平時登錄控制臺的主賬號、子賬號或者協作者賬號
服務角色是一種定義好帶有某些權限的角色,可以將這個角色賦予某個載體,可以是某個其他賬戶,也可以是騰訊云下一個產品的服務提供者,CAM 會默認為產品提供一個預設的載體和默認的角色,例如 TKE 的默認角色就是 TKE_QCSRole,而載體就是 ccs.qcloud.com。
而這個角色有什么用處呢?舉個 TKE 的例子,比如 TKE 的 service-controller 會 Watch 集群內的 Service 資源,如果需要創建 LoadBalance 類型的 Service,會通過云 API 購買并創建 CLB 資源,而 service-controller 是 TKE 平臺為用戶部署的,去訪問云 API 需要有身份,這個身份就是 ccs.qcloud.com 載體,而權限則需要用戶給載體授予一個角色,即 TKE_QCSRole。只有用戶在授權 TKE 載體之后,TKE 才可以通過服務扮演的方式代替用戶購買 CLB。下面我會簡單為你介紹如何給用戶授權,以及如何給 TKE 平臺授予角色。
定制策略
TKE 通過接入 CAM,對集群的 API 接口級別進行權限細分,需要您在 CAM 控制臺對子賬戶進行不同的權限授予。同時 TKE 也在 CAM 側提供了預設的權限,提供您默認選擇,例如:
也可以自定義策略,具體策略定制請參考 CAM 產品介紹文檔
例如擁有只讀權限的子賬戶嘗試修改集群名稱,將會在 API 接口時校驗 CAM 權限失敗
劃分用戶組
可以依據團隊的職責劃分好用戶組,將之前規劃好的自定義策略綁定到一個用戶組上,來方便的進行權限管理。例如:有新同學入職時可方便的加入指定用戶組(如運維組),就可以獲取到該用戶組的權限,避免了繁瑣的權限配置操作。
授予 TKE 角色權限
使用 TKE 容器服務需要授予 TKE 平臺為您操作 CVM\CLB\VPC\CBS 等權限,所以首次訪問 TKE 控制臺需要確保同意授權,即創建預設角色 TKE_QCSRole,此角色默認授予 TKE 載體,該載體會通過 CAM 獲取操作您集群的臨時密鑰,來進行相應的云 API 操作。
更多
更多豐富的平臺側訪問控制用法請訪問 CAM 產品說明文檔
Kubernetes 訪問控制
介紹完平臺側資源的訪問控制,我們再來看看 TKE 集群內的資源如何進行權限管理。當不同的子賬戶都擁有訪問同一個 TKE Kubernetes 集群權限之后,如何保證不同的子賬戶,對于集群內資源擁有不同的角色和權限呢?讓我們首先從社區的 Kubernetes 訪問鏈路來分析整個過程,從而向您介紹 TKE 是如何實現容器服務子賬戶對接 Kubernetes 認證授權體系的。
Overview
首先從宏觀的角度看下 Kubernetes 的請求鏈路是如何進行的。圖片來源于 k8s 社區官網。
可以大概了解到一個請求的鏈路是依次通過 Authentication(認證,簡稱 Authn)、Authorization(授權,簡稱 Authz)、AdmissionControl(準入控制),從而獲取到后端持久化的數據。
從圖中可以看到 Authn、Authz、AdmissionControl 是由多個模塊組成的,每個步驟都有多種方式構成的。
在進入認證模塊之前會將 HTTP 的 Request 進行構建 context,而 context 中就包含了用戶的 RequestInfo,userInfo、Verb、APIGroup、Version、Namespace、Resource、Path 等。
帶著這些信息,下面我們來一次看下準入過程中的每個步驟吧。
Kubernetes 認證
認證的過程的證明 user 身份的過程。
Kubernetes 中有兩類用戶,一類是 ServiceAccount,一類是集群真實的用戶。
ServiceAccount 賬戶是由 Kubernetes 提供 API(資源)進行創建和管理的,ServiceAccount 可以認為是特殊的 Secret 資源,可用戶集群內資源訪問 APIServer 的認證所用。通過可以通過 mount 的方式掛載到 Pod 內進行使用。
真實的用戶通常是從外部發起請求訪問 APIServer,由管理員進行管理認證憑證,而 Kubernetes 本身不管理任何的用戶和憑證信息的,即所有的用戶都是邏輯上的用戶,無法通過 API 調用 Kubernetes API 進行創建真實用戶。
Kubernetes 認證的方式眾多,常見的有 TLS 客戶端證書雙向認證、BearerToken 認證、BasicAuthorization 或認證代理(WebHook)
所有的認證方式都是以插件的形式串聯在認證鏈路中,只要有一種認證方式通過,即可通過認證模塊,且后續的認證方式不會被執行。
在此處參考一點點 Kubernetes APIServer Authentication 模塊的代碼,可以發現,任何的認證方式都是一下 Interface 的實現方式都是接收 http Request 請求,然后會返回一個 user.Info 的結構體,一個 bool,以及一個 error
// Request attempts to extract authentication information from a request and returns
// information about the current user and true if successful, false if not successful,
// or an error if the request could not be checked.
type Request interface { AuthenticateRequest(req *http.Request) (user.Info, bool, error)
}
user.Info 中包含了用戶的信息,包括 UserName、UUID、Group、Extra。
bool 返回了用戶是否通過認證,false 的話即返回無法通過認證,即返回 401 錯誤。
error 則返回了當 Request 無法被檢查的錯誤,如果遇到錯誤則會繼續進行下一種注冊的方式進行認證。
如果認證通過,則會把 user.Info 寫入到到請求的 context 中,后續請求過程可以隨時獲取用戶信息,比如授權時進行鑒權。
下面我會以 Kubernetes 代碼中的認證方式順序,挑選幾項認證方式,并結合 TKE 開啟的認證方式來向你介紹 TKE 創建的 Kubernetes 集群默認的認證策略。
Basic Authentication
APIServer 啟動參數 –basic-auth-file=SOMEFILE 指定 basic 認證的 csv 文件,在 APIServer 啟動之后修改此文件都不會生效,需要重啟 APIServer 來更新 basic authentication 的 token。csv 文件格式為:token,user,uid, group1,group2,group3。
請求時,需要指定 HTTP Header 中 Authentication 為 Basic,并跟上 Base64Encode(user:passward) 值。
x509 客戶端證書
APIServer 啟動參數 –client-ca-file=SOMEFILE 指定 CA 證書,而在 TKE 的 K8s 集群創建過程中,會對集群進行自簽名 CA 密鑰和證書用于管理,如果用戶下發的客戶端證書是由此 CA 證書的密鑰簽發的,那么就可以通過客戶端證書認證,并使用客戶端證書中的 CommonName、Group 字段分別作為 Kubernetes 的 UserInfo 中 Username 和 Group 信息。
目前 TKE 對接子賬戶都是通過自簽名的 CA 憑證進行簽發子賬戶 Uin 對應 CN 的客戶端證書。
Bearer Token
Bearer Token 的認證方式包含很多,比如啟動參數指定的、ServiceAccount(也是一種特殊的 BeaerToken)、BootstrapToken、OIDCIssure、WebhookToken
1. 默認指定 Token csv 文件
APIServer 啟動參數 –token-auth-file=SOMEFILE 指定 Bearer Token 認證的 csv 文件。和 Basic Authentication 方式相似,只不過請求 APIServer 時,指定的 HTTP 認證方式為 Bearer 方式。此 Bearer 后直接跟 passward 即可。csv 文件格式為:password,user,uid, group1,group2,group3。
請求時,需要指定 HTTP Header 中 Authentication 為 Bearer,并跟上 Base64Encode(user:passward) 值。
2. ServiceAccount
ServiceAccount 也是一種特殊 beaer token,ServiceAccount 在 Kubernetes 中是一種資源,創建一個 ServiceAccount 資源之后默認會創建一個 Secret 資源,而 Secret 資源中就包含了一個 JWT 格式的 Token 字段,以 Bearer Token 的方式請求到 Kube-APIServer,Kube-APIServer 解析 token 中的部分 user 信息,以及 validate 以下 ServiceAccount 是否存在即可進行認證檢查。這種方式即之前提到的“兩種用戶”中常見的集群內認證方式,ServiceAccount,主要用于集群內資源訪問 APIServer,但不限于集群內。
3. BootstrapToken
此項開關在 Kubernetes v1.18 版本中才為 stable 版本,此類 Token 是專門用來引導集群安裝使用的,需要配合 controller-manager 的 TokenCleaner。
目前 TKE 默認開啟此配置。
4. OpenID Connect Tokens
OIDCToken 的認證方式是結合 OAuth3 向身份提供方獲取 ID Token 來訪問 APIServer。
如需要開啟此項功能,需要在 APIServer 的啟動參數中指定 oidc 的配置參數,例如 –oidc-issuer-url 指定 oidc 身份提供方的地址,–oidc-client-id 指定身份提供方側的賬戶 ID,–oidc-username-claim 身份提供方的用戶名。
具體可參考 Kubernetes 官方文檔,目前公有云 TKE 沒有使用此參數對接騰訊云賬戶,因為涉及用戶需要主動登錄授權后才可返回 Id Token,和當前官網交互沖突,可以在后續 CLI 工具中實現。
5. Webhook Token Server
Webhook Token 是一種 hook 的方式來校驗是否認證通過。
APIServer 啟動參數 –authentication-token-webhook-config-file 及 –authentication-token-webhook-cache-ttl 來分別指定 Webhook 地址以及 token 的 cache ttl。
若 APiServer 開啟此方式進行認證校驗,則在接受到用戶的 Request 之后,會包裝 Bearer Token 成一個 TokenReview 發送給 WebHookServer,Server 端接收到之后會進行校驗,并返回 TokenReview 接口,在 status 字段中進行反饋是否通過校驗通過和 user.Info 信息。
總結
以上即為 Kubernetes APIServer 認證的幾種方式,TKE 在每種認證方式都有支持。供用戶靈活使用。
目前 TKE 正在推使用 x509 客戶端證書方式來進行認證管理,以方便進行對接子賬戶的創建、授權管理、更新。
Kubernetes 授權
Kubernetes 的授權模式支持一下幾種,和認證一樣,參考開始說的 RequestInfo context,可知用戶 Reqeust 的 context 除了認證需要的 userInfo,還有一些其他的字段例如 Verb、APIGroup、APIVersion、Resource、Namespaces、Path……
授權就是判斷 user 是否擁有操作資源的相應權限。
Kubernetes 支持 AlwaysAllow、AlwaysDeny、Node、ABAC、RBAC、Webhook 授權 Mode,和認證一樣,只要有一種鑒權模塊通過,即可返回資源。
在這里重點介紹下面兩種方式
RBAC
RBAC(Role-Based Access Control),Kubernetes 提供 ClusterRole、Role 資源,分別對應集群維度、Namespace 維度角色權限管控,用戶可以自定義相應的 ClusterRole、Role 資源,綁定到已經認證的 User 之上。
如下 tke:pod-reader ClusterRole,定義了該角色可以訪問 core apigroup 下面對 pods 資源的 get/watch/list 操作
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: tke:pod-reader
rules:
- apiGroups: [ ] # 指定核心 API 組
resources: [pods]
verbs: [get , watch , list]
apiVersion: rbac.authorization.k8s.io/v1
# 此角色綁定使得用戶 alex 能夠讀取 default 命名空間中的 Pods
kind: ClusterRoleBinding
metadata:
name: alex-ClusterRole
subjects:
- kind: User
name: alex
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: tke:pod-reader # 這里的名稱必須與你想要綁定的 Role 或 ClusterRole 名稱一致
apiGroup: rbac.authorization.k8s.io
通過以上的 yaml 配置,通過認證模塊到達授權模塊的 requestInfo 中 userInfo 信息是 alex 的請求,在授權模塊中走到 RBAC 授權模塊時,則會進行查詢集群的 ClusterRole/ClusterRoleBinding 信息。進行判斷是否擁有 context 相應操作的權限。
TKE 的對接子賬戶的權限授權策略就是使用的 Kubernetes 原生的 RBAC 進行對子賬戶資源訪問控制,這樣符合原生,符合有 K8s 使用習慣的用戶。
WebHook
Webhook 模式是一種基于 HTTP 回調的方式,通過配置好授權 webhook server 地址。當 APIServer 接收到 request 的時候,會進行包裝 SubjectAccessReview 請求 Webhook Server,Webhook Server 會進行判斷是否可以訪問,然后返回 allow 信息。
以下是 kubernetes 社區一個例子,以供參考。
{
apiVersion : authorization.k8s.io/v1beta1 ,
kind : SubjectAccessReview ,
spec : {
resourceAttributes : {
namespace : kittensandponies ,
verb : get ,
group : unicorn.example.org ,
resource : pods
},
user : alex ,
group : [
group1 ,
group2
]
}
apiVersion : authorization.k8s.io/v1beta1 ,
kind : SubjectAccessReview ,
status : {
allowed : true
}
}
目前 TKE 沒有考慮使用 Webhook 的模式,但是 Webhook 模式提供了強大的靈活性,比如對接 CAM,實現 K8s 權限對接到平臺側,但是也有一定的風險和挑戰,比如依賴 CAM 的穩定性;請求延遲、緩存 /TTL 的配置;CAM action 配置與 K8s 權限對應關系。此項授權模式仍然在考慮中,有需求的用戶可以反饋。
準入控制
什么是 admission controller?
In a nutshell, Kubernetes admission controllers are plugins that govern and enforce how the cluster is used.
Admission controllers 是 K8s 的插件,用來管理和強制用戶如何來操作集群。
Admission controllers 主要分為兩個 phase,一個是 mutating,一個是 validating。這兩個階段都是在 authn authz 之后的,mutating 做的變更準入,就是會對 request 的 resource,進行轉換,比如填充默認的 requestLimit?而 validating admission 的意思就是驗證準入,比如校驗 Pod 副本數必須大于 2。
API Server 請求鏈路:
ValidatingAdmissionWebhooks and MutatingAdmissionWebhooks, both of which are in beta status as of Kubernetes 1.13.
k8s 支持 30 多種 admission control 插件,而其中有兩個具有強大的靈活性,即 ValidatingAdmissionWebhooks 和 MutatingAdmissionWebhooks,這兩種控制變換和準入以 Webhook 的方式提供給用戶使用,大大提高了靈活性,用戶可以在集群創建自定義的 AdmissionWebhookServer 進行調整準入策略。
TKE 中 1.10 及以上版本也默認開啟了 ValidatingAdmissionWebhooks、MutatingAdmissionWebhooks
了解更多 Admission Controller 參考這里
kubernetes 權限對接子賬戶
TKE 權限實現對接子賬戶主要的方案是:x509 客戶端認證 +Kubernetes RBAC 授權。
認證
每個子賬戶都擁有單獨的屬于自己的客戶端證書,用于訪問 KubernetesAPIServer。
用戶在使用 TKE 的新授權模式時,不同子賬戶在獲取集群訪問憑證時,即前臺訪問集群詳情頁或調用 DescribeClusterKubeconfig 時,會展示子賬戶自己的 x509 客戶端證書,此證書是每個集群的自簽名 CA 簽發的。
該用戶在控制臺訪問 Kubernetes 資源時,后臺默認使用此子賬戶的客戶端證書去訪問用戶 Kubernetes APIServer。
支持子賬戶更新自己的證書。
支持主賬戶或集群 tke:admin 權限的賬戶進行查看、更新其他子賬戶證書。
授權
TKE 控制臺通過 Kubernetes 原生的 RBAC 授權策略,對子賬戶提供細粒度的 Kubernetes 資源粒度權限控制。
提供授權管理頁,讓主賬號和集群創建者默認擁有管理員權限,可以對其他擁有此集群 DescribeCluster Action 權限的子賬戶進行權限管理。
并提供預設的 ClusterRole。
開發人員(tke:ns:dev):對所選命名空間下控制臺可見資源的讀寫權限,需要選擇指定命名空間。
只讀用戶(tke:ns:ro):對所選命名空間下控制臺可見資源的只讀權限,需要選擇指定命名空間。
管理員(tke:admin):對所有命名空間下資源的讀寫權限,對集群節點,存儲卷,命名空間,配額的讀寫權限,可子賬號和權限的讀寫權限
運維人員(tke:ops):對所有命名空間下控制臺可見資源的讀寫權限,對集群節點,存儲卷,命名空間,配額的讀寫權限
開發人員(tke:dev):對所有命名空間下控制臺可見資源的讀寫權限
受限人員(tke:ro):對所有命名空間下控制臺可見資源的只讀權限
用戶自定義 ClusterRole
所有命名空間維度:
指定命名空間維度:
所有預設的 ClusterRole 都將帶有固定 label:cloud.tencent.com/tke-rbac-generated: true
所有預設的 ClusterRoleBinding 都帶有固定的 annotations:cloud.tencent.com/tke-account-nickname: yournickname,及 label:cloud.tencent.com/tke-account: yourUIN
更多
當然,除了 TKE 控制臺提供的預設授權策略,管理員也可以通過 kubectl 操作 ClusterRole/Role 來實現自定義角色的靈活配置細粒度權限,以及操作 ClusterRoleBinding/RoleBinding 進行權限綁定,綁定到任意的角色權限之上。
例如你想設置 CAM 側用戶組為 productA 產品的 pod-dev 的用戶權限只能夠 get/list/watch product- a 命名空間下的 pods 資源,則你可以這樣操作:
創建自定義 ClusterRole/Role:dev-pod-reader,yaml 實例如下,文件名為 developer.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole # 這里使用 ClusterRole 可以復用給產品其他命名空間
metadata:
name: pod-dev # pod-dev 此角色為只能讀取 pod 的開發
rules:
- apiGroups: [ ] # 指定核心 API 組
resources: [pods]
verbs: [get , watch , list]
使用 kubectl 或者通過 TKE 控制臺 YAML 創建資源創建上述 Role
綁定 dev 用戶組下的 dev1、dev2、dev3 用戶,綁定自定義權限 pod-dev 到 product- a 命名空間下
從此 dev1,dev2,dev3 用戶則只能使用 get/list/watch 訪問 product- a 下的 pods 資源
$ kubectl --kubeconfig=./dev.kubeconfig get pods
Error from server (Forbidden): pods is forbidden: User 10000001xxxx-1592395536 cannot list resource pods in API group in the namespace default
$ kubectl --kubeconfig=./dev.kubeconfig get pods -n product-a
No resources found.
看完上述內容,你們對怎么實現 TKE 及 Kubernetes 訪問權限控制有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注丸趣 TV 行業資訊頻道,感謝大家的支持。