k8s入门到实战(十三)—— 认证与鉴权

认证与鉴权

官网:https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/

访问控制

客户端进行认证和鉴权操作

在 k8s 集群中,客户端通常有两类:

  • User Account:一般是独立于 k8s 之外的其他服务管理的用户账号

  • Service Account:k8s 管理的账号,用于为 Pod 中的服务进程在访问 k8s 时提供身份标识

ApiServer 是访问及管理资源对象的唯一入口。任何一个请求访问 ApiServer,都要经过下面三个流程:

  • Authentication(认证):身份鉴别,只有正确的账号才能够通过认证。
  • Authorization(授权):判断用户是否有权限对访问的资源执行特定的动作。
  • Admission Control(准入控制):用于补充授权机制以实现更加精细的访问控制功能.

认证管理

HTTP Token 认证:token 认证

HTTP Base 认证:用户名+密码

HTTPS 证书认证:CA 根证书认证

k8s 集群安全的最关键点在于如何识别并认证客户端身份,它提供了3种客户端身份认证方式:

  • HTTP Base 认证:通过用户名 + 密码的方式认证

这种认证方式是把 "用户名:密码" 用 BASE64 算法进行编码后的字符审放在 HTTP 请求中的 Header Authrizaton 域里发送给服务端。服务端收到后进行解码,获取用户名及密码,然后进行用户身份认证的过程。

  • HTTP Token认证:通过一个 Token 来识别合法用户

这种认证方式是用一个很长的 Token 来表明客户身份的一种方式,每 Token 对应一个用户,当客户端发起 APi 调用请求时,在 HTTP Header 里放入 Token,API Server 接到 Token 后会跟服务器中保存的 token 进行比对,然后进行用户身份认证的过程.

  • HTTPS证书认证:基于CA根证书签名的双向数字证书认证方式

这种认证方式是安全性最高的一种方式,但是同时也是操作起来最麻烦的一种方式

HTTPS 认证大体分为3个过程:

  1. 证书申请和下发, HTTPS 通信双方的服务器向 CA 机构申请证书,CA 机构下发根证书、服务端证书及私钥给申请者
  2. 客户端和服务端的双向认证
  • 客户端向服务器端发起清求,服务端下发自己的证书给客户端, 客户端接收到证书后,通过私钥解密证书,在证书中获得服务端的公钥,客户端利用服务器端的公钥认证证书中的信息,如果一致,则认可这个服务器
  • 客户端发送自己的证书给服务器端,服务端接收到证书后,通过私钥解密证书,在证书中获得客户端的公钥,并用该公钥认证证书信息,确认客户端是否合法
  1. 服务端和客户端进行通信 服务端和客户端协商好加密方案后,客户端会产生一个随机的秘钥并加密,然后发送到服务端。服务器端接收这个秘钥后,双方按下来通信的所有内容都通过该随机秘钥加密。

注意:k8s 允许同时配置多种认证方式,只要其中任意一个方式认证通过即可。

授权管理

授权发生在认证成功之后,通过认证就可以知道请求用产是准,然后 k8s 会根据事先定义的授权策略来决定用户是否有权限访问,这个过程就称为授权。

鉴权:每个发送到 ApiServer 的请求都带上了用户和资源的信息:比发送求的用户、请求的路径资源 、请求的动作 get create delete等,授权就是根据文些信息和授权策路进行比较,如果符合策略,则认为授权通过,否则会返回错误。

API Server 目前支持以下几种授权策略:

  • AlwaysDeny:表示拒绝所有请求,一般用于测试
  • AlwaysAllow:允许接收所有请求,相当于集群不需要授权流程 (k8s 默认的策略)
  • ABA:基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制
  • Webhook:通过调用外部 REST 服务对用户进行授权
  • Node:是一种专用模式,用于对 kubelet 发出的请求进行访问控制
  • RBAC:基于角色的访问控制(kubeadm 安装方式下的默认选项)

RBAC(Role-Based Access Control)基于角色(Role-权限)的访问控制,主要是在描述一件事情: 给哪些对象授予了哪些权限

