k8sday17安全机制

一、安全机制说明

在k8s集群中,API Server是集群内部各个通信组件的中介,是外部控制的入口,所以k8s的安全机制主要是针对保护API Server来设置。

二、认证

1、常见认证方式

Kubernetes 集群的客户端认证方式主要分为以下几种:

1. 客户端证书认证(X.509 Client Certificates)
  • 原理:通过为客户端签发 X.509 证书,并在请求时携带该证书,API Server 使用预先配置的 CA 证书进行验证。

  • 配置方式 :证书和私钥配置在 kubeconfig 文件中,API Server 启动时通过 --client-ca-file 指定 CA 证书。

  • 特点:安全性高,支持双向 TLS 认证,常用于 kubectl 和集群组件间通信。

2. 静态 Token 认证(Static Token File)
  • 原理 :API Server 启动时加载一个包含用户名、用户组、Token 等信息的静态文件(通过 --token-auth-file 指定)。

  • 使用方式 :客户端在 HTTP Header 中加入 Authorization: Bearer <token> 进行认证。

  • 特点:简单但不灵活,Token 长期有效,修改需重启 API Server。

3. Service Account Token 认证
  • 原理:Kubernetes 自动为每个命名空间创建 ServiceAccount,并为其生成 JWT Token。

  • 使用场景:Pod 内进程访问 API Server 时使用,Token 自动挂载到 Pod 中。

  • 特点:适用于集群内部服务认证,Token 由 API Server 签发并验证。

4. Bootstrap Token 认证
  • 原理:用于节点加入集群时的认证,Token 通过 Secret 存储在 kube-system 命名空间中。

  • 使用场景:集群扩容或新节点加入时使用。

5. OpenID Connect(OIDC)Token 认证
  • 原理:基于 OAuth 2.0 和 OIDC 协议,通过外部身份提供商(如 Google、Azure AD)进行认证。

  • 配置方式 :API Server 启动参数中配置 --oidc-issuer-url--oidc-client-id 等。

  • 特点:适用于与外部身份系统集成,支持单点登录(SSO)。

6. Webhook Token 认证
  • 原理:通过远程 Webhook 服务验证 Bearer Token,API Server 将 Token 转发给 Webhook 服务进行认证。

  • 配置方式 :API Server 启动参数中配置 --authentication-token-webhook-config-file 指定 Webhook 服务的 kubeconfig 文件。

  • 特点:可扩展性强,支持自定义认证逻辑和外部身份系统(如 LDAP、SAML)。

7. 身份认证代理(Authenticating Proxy)
  • 原理:通过反向代理(如 Nginx、OAuth2 Proxy)在请求头中注入用户身份信息,API Server 信任代理并提取用户信息。

  • 配置方式 :API Server 通过 --requestheader-username-headers 等参数配置信任的头信息。

  • 特点:适用于统一认证网关场景,减少客户端配置复杂度。

8. HTTP Basic 认证
  • 原理:通过用户名和密码进行认证,信息以 Base64 编码后放在 HTTP Header 中。

  • 特点:简单但不安全,通常需配合 HTTPS 使用,生产环境较少使用。

9. 匿名认证
  • 原理:允许未经认证的请求访问集群资源,默认关闭。

  • 配置方式 :通过 API Server 启动参数 --anonymous-auth=true 开启。

  • 特点:存在安全风险,生产环境建议关闭。

10. client-go 凭据插件(Exec Credential Plugins)
  • 原理:通过外部命令动态获取认证凭据(如 Token 或证书),支持自定义认证协议(如 LDAP、Kerberos)。

  • 配置方式 :在 kubeconfig 文件中配置 exec 字段,指定外部命令及其参数。

  • 特点:灵活性高,支持与外部身份系统集成。

认证方式 安全性 适用场景 配置复杂度 备注
客户端证书 kubectl、组件通信 默认推荐方式
静态 Token 简单场景 Token 长期有效
Service Account Pod 内服务认证 自动挂载
Bootstrap Token 节点加入集群 临时 Token
OIDC Token 外部身份系统集成 支持 SSO
Webhook Token 自定义认证逻辑 可扩展性强
身份认证代理 统一认证网关 需配置代理信任
HTTP Basic 测试环境 不安全,需 HTTPS
匿名认证 公开访问 建议关闭
client-go 插件 复杂外部系统集成 支持动态认证

2、部分认证方式讲解

由于k8s中支持的认证方式较多,我选择其中三个较常用的认证方式进行讲解

2.1HTTPS证书认证(客户端证书)

