首先Kubernetes中账户区分为:User Accounts(用户账户) 和 Service Accounts(服务账户) 两种,它们的设计及用途如下:
UserAccount是给kubernetes集群外部用户使用的,例如运维或者集群管理人员,使用kubectl命令时用的就是UserAccount账户。
UserAccount是全局性,在集群所有namespaces中,名称具有唯一性,默认情况下用户为admin;
用户名称可以在kubeconfig中查看
[root@k8s-master ~]# cd ~/.kube/
[root@k8s-master .kube]# ls
cache config http-cache
[root@k8s-master .kube]# cat config
users:
- name: kubernetes-admin
user:
ServiceAccount是给运行在Pod的程序使用的身份认证,Pod容器的进程需要访问API Server时用的就是ServiceAccount账户;当你创建 pod 的时候,如果你没有指定一个 ServiceAccount,系统会自动的在与该 pod 相同的 namespace 下为其指派一个 default ServiceAccount。
Kubernetes设计了一种Secret资源,分为两类,一种是用于 ServiceAccount 的 kubernetes.io/ service-account-token,就是上边说的 SA,每创建一个SA,就会随之创建一个Secret;另一种就是用户自定义的保密信息Opaque。
ServiceAccount仅局限它所在的namespace,所以在创建namespace时会自动创建一个默认的 SA,而 SA 创建时,也会创建对应的 Secret,下面操作验证下:
[root@k8s-master ~]# kubectl create namespace spacex #创建名称空间
namespace/spacex created
[root@k8s-master ~]# kubectl get sa -n spacex #名称空间创建完成后会自动创建一个sa
NAME SECRETS AGE
default 1 19s
[root@k8s-master ~]# kubectl describe sa default -n spacex #查看sa描述
Name: default
Namespace: spacex
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-gpvrn
Tokens: default-token-gpvrn
Events: <none>
[root@k8s-master ~]# kubectl get secret -n spacex #同时也会自动创建一个secret
NAME TYPE DATA AGE
default-token-gpvrn kubernetes.io/service-account-token 3 69s
在创建的名称空间中新建一个pod
vi sa-pods.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-sa
namespace: spacex
spec:
containers:
- name: nginx
image: ikubernetes/myapp:v1
ports:
- containerPort: 80
name: www
查看 pod
[root@k8s-master ~]# kubectl create -f sa-pods.yaml
pod/test-sa created
[root@k8s-master ~]# kubectl get pod -n spacex
NAME READY STATUS RESTARTS AGE
test-sa 1/1 Running 0 112s
名称空间新建的pod如果不指定sa,会自动挂载当前名称空间中默认的sa(default)
[root@k8s-master ~]# kubectl describe pod test-sa -n spacex
Name: test-sa
Namespace: spacex
Priority: 0
Node: k8s-node2/192.168.200.130
Start Time: Mon, 05 Feb 2024 14:14:20 +0800
Labels: <none>
Annotations: <none>
Status: Running
IP: 10.244.2.192
IPs:
IP: 10.244.2.192
Containers:
nginx:
Container ID: docker://2a35e0adf4127115fc1be32ba59800a03e81cfd0852253db9f4d5f3658b41d6b
Image: ikubernetes/myapp:v1
Image ID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 05 Feb 2024 14:14:20 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-gpvrn (ro)
创建一个sa 名称为admin
[root@k8s-master ~]# kubectl create serviceaccount admin
serviceaccount/admin created
[root@k8s-master ~]# kubectl get sa
NAME SECRETS AGE
admin 1 9s
default 1 17d
kindly-robin-mychart 1 24h
查看名称为admin的sa的信息,系统会自动创建一个token信息
[root@k8s-master ~]# kubectl describe sa admin
Name: admin
Namespace: default
Labels:
Annotations:
Image pull secrets:
Mountable secrets: admin-token-79qdr
Tokens: admin-token-79qdr
Events:
会自动创建一个secret(admin-token-rxtrc),用于当前sa连接至当前API server时使用的认证信息,1.24及之后因为安全原因不会自动再创建
[root@k8s-master ~]# kubectl get secret
NAME TYPE DATA AGE
admin-token-79qdr kubernetes.io/service-account-token 3 47s
default-token-pj9g7 kubernetes.io/service-account-token 3 17d
kindly-robin-mychart-token-54rjt kubernetes.io/service-account-token 3 24h
mysecret Opaque 2 3d21h
tomcat-ingress-secret kubernetes.io/tls 2 3h49m
创建一个pod应用刚刚创建的sa
vi deploy-sa.yaml
apiVersion: v1
kind: Pod
metadata:
name: sa-demo
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: httpd
containerPort: 80
pod会自动挂载自己sa的证书
[root@k8s-master ~]# kubectl create -f deploy-sa.yaml
pod/sa-demo created
[root@k8s-master ~]# kubectl describe pod sa-demo
Name: sa-demo
Namespace: default
Priority: 0
Node: k8s-node1/192.168.200.129
Start Time: Mon, 05 Feb 2024 14:25:44 +0800
Labels: app=myapp
release=canary
Annotations: <none>
Status: Running
IP: 10.244.1.178
IPs:
IP: 10.244.1.178
Containers:
myapp:
Container ID: docker://05b13f4e4029037626f2e2407d3379ed6e0beb5ac02396ae9d1268f1778b89bb
Image: ikubernetes/myapp:v2
Image ID: docker-pullable://ikubernetes/myapp@sha256:85a2b81a62f09a414ea33b74fb8aa686ed9b168294b26b4c819df0be0712d358
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 05 Feb 2024 14:25:44 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from admin-token-79qdr (ro)
RBAC介绍
在Kubernetes中,所有资源对象都是通过API对象进行操作,他们保存在etcd里。而对etcd的操作我们需要通过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而授权的机制是通过RBAC:基于角色的访问控制实现。
在 RBAC API 中,一个角色包含了一套表示一组权限的规则。权限以累加形式累积(没有”否定”的规则)。Role 是定义在一个 namespace 中,而 ClusterRole 是集群级别的。
Role and ClusterRole
一个 Role 对象只能用于授予对某一单一命名空间中资源的访问权限。以下示例描述了”default”命名空间中的一个 Role 对象的定义,用于授予对 pod 的读访问权限:
下面我们定义一个Role:
vim roles.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role
namespace: spacex
rules:
- apiGroups: [""] # 为空表示为默认的core api group
resources: ["pods"] # 数据源类型
verbs: ["get","watch","list"] #赋予的权限
ClusterRole 具有与 Role 相同权限角色控制能力,不同的就是 Cluster Role是集群级别,它可以用于:
集群级别的资源控制(例如 node 访问权限)
非资源型 endpoints(例如对某个目录或文件的访问:/healthz)
所有命名空间资源控制(Pod、Deployment等)
vim clusterroles.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: test-clusterrole
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get","create","list"]
以上Cluster role策略表示,有get,create,list整个集群service的权限
下面开始创建
[root@k8s-master ~]# kubectl create -f roles.yaml
role.rbac.authorization.k8s.io/test-role created
[root@k8s-master ~]# kubectl create -f clusterroles.yaml
clusterrole.rbac.authorization.k8s.io/test-clusterrole created
[root@k8s-master ~]# kubectl get role -n spacex
NAME CREATED AT
test-role 2024-02-05T07:05:01Z
[root@k8s-master ~]# kubectl get clusterrole -n spacex
NAME CREATED AT
test-clusterrole 2024-02-05T07:06:29Z
可以看到,role和cluster role都已经创建成功,但是clusterrole除了这次创建的还有许多,其中以system开头的全部是系统所用的,其他的都是在装一些插件时自动添加的,也要注意,我们自己创建cluster role时不要以system开通,以免分不清楚.
RoleBinding and ClusterRoleBinding
角色绑定将一个角色中定义的各种权限授予一个或者一组用户。角色绑定包含了一组相关主体(即 subject,包括用户 ——User、用户组 ——Group、或者服务账户 ——Service Account)以及对被授予角色的引用。在命名空间中可以通过 RoleBinding 对象授予权限,而集群范围的权限授予则通过 ClusterRoleBinding 对象完成。
创建RoleBinding
vim rolebindings.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rolebinding
namespace: spacex
subjects:
- kind: User # 权限资源类型
name: spacex # 权限名称
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role #要绑定的Role的类型(可以是Role或ClusterRole)
name: test-role # Role的名称
apiGroup: rbac.authorization.k8s.io
此策略表示,将名称为test-role的Role的权限资源赋予名为spacex的用户,仅作用于spacex namespace。
创建ClusterRoleBinding
vi clusterrolebindings.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: test-clusterrolebinding
subjects:
- kind: Group
name: spacex
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: test-clusterrole
apiGroup: rbac.authorization.k8s.io
以上策略表示,将name为test-clusterrole的ClusterRole的资源权限赋予给groupname为spacex 的用户组,此用户组下所有用户拥有对整个集群的 test-clusterrole内的资源权限。