其中涉及到了下面几个概念:

  • 资源:对集群中资源和非资源均拥有完整的覆盖
  • 对象:User、Groups, ServiceAccount
  • 角色:代表着一组定义在资源上的可操作动作(权限)的集合
  • 绑定:将定义好的角色跟用户绑定在一起, RBAC 引入了4个顶级资源对象 yaml kind类型。
  • Role 、ClusterRole:角色,用于指定一组权限
    • 一个角色就是一组权限的集合。
    • apiGroups:支持的API组列表 ''apps", "autoscaling", "batch"
    • resources:支持的资源对象列表 "services", "endpoints", "pods" , "secrets" , "configmaps" , "crontabs", "deployments", "jobs", "nodes", "rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"
    • verbs:对资源对象的操作方法列表 "get", "list", "watch", "create", "update", "patch", "delete", "exec"
  • RoleBinding、ClusterRoleBinding:角色绑定,用于将角色 (权限) 赋予给对象
    • 角色绑定用来把一个角色绑定到一个目标对象上,绑定目标可以是 User、Group 或者 ServiceAccount。
    • RoleBinding 可以引用 ClusterRole,对属于同一命名空间内 ClusterRole 定义的资源主体进行授权。

准入控制

通过了前面的认证和授权之后,还需要经过准入控制处理通过之后,apiserver 才会处理这个请求。

准入控制机制是 k8s API Server 中一个非常强大的功能,它允许对进入 k8s 集群的请求做出控制。API Server 会在对象(如 Pod、Node、Service 等)被保存到 etcd 数据库之前,对该对象进行检查和修改。准入控制可用于实施强制性的数据验证、安全功能、自动化操作等功能。

一句话:就是在创建资源经过身份验证之后,kube-apiserver 在数据写入 etcd 之前做一次拦截,然后对资源进行更改、判断正确性等操作。

API Server 内置了许多准入控制器,常用的包含如下几种。

  1. AlwaysAdmit:允许所有请求。
  2. AlwaysDeny:拒绝所有请求 ,仅应该用于测试。
  3. AlwaysPulllmages :总是下载镜像,即每次创建 Pod 对象之前都要去下载镜像,常用于多租户环境中以确保私有镜像仅能够被拥有权限的用户使用。
  4. NamespaceLifecycle :拒绝于不存在的名称空间中创建资源,而删除名称空间将会 级联删除其下的所有其他资源。
  5. LimitRanger :可用资源范围界定,用于监控对设置了 LimitRange 的对象所发出的 所有请求,以确保其资源、请求不会超限。
  6. ServiceAccount :用于实现 Service Account 管控机制的自动化,实现创建 Pod 对象 时自动为其附加相关的 Service Account 对象。
  7. PersistentVolumeLabel :为那些由云计算服务商提供的 PV 自动附加 region 或 zone 标签,以确保这些存储卷能够正确关联且仅能关联到所属的 region 或 zone。
  8. DefaultStorageClass :监控所有创建 PVC 对象的请求,以保证那些没有附加任何专 用 Storag巳Class 的请求会自动设定一个默认值。
  9. ResourceQuota : 用于对名称空间设置可用资源的上限,并确保在其中创建的任何设 置了资源限额的对象都不会超出名称空间的资源配额。
  10. DefaultTolerationSeconds :如果 Pod 对象上不存在污点宽容期限,则为它们设置默 认的宽容期,以宽容" notready:N oExecute"和" unreachable:N oExctute "类的污点 5 分钟 时间。
  11. ValidatingAdmission Webhook :并行调用匹配当前请求的所有验证类的 Webhook, 任何一个校验失败,请求即失败。
  12. MutatingAdmissionWebhook :串行调用匹配当前请求的所有变异类的 Webhook, 每个调用都可能会更改对象。

一个很简单例子,例如我们要设置 Deployment 可以拥有的副本数量限制,那么可以定义如下所示的验证策略资源对象:

yaml 复制代码
apiVersion: admissionregistration.k8s.io/v1alpha1
kind: ValidatingAdmissionPolicy
metadata:
  name: "demo-policy.example.com"  # 策略对象
