K8S 安全機制 node
1、K8S的安全框架linux
• 訪問K8S集羣的資源須要過三關:認證、鑑權、准入控制
• 普通用戶若要安全訪問集羣API Server,每每須要證書、Token或者用戶名+密碼;Pod訪問,好比ingress控制器Ui的Dashboard都須要ServiceAccount,主要是讓這個容器可以訪問這個API,也就是全部的交互都是經過API的,這可能經過一我的去經過kubectl去交互,也有可能你的程序去調用API,但這些都是須要受權的nginx
• K8S安全控制框架主要由下面3個階段進行控制,每個階段都支持插件方式,經過API Server配置來啓用插件。 web
說在前面的話,也就是每一個階段都是插件化的設計,能夠本身開發插件,把這些集成到步驟裏面,來實現相關的訪問控制,這樣的話你就不須要去修改原有的代碼去增長了,因此k8s設計原則有不少都是以擴展性去設計的,都儘量的讓用戶自定義一些東西,集成到裏面。
json
接下來看一張圖,這是訪問API經歷的一些階段
從上面kubectl、API、UI,訪問的是k8sAPI,k8s的API提供了不少的接口vim
這些都是Apiserver去提供的,也支持不一樣的功能,來完成相關的處理的,相關的認證,再往下就是API內置有三層的受權,第一層就是認證,第二層就是鑑權,第三層就是准入控制,而後經過以後就能夠訪問相關的資源了,這些資源都是從ETCD中去調用的,一些存儲狀態的信息api
傳輸安全:
如今k8s都已經改爲https進行訪問,也就是無論你是kubeadm部署仍是二進制部署,他都是建議你使用https進行全棧的通訊,告別8080,使用6443安全
認證:
API收到用戶發送的請求以後,他會先認證,認證它這邊有三個能夠作到
三種客戶端身份認證: bash
• HTTPS 證書認證:基於CA證書籤名的數字證書認證,也就是k8s,CA簽出來的證書能夠做爲你客戶端訪問攜帶的證書,它會幫你認證,這是一種方式,從這個證書裏面去提取你有沒有權限去訪問。
• HTTP Token認證:經過一個Token來識別用戶。
• HTTP Base認證:用戶名+密碼的方式認證,這是基於http自身的一個認證,不過這個不多人去用,由於安全係數比較低。框架
第一關就是標識你是用哪一個證書進來的,仍是token標識進來的,看看我這裏是否是可信任的,看看我這個token我這裏有沒有相關的受權,也就是我這裏有沒有這個token,若是沒有就不容許經過,而後下面就不會再進行了,若是經過的話,就好比本地已經建立這個token了,有的話就給你放行,進行下一個判斷,也就是第二關受權。
受權:
RBAC(Role-Based Access Control,基於角色的訪問控制):負責完成受權(Authorization)工做。也就是會查看你的訪問符不符合權限,因此它會在這個地方去給你判斷,若是你來的這個身份,雖然有這個身份,可是沒有這個權限訪問這個資源,也會不容許你經過。
受權的資源有不少類型的支持
准入控制:
簡單講就是開發將一些高級的功能,直接插件化的去設計,也就是准入控制器就是一個插件的集合,集合裏面就有一些高級的特性,都是以插件去實現的,若是不啓用這些插件的話,那你就使用不了這個功能,這也就是第三關,也就是你的請求會通過你的插件准入控制,准入控制呢會給你效驗請求的實現的這個方法,到底這個插件有沒有啓用這一塊,不過大多數的方式默認的插件都是啓用的,啓動以後來請求相關的資源,纔會被容許,由於它啓用插件了,若是沒啓動的話也會不經過
Adminssion Control其實是一個准入控制器插件列表,發送到API Server的請求都須要通過這個列表中的每一個准入控制器,插件的檢查,檢查不經過,則拒絕請求。
1.11版本以上推薦使用的插件:
--enable-admission-plugins= \
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
使用RBAC受權
RBAC(Role-Based Access Control,基於角色的訪問控制),容許經過Kubernetes API動態配置策略。也就是即便配置,即時生效,不須要重啓服務
角色
• Role:受權特定命名空間的訪問權限
• ClusterRole:受權全部命名空間的訪問權限
角色綁定
• RoleBinding:將角色綁定到主體(即subject)
• ClusterRoleBinding:將集羣角色綁定到主體
主體(subject)
• User:用戶
• Group:用戶組
• ServiceAccout: 服務帳號
要作一個權限的管理系統,有兩塊,第一塊就是對象是誰,建立的用戶,第二就是權限組,好比建立一個開發組,開發組有哪些權限,能夠訪問這個系統,這也是爲了方便去管理這些權限,來劃分這個權限組,每一個用戶都給他建立一個權限很麻煩,有這個組的話,直接將用戶加入這個組裏面就能夠了,好比來一個開放,並給他設置權限,他是一個來賓用戶的組,這個組裏面只能查看一些東西,可是他是一個開發組的,對一些項目有一些開發權限,管理員進去呢,在這個管理頁面去再去加一個開發組,這樣的話他就有開發組的權限了
K8s和剛纔說的其實都是同樣的,用戶就是這個主體,就是誰來訪問,而後權限組呢就是角色,定義了一組權限的集合,用戶要想將用戶與權限集合作一個附加,將開發附加一個權限組,就稱爲角色綁定,角色裏面又分爲了,角色及集羣角色,集羣角色是受權集羣命名空間的,
也就是k8s有命名空間這一說,因此有分爲了單個命名空間和全部命名空間,這個權限集合的設置,ClusterRole也就是受權全部命名空間,也就是說將某個用戶加入這個權限角色裏,那就意味着它能夠訪問全部命名空間,相關的一些權限。
示例:爲zhaocheng用戶受權default命名空間Pod讀取權限
好比就是隻能查看pod默認的空間的運行的一些資源,像svc,日誌是沒有權限查看的,當你試用期過了以後,再給你加一些權限,再作一些相關的操做
實現這個目標須要完成如下三步
建立RBAC權限策略
Ca.crt 和 Ca.key就是這兩個須要簽發的證書
[root@k8s-master ~]# ls /etc/kubernetes/pki/ apiserver.crt apiserver.key ca.crt front-proxy-ca.crt front-proxy-client.key apiserver-etcd-client.crt apiserver-kubelet-client.crt ca.key front-proxy-ca.key sa.key apiserver-etcd-client.key apiserver-kubelet-client.key etcd front-proxy-client.crt sa.pub
[root@k8s-master ~]# cd demo/ [root@k8s-master demo]# mkdir rbac [root@k8s-master demo]# cd rbac/ [root@k8s-master rbac]# rz -E rz waiting to receive. [root@k8s-master rbac]# ls cert.sh cfssl.sh config.sh rbac.yaml [root@k8s-master rbac]# cat cfssl.sh wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 chmod +x cfssl* mv cfssl_linux-amd64 /usr/bin/cfssl mv cfssljson_linux-amd64 /usr/bin/cfssljson mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo [root@k8s-master rbac]# sh cfssl.sh
而後這裏咱們把咱們證書籤發的腳本拿過來,這裏注意的是簽發用戶的CN這裏是指簽發用戶的用戶名,就是說k8s拿這個CA來認證,它不單效驗是否是我頒發的證書,還要效驗裏面的用戶名,就是CN這個字段是否是受權過的,至關於鑑權那一塊,O是用戶組,也能夠基於這個用戶組去作這個權限限制
[root@k8s-master rbac]# chmod +x cert.sh [root@k8s-master rbac]# vim cert.sh cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "client auth" ], "expiry": "87600h" } } } } EOF cat > zhaocheng-csr.json <<EOF { "CN": "zhaocheng", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes zhaocheng-csr.json | cfssljson -bare zhaocheng [root@k8s-master rbac]# bash cert.sh
主要生成的就是zhaocheng-key.pem zhaocheng.pem
[root@k8s-master rbac]# ls ca-config.json cert.sh cfssl.sh config.sh rbac.yaml zhaocheng.csr zhaocheng-csr.json zhaocheng-key.pem zhaocheng.pem
須要用這兩個證書來對客戶端作請求認證,寫到客戶端受權文件裏,用這個受權文件就能請求這個k8s集羣了
好比公司有多個集羣,那麼這個開發須要登陸這個集羣,須要這個config證書,到時候能夠拿這個來回切換登陸不一樣的集羣
--kubeconfig=zhaocheng.kubeconfig
[root@k8s-master rbac]# vim config.sh kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/pki/ca.crt \ --embed-certs=true \ --server=https://192.168.30.21:6443 \ --kubeconfig=zhaocheng.kubeconfig 設置客戶端認證 kubectl config set-credentials zhaocheng \ --client-key=zhaocheng-key.pem \ --client-certificate=zhaocheng.pem \ --embed-certs=true \ --kubeconfig=zhaocheng.kubeconfig 設置默認上下文 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=zhaocheng \ --kubeconfig=zhaocheng.kubeconfig 設置當前使用配置 kubectl config use-context kubernetes --kubeconfig=zhaocheng.kubeconfig [root@k8s-master rbac]# bash config.sh [root@k8s-master rbac]# cat zhaocheng.kubeconfig
如今就能夠拿這個kubeconfig去訪問集羣了
到這呢實際上是到認證這個地方給打回去了,node節點是沒有訪問權限的,已經識別出來是zhaocheng用戶了,可是鑑權這塊沒有相關的受權,因此如今要爲這個用戶受權
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig node Error from server (Forbidden): nodes is forbidden: User "zhaocheng" cannot list resource "nodes" in API group "" at the cluster scope
若是有一個組的命名空間,權限比較大,就是能夠訪問全部命名空間,好比運維來說,有不少的運維,能夠建立集羣的角色,這樣它是管控全部命名空間的角色,這個角色就是針對於特定的命名空間的,好比開發,測試,它只能訪問命名空間的項目,它負責的項目,而後可使用這個指定命名空間,而後就是集羣的綁定,而後綁定到zhaocheng這個用戶身上,這裏我定義的是user,也能夠是group組。
pod也是不能訪問的
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod Error from server (Forbidden): pods is forbidden: User "zhaocheng" cannot list resource "pods" in API group "" in the namespace "default"
[root@k8s-master rbac]# vim rbac.yaml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-pods namespace: default subjects: - kind: User name: zhaocheng apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io [root@k8s-master rbac]# kubectl create -f rbac.yaml
而後如今就能夠進行訪問了
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod NAME READY STATUS RESTARTS AGE my-pod 1/1 Running 0 10h nfs-744d977b46-dh9xj 1/1 Running 0 29h nfs-744d977b46-kcx6h 1/1 Running 0 29h nfs-744d977b46-wqhc6 1/1 Running 0 29h nfs-client-provisioner-fbc77b9d4-kkkll 1/1 Running 0 11h nginx-797db8dc57-tdd5s 1/1 Running 0 8h nginx-a1-6d5fd7b8dd-w647x 1/1 Running 0 4h55m nginx-statefulset-0 1/1 Running 0 7h7m nginx-statefulset-1 1/1 Running 0 7h6m nginx-statefulset-2 1/1 Running 0 7h6m web-0 1/1 Running 0 4h55m web-1 1/1 Running 0 4h53m web-2 1/1 Running 0 4h52m
可是svc是沒有定義的因此還不能訪問
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig svc Error from server (Forbidden): services is forbidden: User "zhaocheng" cannot list resource "services" in API group "" in the namespace "default"
好比咱們加一個別的訪問權限,好比service,deployment
在剛纔咱們的rbac的策略裏面加上這些權限
- apiGroups: [""] resources: ["pods","services"] verbs: ["get", "watch", "list"]
再來測試一下,已經能夠正常去訪問svc了
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 30h my-service ClusterIP None <none> 80/TCP 7h22m nginx ClusterIP None <none> 80/TCP 4h59m service NodePort 10.1.207.32 <none> 80:30963/TCP 8h zhao ClusterIP 10.1.75.232 <none> 80/TCP 7h31m zhaocheng ClusterIP 10.1.27.206 <none> 80/TCP 7h33m
像其餘的受權能夠查看官方提供
https://kubernetes.io/docs/reference/access-authn-authz/rbac/