华子目录
- `Kubernetes API`访问控制
- `UserAccount用户`和`ServiceAccount用户`
- `ServiceAccount`
- 认证(在k8s中建立认证用户)
- 创建`UserAccount`
- `rbac`(`Role Based Access Control`)
- 基于`角色`访问控制授权
- `role`示例
- `clusterrole`示例
- 服务账户的自动化
Kubernetes API
访问控制
Authentication
(认证
)
认证方式
现共有8
种,可以启用一种或多种
认证方式,只要有一种认证方式
通过,就不再进行其它方式的
认证。通常启用X509 Client Certs
和Service Accout Tokens
两种认证方式Kubernetes集群
有两类用户
:由Kubernetes
管理的ServiceAccounts
(服务账户
)和UsersAccounts
(普通账户
)。k8s
中账号
的概念
不是我们理解的账号
,它并不真的存在
,它只是形式上存在
Authorization
(授权
)
必须
经过Authentication认证阶段
,才到Authorization授权
请求,根据所有授权策略
匹配请求资源属性
,决定允许
或拒绝
请求。授权方式
现共有6
种(AlwaysDeny
、AlwaysAllow
、ABAC
、RBAC
、Webhook
、Node
)。默认集群
强制开启RBAC
。
Admission Control
(准入控制
)
- 用于
拦截请求
的一种方式
,运行在认证
、授权
之后,是权限认证链
上的最后一环
,对请求API资源对象
进行修改
和校验
。
UserAccount用户
和ServiceAccount用户
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
中
[root@k8s-master ~]# kubectl run testpod --image myapp:v1
pod/testpod created
[root@k8s-master ~]# kubectl describe pods testpod
#回收
[root@k8s-master ~]# kubectl delete pods testpod
pod "testpod" deleted
#sa是serviceaccounts的缩写
[root@k8s-master ~]# kubectl get sa
NAME SECRETS AGE
default 0 35d
#默认会有一个名为default的serviceaccounts
#详细查看名为default的sa
[root@k8s-master ~]# kubectl describe sa default
Name: default #这表示服务账户的名称是default。在Kubernetes中,每个命名空间都会默认拥有一个名为default的服务账户
Namespace: default #服务账户所在的命名空间是default
Labels: <none> #这个服务账户没有定义任何标签
Annotations: <none> #注解(Annotations)是用于存储非标识性元数据的键值对。这里显示<none>,意味着这个服务账户没有定义任何注解
Image pull secrets: <none> #镜像拉取密钥(Image pull secrets)用于从私有容器镜像仓库拉取镜像。这里显示<none>,意味着这个服务账户没有配置任何用于拉取镜像的密钥
Mountable secrets: <none> #可挂载的密钥(Mountable secrets)是指可以在Pod中作为卷挂载的敏感信息,比如数据库密码、API密钥等。这里显示<none>,意味着这个服务账户没有关联任何可挂载的密钥
Tokens: <none> #令牌(Tokens)通常用于认证和授权。在Kubernetes中,服务账户通常会有一个或多个令牌,用于与API服务器通信。这里显示<none>,可能意味着这个服务账户还没有生成任何令牌,或者信息没有在这个上下文中显示
Events: <none>
创建名为huazi
的sa
[root@k8s-master ~]# kubectl create sa huazi
serviceaccount/huazi created
[root@k8s-master ~]# kubectl get sa
NAME SECRETS AGE
default 0 35d
huazi 0 45s[root@k8s-master ~]# kubectl describe sa huazi
Name: huazi
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: <none>
Tokens: <none>
Events: <none>
创建名为docker-auth
的类型为docker-registry
的secret资源
[root@k8s-master ~]# kubectl create secret docker-registry \
> docker-auth \
> --docker-server harbor.huazi.org \
> --docker-username admin \
> --docker-password 123456 \
> --docker-email huazi@huazi.org
secret/docker-auth created
[root@k8s-master ~]# kubectl get secrets
NAME TYPE DATA AGE
docker-auth kubernetes.io/dockerconfigjson 1 52s
我们harbor
上有个私有仓库
#node1退出登录并清除myapp:v1
[root@k8s-node1 ~]# docker logout harbor.huazi.org
Removing login credentials for harbor.huazi.org[root@k8s-node2 ~]# docker rmi harbor.huazi.org/huazi/myapp:v1
#node2退出登录并清除myapp:v1
[root@k8s-node2 ~]# docker logout harbor.huazi.org
Removing login credentials for harbor.huazi.org[root@k8s-node1 ~]# docker rmi harbor.huazi.org/huazi/myapp:v1
#harbor.huazi.org/huazi/myapp:v1是私有仓库huazi中的镜像
#此时testpod默认使用的是default中的认证,但是default中的Image pull secrets中没有认证
[root@k8s-master ~]# kubectl run testpod --image harbor.huazi.org/huazi/myapp:v1
pod/testpod created[root@k8s-master ~]# kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: <none>
Tokens: <none>
Events: <none>#我们发现镜像拉取失败
#在创建pod时会镜像下载会受阻,因为docker私有仓库下载镜像需要认证
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 0/1 ErrImagePull 0 2s 10.224.114.157 k8s-node1.org <none> <none>
[root@k8s-master ~]# kubectl edit sa huazi
serviceaccount/huazi edited
#我们发现Image pull secrets有认证了
[root@k8s-master ~]# kubectl describe sa huazi
Name: huazi
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: docker-auth
Mountable secrets: <none>
Tokens: <none>
Events: <none>
我们如果是用huazi
这个sa认证
的话,就可以把镜像拉下来
#先回收
[root@k8s-master ~]# kubectl delete pods testpod
pod "testpod" deleted
#创建一个pod,指定sa
[root@k8s-master ~]# vim pod.yml
[root@k8s-master ~]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:name: testpod
spec:serviceAccountName: huazi #sa认证指定huazicontainers:- image: harbor.huazi.org/huazi/myapp:v1name: myappv1
不指定serviceAccountName
的话,就会使用默认
的huazi
[root@k8s-master ~]# kubectl apply -f pod.yml
pod/testpod created
#发现运行成功
[root@k8s-master secret]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 1/1 Running 0 7s 10.244.1.14 k8s-node1.org <none> <none>
认证(在k8s中建立认证用户)
创建UserAccount
- 可以把
k8s
看作一个系统
,系统中
的每个用户
都有不同的权限
在k8s
中建立认证用户
#查看用户
[root@k8s-master ~]# kubectl config view
kubernetes-admin
用户是管理员用户
,有所有的权限
,管理员的认证文件在/etc/kubernetes/pki/
目录下
[root@k8s-master ~]# cd /etc/kubernetes/pki/
[root@k8s-master pki]# ls
apiserver.crt apiserver-kubelet-client.key front-proxy-ca.key
apiserver-etcd-client.crt ca.crt front-proxy-client.crt
apiserver-etcd-client.key ca.key front-proxy-client.key
apiserver.key etcd sa.key
apiserver-kubelet-client.crt front-proxy-ca.crt sa.pub
#做证书
[root@k8s-master pki]# openssl genrsa -out huazi.key 2048
[root@k8s-master pki]# openssl req -new -key huazi.key -out huazi.crt -subj "/CN=huazi"
[root@k8s-master pki]# openssl x509 -req -in huazi.crt -CA ca.crt -CAkey ca.key -CAcreateserial -out huazi.crt -days 365
#建立k8s中的用户
[root@k8s-master pki]# kubectl config set-credentials huazi \
> --client-certificate /etc/kubernetes/pki/huazi.crt \ #指定证书
> --client-key /etc/kubernetes/pki/huazi.key \ #指定key
> --embed-certs=true #表示将写入/etc/kubernetes/admin.conf配置文件
User "huazi" set.
[root@k8s-master pki]# kubectl config view
设置安全上下文
,将huazi
用户映射到huazi@kubernetes
中
#设置`安全上下文`,将`huazi`用户映射到`huazi@kubernetes`中
[root@k8s-master pki]# kubectl config set-context huazi@kubernetes --cluster kubernetes --user huazi
Context "huazi@kubernetes" created.
切换用户
#切换用户
[root@k8s-master pki]# kubectl config use-context huazi@kubernetes
Switched to context "huazi@kubernetes".
#这里报错是因为该huazi用户还没有被授权
[root@k8s-master pki]# kubectl get pods
Error from server (Forbidden): pods is forbidden: User "huazi" cannot list resource "pods" in API group "" in the namespace "default"
#切换回admin
[root@k8s-master pki]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
#删除指定的用户
[root@k8s-master pki]# kubectl config delete-user huazi
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
[root@k8s-master ~]# mkdir rbac
[root@k8s-master ~]# cd rbac/
role
示例
#创建一个名为myrole的role
[root@k8s-master rbac]# kubectl create role myrole --verb get --resource pods --dry-run=client -o yaml > myrole.yml[root@k8s-master rbac]# vim myrole.yml
[root@k8s-master rbac]# cat myrole.yml
apiVersion: rbac.authorization.k8s.io/v1 #指定了使用 RBAC API 的版本 v1
kind: Role #这是一个Role对象
metadata:name: myrole #Role的名称
rules: #Role的权限规则
- apiGroups: #表示这个规则适用于核心 Kubernetes API 组中的资源- ""resources: #资源设定- pods #指定了规则适用的资源是 Podsverbs: #指定对Pods执行的操作- get #获取一个或多个 Pod 的详细信息- watch #观察 Pod 的变化,通常用于实时更新- list #列出所有 Pod- create #创建新的Pod- update #更新现有Pod的状态或配置- patch #部分更新现有Pod的状态或配置- delete #删除一个或多个 Pod
[root@k8s-master rbac]# kubectl apply -f myrole.yml
role.rbac.authorization.k8s.io/myrole created
#查看角色
[root@k8s-master rbac]# kubectl get role
NAME CREATED AT
myrole 2024-11-09T08:23:52Z[root@k8s-master rbac]# kubectl describe role myrole
Name: myrole
Labels: <none>
Annotations: <none>
PolicyRule:Resources Non-Resource URLs Resource Names Verbs--------- ----------------- -------------- -----pods [] [] [get watch list create update patch delete]
role角色
建立好之后,建立角色绑定
#在default命名空间中给huazi用户和myrole角色进行绑定
[root@k8s-master rbac]# kubectl create rolebinding rolebind-huazi-myrole --namespace default --role myrole --user huazi --dry-run=client -o yaml > rolebind.yml[root@k8s-master rbac]# vim rolebind.yml
[root@k8s-master rbac]# cat rolebind.yml
apiVersion: rbac.authorization.k8s.io/v1 #指定了使用 RBAC API 的版本 v1
kind: RoleBinding #表示这是一个RoleBinding对象
metadata:name: rolebind-huazi-myrole #RoleBinding的名称namespace: default #指定了这个RoleBinding适用的命名空间是 default
roleRef: #Role对象apiGroup: rbac.authorization.k8s.iokind: Rolename: myrole
subjects: #定义了RoleBinding适用的主体(即谁可以使用这个 Role)
- apiGroup: rbac.authorization.k8s.iokind: User #主体是一个User对象name: huazi #User名称
[root@k8s-master rbac]# kubectl apply -f rolebind.yml
rolebinding.rbac.authorization.k8s.io/rolebind-huazi-myrole created
#查看对象绑定
[root@k8s-master rbac]# kubectl get rolebindings.rbac.authorization.k8s.io
NAME ROLE AGE
rolebind-huazi-myrole Role/myrole 2s[root@k8s-master rbac]# kubectl describe rolebindings.rbac.authorization.k8s.io
Name: rolebind-huazi-myrole
Labels: <none>
Annotations: <none>
Role:Kind: RoleName: myrole
Subjects:Kind Name Namespace---- ---- ---------User huazi
#切换到huazi用户
[root@k8s-master rbac]# kubectl config use-context huazi@kubernetes
Switched to context "huazi@kubernetes".
#由于我们设置了权限,就可以做相应操作
[root@k8s-master rbac]# kubectl run testpod --image myapp:v1
pod/testpod created[root@k8s-master rbac]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 1/1 Running 0 11s 10.224.114.161 k8s-node1.org <none> <none>
但是我们只对pods资源
做了相应权限
,没有对svc资源
做,所以不能对svc资源
做相关操作
#我们发现都是报错
[root@k8s-master rbac]# kubectl expose pod testpod --port 8080 --target-port 80
Error from server (Forbidden): services is forbidden: User "huazi" cannot create resource "services" in API group "" in the namespace "default"[root@k8s-master rbac]# kubectl get svc
Error from server (Forbidden): services is forbidden: User "huazi" cannot list resource "services" in API group "" in the namespace "default"
但是role
只针对一个命名空间
,在其他的命名空间
中没有权限
,clusterrole
对于集群中的所有命名空间
,权限
都是生效的
#切换到admin
[root@k8s-master rbac]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".#回收
[root@k8s-master rbac]# kubectl delete pods testpod
pod "testpod" deleted
clusterrole
示例
#创建一个名为myclusterrole的clusterrole
[root@k8s-master rbac]# kubectl create clusterrole myclusterrole --resource=services --verb get --dry-run=client -o yaml > myclusterrole.yml#对每一个资源分开进行控制
[root@k8s-master rbac]# vim myclusterrole.yml
[root@k8s-master rbac]# cat myclusterrole.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: myclusterrole
rules:
- apiGroups:- ""resources:- servicesverbs:- get- list- watch- create- update- patch- delete
- apiGroups:- appsresources:- deploymentsverbs:- get- list- watch- create- update- patch- delete
[root@k8s-master rbac]# kubectl apply -f myclusterrole.yml
clusterrole.rbac.authorization.k8s.io/myclusterrole created
#查看创建的clusterrole
[root@k8s-master rbac]# kubectl get clusterrole myclusterrole
NAME CREATED AT
myclusterrole 2024-11-09T08:52:47Z#我们发现如果有点的话,apiGroups下就要写相关的内容
[root@k8s-master rbac]# kubectl describe clusterrole myclusterrole
Name: myclusterrole
Labels: <none>
Annotations: <none>
PolicyRule:Resources Non-Resource URLs Resource Names Verbs--------- ----------------- -------------- -----services [] [] [get list watch create update patch delete]deployments.apps [] [] [get list watch create update patch delete]
#创建名为clusterrolebind-huazi-myclusterrole的角色绑定
[root@k8s-master rbac]# kubectl create clusterrolebinding clusterrolebind-huazi-myclusterrole --clusterrole myclusterrole --user huazi --dry-run=client -o yaml > clusterrolebing.yml[root@k8s-master rbac]# vim clusterrolebing.yml
[root@k8s-master rbac]# cat clusterrolebing.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: clusterrolebind-huazi-myclusterrole
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.iokind: Username: huazi
[root@k8s-master rbac]# kubectl apply -f clusterrolebing.yml
clusterrolebinding.rbac.authorization.k8s.io/clusterrolebind-huazi-myclusterrole created
#查看角色绑定
[root@k8s-master rbac]# kubectl get clusterrolebinding clusterrolebind-huazi-myclusterrole
NAME ROLE AGE
clusterrolebind-huazi-myclusterrole ClusterRole/myclusterrole 45s[root@k8s-master rbac]# kubectl describe clusterrolebinding clusterrolebind-huazi-myclusterrole
Name: clusterrolebind-huazi-myclusterrole
Labels: <none>
Annotations: <none>
Role:Kind: ClusterRoleName: myclusterrole
Subjects:Kind Name Namespace---- ---- ---------User huazi
#切换角色
[root@k8s-master rbac]# kubectl config use-context huazi@kubernetes
Switched to context "huazi@kubernetes".
#运行pod
[root@k8s-master rbac]# kubectl run testpod --image myapp:v1
pod/testpod created#查看pod
[root@k8s-master rbac]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
testpod 1/1 Running 0 8s 10.224.24.158 k8s-node2.org <none> <none>#做service服务
[root@k8s-master rbac]# kubectl expose pods testpod --port 8080 --target-port 80
service/testpod exposed#查看service服务
[root@k8s-master rbac]# kubectl get svc testpod
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
testpod ClusterIP 10.105.140.35 <none> 8080/TCP 14s
#删除pod
[root@k8s-master rbac]# kubectl delete pods testpod
pod "testpod" deleted#删除svc
[root@k8s-master rbac]# kubectl delete svc testpod
service "testpod" deleted
#切换回admin
[root@k8s-master rbac]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
服务账户的自动化
服务账户准入控制器
(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
”的服务账户