精简总结:HTTPS证书认证就是在客户端和服务端均信任的 CA 架构下,实现 TLS 双向握手进行身份认证和授权的方式。

客户端和服务器端向二者均信任的 CA 架构进行证书请求,CA 架构下发证书后,二者实现 TLS 双向握手(客户端发起 HTTPS → 服务端返回自己的证书 → 客户端验证服务端证书 →服务端要求客户端证书 → 客户端发送自己的证书 → 服务端用公钥对客户端证书做链式验证 → 握手完成,建立加密通道),由由 API Server 验证,并把证书的 CN/O 映射到 RBAC 身份即可。

①、HTTPS 认证方式(补充)
Ⅰ、HTTPS 单向认证

客户端认证服务端,如访问百度等等的网页。

首先客户端向服务端发送请求(包含客户端支持的https版本),服务器选择二者均支持的https版本并向客户端发送公钥/证书,然后客户端拿着自己的 CA 架构对服务端发来的公钥进行安全认证,如果公钥不可信会提醒客户端该网页的证书不可信,可能存在什么虚假信息等等,如果可信则客户端向服务器端发送自己的对称加密的算法,接着服务器端从中选择合适的算法返还给客户端,至此客户端和服务器端就形成了自己的加密算法,客户端在收到后会创建随机字符串作为加密密钥,再对此经过加密,向服务器端发送公钥,服务器端拿到后对此进行解密,得到对称加密的密钥

Ⅱ、HTTPS 双向认证(mTLS)

客户端和服务端互相认证,如ATM取钱。

https的双向认证和单向认证差不多,只不过是多了服务端认证客户端,确保是正确可执行的用户。

k8s中的API Server就是使用的HTTPS 的双向认证。

2.2HTTP Token认证(静态 Token)

精简总结:HTTP Token 认证就是用一个通过特殊编码方式的且难以被模仿的字符串------ Token 来进行身份认证的方式

Token 是一个很长很复杂的字符串,存储在 API Server 的可访问文件中,每当客户端发起 API 的调用请求时,要在 HTTP Header 中放入 Token,之后 API 会去寻找你的 Token是否在可访问文件中存在,如果存在且匹配则身份认证成功,不存在就拒绝调用请求。

2.3HTTP Basic 认证

精简总结:HTTP Basic 认证就是通过用户名和密码进行认证的方式。

将用户名和密码信息以 Base64 编码后生成的字符串放在 HTTP Header 中,将其发给服务端,服务端再次进行编码得到你的用户名和密码,如果正确且相互匹配则身份认证成功,否则失败,拒绝请求。

3、必须认证+mTLS的组件/角色

3.1需认证不需mTLS

其余 常驻 Master 节点且与 API Server 同机 的组件,默认走本地非安全端口 127.0.0.1:8080,不强制 双向 TLS,但生产环境仍建议关掉 8080 端口,全部强制 mTLS。

3.2需认证需mTLS

在 Kubernetes 集群里,只要"客户端 ≠ API Server 本机" ,就必须走 HTTPS 6443 端口 + 双向 TLS(mTLS) ;换句话说,下面这些组件/角色 无一例外 都要做双向认证:

  • kubelet(每个节点)【自动颁发证书】

  • kube-proxy(每个节点)【手动颁发证书】

  • kubectl(任何一台管理机)【手动颁发证书】

  • 以 Pod 形式运行、但 使用自己证书 的扩展控制器/Operator(如 Calico-kube-controllers、metrics-server 等)

  • 外部调用方(CI/CD、Webhook、自定义 Controller)------只要它不在 Master 本机

精简总结:较安全环境可走非安全地址端口,非安全环境必须mTLS,生产环境强制mTLS。

组件/场景 必须 mTLS 默认端口 备注
kubelet → API Server 6443 自动轮换证书
kube-proxy → API Server 6443 DaemonSet 挂载证书
kubectl → API Server 6443 kubeconfig 证书或 token
Controller/Scheduler → API Server 6443 1.20+ 已无 8080
Pod(ServiceAccount Token)→ API Server ❌(只需单向 TLS) 6443 非 mTLS,但强制 TLS
自定义/外部 Controller → API Server 6443 客户端证书或 Token
3.3补充SA

ServiceAccount 是 Kubernetes 用来给 "Pod 内进程" 提供 "集群内身份 + 调用 API Server 的凭据" 的原生对象。

主要包括:

  • ca.crt:集群根证书,用于Pod确定API Server的安全性

  • token:用于API Server确认Pod的安全性

  • namespace:标识Pod的作用域

