华子目录
- `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, serviceAccountRole:角色,它其实是一组规则,定义了一组对Kubernetes API对象的操作权限RoleBinding:定义了“被作用者”和“角色”的绑定关系
rbac包括四种类型:Role、ClusterRole、RoleBinding、ClusterRoleBindingRole和ClusterRoleRole是一系列的权限的集合,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”的服务账户
