Kubernetes API 访问控制
Authentication(认证)
-
认证方式现共有8种,可以启用一种或多种认证方式,只要有一种认证方式通过,就不再进行其它方式的认证
- 通常启用 X509 Client Certs 和 Service Accout Tokens 两种认证方式
-
Kubernetes集群有两类用户:
- 由Kubernetes管理的Service Accounts (服务账户)
- (Users Accounts) 普通账户
- k8s中账号的概念不是我们理解的账号,它并不真的存在,它只是形式上存在
Authorization(授权)
- 必须经过认证阶段,才到授权请求,根据所有授权策略匹配请求资源属性,决定允许或拒绝请求
- 授权方式现共有6种,AlwaysDeny、AlwaysAllow、ABAC、RBAC、Webhook、Node
- 默认集群强制开启 RBAC
Admission Control(准入控制)
- 用于拦截请求的一种方式,运行在认证、授权之后,是权限认证链上的最后一环,对请求API资源对象进行修改和校验。
UserAccount与ServiceAccount
-
用户账户是针对人而言的。 服务账户是针对运行在 pod 中的进程而言的
-
用户账户是全局性的。 其名称在集群各 namespace 中都是全局唯一的,未来的用户资源不会做 namespace 隔离, 服务账户是 namespace 隔离的
-
集群的用户账户可能会从企业数据库进行同步,其创建需要特殊权限,并且涉及到复杂的业务流程
-
服务账户创建的目的是为了更轻量,允许集群用户为了具体的任务创建服务账户 ( 即权限最小化原则 )
ServiceAccount
-
服务账户控制器(Service account controller)
-
服务账户管理器管理各命名空间下的服务账户
-
每个活跃的命名空间下存在一个名为 “default” 的服务账户
-
-
服务账户准入控制器(Service account admission controller)
- 相似pod中 ServiceAccount默认设为 default。
- 保证 pod 所关联的 ServiceAccount 存在,否则拒绝该 pod。
- 如果pod不包含ImagePullSecrets设置那么ServiceAccount中的ImagePullSecrets 被添加到pod中
- 将挂载于 /var/run/secrets/kubernetes.io/serviceaccount 的 volumeSource 添加到 pod 下的每个容器中
- 将一个包含用于 API 访问的 token 的 volume 添加到 pod 中
ServiceAccount 运用
建立名字为 moon 的 ServiceAccount
[root@k8s-master ~]# kubectl create sa moon
[root@k8s-master ~]# kubectl describe sa moon
Name: moon
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
# 无内容
Mountable secrets: <none>
Tokens: <none>
Events: <none>
建立 secrets
[root@k8s-master ~]# kubectl create secret docker-registry docker-login --docker-username admin --docker-password aaa --docker-server ooovooo.org --docker-email admin@ooovooo.org
secret/docker-login created
[root@k8s-master ~]# kubectl describe secrets docker-login
Name: docker-login
Namespace: default
Labels: <none>
Annotations: <none>
Type: kubernetes.io/dockerconfigjson
Data
====
.dockerconfigjson: 113 bytes
将 secrets 注入到 sa 中
[root@k8s-master ~]# kubectl edit sa moon
apiVersion: v1
imagePullSecrets:
- name: docker-login
kind: ServiceAccount
...
[root@k8s-master ~]# kubectl describe sa moon
Name: moon
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: docker-login
# 注入成功
Mountable secrets: <none>
Tokens: <none>
Events: <none>
创建 Harbor 私有仓库并使用 Pod 访问私有仓库
# Harbor 建立名为 sun 私有仓库
[root@ooovooo harbor]# docker tag ooovooo.org/library/nginx:latest ooovooo.org/sun/nginx:latest
[root@ooovooo harbor]# docker push ooovooo.org/sun/nginx:latest
# 拉取私有仓库镜像 使用绝对路径
[root@k8s-master ~]# kubectl run 001 --image ooovooo.org/sun/nginx --dry-run=client -o yaml > 001.yml
[root@k8s-master ~]# kubectl apply -f 001.yml
[root@k8s-master ~]# kubectl describe pods 001
...
Warning Failed 14s kubelet Error: ImagePullBackOff
Normal Pulling 0s (x2 over 15s) kubelet Pulling image "ooovooo.org/sun/nginx"
Warning Failed 0s (x2 over 15s) kubelet Failed to pull image "ooovooo.org/sun/nginx": Error response from daemon: unauthorized: unauthorized to access repository: sun/nginx, action: pull: unauthorized to access repository: sun/nginx, action: pull
Warning Failed 0s (x2 over 15s) kubelet Error: ErrImagePull
[root@k8s-master ~]# kubectl get pods 001
NAME READY STATUS RESTARTS AGE
001 0/1 ImagePullBackOff 0 60s
[!warning]
创建 Pod 时,镜像下载错误,其 Docker 私有仓库下载镜像需要认证
Pod 绑定 SA
[root@k8s-master ~]# vim 001.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: "001"
name: "001"
spec:
serviceAccountName: moon
# 绑定
containers:
- image: ooovooo.org/sun/nginx
name: "001"
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
[root@k8s-master ~]# kubectl delete -f 001.yml
[root@k8s-master ~]# kubectl apply -f 001.yml
[root@k8s-master ~]# kubectl get pods 001
NAME READY STATUS RESTARTS AGE
001 1/1 Running 0 60s
[!note]
还可以将 secrets 注入到 sa default 中,这样 Pod 不用绑定 sa moon
认证(在K8s中建立认证用户)
创建 UserAccount
# 建立证书
[root@k8s-master ~]# cd /etc/kubernetes/pki/
[root@k8s-master pki]# openssl genrsa -out moon.key 2048
[root@k8s-master pki]# openssl req -new -key moon.key -out moon.csr -subj "/CN=moon"
[root@k8s-master pki]# openssl x509 -req -in moon.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out moon.crt -days 365
Certificate request self-signature ok
subject=CN = moon
[root@k8s-master pki]# openssl x509 -in moon.crt -text -noout
...
# 建立k8s中的用户
[root@k8s-master pki]# kubectl config set-credentials moon --client-certificate /etc/kubernetes/pki/moon.crt --client-key /etc/kubernetes/pki/moon.key --embed-certs=true
User "moon" set.
[root@k8s-master pki]# kubectl config view
...
- name: moon
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
# 为用户创建集群的安全上下文
[root@k8s-master pki]# kubectl config set-context moon@kubernetes --cluster kubernetes --user moon
Context "moon@kubernetes" created.
# 删除安全上下文
# kubectl config delete-context xxx
# 切换用户 用户在集群中只有用户身份而没有授权
[root@k8s-master pki]# kubectl config use-context moon@kubernetes
Switched to context "moon@kubernetes".
[root@k8s-master pki]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "moon" cannot list resource "pods" in API group "" in the namespace "default"
# 切换回集群管理
[root@k8s-master pki]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
# 删除用户
# kubectl config delete-user moon
RBAC(Role Based Access Control)
基于角色访问控制授权:
-
允许管理员通过Kubernetes API动态配置授权策略
- RBAC就是用户通过角色与权限进行关联
-
RBAC只有授权,没有拒绝授权,所以只需要定义允许该用户做什么即可
-
RBAC的三个基本概念
- Subject:被作用者,它表示k8s中的三类主体, user, group, serviceAccount
- Role:角色,它其实是一组规则,定义了一组对 Kubernetes API 对象的操作权限
- RoleBinding:定义了“被作用者”和“角色”的绑定关系
-
RBAC包括四种类型:Role、ClusterRole、RoleBinding、ClusterRoleBinding
-
Role 和 ClusterRole
-
Role是一系列的权限的集合,Role只能授予单个namespace 中资源的访问权限
-
ClusterRole 跟 Role 类似,但是可以在集群中全局使用
-
Kubernetes 还提供了四个预先定义好的 ClusterRole 来供用户直接使用
-
cluster-amdin、admin、edit、view
-
Role 授权应用
# 生成role的yaml文件
[root@k8s-master ~]# kubectl create role myrole --dry-run=client --verb=get --resource pods -o yaml > myrole.yml
# 更改文件内容
[root@k8s-master ~]# vim myrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
creationTimestamp: null
name: myrole
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- watch
- list
- create
- update
- path
- delete
# 创建role
[root@k8s-master ~]# kubectl apply -f myrole.yml
role.rbac.authorization.k8s.io/myrole created
[root@k8s-master ~]# kubectl describe role myrole
Name: myrole
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get watch list create update path delete]
# 建立角色绑定
[root@k8s-master ~]# kubectl create rolebinding moon --role myrole --namespace default --user moon --dry-run=client -o yaml > rolebinding-myrole.yml
[root@k8s-master ~]# vim rolebinding-myrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: moon
namespace: default
# 角色绑定必须指定 namespace
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: myrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: moon
[root@k8s-master ~]# kubectl apply -f rolebinding-myrole.yml
rolebinding.rbac.authorization.k8s.io/moon created
[root@k8s-master ~]# kubectl get rolebindings.rbac.authorization.k8s.io moon
NAME ROLE AGE
moon Role/myrole 60s
# 切换用户测试授权
[root@k8s-master ~]# kubectl config use-context moon@kubernetes
Switched to context "moon@kubernetes".
[root@k8s-master rbac]# kubectl get pods
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
001 1/1 Running 0 9m31s
# 只针对pod进行了授权,所以svc依然不能操作
[root@k8s-master rbac]# kubectl get svc
Error from server (Forbidden): services is forbidden: User "moon" cannot list resource "services" in API group "" in the namespace "default"
# 切换回管理员
[root@k8s-master rbac]# kubectl config use-context kubernetes-admin@kubernetes
ClusterRole 授权应用
# 建立集群角色
[root@k8s-master ~]# kubectl create clusterrole myclusterrole --resource=deployment --verb get --dry-run=client -o yaml > myclusterrole.yml
[root@k8s-master ~]# vim myclusterrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: myclusterrole
rules:
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
- create
- update
- path
- delete
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- create
- update
- path
- delete
[root@k8s-master ~]# kubectl apply -f myclusterrole.yml
clusterrole.rbac.authorization.k8s.io/myclusterrole created
[root@k8s-master ~]# kubectl describe clusterrole myclusterrole
Name: myclusterrole
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch create update path delete]
deployments.apps [] [] [get list watch create update path delete]
# 建立集群角色绑定
[root@k8s-master ~]# kubectl create clusterrolebinding clusterrolebind-myclusterrole --clusterrole myclusterrole --user moon --dry-run=client -o yaml > clusterrolebind-myclusterrole.yml
[root@k8s-master ~]# vim clusterrolebind-myclusterrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: clusterrolebind-myclusterrole
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: moon
[root@k8s-master ~]# kubectl apply -f clusterrolebind-myclusterrole.yml
clusterrolebinding.rbac.authorization.k8s.io/clusterrolebind-myclusterrole created
[root@k8s-master rbac]# kubectl describe clusterrolebindings.rbac.authorization.k8s.io clusterrolebind-myclusterrole
Name: clusterrolebind-myclusterrole
Labels: <none>
Annotations: <none>
Role:
Kind: ClusterRole
Name: myclusterrole
Subjects:
Kind Name Namespace
---- ---- ---------
User moon
[root@k8s-master ~]# kubectl config use-context moon@kubernetes
# 用户测试
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
001 1/1 Running 0 15m
[root@k8s-master rbac]# kubectl get deployments.apps -A
# 没有对svc授权
[root@k8s-master rbac]# kubectl get svc -A
Error from server (Forbidden): services is forbidden: User "moon" cannot list resource "services" in API group "" at the cluster scope
服务账户的自动化
服务账户准入控制器(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 controller)
服务账户管理器管理各命名空间下的服务账户,并且保证每个活跃的命名空间下存在一个名为 “default” 的服务账户