概述
通路控制主要包括三個部分:
- 認證
- 授權
- 準入控制
認證和授權再apiserver的pod上完成.
- kubernetes API 通路控制
上面的圖檔由三部分組成:
- 首先使用者的請求要通過認證,認證通過許多插件來完成,
- 認證通過後同樣調用插件來進行授權,常用的授權就是node, rbac,
- 第三部分是準入控制,就是對通路的行為再做一些控制,我們也可以不進行控制
認證通或後就可以從etcd裡面擷取資訊了.
- Authentication(認證)
-
認證方式現共有8種,可以啟用一種或多種認證方式,隻要有一種認證方式通過,就不再
進行其它方式的認證。通常啟用X509 Client Certs和Service Accout Tokens兩種認證方式。
-
Kubernetes叢集有兩類使用者:由Kubernetes管理的Service Accounts (服務賬戶)和
(Users Accounts) 普通賬戶。k8s中賬号的概念不是我們了解的賬号,它并不真的存在,
它隻是形式上存在。
- 當我們不指定sa時,預設使用default sa.
-
[[email protected] ~]# kubectl get sa
NAME SECRETS AGE
default 1 21d
[[email protected] ~]# kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-j7pl7
Tokens: default-token-j7pl7
Events: <none>
- Authorization(授權)
- 必須經過認證階段,才到授權請求,根據所有授權政策比對請求資源屬性,決定允許或拒絕請求。授權方式現共有6種,AlwaysDeny、AlwaysAllow、ABAC、RBAC、Webhook、Node。預設叢集強制開啟RBAC。
- Admission Control(準入控制)
- 用于攔截請求的一種方式,運作在認證、授權之後,是權限認證鍊上的最後一環,對請求API資源對象進行修改和校驗。
- 通路k8s API Server的用戶端主要分為兩類:
- kubectl :使用者家目錄中的 .kube/config 裡面儲存了用戶端通路API Server的密鑰相關資訊,這樣當用kubectl通路k8s時,它就會自動讀取該配置檔案,向API Server發起認證,然後完成操作請求。
- pod:Pod中的程序需要通路API Server,如果是人去通路或編寫的腳本去通路,這類通路使用的賬号為:
;而Pod自身去連接配接API Server時,使用的賬号是:UserAccount
,生産中後者使用居多。ServiceAccount
kubectl向apiserver發起的指令,采用的是
http
方式,其實就是對
URL
發起增删改查的操作。
}[[email protected] ~]#kubectl proxy --port=8888 & 用 proxy 打開一個端口,可以直接用curl通路.
[[email protected] ~]# netstat -tnlp | grep 8888
tcp 0 0 127.0.0.1:8888 0.0.0.0:* LISTEN 18339/kubectl
[[email protected] ~]# curl http://localhost:8888/api/v1/namespaces/default
{
"kind": "Namespace",
"apiVersion": "v1",
"metadata": {
"name": "default",
...
[[email protected] ~]# curl http://localhost:8888/apis/apps/v1/namespaces/default/deployments
{
"kind": "DeploymentList",
"apiVersion": "apps/v1",
"metadata": {
"selfLink": "/apis/apps/v1/namespaces/default/deployments",
"resourceVersion": "793632"
},
"items": [
...
以上兩種api的差別是:
- api它是一個特殊連結,隻有在核心v1群組中的對象才能使用。
- apis 它是一般API通路的入口固定格式名。
UserAccount與serviceaccount的差別:
- 使用者賬戶是針對人而言的。 服務賬戶是針對運作在 pod 中的程序而言的。
- 使用者賬戶是全局性的。 其名稱在叢集各 namespace 中都是全局唯一的,未來的使用者資源不會做 namespace 隔離, 服務賬戶是 namespace 隔離的。
- 通常情況下,叢集的使用者賬戶可能會從企業資料庫進行同步,其建立需要特殊權限,并且涉及到複雜的業務流程。 服務賬戶建立的目的是為了更輕量,允許叢集使用者為了具體的任務建立服務賬戶 ( 即權限最小化原則 )。
[[email protected] ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://172.25.254.2:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: k[email protected]
current-context: [email protected]
kind: Config
preferences: {}
users:
- name: kubernetes-admin /這就是使用者帳号
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
認證
建立serviceaccount:
建立serviceaccount:
[[email protected] ~]# kubectl create serviceaccount admin
serviceaccount/admin created
[[email protected] ~]# kubectl get sa
NAME SECRETS AGE
admin 1 5s
default 1 21d
[[email protected] ~]# kubectl describe sa admin
Name: admin
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none> /鏡像拉取的secrets
Mountable secrets: admin-token-lbb4q /叢集自動建立了token令牌.確定sa 建立會後可用
Tokens: admin-token-lbb4q
Events: <none>
此時時沒有授權的.但是我們還可以網sa 中加入一些參數,比如鏡像拉取的secrets:
[[email protected] cm]# kubectl get secrets
NAME TYPE DATA AGE
admin-token-lbb4q kubernetes.io/service-account-token 3 5m51s
basic-auth Opaque 1 9d
db-user-pass Opaque 2 8d
default-token-j7pl7 kubernetes.io/service-account-token 3 21d
dev-db-secret Opaque 2 8d
myregistrykey kubernetes.io/dockerconfigjson 1 8d /這是我們之前建立的一個用于拉取鏡像的secret
tls-secret kubernetes.io/tls 2 9d
[[email protected] cm]# vim pod.yml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: game2048
image: reg.caoaoyuan.org/caoaoyuan/game2048
imagePullSecrets:
- name: myregistrykey 我們在使用的時候必須要再資源清單中指定才可以使用.
[[email protected] cm]# kubectl apply -f pod.yml
kubc pod/mypod created
[[email protected] cm]# kubectl describe pod mypod
Volumes:
default-token-j7pl7:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-j7pl7 /系統進行挂載
我們就可以把這個secret 加入到指定的 sa中,這樣每次建立pod就不用指定了.
添加secrets到serviceaccount中:
[[email protected] cm]# kubectl patch serviceaccount admin -p '{"imagePullSecrets": [{"name":"myregistrykey"}]}'
serviceaccount/admin patched
[[email protected] cm]# kubectl describe sa admin
Name: admin
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: myregistrykey /加近來了
Mountable secrets: admin-token-lbb4q
Tokens: admin-token-lbb4q
Events: <none>
更改pod檔案;
[[email protected] cm]# vim pod.yml
[[email protected] cm]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: game2048
image: reg.caoaoyuan.org/caoaoyuan/game2048
serviceAccountName: admin /直接指定sa即可
[[email protected] scheduler]# kubectl delete -f deployment.yml
deployment.apps "deployment-v1" deleted
[[email protected] scheduler]# kubectl describe pod mypod
Volumes:
admin-token-lbb4q:
Type: Secret (a volume populated by a Secret)
SecretName: admin-token-lbb4q /就是我們指定的admin 的sa了
如果我們不指定的話就會使用預設的sa, 但是裡面是沒有secret的,就會拉取鏡像失敗.
[[email protected] cm]# kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name":"myregistrykey"}]}'
serviceaccount/default patched
[[email protected] cm]# kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: myregistrykey /加到預設sa中去
Mountable secrets: default-token-j7pl7
Tokens: default-token-j7pl7
Events: <none>
[[email protected] cm]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myapp 沒有指定sa
image: myapp:v1
kubec [[email protected] cm]# kubectl apply -f pod.yml
pod/mypod created
[[email protected] cm]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mypod 1/1 Running 0 6s 成功運作起來了
通過這種方式,我們就是 将認證資訊添加到serviceAccount中,要比直接在Pod指定imagePullSecrets要安全很多。
建立UserAccount:
建立UserAccount:
用于登陸叢集,連接配接api,給使用者使用.
首先給使用者建立證書:
[[email protected] cm]# cd /etc/kubernetes/pki/ /證書建立目錄
/生成key
[[email protected] pki]# openssl genrsa -out test.key 2048
Generating RSA private key, 2048 bit long modulus
/生成證書請求
[[email protected] pki]# openssl req -new -key test.key -out test.csr -subj "/CN=test"
[[email protected] pki]# ls
test.key test.csr ...
/生成證書
[[email protected] pki]# openssl x509 -req -in test.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out test.crt -days 365
Signature ok
subject=/CN=test
Getting CA Private Key
/設定test用使用者,并識别證書和key
[[email protected] pki]# kubectl config set-credentials test --client-certificate=/etc/kubernetes/pki/test.crt --client-key=/etc/kubernetes/pki/test.key --embed-certs=true
User "test" set.
[[email protected] pki]# kubectl config view
...
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: test 使用者出現了
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
加入到context\中
[[email protected] pki]# kubectl config set-context [email protected] --cluster=kubernetes --user=test
Context "[email protected]" created.
[[email protected] pki]# kubectl config view
..
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: [email protected]
- context:
cluster: kubernetes
user: test
name: [email protected]
current-context: [email protected]
kind: Config
preferences: {}
...
/切換
[[email protected] pki]# kubectl config use-context [email protected]
Switched to context "[email protected]".
[[email protected] pki]# kubectl get pod
Error from server (Forbidden): pods is forbidden: User "test" cannot list resource "pods" in API group "" in the namespace "default"
此時使用者通過認證,但還沒有權限操作叢集資源,需要繼續添加授權。
授權
- RBAC(Role Based Access Control):基于角色通路控制授權。
- 允許管理者通過Kubernetes API動态配置授權政策。RBAC就是使用者通過角色與權限進行關聯。
- RBAC隻有授權,沒有拒絕授權,是以隻需要定義允許該使用者做什麼即可。不用直接解綁就行
- RBAC包括四種類型:Role、ClusterRole、RoleBinding、ClusterRoleBinding。
- RBAC的三個基本概念 :
- Subject:被作用者,它表示k8s中的三類主體, user, group, serviceAccount
- Role:角色,它其實是一組規則,定義了一組對 Kubernetes API 對象的操作權限。
- RoleBinding:定義了“被作用者”和“角色”的綁定關系。
- Role 和 ClusterRole
- Role是一系列的權限的集合,Role隻能授予單個namespace 中資源的通路權限。
- ClusterRole 跟 Role 類似,但是可以在叢集中全局使用。
我們先切回管理者使用者,進行授權
[[email protected]2 pki]# kubectl config use-context [email protected]
Switched to context "[email protected]".
[[email protected] pki]# kubectl get pod
No resources found in default namespace.
角色 和 角色綁定
[[email protected] ~]# mkdir rbac
[[email protected] ~]# cd rbac/
[[email protected] rbac]# vim role.yml
[[email protected] rbac]# cat role.yml
kind: Role /rbac類型為role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default /針對預設namespace
name: myrole
rules:
- apiGroups: [""]
resources: ["pods"] /授權對應的資源
verbs: ["get", "watch", "list", "create", "update", "patch", "delete"] /對應的權限,自己定義
[[email protected] rbac]# kubectl apply -f role.yml
kubec role.rbac.authorization.k8s.io/myrole created
[[email protected] rbac]# kubectl get role
NAME CREATED AT
myrole 2020-07-10T04:35:24Z
[[email protected] rbac]# kubectl describe role myrole
Name: myrole
Labels: <none>
Annotations: PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get watch list create update patch delete]
- RoleBinding和ClusterRoleBinding
- RoleBinding是将Role中定義的權限授予給使用者或使用者組。它包含一個subjects清單(users,groups ,service accounts),并引用該Role。
- RoleBinding是對某個namespace 内授權,ClusterRoleBinding适用在叢集範圍内使用。
綁定:
[[email protected] rbac]# vim role.yml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: myrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "create", "update", "patch", "delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: test-read-pods
namespace: default /針對的預設命名空間
subjects:
- kind: User /綁定使用者
name: test /使用者名
apiGroup: rbac.authorization.k8s.io /api組
roleRef:
kind: Role /綁定角色
name: myrole
apiGroup: rbac.authorization.k8s.io
[[email protected] rbac]# kubectl apply -f role.yml
role.rbac.authorization.k8s.io/myrole unchanged
rolebinding.rbac.authorization.k8s.io/test-read-pods created
[[email protected] rbac]# kubectl config use-context [email protected]
Switched to context "[email protected]".
[[email protected] rbac]# kubectl run demo --image=busybox --restart=Never
pod/demo created /可以建立pod
[[email protected] rbac]# kubectl get pod
NAME READY STATUS RESTARTS AGE
demo 0/1 Completed 0 7s 檢視pod
[[email protected] rbac]# kubectl delete pod demo
pod "demo" deleted
[[email protected] rbac]# kubectl get svc
Error from server (Forbidden): services is forbidden: User "test" cannot list resource "services" in API group "" in the namespace "default"
[[email protected] rbac]# kubectl get cm
Error from server (Forbidden): configmaps is forbidden: User "test" cannot list resource "configmaps" in API group "" in the namespace "default"
[[email protected] rbac]# kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "test" cannot list resource "pods" in API group "" in the namespace "kube-system"
可以看出 test 這個使用者賬戶值可以對 pod 進行相應的操作,對于沒有授權的不可以操作.而且隻能在授權的命名空間内.
而且建立 控制器 cm,等等都是不可以的.
叢集角色
[[email protected] rbac]# kubectl config use-context [email protected]
Switched to context "[email protected]".
依然先切回管理者,進行授權
[[email protected] rbac]# vim role.yml
..上面不變,隻在下面添加:
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: myclusterrole
rules: /多個規則
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "delete", "create", "update"]
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
叢集角色不僅可以 使用 clusterrolebinding 進行綁定,還可以使用 rolebinding 綁定:
[[email protected] rbac]# vim role.yml
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: myclusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list", "delete", "create", "update"]
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rolebind-myclusterrole
namespace: default 同樣隻能指定一個命名空間.
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole /綁定叢集角色
name: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: test /綁定使用者
[[email protected] rbac]# kubectl get deployments.apps
No resources found in default namespace. /可以對控制器進行操作了
[[email protected] rbac]# kubectl get deployments.apps -n kube-system
Error from server (Forbidden): deployments.apps is forbidden: User "test" cannot list resource "deployments" in API group "apps" in the namespace "kube-system"
但是還是不能跨namespace 進行使用,因為我們使用的是角色綁定而不是叢集角色綁定.
叢集角色綁定:
[[email protected] rbac]# vim role.yml
...
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: 叢集角色綁定不用指定namespace,因為是針對所有namespace的.
name: clusterrolebinding-myclusterrole
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: test
[[email protected] rbac]# kubectl apply -f role.yml
[[email protected] rbac]# kubectl config use-context [email protected]
Switched to context "[email protected]".
[[email protected] rbac]# kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
[email protected] kubernetes kubernetes-admin
* [email protected] kubernetes test
[[email protected] rbac]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-76d4774d89-9fp2s 1/1 Running 1 2d23h
calico-node-bg9c4 1/1 Running 9 11d
calico-node-lvxrc 1/1 Running 8 11d
calico-node-smn7b 1/1 Running 9 11d
coredns-5fd54d7f56-2d7h9 1/1 Running 1 2d22h
[[email protected] rbac]# kubectl get deployments.apps -n kube-system
NAME READY UP-TO-DATE AVAILABLE AGE
calico-kube-controllers 1/1 1 1 11d
coredns 2/2 2 2 21d
就可以擷取所有namespace下的 pod 和 deployment 的指定操作權限了.
但是隻能對pod 和 deployment 進行操作,因為沒指定其他的權限,clusterrole 隻是可以對所有的命名空間操作,
準入控制
我們在最初搭建叢集的時候,并沒有做一些證書,或者token的建立操作,但是我們仍然可以正常使用,這是因為叢集自動化的幫我們建立了一些内容.
- 服務賬戶(sa)的自動化
- 服務賬戶準入控制器(Service account admission controller)
- 如果該 pod 沒有 ServiceAccount 設定,将其 ServiceAccount 設為 default。
- 保證 pod 所關聯的 ServiceAccount 存在,否則拒絕該 pod。
- 如果 pod 不包含 ImagePullSecrets 設定,那麼 将 ServiceAccount 中的ImagePullSecrets 資訊添加到 pod 中。
- 将一個包含用于 API 通路的 token 的 volume 添加到 pod 中。
- 将挂載于 /var/run/secrets/kubernetes.io/serviceaccount 的 volumeSource 添加到pod 下的每個容器中。
- 服務賬戶準入控制器(Service account admission controller)
[[email protected] rbac]# kubectl create namespace linux
namespace/linux created
[[email protected] rbac]# kubectl get sa -n linux
NAME SECRETS AGE
default 1 7s /自動建立的sa
[[email protected] rbac]# kubectl -n kube-system describe pod coredns-5fd54d7f56-2d7h9
/var/run/secrets/kubernetes.io/serviceaccount from coredns-token-t4kqs (ro) /自動建立的token
- Token 控制器(Token controller)
- 檢測服務賬戶的建立,并且建立相應的 Secret 以支援 API 通路。
- 檢測服務賬戶的删除,并且删除所有相應的服務賬戶 Token Secret。
- 檢測 Secret 的增加,保證相應的服務賬戶存在,如有需要,為 Secret 增加 token。
- 檢測 Secret 的删除,如有需要,從相應的服務賬戶中移除引用。
kubec [[email protected] rbac]# kubectl get sa
NAME SECRETS AGE
admin 1 3h21m /這是我們自己建立的sa
default 1 21d
[[email protected] rbac]# kubectl get secrets
NAME TYPE DATA AGE
admin-token-lbb4q kubernetes.io/service-account-token 3 3h21m secret
basic-auth Opaque 1 9d
..
[[email protected] rbac]# kubectl delete sa admin
serviceaccount "admin" deleted
[[email protected] rbac]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth Opaque 1 9d
删除sa後secret也不見了.
-
服務賬戶控制器(Service account controller)
服務賬戶管理器管理各命名空間下的服務賬戶,并且保證每個活躍的命名空間下存在
一個名為 “default” 的服務賬戶
[[email protected] rbac]# kubectl create namespace linux
namespace/linux created
[[email protected] rbac]# kubectl get secrets -n linux
NAME TYPE DATA AGE
default-token-z59zk kubernetes.io/service-account-token 3 9s
[[email protected] rbac]# kubectl -n linux delete sa default /删除預設sa
serviceaccount "default" deleted
[[email protected] rbac]# kubectl get sa -n linux
NAME SECRETS AGE
default 1 7s
[[email protected] rbac]# kubectl get secrets -n linux
NAME TYPE DATA AGE
default-token-qp48s kubernetes.io/service-account-token 3 34s
我們可以看出建立命名空間時會自動建立一個secret,而且當我們删除了建立的預設的sa時,回立即重新拉起一個sa,并删除之前的secret,重新拉起一個.
- Kubernetes 還擁有“使用者組”(Group)的概念:
- ServiceAccount對應内置“使用者”的名字是:
- system:serviceaccount:<ServiceAccount名字 >
- 而使用者組所對應的内置名字是:
- system:serviceaccounts:<Namespace名字 >
示例1:表示mynamespace中的所有ServiceAccount
subjects:
- kind: Group
name: system:serviceaccounts:mynamespace
apiGroup: rbac.authorization.k8s.io
示例2:表示整個系統中的所有ServiceAccount
subjects:
- kind: Group
name: system:serviceaccounts 不指定命名空間
apiGroup: rbac.authorization.k8s.io
Kubernetes 還提供了四個預先定義好的 ClusterRole 來供使用者直接使用:
他們各自有不同的權限
[[email protected] rbac]# kubectl get clusterrole
NAME CREATED AT
admin 2020-06-18T09:31:41Z
cluster-admin 2020-06-18T09:31:41Z
edit 2020-06-18T09:31:41Z
view 2020-06-18T09:31:42Z
[[email protected] rbac]# kubectl describe clusterrole cluster-admin
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
*.* [] [] [*]
[*] [] [*]
這是其中嗯權限最大的
例如:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: readonly-default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: view 我們可以用系統的叢集角色,賦予給這個sa 權限
apiGroup: rbac.authorization.k8s.io
準入控制主要是通過插件來完成的.