bash 复制代码
  # 1. 创建
  # 创建语句可直接 kubectl create sa <你的SA名称> -n <要放在的命名空间>
  kubectl create serviceaccount api-bot -n dev
  ​
  # 2. 赋权(RBAC),下方授权有讲
  kubectl create role dev-reader --verb=get,list --resource=pods -n dev
  kubectl create rolebinding dev-reader-binding \
    --role=dev-reader --serviceaccount=dev:api-bot -n dev
  ​
  # 3. 在 Pod 里引用
  apiVersion: v1
  kind: Pod
  metadata:
    name: job-pod
    namespace: dev
  spec:
    serviceAccountName: api-bot        # 关键字段
    containers:
    - image: bitnami/kubectl:latest
      command: ["kubectl","get","pods"]

4、kubeconfig

4.1kubeconfig 是什么
  • 作用:告诉 kubectl/任何 client-go 程序「连哪个集群、用什么身份、默认命名空间」。

  • 本质:一个 YAML(默认 ~/.kube/config),可内嵌或引用证书、Token、Exec 插件。

4.2文件结构

以下给出一个大致yaml文件,如果想看自己的可以进入主节点(control plane)使用cat ~/.kube/config查看

bash 复制代码
  # 1. 集群列表
  apiVersion: v1
  clusters:
    - cluster:
      certificate-authority-data: LS0tLS1CRUdJTiBD...   # 当前集群 CA 证书
      server: https://10.0.0.10:6443        # 当前集群地址和端口
      name: kind-my-multi-node-cluster1     # 由于我是用kind创建的集群,所以我的集群名字前带有kind
  # 2. 用户列表(身份)
  users:
  - name: kind-my-multi-node-cluster1
    user:
      client-certificate-data: LS0tLS1CRUdJTiBD...      # 用户证书
      client-key-data: LS0tLS1CRUdJTiBSU0Eg...          # 用户私钥
  - name: bob-token
    user:
      token: eyJhbGciOiJSUzI1NiIsIm...
  ​
  # 3. 上下文(把 cluster + user + 默认 ns 绑定)
  contexts:
  - context:
      cluster: kind-my-multi-node-cluster1
      user: kind-my-multi-node-cluster1
    name: kind-my-multi-node-cluster1
  current-context: kind-my-multi-node-cluster1
  kind: Config
  preferences: {}
  ​
  # 4. 当前默认上下文
  current-context: prod-alice

注意以上四大项顺序可能不同

当我们使用 kubectl 执行命令时,会去调用 ~/.kube/config的kubeconfig文件

三、授权

Kubernetes 提供了多种授权机制来控制用户和服务账户对集群资源的访问权限。

1、授权模式概述

Kubernetes 支持以下授权模式(可同时启用多个):

  • Node Authorization - 专门授权 kubelet

  • ABAC (Attribute-Based Access Control) - 基于属性的访问控制

  • RBAC (Role-Based Access Control) - 基于角色的访问控制(最常用)

  • Webhook - 外部授权服务集成

主流实现:RBAC(Role-Based Access Control)

2、RBAC(基于角色的访问控制)

2.1核心组件

RBAC提供了4个顶级资源对象:

  • Role :定义在特定命名空间 中的权限集合

  • ClusterRole :定义在集群 范围的权限集合

  • RoleBinding :将角色绑定到用户/组/服务账户(命名空间 内)

  • ClusterRoleBinding :将集群角色绑定到用户/组/服务账户(集群 范围)

以上四个均可通过kubectl与API进行操作

2.2配置文件举例
①、Role
bash 复制代码
  apiVersion: rbac.authorization.k8s.io/v1
  kind: Role
  metadata:
    namespace: default              # 命名空间
    name: pod-reader
  rules:
  - apiGroups: [""]                 # 空字符串表示核心API组
    resources: ["pods"]             # 操作的资源类型
    verbs: ["get", "watch", "list"]
  # 即将 "get", "watch", "list" 这些操作授予给一个 Role(命名空间级权限对象),名字叫 pod-reader,位于 default 命名空间。

Role刚创建出来其权限是0,不存在一开始就有很多权限,Role只可以定义在一个命名空间,如果要跨命名空间则要创建ClusterRole。rules中的权限可增加多个。

②、ClusterRole
bash 复制代码
  
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRole
  metadata:
                                 # 和 Role 的区别在于没有命名空间
    name: secret-reader
  rules:
  - apiGroups: [""]                 # 空字符串表示核心API组
    resources: ["secrets"]
    verbs: ["get", "watch", "list"]
  # 即将 "get", "watch", "list" 这些操作授予给一个 ClusterRole(集群级权限对象),名字叫 secret-reader