spec:
  matchConstraints:
    resourceRules:
    - apiGroups:   ["apps"]
      apiVersions: ["v1"]
      operations:  ["CREATE", "UPDATE"]
      resources:   ["deployments"]
  validations:
    - expression: "object.spec.replicas <= 5"

该对象中的 expression 字段的值就是用于验证准入请求的 CEL 表达式,我们这里配置的 object.spec.replicas <= 5,就表示要验证对象的 spec.replicas 属性值是否大于 5,而 matchConstraints 属性则声明了该 ValidatingAdmissionPolicy 对象可以验证哪些类型的请求,我们这里是针对 Deployment 资源对象。

认证方案

kubeconfig:

kubeconfig 文件包含集群参数(CA证书、API Server地址),客户端参数,集群context信息(集群名称、用户名)。

ServiceAccount:

Pod 中的容器访问 API Server。因为 Pod 的创建和销毁是动态的,所以要为它手动生成证书是不可行的,k8s 使用 Service Account 解决 Pod 访问 API Server 的认证问题。

小结

API Server 是集群内部各个组件通讯的中介,也是外部控制的入口。k8s 使用认证(Authentication)、鉴权(Authorization)、准入控制(Admission Control)三步来确保 API Server 的安全。

认证和鉴权:

  • 认证(authencation):通过只代表通讯双方是可信的
  • 鉴权(authorization):确定请求方有哪些资源权限

Service Count

UserAccount:给集群外用户访问 API Server,执行 kubectl 命令时用的就是该账号。它是全局性的,跨 namespace,通常为 admin,也可以自定义

shell 复制代码
$ cat /root/.kube/config
users:
- name: kubernetes-admin
  user:

ServiceAccount:Pod 容器访问 API Server 的身份认证。它与 namespace 绑定,每个 namespace(包含 default)都会自动创建一个默认的 SA。创建 Pod 时,如果未指定 SA, 则使用默认的 SA,可通过配置 spec.serviceAccount 指定 SA。

shell 复制代码
# default namespace SA

# kubectl get sa default -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2024-3-27T13:12:44Z"
  name: default
  namespace: default
  resourceVersion: "368"
  uid: e29de9ec-84ae-4e47-8778-dd8ed09e8f8d

SA 是一种特殊的 secret,类型为 kubernetes.io/service-account-token,它由三部分组成:

  • token:由 API Server 私钥签发的 JWT,Pod 访问 API Server 的凭证
  • ca.crt:根证书,用于 Client 端验证 API Server 发送的证书,与 /etc/kubernetes/pki/ca.pem 一致
  • namespace:该 service-account-token 的作用域名空间,Pod 所属 namespace
shell 复制代码
[root@k8s-master ~]# kubectl run -it nginx --image=nginx -- /bin/bash
If you don't see a command prompt, try pressing enter.
root@nginx:/# cd /run/secrets/kubernetes.io/serviceaccount/
root@nginx:/run/secrets/kubernetes.io/serviceaccount# ll
bash: ll: command not found
root@nginx:/run/secrets/kubernetes.io/serviceaccount# ls
ca.crt	namespace  token

自定义SA

shell 复制代码
$ kubectl create ns my-ns
$ kubectl create sa my-sa -n my-ns

$ kubectl get sa -n my-ns
NAME      SECRETS   AGE
default   1         18s
my-sa     1         12s

$ kubectl get secret -n my-ns
NAME                  TYPE                                  DATA   AGE
default-token-xp4hg   kubernetes.io/service-account-token   3      42s
my-sa-token-xs257     kubernetes.io/service-account-token   3      36s

资源属性

yaml 复制代码
apiVersion: v1       # ServiceAccount所属的API群组及版本
kind: ServiceAccount # 资源类型标识
metadata:
  name <string>                        # 资源名称
  namespace <string>                   # ServiceAccount是名称空间级别的资源

