Kubernetes是一個分佈式集羣管理工具, 保證集羣的安全性是一個重要任務. API Server是集羣內部各個組件通訊的中介, 也是外部控制的入口. 因此Kubernetes的安全機制基本圍繞保護API Server來設計. Kubernetes使用了認證(Authentication), 鑑權(Authorization), 准入控制(Admission Control)三步來保證API Server的安全node
HTTP Token的認證是用一個很長的特殊編碼方式的而且難以被模仿的字符串-token來表達客戶的一種方式. Token是一個很長的很複雜的字符串, 每一個token對應一個用戶名存儲在API Server能訪問的文件中. 當客戶點發起API 調用時, 須要在HTTP Header裏放入tokenlinux
用戶名+ : + 密碼用BASE64算法進行編碼後的字符串放在HTTP Request中的Heather Authorization域裏發送給服務端, 服務端收到後進行編碼, 獲取用戶名及密碼算法
token是使用API Server私鑰簽名的JWT. 用於訪問API Server時, server端認證json
ca.crt, 根證書. 用於Client端驗證API Server發送的證書api
namespace 表示這個service-account-token的做用域名空間安全
Kubernetes組件對API Server的訪問: kubectl、Controller Manager、Scheduler、kubelet、kube-proxy分佈式
Kubernetes管理的Pod對容器的訪問: Pod(dashborad也是以Pod形式運行)ide
Controller Manager、Scheduler與API Server在同一臺機器, 因此直接使用API Server的非安全端口訪問, --insecure-bind-address=127.0.0.1工具
Kubectl、kubelet、kube-proxy訪問API Server就須要證書進行HTTPS雙向認證測試
手動簽發: 經過K8S集羣的跟CA進行簽發HTTPS證書
2 .須要認證的節點
兩種類型
安全性說明:
證書頒發
3 . kubeconfig
kubeconfig文件包含集羣參數(CA證書、API Server地址), 客戶端參數(上面生成的證書和私鑰), 集羣context信息(集羣名稱, 用戶名). Kubernetes組件經過啓動時指定不一樣的kubeconfig文件能夠切換到不一樣的集羣
4 .ServiceAccount
Pod中的容器訪問API Server, 由於Pod的建立、銷燬是動態的, 因此要爲他手動生成證書就不可行了. Kubernetes使用了 Service Account解決Pod訪問API Server的認證問題
5 .Secret與SA關係
Kubernetes設計了一種資源對象 Secret. 分爲兩類 1. 用於 ServiceAccount的service-account-token, 2. 用於保存用戶自定義保密信息的Opaque. Service Account中用到包含三個部分 : Token ca.crt namespace
kubectl get secret --all-namespaces kubectl describe secret default-token-fpmdh --all-namespaces
默認狀況下, 每一個namespace都會有一個ServiceAccount, 若是Pod在建立時沒有指定ServiceAccount, 就會使用Pod所需的namespace的ServiceAccount
認證過程, 只是確認通訊的雙方是可信的, 能夠互相通訊. 而鑑權是肯定請求方有哪些資源的權限.API Server目前支持如下幾種受權策略(經過API Server啓動參數 --authorization-mode 設置)
AlwaysDeny: 表示拒絕全部的請求, 通常用於測試
AlwaysAllow: 容許接受全部的請求, 通常用於測試
ABAC(Attribute-Based Access Control) : 基於屬性的訪問控制, 表示使用用戶配置的受權規則對用戶請求進行匹配和控制 (已經被淘汰, 不能及時更新)
Webbook: 經過調用外部REST服務對用戶進行受權
RBAC(Role-Based Access Control)基於角色的訪問控制, 在Kubernetes1.5引入, 稱爲默認標準. 相比其餘方式, 擁有如下優點:
對集羣中的資源和非資源均擁有完整的覆蓋
整個RBAC徹底由幾個API對象完成, 同其餘API對象同樣, 能夠用kubectl或API進行操做
RBAC引入了4個新的頂級資源對象: Role 、ClusterRole 、RoleBinding 、ClusterRoleBinding 4種對象類型都可以經過kubectl與API操做
Kubernetes並不會提供用戶管理, Kubernetes組件(kubectl、kube-proxy)或是其餘定義的用戶在向CA申請證書時, 須要提供一個證書請求文件
{ "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names":[ { "c": "CN", "ST": "HangZhou", "L": "XS", "O": "system:masters", "OU": "System" } ] }
API Server會把客戶端證書的CN字段做爲User, 把names.O字段做爲Group
kubelet使用TLS Bootstraping認證時, API Server可使用 Bootstrap Tokens或者 Token Authentication file驗證=token, 不管哪種, Kubernetes都會爲token綁定一個默認的User和Group
Pod使用ServiceAccount認證時, service-account-token中的JWT會保存User信息, 有了用戶信息,再建立一對角色/角色綁定(集羣角色/集羣角色綁定)資源對象,就能夠完成權限綁定了
Role and ClusterRole
在RBAC API中, Role表示一組規則權限. 權限只會增長(累加權限) , 不存在一個資源一開始就有不少權限而經過RBAC對其進行減小的操做; Role能夠定義在一個namespace中, 若是想要跨namespace則能夠建立ClusterRole
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"]
ClusterRole具備與Role相同的權限角色控制能力, 不一樣的是ClusterRole是集羣級別的, ClusterRole能夠用於:
集羣級別的資源控制(如: node訪問權限)
非資源型endpoint是(如: /healthz 訪問)
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: secret-reader rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"]
RoleBinding and ClusterRoleBinding
RoleBinding能夠將角色中定義的權限授予用戶或用戶組, RoleBinding包含一組權限列表(subjects) , 權限列表中包含有不一樣形式的待受權權限資源類型(User, groups, or service accounts); RoleBinding一樣包含對被Bind的Role引用; RoleBinding適用於某個命名空間內受權, 而ClusterRoleBinding適用於集羣範圍內的受權
將default命名空間的pod-readerRole授予jane用戶, 此後jane用戶在default命名空間中將具備pod-reader的權限
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-pods namespace: default subjects: - kind: User name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
RoleBinding一樣能夠引用ClusterRole來對當前namespace內用戶、用戶組或ServiceAccount進行受權, 這種操做容許集羣管理員在整個集羣內定義一些通用的ClusterRole, 而後在不一樣的namespace中使用RoleBinding來引用.
如 : 如下RoleBinding引用一個ClusterRole, 這個ClusterRole具備整個集羣內對secrets的訪問權限;可是其受權用戶dave只能訪問development空間中的secrets(由於RoleBinding定義在development命名空間)
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-secrets namespace: development subjects: - kind: User name: dave apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
使用ClusterRoleBinding能夠對整個集羣中的全部的命名空間資源權限進行受權; 如下ClusterRoleBinding樣例展現了受權manager組內全部用戶在所有命名空間中對secrets進行訪問
kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: read-secrets-global subjects: - kind: Group name: manager roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
Resources
Kubernetes集羣內一些資源通常以其名稱字符串來表示, 這些字符串通常會在API的URL地址中出現; 同時某些資源也會包含子資源, 例如logs資源就屬於Pods的子資源, API中URL樣例以下
GET /api/v1/namespaces/{namespace}/pods/{name}/log
若是要在RBAC受權模型中控制這些子資源的訪問權限, 能夠經過 / 分隔符來實現, 如下是 一個定義Pods資源logs訪問權限的Role定義樣例
kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: namespace: default name: pod-and-pod-logs-reader rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list"]
to Subjects
RoleBinding和ClusterRoleBinding能夠將Role綁定到Subjects; Subjects能夠是Groups、users或者Service Accounts
Subjects中Users使用字符串表示, 能夠是一個普通的名字字符串, 如alice; 也能夠是email格式的郵箱地址; 甚至是一組字符串形式的數字ID. 可是Users的前綴system:是系統保留的, 集羣管理員應該確保普通用戶不會使用這個前綴格式.
Groups書寫格式與Users相同, 都爲一個字符串, 而且沒有特定的格式要求; 一樣system:前綴爲系統保留
建立一個用戶只能管理dev空間:
{ "CN": "devuser", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names":[ { "c": "CN", "ST": "HangZhou", "L": "HangZhou", "O": "k8s", "OU": "System" } ] } # 下載證書生成工具 wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 mv cfssl_linux-amd64 /usr/local/bin/cfssl wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 mv cfssljson_linux-amd64 /usr/local/bin/cfssljson wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /root/devuser-csr.json | cfssljson -bare devuser # 設置集羣參數 export KUBE_APISERVER="https://172.16.11.207:6443" kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/pki/ca.crt \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=devuser.kubeconfig # 設置客戶端認證參數 kubectl config set-credentials devuser \ --client-certificate=/etc/kubernetes/pki/devuser.pem --client-key=/etc/kubernetes/pki/devuser-key.pem --embed-certs=true \ --kubeconfig=devuser.kubeconfig #設置上下文參數 kubectl config set-context kubernetes --cluster=kubernetes \ --user=devuser \ --namespace=dev \ --kubeconfig=devuser.kubeconfig # 設置上下文 kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig cp -f ./devuser.kubeconfig /root/.kube/config kubectl create rolebindingdevuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev
准入控制是API Server的插件集合, 經過添加不一樣的插件, 實現額外的准入控制規則.甚至於API Server的一些主要的功能都須要經過Admission Controllers實現, 好比 : ServiceAccount
K8S1.14推薦列表
NamespaceLifecycle LimitRanger ServiceAccount DefaultStorageClass DefaultTolerationSeconds MutatingAdmissionWebbook ValidatingAdmissionWebbook ResourceQuota
列舉一些插件功能:
namespaceLifecycle: 防止在不存在的namespace上建立對象, 方式刪除系統預置的namespace, 刪除namespace時, 連帶刪除全部的資源對象.
LimitRanger: 確保請求的資源不會超過資源所在的Namespace的LimitRange的限制
ServiceAccount: 實現了自動化添加ServiceAccount