如何保證`Kubernetes`系統(tǒng)安全?我們可以從以下三大部分進行學(xué)習(xí),、研究和設(shè)計:首當其沖的就是`apiserver`,,他是系統(tǒng)安全三板斧中的第一道關(guān)卡,其作用為:who,?誰能進入我們的`kubernetes`集群,,這個誰可以是客戶端用戶、應(yīng)用程序,,也可以是集群中的`node`節(jié)點,。你可能對后半句話有些疑慮。防范外部的訪問我是知道的,,為什么還要防范集群內(nèi)部的請求呢,?容我先來舉個栗子,如果你了解,、運維過`spring cloud`,,那你應(yīng)該會碰到這個難題:每個環(huán)境我們都有注冊中心`eureka`,那我們?nèi)绾伪U蠎?yīng)用不會出現(xiàn)亂注冊的情況呢,? 比如:生產(chǎn)環(huán)境的應(yīng)用注冊到測試環(huán)境的`eureka`?測試環(huán)境的應(yīng)用注冊到生產(chǎn)環(huán)境的`eureka`,?無論哪個情況發(fā)生,都是很致命的,!也許你會考慮,,借助一系列配置管理的規(guī)范或者`ITIL`流程,又或者基于人員角色的分而治之來規(guī)避這個情況的發(fā)生,,但這都是治標不治本的,!重點在于缺少雙向認證的功能!換句話來說就是:誰能注冊到我這里來,,我是要有驗證的,,而不是隨便讓你可以進行服務(wù)的注冊。這個雙向認證的思想,,在`kubernetes`中尤為重要,,不是所有知道我們集群主節(jié)點信息或者`join`信息的節(jié)點都可以肆意加入集群,這是很有風險的,。`kubernetes`的`bootstrap token`引導(dǎo)令牌(會在后面章節(jié)講解)就此誕生,!他會向已知可信任的`node`節(jié)點頒發(fā)一個引導(dǎo)令牌,其中會有一個失效期,可能是12小時,,也可能是1天,,這取決于集群管理員的配置。 他會告訴`node`節(jié)點,,你必須要在這段時間內(nèi)加入集群,,否則我就不信任你了,你也就不能再加入集群了,。同時`apiserver`也通過各種`https`證書,,保證了集群內(nèi)外部的數(shù)據(jù)交互的安全。 接著就是系統(tǒng)安全三板斧中的第2道關(guān)卡:RBAC,!基于角色的訪問控制(`Role-Based Access Control`, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group實現(xiàn)授權(quán)決策,,允許管理員通過`Kubernetes API`動態(tài)配置策略,其職責為:what,?對于已知的客戶端用戶,,他們需要什么的權(quán)限,他們能夠操作什么類型的資源,,這就是他所負責的事情了,。? 首先,定義一個服務(wù)賬號`service account`,,也就是定義角色,; ? 接著,定義一個`role`策略,,比如:允許查看`pod`,,禁止`describe`pod等; ? 最后,,將定義好的角色和`role`策略進行綁定(`binding`)即可,。 ? `role`+`rolebinding`=作用于對應(yīng)名稱空間的策略; ? `clusterrole`+`clusterrolebinding`=作用域集群級別的策略,; ? `clusterrole`+`rolebinding`=作用于對應(yīng)名稱空間的策略,,作用同第一條,。其好處是更靈活更簡潔,。 如果你配置過jumpserver的用戶組、機器組和授權(quán),,想必很好理解,。// Admission Controller //最后,把手整個系統(tǒng)安全的就是`Admission Controller`準入控制器了,。 對于已知用戶,,他可以管理(可能是查看、也可能是新建,、也可能會刪除等等)其命名空間或者對應(yīng)集群下的所有授權(quán)資源,。但這里有一個問題,!不知道,你想到了沒有,?如何去校驗用戶的操作是否合規(guī)呢,?例如:是否在`yaml`中配置了`limits`和`requets`字段,又或者研發(fā)人員配置的這兩個字段是否合理,?這也是十分重要的一個環(huán)節(jié),,對于初創(chuàng)公司或者是`kubernetes`初建設(shè)團隊,這個環(huán)節(jié)可能也可容許暫時被忽略,,大家基于一定的自覺,、團隊研發(fā)和上線流程的規(guī)范,來軟限制這點,。但當你的團隊,、集群越來越大的時候,`Admission Controller`準入控制器的上線和把控是缺一不可的,!以下所有操作都基于創(chuàng)建的`ilinux`用戶進行,,并且每個操作之前需要刪除之前配置過的權(quán)限,否則會相互影響應(yīng)用場景:某個名稱空間級別的權(quán)限授權(quán)我們先編輯`role:res-reader.yaml`,,定義規(guī)則為:`default`名稱空間下,,只能`get`、`list`和`watch`相關(guān)資源:kind: Role #名稱空間權(quán)限 apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default #只能讀取default名稱空間下的對應(yīng)規(guī)則 name: res-reader rules: - apiGroups: [''] # '' 表示核心群組:core API group resources: ['pods', 'pods/log', 'services'] verbs: ['get', 'list', 'watch'] 然后我們來定義授權(quán)綁定`rolebinding:ilinux-res-reader.yaml`,,其作用是將`ilinux`用戶,,綁定到我們上面定義的名為`res-reader`的權(quán)限上。kind: RoleBinding #名稱空間級別權(quán)限綁定;ClusterRoleBinding為集群級別的權(quán)限綁定 apiVersion: rbac.authorization.k8s.io/v1 metadata: name: ilinux-res-reader #增加可讀性,,命名規(guī)則:<用戶>-<權(quán)限> namespace: default subjects: - kind: User name: ilinux apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: res-reader apiGroup: rbac.authorization.k8s.io 依次`apply`配置文件,,發(fā)現(xiàn)`ilinux`用戶在`default`名稱空間下有對應(yīng)`pods`, `pods/log`, `services`的對應(yīng)權(quán)限,和預(yù)期一樣[root@centos-1 RBAC]# kubectl get pod --kubeconfig=/tmp/ilinux.kubeconfig NAME READY STATUS RESTARTS AGEngx-new-cb79d555-hfc7h 1/1 Running 0 10d [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11d [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig -n ingress-nginx Error from server (Forbidden): services is forbidden: User 'ilinux' cannot list resource 'services' in API group '' in the namespace 'ingress-nginx' 2.ClusterRole+ClusterRoleBinding應(yīng)用場景:k8s集群級別的權(quán)限授權(quán)編輯`ClusterRole:cluster-res-reader.yaml`,。kind: ClusterRole #集群范圍權(quán)限 apiVersion: rbac.authorization.k8s.io/v1 metadata: name: cluster-res-reader rules: - apiGroups: [''] # '' 表示核心群組:core API group resources: ['pods', 'pods/log', 'services'] verbs: ['get', 'list', 'watch'] 編輯`ClusterRoleBinding:cluster-ilinux-res-reader.yaml`,。kind: ClusterRoleBinding #ClusterRoleBinding為集群級別的權(quán)限綁定 apiVersion: rbac.authorization.k8s.io/v1 metadata: name: cluster-ilinux-res-reader #增加可讀性,命名規(guī)則:<用戶>-<權(quán)限> subjects: - kind: User name: ilinux apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: cluster-res-reader apiGroup: rbac.authorization.k8s.io 依次`apply`配置文件,,并通過以下命令觀察權(quán)限生成情況,。[root@centos-1 RBAC]# kubectl get clusterrole [root@centos-1 RBAC]# kubectl get clusterrolebinding 這時,我們發(fā)現(xiàn)`ilinux`用戶已經(jīng)具有集群級別(所有名稱空間)的對應(yīng)權(quán)限,。[root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-controller NodePort 10.99.160.254 <none> 80:30080/TCP,443:30443/TCP 26h [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11d 3.ClusterRole+RoleBinding應(yīng)用場景:交叉使用,,其中`ClusterRole`策略會降級成`rolebinding`名稱空間級別的策略,效果和`role+rolebinding`一樣,。好處:在名稱空間很多的時候,,重復(fù)權(quán)限的配置文件會少一半,而且更靈活。使用上面的`ClusterRole`(`cluster-res-reader.yaml`),,并`apply-f`,,編輯`rolebinding`:`cluster-default-ilinux-res-reader.yaml`。kind: RoleBinding #名稱空間級別權(quán)限綁定;ClusterRoleBinding為集群級別的權(quán)限綁定 apiVersion: rbac.authorization.k8s.io/v1 metadata: name: cluster-default-ilinux-res-reader #增加可讀性,,命名規(guī)則:<用戶>-<權(quán)限> namespace: default subjects: - kind: User name: ilinux apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: cluster-res-reader apiGroup: rbac.authorization.k8s.io 測試和預(yù)期一樣,,`ClusterRole`降級成`default`名稱空間的權(quán)限了[root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 11d [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig -n ingress-nginx Error from server (Forbidden): services is forbidden: User 'ilinux' cannot list resource 'services' in API group '' in the namespace 'ingress-nginx'
|