③、RoleBinding
bash 复制代码
  apiVersion: rbac.authorization.k8s.io/v1
  kind: RoleBinding
  metadata:
    name: read-pods
    namespace: default
  subjects:                              # 绑定对象
  - kind: User                           # 授予身份1,绑定的是一个用户
    name: jane                           # 身份1的名字(自定义)
    apiGroup: rbac.authorization.k8s.io
  - kind: ServiceAccount                 # 授予身份2,绑定的是一个SA
    name: default                        # 身份2的名字(自定义)
    namespace: kube-system
  roleRef:                               # 要引用的角色(角色来源)
    kind: Role                           # 引用的是命名空间级的 Role(而非 ClusterRole)
    name: pod-reader                     # 引用的 Role 的名称叫 pod-reader
    # 该对象必须与 RoleBinding 位于同一个命名空间
    apiGroup: rbac.authorization.k8s.io  # 指定 Role 所属的 API 组,固定值
  # 即创建了一个 RoleBinding(命名空间级权限绑定),名字叫 read-pods,位于 default 命名空间。把 Role pod-reader 的权限授予两个身份 User 和 ServiceAccount
④、ClusterRoleBinding
bash 复制代码
  apiVersion: rbac.authorization.k8s.io/v1
  kind: ClusterRoleBinding
  metadata:
    name: read-secrets-global
  subjects:                                # 绑定对象
  - kind: Group                            # 绑定的是一个组
    name: manager                          # 组的名称
    apiGroup: rbac.authorization.k8s.io
  roleRef:                                 # 要引用的角色(角色来源)
    kind: ClusterRole                      # 引用的是集群级的 ClusterRole(而非 Role)
    name: secret-reader                    # 引用的 ClusterRole 的名称叫 secret-reader 
    apiGroup: rbac.authorization.k8s.io
  # 即创建了一个 ClusterRoleBinding(集群级权限绑定),名字叫 read-secrets-global。把一个名称叫 secret-reader 的 ClusterRole 权限授予身份 Group
2.3配合绑定关系
①、Role+RoleBinding

即在当前命名空间内,将角色绑定,最终是命名空间级别

②、ClusterRole+ClusterRoleBinding

即在当前集群内,将集群角色绑定,最终是集群级别

③、ClusterRole+RoleBinding

相当于降维,即在当前命名空间内,将集群角色绑定(可减小资源开销),最终是命名空间级别

2.4RBAC规则解析
①、rules字段结构

每个规则包含:

  • apiGroups:资源所属的API组("" 表示核心组)

  • resources:资源类型名称(复数形式)

  • verbs:操作动词(如 get, list, create, update, delete, watch)

  • resourceNames:可选,指定具体资源实例名称

  • nonResourceURLs:非资源端点(如 "/healthz")

②、apiGroups(分组)
分组字符串 说明 / 常见资源
""(空串) 核心组(Core)。Pod、Service、ConfigMap、Secret、Node、Namespace、Event ...
apps Deployment、StatefulSet、DaemonSet、ReplicaSet、ControllerRevision
batch Job、CronJob
autoscaling HorizontalPodAutoscaler(HPA)
networking.k8s.io Ingress、NetworkPolicy、IngressClass
policy PodDisruptionBudget、PodSecurityPolicy(已弃用)

以上分组只是部分,详情请见官方文档

③、resources(资源)
  • ""pods, services, configmaps, secrets, endpoints, events, persistentvolumeclaims, persistentvolumes, nodes, namespaces, serviceaccounts, resourcequotas, limitranges

  • appsdeployments, statefulsets, daemonsets, replicasets, controllerrevisions

  • batchjobs, cronjobs

以上只列出每个分组最常用的;完整列表可用 kubectl api-resources -o wide

每个大资源其下会有子资源

④、verbs(动作)
动词 含义 典型组合
get 读取单个资源 只读
list 读取集合 只读
watch 监听变化 只读
create 新建资源
update 整体更新资源
patch 局部更新资源
delete 删除单个资源
deletecollection 批量删除集合
* 所有动作(通配符) 超级权限

四、准入控制

当 API Server 已经通过 认证 & 鉴权 ,但在真正持久化之前 ,由一组 准入插件(Admission Webhook 或内置控制器) 再对资源做 "增删改"拦截或修改

主要是对额外功能的添加以及有权限但不合理的行为的过滤。