1. 安全管理的概述

k8s 对我们整个系统的认证,授权,访问控制做了精密的设置;对于 k8s 集群来说,apiserver 是整 个集群访问控制的唯一入口,我们在 k8s 集群之上部署应用程序的时候,也可以通过宿主机的 NodePort 暴露的端口访问里面的程序,用户访问 kubernetes 集群需要经历如下认证过程:认证 ->授权->准入控制(adminationcontroller)

1.1 认证

认证其实就是对客户端的认证,通俗点就是用户名密码的验证

1.2 授权

授权是对资源的授权,k8s 中的资源无非是容器,最终其实就是容器的计算,网 络,存储资源,当一个请求经过认证后,需要访问某一个资源(比如创建一个 pod),授权检查会根 据授权规则判定该资源(比如某 namespace 下的 pod)是否是该客户可访问的。

1.3 准入控制

准入控制器位于 API Server 中,在对象被持久化之前,准入控制器拦 截对 API Server 的请求,一般用来做身份验证和授权。我们在部署 Kubernetes 集群的时候都会默认开启一系列准入控制器,如果没有设置这些准入控制 器的话可以说你的 Kubernetes 集群就是在裸奔,应该只有集群管理员可以修改集群的准入控制 器。

k8s 的整体架构也是一个微服务的架构,所有的请求都是通过一个 GateWay,也就是 kubeapiserver 这个组件(对外提供 REST 服务),k8s 中客户端有两类,一种是普通用户,一种是集群 内的 Pod,这两种客户端的认证机制略有不同,但无论是哪一种,都需要依次经过认证,授权,准 入这三个机制。

2. 认证

2.1 token 令牌认证

双方有一个共享密钥,服务器上先创建一个密码下来,客户端登陆的时候拿这个密码登陆即可,这个 就是对称密钥认证方式;k8s 提供了一个 restful 风格的接口,它的所有服务都是通过 http 协议提 供的,因此认证信息只能经由 http 协议的认证首部进行传递,这种认证首部进行传递通常叫做令牌;

2.2 ssl认证

对于 k8s 访问来讲,ssl 认证能让客户端确认服务器的认证身份,我们在跟服务器通信的时候,需要 服务器发过来一个证书,我们需要确认这个证书是不是 ca 签署的,如果是我们认可的 ca 签署的, 里面的 subj 信息与我们访问的目标主机信息保持一致,没有问题,那么我们就认为服务器的身份得 到认证了,k8s 中最重要的是服务器还需要认证客户端的信息,kubectl 也应该有一个证书,这个证 书也是 server 所认可的 ca 签署的证书,双方需要互相认证,实现加密通信,这就是 ssl 认证。

2.3 kubernetes 上的账号

User account:实实在在现实中的人,人可以登陆的账号,客户端想要对 apiserver 发起请求, apiserver 要识别这个客户端是否有请求的权限,那么不同的用户就会有不同的权限,靠用户账号表 示,叫做 username

ServiceAccount:方便 Pod 里面的进程调用 Kubernetes API 或其他外部服务而设计的,是 kubernetes 中的一种资源。

默认的 service account 仅仅只能获取当前 Pod 自身的相关属性,无法观察到其他名称空间 Pod 的相关属性信息。如果想要扩展 Pod,假设有一个 Pod 需要用于管理其他 Pod 或者是其他资源对 象,是无法通过自身的名称空间的 serviceaccount 进行获取其他 Pod 的相关属性信息的,此时就需要进行手动创建一个 serviceaccount,并在创建 Pod 时进行定义。那么 serviceaccount 该如 何进行定义呢?实际上,service accout 也属于一个 k8s 资源,serviceAccount 也属于标准的 k8s 资源,可以创建一个 serviceAccount,创建之后由我们创建的 pod 使用 serviceAccountName 去加载自己定义的 serviceAccount 就可以了

--- 1. 创建一个serviceaccount
[root@k8s-master /manifests/serviceaccount]# kubectl create serviceaccount test
serviceaccount/test created
[root@k8s-master /manifests/serviceaccount]# kubectl get sa
--- 2. 查看这个账号的详细信息
[root@k8s-master /manifests/serviceaccount]# kubectl  describe sa test 
Name:                test
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   test-token-4wb8b
Tokens:              test-token-4wb8b
Events:              <none>
## 上面可以看到生成了一个 test-token-4wb8b的 secret 和 test-token-4wb8b的 token
--- 3. secret 显示如下
[root@k8s-master /manifests/serviceaccount]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-crxrc   kubernetes.io/service-account-token   3      5d18h
test-token-4wb8b      kubernetes.io/service-account-token   3      19h
[root@k8s-master /manifests/serviceaccount]# kubectl  describe secret test-token-4wb8b
## 上面可以看到生成了 test-token-4wb8b 的 token 详细信息,这个 token 就是 sa 连接 apiserver的认证信息,这个 token 也是登陆 k8s dashboard 的 token,这些是一个认证信息,能够登陆k8s,能认证到 k8s,但是不能做别的事情,不代表权限,想要做其他事情,需要授权

