1、k8s中的訪問控制
API server作爲kubernetes集羣系統的網關,是訪問及管理資源對象的唯一入口,而其他所有的組件及kubectl命令都要經由此網關進行集羣的訪問和管理。而各組件及客戶端每一次的訪問請求都要有api server進行合法性校驗,包括身份鑑別、操作權限驗證等。所有的檢查通過之後才能訪問或存入數據於後端的etcd中。客戶端的認證操作是由api server配置的一到多個認證插件完成,授權操作由一到多個授權插件進行,而通過授權檢測的用戶所請求的相關操作還要經由一到多個准入控制插件的遍歷檢測。
(1)用戶賬號和用戶組
客戶端訪問API服務的途徑通常有三種分別是kubectl、客戶端庫、REST接口,而執行此類請求的主體通常有兩類分別是常規用戶(User Account)和服務賬號(Service Account)。
①User Account:一般是獨立於kubernetes之外的其他服務管理的用戶賬號,如管理員分發的祕鑰、keystone一類的用戶 存儲等。Kubernetes中不存在標識此類用戶賬戶的對象,因此,不能被直接添加進kubernetes系統中。該賬號通常用於複雜的業務邏輯管控,它作用於系統全局,故其名稱必須全局唯一。
②Service Account:是由kubernetes API管理的賬號,用於爲Pod中的服務進程在訪問Kubernetes API時提供身份標識。該賬戶需要綁定於特定的名稱空間,他們由API server創建或,附帶着一組存儲爲secret的用於訪問api的憑證。Service Account隸屬於名稱空間,僅用於實現某些特定的操作任務。
用戶組是用戶賬號的邏輯集合,本身並無操作權限,但附加於組上的權限可由其內部的所有用戶繼承,以實現高效的授權管理機制。Kubernetes中附帶着一些內建的用於特殊目的的組。
(2)認證、授權與准入控制
Kubernetes使用身份認證插件對API請求進行身份認證時支持的認證方式包括客戶端認證、承載令牌認證(bearer tokens)、身份驗證代理(authingenticating proxy)及http base認證等。API Server同時支持多種認證機制,但至少分別爲Service Accoun和User Account各自啓用一個認證插件。API server支持的具體認證方式有:
①X509客戶端證書認證
②靜態令牌文件(Static Token File):由kube-apiserver的命令行工具—token-auth-file加載
③引導令牌(Bootstrap Tokens):動態管理承載令牌進行身份認證的方式,常用於簡化新建kubernetes集羣的節點認證過程
④靜態密碼文件
⑤服務賬戶令牌
⑥OpenID連接令牌
⑦Webhook令牌
⑧認證代理
⑨Keystone密碼
⑩匿名請求
身份認證後具體的操作請求還需要轉交給授權插件進行許可權限檢查。API server主要支持使用四類內建的授權插件來定義用戶的操作權限:
①Node:基於pod資源的目標調度節點來實現對kubelet的訪問控制
②ABAC(attribute-based access control):基於屬性的訪問控制
③RBAC(role-based access control):基於角色的訪問控制
④Webhook:基於HTTP回調機制通過外部REST服務檢查確認用戶授權的訪問控制
准入控制器用於在客戶端請求經過身份驗證和授權檢查之後但在對象持久化存儲etcd之前攔截請求,用於實現在資源的創建、更新和刪除操作期間強制執行對象的語義驗證等功能,API Server內置的常用准入控制器有:
①AlwaysAdmit:允許所有的請求
②AlwaysDeny:拒絕所有的請求,僅用於測試
③AlwaysPullImages:總是下載鏡像,常用於多租戶環境中
④NamespaceLifecycle:拒絕與不存在的名稱空間中創建資源
⑤LimitRange:可用資源的範圍界定
⑥ServiceAccount:用於實現Service Account管控機制的自動化
2、服務賬號的管理與應用
服務賬戶就是用於讓Pod對象內的容器進程訪問其他服務時提供身份認證信息的賬戶。一個Service Account資源一般由用戶名及相關的Secret對象組成。
(1)Service Account自動化
Kubernetes系統通過三個獨立的組件間的相互協作來實現服務賬戶的自動化,三個組件分別爲Service Account准入控制器、令牌控制器(token controller)和Service Account賬戶控制器。
①Service Account准入控制器是API Service的一部分,負責在創建更新Pod時對其按需進行Service Account對象相關信息的修改。
②令牌控制器是controller-manager的子組件,工作與異步模式;主要監控Service Account的創建刪除操作、Secret對象的添加刪除操作。
(2)創建服務賬戶
Service Account是kubernetes API上的一種資源類型,隸屬於名稱空間,用於讓Pod對象內部的應用程序在API Service通信時完成身份認證。每個名稱空間都有一個名爲default的默認資源對象。
]# kubectl get serviceaccounts --all-namespaces
NAMESPACE NAME SECRETS AGE
default default 1 112d
ingress-nginx default 1 110d
kube-public default 1 112d
每個pod均可附加其所屬名稱空間中的一個Service Account資源,且只能附加一個,但一個Service Account資源可由其所屬的名稱空間中的多個pod共享使用,在創建pod時,可通過”spec.serviceAccountName”字段直接指定要是用的Service Account對象。
Service Account資源的創建可通過yaml配置文件創建,也可通過命令創建。通過命令創建Service Account資源的命令格式如下:
kubectl create serviceaccount NAME [--dry-run] [options]
通過資源配置清單定義一個Service Account資源如下:
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-demo
namespace: default
(3)調用imagePullSecret資源對象
ServiceAccount資源還可以基於spec.imagePullSecret字段附帶一個由下載鏡像專用的Secret資源組成的列表,用於在容器創建時,從某私有鏡像倉庫下載鏡像之前進行服務認證。
# 創建一個用於在阿里雲認證的secrete資源
]# kubectl create secret docker-registry aliyun-registry --docker-username=dayi123 --docker-password=dayi123 [email protected] --docker-server=registry.cn-hangzhou.aliyuncs.com
secret/aliyun-auth created
# 定義serviceaccount資源
]# cat aliyun-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-demo
namespace: default
imagePullSecrets:
- name: aliyun-registry
# 創建該secrete
]# kubectl create -f aliyun-sa.yaml
serviceaccount/sa-demo created
# 定義pod資源,並去阿里雲私有倉庫中拉取鏡像並運行
]# cat pod-sa.yaml
apiVersion: v1
kind: Pod
metadata:
name: sa-demo
spec:
serviceAccountName: sa-demo
containers:
- name: aliyun-busybox
image: registry.cn-hangzhou.aliyuncs.com/dayi123/busybox:v1.1
3、X.509數字證書認證
Kubernetes支持的各種認證方式中基於TLS/SSL協議的客戶端認證以其安全性高且易於實現等特性成爲主要使用的認證方式。在服務端與客戶端相互認證的場景中,雙方各自都需要配備一套證書,並擁有信任的簽證機構的列表。
(1)kubernetes中的ssl/tls認證
處於安全的目的,kubernetes集羣中masteer的各組件(API server,controller-manager和scheduler)需要基於SSL/TLS向外提供服務,master的組件與集羣中的組件(如節點組件kubelet,kube-proxy)通信時需要雙向的身份認證。
①etcd集羣內各節點的通信以及各節點與客戶端之間的通信都應該以加密的方式進行並需要身份驗證
②API Server與客戶端之間採用HTTPS通信可實現通信與認證功能
③集羣中的應用與客戶端的通信經由不可行的網絡傳輸時也需要用到TLS/SSL協議。
(2)客戶端配置文件
1)kubectlconfig
客戶端的配置文件kubeconfig爲初始化集羣后生成的配置文件,默認路勁爲”$HOME/.kube/config”.。kubeconfig配置文件可以爲kubectl、kubelet、kube-controller-manager等在內的API Server的各類客戶端提供接入多個集羣的相關配置信息。使用”kubectl config view”命令能夠顯示當前正在使用的配置文件。
]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.16.196:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
kubeconfig配置文件中的主要配置信息如下:
①clusters:集羣列表,包含訪問API Server的rul和所屬集羣的名稱
②users:contexts:用戶列表
③kubelet的可用上下文列表
④current-context:kubelet當前使用的上下文名稱
在使用默認的配置文件時用戶也可以按需自定義相關的配置信息於kubeconfig配置文件中,以實現使用不同的用戶賬號接入集羣等功能。Kubectl config命令的常用操作有:
①kubectl config view:打印當前正在使用的配置文件
②kubectl config set-cluster:設置kubeconfig的clusteer配置段
③kubectl config set-credentials:設置kubeconfig 的user配置段
④kubectl config set-context:設置kubeconfig的contexts的配置段
⑤kubectl config use-context:設置kubeconfig的current-context配置段
2)創建基於SSL/TLS的認證的自定義用戶賬號
使用kubeadm部署的kubernetes集羣默認提供了擁有集羣管理權限的kubeconfig配置文件/etc/Kubernetes/admin.conf,它可被複制到任何有着kubectl的主機上以用於管理整個集羣。管理員可以創建基於SSL/TLS認證的自定義用戶賬號,以授權非管理員的集羣資源使用權限,配置過程如下:
首先爲用戶創建私鑰及證書文件,保存於/etc/Kubernetes/pki目錄中:
#創建私鑰文件
]# cd /etc/kubernetes/pki/
]# (umask 077;openssl genrsa -out kube-user01.key 2048)
# 創建證書籤署請求
]# openssl req -new -key kube-user01.key -out kube-user01.csr -subj "/CN=kube-user01/O=kubernetes"
# 簽署證書
]# openssl x509 -req -in kube-user01.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kube-user01.crt -days 3650
# 驗證證書信息
]# openssl x509 -in kube-user01.crt -text -noout
證書文件創建完成後需要以默認的管理員kubernetes-admin@kubernetes爲新建的kube-user01設定kubeconfig配置文件,默認會保存於當前系統用戶的.kube/config文件中,也可以通過kubectl使用—lubeconfig選項指定自定義的專用文件路勁。
# 配置集羣信息
]# kubectl config set-cluster kubernetes --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.16.196:6443
# 配置客戶端證書及祕鑰
]# kubectl config set-credentials kube-user01 --embed-certs=true --client-certificate=/etc/kubernetes/pki/kube-user01.crt --client-key=/etc/kubernetes/pki/kube-user01.key
# 配置context,用來組合cluster和credentials
]# kubectl config set-context kube-user01@kubernetes --cluster=kubernetes --user=kube-user01
# 切換到新建的用戶
]# kubectl config use-context kube-user01@kubernetes
# 由於沒有授權所以不能請求pod
]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "kube-user01" cannot list resource "pods" in API group "" in the namespace "default"
# 繼續切回到admin用戶
]# kubectl config use-context kubernetes-admin@kubernetes
(3)TLS boottstrapping機制
Kubelet TLS Bootstrapping機制是由kubelet自行生成私鑰和證書籤署請求,然後發送給集羣上的證書籤署進程(CA),由管理員驗證請求後予以簽署直接控制進程自動統一部署。
4、基於角色的訪問控制
RBAC是一種新型、靈活且使用廣泛的訪問控制機制。在RBAC中用於(user)就是一個可以獨立訪問數據資源的主體(Subject),角色是指一個組織或任務中的工作或者位置,它代表了一種權利、資格和責任。許可(Permission)就是允許對一個或多個客體(Object)執行的操作。RBAC試講權限授予角色之上。
(1)RBAC授權插件
RBAC用於界定那些主體(Subject)能夠或不能夠操作(verb)哪個或哪類對象(Object)。Verb包括create、apply、delete、update、patch、edit和get等。
RBAC授權插件支持Role和ClusterRole兩類角色,Role作用於名稱空間級別,用於定義名稱空間內的資源權限集合,ClusterRole用於組織集羣級別的資源權限集合。而對這兩類角色進行授權時需要用到RoleBinding和ClusterRoleBinding兩種資源類型。
RoleBingding用於將Role上的許可權限綁定到一個或一組用戶上,它隸屬於且僅能作用於一個名稱空間;綁定時,可以應用同一名稱中的Role,也可以應用集羣級別的ClusterRole.
ClusterRoleBingding則把ClusterRole中定義的許可權限綁定在一個或一組用戶之上,僅可以引用集羣級別的ClusterRole。
(2)Role和RoleBinding
1)Role
Role僅是一組許可(permission)權限的集合,它描述了那些資源可執行何種操作,資源配置清單中使用rules字段嵌套授權規則,role的創建可通過命令創建或資源配置清單創建,創建role的命令如下:
kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]
定義一個role的資源配置清單文件如下:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: pods-reader
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","list","watch"]
在上述的資源配置清單中,rules主要用於定義策略規則,但不包含策略應用的目標,可內嵌的字段如下:
apiGroups:包含了資源API組的名稱,支持列表格式指定的多個組,空串(“”)標識 核心組。
resourceNames:規則應用的目標資源名稱列表,默認爲資源類型下的所有資源
resources:規則應用的目標資源類型組成的列表,ResourceAll標識所有的資源
verb:可應用至此規則匹配到的所有資源類型的操作列表,可用的選項有:get、list、create、update、patch、watch、proxy、redirect、dekete和deletecollection。
nonResourceURLs:定義用戶應該有權限訪問的網址列表,並非名稱空間級別的資源。只能永於ClusterRole和ClusterRoleBinding
2)RoleBinding
角色本身不能作爲動作執行的主體,他們需要綁定到主體(user,group,service account)之上才能發生作用。RoleBinding用於將Role中定義的權限賦予一個或一組用戶;同時RoleBinding僅能夠引用同一名稱空間中的Role對象完成授權。RoleBinding由一組主體以及一個要應用來賦予這組主體的Role或ClusterRole組成。RoleBinding的創建也可通過命令創建或者定義資源清單創建。
通過命令創建的命令格式如下:
kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname]
定義一個RoleBinding的資源配置清單如下:
]# cat role-pods-reader-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: admin-services
namespace: testing
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kube-user01
如果將該RrolBinding資源應用到集羣中,kube-user01用於便有了讀取testing名稱空間中pod資源的權限。
# 創建該RoleBinding
]# kubectl create -f role-pods-reader
# 切換用戶到kube-user01
]# kubectl config use-context kube-user01@kubernetes
# 讀取testing名稱空間中的pod資源
]# kubectl get pods -n testing
No resources found.
RoleBinding不能擴名稱空間使用,但主體中的用戶賬號、用戶組和服務賬號不受名稱空間的限制,因此管理員可以爲一個主體通過不同的RoleBinding資源綁定多個名稱空間中的角色。
RoleBinding的配置主要包含兩個嵌套的字段subjects和roleRef,roleRef的值是單個對象,用於指定要綁定的Role或ClusterRole;subject用於指定要綁定的主體,
subject主要的嵌套字段如下:
apiGroup:要應用的主體所屬的API羣組,ServiceAccount類的主體默認值爲””,user和group類主體的默認值爲”rbac.authorization.k8s.io”
kind:要引用的資源對象所屬的類別,可用值爲User、Group、ServiceAccount
name:引用的主體名稱
namespace:引用主體所屬的名稱空間
roleRef的主要嵌套字段如下:
apiGroup:應用的資源所屬的API羣組
kind:引用的資源所屬的類別
name:引用的資源的名稱
(3)ClusterRole和ClusterRoleBinding
ClusteerRole資源除了能夠管理與Role資源一樣的許可權限之外,還可用於集羣級組件的授權,ClusterRole資源的定義方式與Role資源類似。
# 定義一個具有訪問集羣節點信息的clusterrole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nodes-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs:
- get
- watch
- list
ClusterRoleBinding是集羣級別的資源,它不屬於名稱空間,所以不需要指定名稱空間;RoleBinding也能夠將主題綁定至ClusterRole資源之上,但僅能夠賦予用戶訪問RoleBinding資源本身所在的名稱空間之內可由ClusterRole賦予的權限。
集羣級別的資源(如nodes、pv)以及非資源型的URL不屬於名稱空間級別所以無法通過RoleBinding授權,但可通過ClusterRoleBinding授權,但這類資源的讀取權限已經由系統默認名稱爲system:discovery的ClusterRole和ClusterRoleBinding兩個資源自動設定。
]# kubectl get clusterrolebinding system:discovery -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
. . . . . .
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:discovery
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:authenticated
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:unauthenticated
由上面的結果可知,ClusterRoleBinding綁定了system:authenticated和system:unauthencated兩個組,這包括了所有的用戶賬號,因此所有的用戶均由權限請求讀取這些資源,任何發往API Server的此類端點的請求都會得到響應。
(4)聚合型的ClusterRole
K8s自1.9版本開始支持ClusterRole在Role字段中嵌套aggregationRule字段來整合其他的Cluster對象的規則,這種類型的ClusterRole的權限受限於控制器,他們由所有被標籤選擇器匹配到的用於聚合的ClusterRole的授權規則合併生成。聚合型ClusterRole的規則會隨着標籤選擇器的匹配結果動態變化。
(5)面向用戶內建的ClusterRolle
API Server內建了一組默認的ClusterRole和ClusterRoleBinding以預留系統使用,其中大多數以“system:”爲前綴。而內建的ClusterRole資源cluster-admin擁有管理集羣所有資源的權限,他基於同名的ClusterRoleBinding資源綁定到了”system:master”組上,這以爲這所有隸屬於此組的用戶都將具有集羣的超級管理權限。
5、准入控制器
認證插件和授權插件完成身份認證和權限檢查之後,准入控制器將攔截那些創建、更新和刪除的相關操作請求以強制實現控制器中實現的功能。
(1)LimitRange資源與准入控制器
LimitRange資源在每個名稱空中爲每個容器指定最小及最大的計算資源用量,甚至是設置默認的計算資源需求和計算資源限制。
LimitRaneg資源支持限制容器、Pod和PersistentVolumeClaim三種資源對象的系統資源用量。定義一個容器cpu資源限制如下:
]# cat limitrange-cpu.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-limit-range
spec:
limits:
- default:
cpu: 1000m
defaultRequest:
cpu: 1000m
min:
cpu: 500m
max:
cpu: 2000m
maxLimitRequestRatio:
cpu: 4
type: Container
(2)ResourceQuota資源與准入控制器
ResourceQuota資源用於定義名稱空間的對象數量或系統資源配額,它支持限制每種資源類型的對象總數以及所有對象所能消耗的計算資源及存儲資源總量。
ResourceQuota對象可限制指定名稱空間中非終止狀態的所有pod對象的計算資源需求及計算資源的限制總量:
①cpu或requests.cpu:cpu資源需求的總量限制
②memory或requests.memory:內存資源需求的總量限制
③limits.cpu:cpu資源限制的總量限制
④limits.memory:內存資源限制的總量限制
ResourceQuota資源還支持限制特定名稱空間中可以使用的PVC數量和這些PVC資源的空間總大小,以及特定名稱空間中可在指定的StorageClass上使用的PVC數量和這些PVC資源總數:
①requests.storage:所有PVC存儲需求的總量限制
②persistentvolumeclaims:可以創建的pvc總數
③<storage-class-name>.storageclass.storage.k8s.io/requests.storage:指定存儲類上可使用的所有PVC存儲需求的總量限額
④<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims:指定存儲類上可使用的PVC總數
⑤requests.ephemeral-storage:所有pod可用的本地臨時存儲需求的總量
⑥limits.ephemeral-storage:所有pod可用的本地臨時存儲限制的總量
# 創建一個resourcesquota對象並查看
]# cat resourcequota-test.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota-example
spec:
hard:
pods: "5"
requests.cpu: 5
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
count/deployments.apps: "1"
count/deployments.extensions: "1"
persistentvolumeclaims: "2"
]# kubectl describe resourcequota quota-example
Name: quota-example
Namespace: default
Resource Used Hard
-------- ---- ----
count/deployments.apps 0 1
count/deployments.extensions 0 1
limits.cpu 0 2
limits.memory 0 2Gi
persistentvolumeclaims 4 2
pods 4 5
requests.cpu 0 5
requests.memory 0 1Gi
在名稱空間上啓用了CPU和內存等系統資源的配額後,用戶創建Pod對象時必須指定資源需求或資源限制,否則會觸發ResouceQuota准入控制器拒絕相應的操作。同事資源配額僅對那些在ResourceQuota對象創建之後生成的對象有效,對已經存在的對象不會產生任何的影響。
(3)PodSecurityPolicy
PSP是集羣級別的資源類型,用於控制用戶在配置pod資源的期望狀態時可以設定的特殊類的權限。但PSP對象定義的策略本身並不會直接發生作用,需要經由PodSecurityPolicy准入控制器檢查並強制生效。不過PSP准入控制器默認是處於未啓用狀態。
設定重要的Pod安全策略,而後啓用PSP准入控制器使其生效的方法
1)設置特殊及受限的PSP對象
2)創建ClusterRole並完成賬戶綁定
3)啓用PSP准入控制器