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

  • apps 组deployments, statefulsets, daemonsets, replicasets, controllerrevisions

  • batch 组jobs, cronjobs

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

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

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

四、准入控制

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

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