在 K8S 集群当中,每一个用户对资源的访问都是需要通过 apiserver 进行通信认证才能进行访问 的,那么在此机制当中,对资源的访问可以是 token,也可以是通过配置文件的方式进行保存和使用 认证信息,可以通过 kubectl config 进行查看配置

[root@k8s-master /manifests/serviceaccount]# kubectl config view 
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.0.160:6443       ## apiserver 的地址
  name: kubernetes                           ## 集群的名字 
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes          ## 上下文的名字
current-context: kubernetes-admin@kubernetes ## 当前上下文的名字
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

3. 授权

如果用户通过认证,什么权限都没有,需要一些后续的授权操作,如对资源的增删该查等, kubernetes1.6 之后开始有 RBAC(基于角色的访问控制机制)授权检查机制。

3.1 什么是RBAC(基于角色的访问控制)

让一个用户(Users)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在 授权机制当中,只需要将权限授予某个角色,此时用户将获取对应角色的权限,从而实现角色的访问 控制。

在 k8s 的授权机制当中,采用 RBAC 的方式进行授权,其工作逻辑是,把对对象的操作权限定义到 一个角色当中,再将用户绑定到该角色,从而使用户得到对应角色的权限。如果通过 rolebinding 绑定 role,只能对 rolebingding 所在的名称空间的资源有权限,比如user1 这个用户绑定到 role1 上,只对 role1 这个名称空间的资源有权限,对其他名称空间资源没有权限,属于名称空间级别的。

另外,k8s 为此还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有可操作的权限,从而将 User2 通过 ClusterRoleBinding 到 ClusterRole,从而使 User2 拥有集群的操作权限。

上面我们说了两个角色绑定:

(1)用户通过 rolebinding 绑定 role

(2)用户通过 clusterrolebinding 绑定 clusterrole

还有一种:rolebinding 绑定 clusterrole

4. 准入控制

一般而言,准入控制只是用来定义我们授权检查完成之后的后续的其他安全检查操作的,进一步补充 了授权机制,由多个插件组合实行,一般而言在创建,删除,修改或者做代理时做补充。

kubernetes 中账户区分为:User Accounts(用户账户) 和 Service Accounts(服务账户) 两种:

UserAccount 是给 kubernetes 集群外部用户使用的,例如运维或者集群管理人员。

ServiceAccount 是 Pod 使用的账号,Pod 容器的进程需要访问 API Server 时用的就是 ServiceAccount 账户;ServiceAccount 仅局限它所在的 namespace,每个 namespace 创建时都会 自动创建一个 default service account;创建 Pod 时,如果没有指定 Service Account,Pod 则会使 用 default Service Account。

5. RBAC的认证策略

在 Kubernetes 中,所有资源对象都是通过 API 进行操作,他们保存在 etcd 里。而对 etcd 的操作 我们需要通过访问 kube-apiserver 来实现,上面的 Service Account 其实就是 APIServer 的认证过 程,而授权的机制是通过 RBAC:基于角色的访问控制实现。

RBAC 有四个资源对象,分别是 Role、ClusterRole、RoleBinding、ClusterRoleBinding

5.1 Role: 角色

一组权限的集合,在一个命名空间中,可以用其来定义一个角色,只能对命名空间内的资源进行授权。如果是集群级别的资源,则需要使用 ClusterRole。例如:定义一个角色用来读取 Pod 的权限

[root@k8s-master /manifests/serviceaccount]# cat role.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: rbac
  name: pod-read
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

rules 中的参数说明: 
1、apiGroups:支持的 API 组列表,例如:"apiVersion: batch/v1"等 
2、resources:支持的资源对象列表,例如 pods、deplayments、jobs 等 
3、resourceNames: 指定 resource 的名称 
4、verbs:对资源对象的操作方法列表。 

5.2 ClusterRole:集群角色

具有和角色一致的命名空间资源的管理能力,还可用于以下特殊元素的授权

1、集群范围的资源,例如 Node

2、非资源型的路径,例如:/healthz

3、包含全部命名空间的资源,例如 Pods

## 定义一个集群角色可让用户访问任意 secrets 
[root@k8s-master /manifests/serviceaccount]# cat clusterRole.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole 
metadata: 
 name: secrets-clusterrole 
rules: 
- apiGroups: [""] 
  resources: ["secrets"] 
  verbs: ["get","watch","list"]

5.3 RoleBinding:角色绑定、ClusterRolebinding:集群角色绑定