automountServiceAccountToken <boolean> # 是否让Pod自动挂载API令牌
secrets <[]Object>          # 以该SA运行的Pod所要使用的Secret对象组成的列表
  apiVersion <string>       # 引用的Secret对象所属的API群组及版本,可省略
  kind <string>             # 引用的资源的类型,这里是指Secret,可省略
  name <string>             # 引用的Secret对象的名称,通常仅给出该字段即可
  namespace <string>        # 引用的Secret对象所属的名称空间
  uid <string>              # 引用的Secret对象的标识符;
imagePullSecrets <[]Object> # 引用的用于下载Pod中容器镜像的Secret对象列表
  name <string>             # docker-registry类型的Secret资源的名称

Pod 中 SA 配置:

shell 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: nginx-sa
  namespace: my-ns
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
  serviceAccountName: my-sa   # 指定 SA

RBAC

ServiceAccount 是 APIServer 的认证过程,而授权机制通过 RBAC:基于角色的访问控制实现(Role-based access control)

规则配置到角色上,用户就可以绑定角色获得对应的规则权限。

k8s 中所有资源对象都是模块化的 API 对象,允许执行 CRUD 操作:

资源:pods,configmaps,deployments,nodes,secrets,namespaces,services 等

动作:create,get,delete,list,update,edit,watch,exec,patch

Role 和 ClusterRole

Role:表示一组规则权限,权限只会增加(累加权限),它定义的规则,只适用于单个 namespace

ClusterRole:集群级别的权限控制

yaml 复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: my-role
  namespace: my-ns
rules:
- apiGroups: [""]
  resources: ["pods"] 
  verbs: ["get","watch","list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get","list","create","update","patch","delete","watch"]
  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: my-clusterrole
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","create","list"]

系统默认的 ClusterRole: cluster-admin,具有所有资源的管理权限

shell 复制代码
$ kubectl get clusterrole cluster-admin -o yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: cluster-admin
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'

Subject:

尝试访问和操作 API Server 的对象:

  • UserAccount:集群外的用户账号
  • Group:用户组,集群中有一些默认创建的组,比如 cluster-admin
  • ServiceAccount:集群内的服务账号,它和 namespace 进行关联,适用于集群内部运行的应用程序,需要通过 API 来完成权限认证,所以在集群内部进行权限操作,我们都需要使用到 ServiceAccount

RoleBinding:将 Role 或 ClusterRole 授权给 Subject,它与 namespace 绑定

ClusterRoleBinding:将 ClusterRole 授权给 Subject,属于集群范围内的授权,与 namespace 无关

Yaml 复制代码
# 绑定 Role
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-rolebinding-1
  namespace: my-ns
subjects:
- kind: User    # 权限资源类型
  name: kuangshen     # 名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: my-role
  apiGroup: rbac.authorization.k8s.io

# 绑定 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-rolebinding-2
  namespace: my-ns
subjects:
- kind: User
  name: kuangshen
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: my-clusterrole
  apiGroup: rbac.authorization.k8s.io
  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-clusterrolebinding
subjects:
- kind: Group
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: my-clusterrole
  apiGroup: rbac.authorization.k8s.io
相关推荐
2501_9240641121 小时前
2025年优测平台:微服务全链路性能瓶颈分析与最佳实践
微服务·云原生·架构·性能瓶颈·全链路性能
石小千1 天前
Ubuntu24.04 安装Docker
运维·docker·容器
scriptsboy1 天前
Halo Docker 迁移方法
运维·docker·容器
隐语SecretFlow1 天前
【隐语Secretflow】一文速通基于可信执行环境 (TEE) 的零信任计算系统
云原生·kubernetes·开源
R.lin1 天前
Docker核心原理详解
运维·docker·容器
MarkHD1 天前
车辆TBOX科普 第70次 AUTOSAR Adaptive、容器化与云原生的融合革命
云原生·wpf
Dobby_051 天前
【k8s】集群安全机制(一):认证
运维·安全·kubernetes
测试人社区-小明1 天前
测试领域的“云原生”进化:Serverless Testing
人工智能·科技·云原生·面试·金融·serverless·github
阿基米东1 天前
Traefik:为云原生而生的自动化反向代理
运维·云原生·自动化
纷飞梦雪1 天前
排查k8s连接mysql的pod
云原生·容器·kubernetes