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的作用域
# 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 devkubectl create rolebinding dev-reader-binding \--role=dev-reader --serviceaccount=dev:api-bot -n dev# 3. 在 Pod 里引用apiVersion: v1kind: Podmetadata:name: job-podnamespace: devspec:serviceAccountName: api-bot # 关键字段containers:- image: bitnami/kubectl:latestcommand: ["kubectl","get","pods"]
4、kubeconfig
4.1kubeconfig 是什么
作用:告诉 kubectl/任何 client-go 程序「连哪个集群、用什么身份、默认命名空间」。
本质:一个 YAML(默认 ~/.kube/config),可内嵌或引用证书、Token、Exec 插件。
4.2文件结构
以下给出一个大致yaml文件,如果想看自己的可以进入主节点(control plane)使用cat ~/.kube/config查看
# 1. 集群列表apiVersion: v1clusters:- 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-cluster1user:client-certificate-data: LS0tLS1CRUdJTiBD… # 用户证书client-key-data: LS0tLS1CRUdJTiBSU0Eg… # 用户私钥- name: bob-tokenuser:token: eyJhbGciOiJSUzI1NiIsIm…# 3. 上下文(把 cluster + user + 默认 ns 绑定)contexts:- context:cluster: kind-my-multi-node-cluster1user: kind-my-multi-node-cluster1name: kind-my-multi-node-cluster1current-context: kind-my-multi-node-cluster1kind: Configpreferences: {}# 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
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata:namespace: default # 命名空间name: pod-readerrules:- apiGroups: [""] # 空字符串表示核心API组resources: ["pods"] # 操作的资源类型verbs: ["get", "watch", "list"]# 即将 "get", "watch", "list" 这些操作授予给一个 Role(命名空间级权限对象),名字叫 pod-reader,位于 default 命名空间。
Role刚创建出来其权限是0,不存在一开始就有很多权限,Role只可以定义在一个命名空间,如果要跨命名空间则要创建ClusterRole。rules中的权限可增加多个。
②、ClusterRole
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:# 和 Role 的区别在于没有命名空间name: secret-readerrules:- apiGroups: [""] # 空字符串表示核心API组resources: ["secrets"]verbs: ["get", "watch", "list"]# 即将 "get", "watch", "list" 这些操作授予给一个 ClusterRole(集群级权限对象),名字叫 secret-reader
③、RoleBinding
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: read-podsnamespace: defaultsubjects: # 绑定对象- kind: User # 授予身份1,绑定的是一个用户name: jane # 身份1的名字(自定义)apiGroup: rbac.authorization.k8s.io- kind: ServiceAccount # 授予身份2,绑定的是一个SAname: default # 身份2的名字(自定义)namespace: kube-systemroleRef: # 要引用的角色(角色来源)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
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:name: read-secrets-globalsubjects: # 绑定对象- kind: Group # 绑定的是一个组name: manager # 组的名称apiGroup: rbac.authorization.k8s.ioroleRef: # 要引用的角色(角色来源)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 或内置控制器) 再对资源做 “增删改”拦截或修改。
主要是对额外功能的添加以及有权限但不合理的行为的过滤。