角色绑定和集群角色绑定用于把一个角色绑定在一个目标上,可以是 User,Group,Service Account,使用 RoleBinding 为某个命名空间授权,使用 ClusterRoleBinding 为集群范围内授 权。

## 将在 rbac 命名空间中把 pod-read 角色授予用户 es 
[root@k8s-master /manifests/serviceaccount]# cat rolebinding-es.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: 
 name: pod-read-bind 
 namespace: rbac 
subjects:
 - kind: User
   name: es 
   apiGroup: rbac.authorization.k8s.io
roleRef:
   kind: Role
   name: pod-read 
   apiGroup: rbac.authorization.k8s.io

[root@k8s-master /manifests/serviceaccount]# kubectl get role,rolebinding -n rbac
NAME                                      CREATED AT
role.rbac.authorization.k8s.io/pod-read   2025-09-24T02:34:39Z

NAME                                                  ROLE            AGE
rolebinding.rbac.authorization.k8s.io/pod-read-bind   Role/pod-read   90s

RoleBinding 也可以引用 ClusterRole,对属于同一命名空间内的 ClusterRole 定义的资源主体进 行授权, 例如:es 能获取到集群中所有的资源信息

[root@k8s-master /manifests/serviceaccount]# cat rolebinding-es-allresource.yaml 
apiVersion: rbac.authorization.k8s.io/v1 
kind: RoleBinding 
metadata: 
 name: es-allresource 
 namespace: rbac 
subjects: 
- kind: User 
  name: es 
  apiGroup: rbac.authorization.k8s.io 
roleRef: 
  apiGroup: rbac.authorization.k8s.io 
  kind: ClusterRole 
  name: cluster-admin 

[root@k8s-master /manifests/serviceaccount]# kubectl describe rolebinding/es-allresource -n rbac 
Name:         es-allresource
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind  Name  Namespace
  ----  ----  ---------
  User  es  

集群角色绑定的角色只能是集群角色,用于进行集群级别或对所有命名空间都生效的授权 例如:允许 manager 组的用户读取所有 namaspace 的 secrets

[root@k8s-master /manifests/serviceaccount]# cat  ClusterRoleBinding.yaml 
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-secret-global
subjects:
- kind: Group
  name: manager
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-read
  apiGroup: rbac.authorization.k8s.io

6. Service Account 的授权管理

Service Account 也是一种账号,是给运行在 Pod 里的进程提供了必要的身份证明。需要在 Pod 定义中指明引用的 Service Account,这样就可以对 Pod 的进行赋权操作。例如:pod 内可获取 rbac 命名空间的所有 Pod 资源,pod-reader-sc 的 Service Account 是绑定了名为 pod-read 的 Role

[root@k8s-master /manifests/pod]# cat nginx.yaml 
apiVersion: v1  
kind: Pod  
metadata:  
  name: demo-pod  
  namespace: rbac  
spec:
  serviceAccountName: pod-reader-sc
  containers:      
  - name:  nginx
    ports:
    - containerPort: 80 
    image: '192.168.0.77:32237/uat/nginx:1.22'

默认的 RBAC 策略为控制平台组件、节点和控制器授予有限范围的权限,但是除 kube-system 外 的 Service Account 是没有任何权限的。

--- 1. 为一个命名空间中名为 default 的 Service Account 授权
## 如果一个应用没有指定 serviceAccountName,则会使用名为 default 的 Service Account。
## 注意,赋予 Service Account “default”的权限会让所有没有指定 serviceAccountName 的 Pod都具有这些权限 
## 例如,在 my-namespace 命名空间中为 Service Account“default”授予只读权限: 
kubectl create rolebinding default-view --clusterrole=view --serviceaccount=my-namespace:default --namespace=my-namespace 

--- 2. 为命名空间中所有 Service Account 都授予一个角色
# 如果希望在一个命名空间中,任何 Service Account 应用都具有一个角色,则可以为这一命名空间的 Service Account 群组进行授权
kubectl create rolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts:my-namespace --namespace=my-namespace

--- 3. 为集群范围内所有 Service Account 都授予一个低权限角色 
kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view --group=system:serviceaccounts 

--- 4. 为所有 Service Account 授予超级用户权限 
kubectl create clusterrolebinding serviceaccounts-view --clusterrole=cluster-admin --group=system:serviceaccounts  

7. 使用 kubectl 命令行工具创建资源对象

--- 1. 在命名空间 rbac 中为用户 es 授权 admin ClusterRole: 
kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac 

--- 2. 在命名空间 rbac 中为名为 myapp 的 Service Account 授予 view ClusterRole: 
kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac 

--- 3. 在全集群范围内为用户 root 授予 cluster-admin ClusterRole
kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root 

--- 4. 在全集群范围内为名为 myapp 的 Service Account 授予 view ClusterRole:
kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp