k8s认证和授权

k8s访问控制简介

在Kubernetes中API Server是访问和管理资源对象的唯一入口。所有客户端均要通过API Server访问或者改变集群状态以及完成数据存储,API Server会对每一次请求进行合法性校验,校验包括:用户身份验证、操作权限验证以及操作是否符合全局规范约束等。所有检查均正常完成才能访问或存储数据到etcd。如下图所示:
在这里插入图片描述

客户端认证操作由API Server配置的一到多个认证插件完成,收到请求后API Server会串行调用这些插件,直到一个插件可以成功识别用户身份为止。授权操作同样由一到多个授权插件完成,也是串行被调用,直到其中一个插件验证权限成功,这些插件负责检测用户是否有权限执行发出的资源操作请求。最后,通过授权检测的用户的相关修改请求还要经由一到多个准入控制器插件的遍历式检测,例如:补全资源对象缺失字段默认值、检查资源对象字段值是或否符合要求等,任何一个插件检测失败都会导致请求被拒绝。

下面分别介绍一下认证、授权和准入

认证

k8s将所有客户端发起的请求的请求主体分为两类:用户账户(User Account)和服务账户(Service Account)

  • 用户账户:其使用主体一般是真正的用户,比如集群管理员用户。这类账户一般由外部的用户管理系统存储和管理,k8s本身并不维护这一类任何用户账户的信息,仅仅用于检验用户是否有权限执行其请求的操作
  • 服务账户:其使用主体是应用程序,专用于为Pod中的进程提供访问API Server的身份标识;Service Account属于名称空间级别,有API Server或者管理员手动创建,通常会绑定一个保存着访问API Sever认账凭据的Secret,可用同一名称空间下的Pod方式API Server时使用

k8s使用身份验证插件对API请求进行身份验证,它允许管理员自定义服务账户和用户账户要启用的插件,并支持各自同时启用多种认证机制。如果启用了多种认证机制,账户认证过程由认证插件以串行的方式进行,直到其中一个认证机制成功完成即结束。若认证失败,服务器香影401状态码,反之请求者会被k8s识别为某个具体的用户,并且该连接上的后续操作都会以此用户身份进行。

k8s支持的认证方式有如下几种,但不仅限于这些方式:

  1. 静态令牌文件
  2. X509客户端证书验证
  3. 引导令牌(Bootstarp Token)
  4. Service Account令牌认证
  5. Webhook令牌认证
  6. OpenID Connect令牌认证
授权

为了校验用户的操作许可,成功通过身份验证后的请求还要交给授权插件进行权限检查,以确保其拥有执行相应操作的许可。API Server主要支持以下4类内置的授权插件来检查用户的操作权限:

  1. Node:基于Pod资源的调度目标节点来实现对kubelet的访问控制
  2. ABAC:基于属性的访问控制
  3. RBAC:基于角色的访问控制
  4. Webhook:基于HTTP的回调机制实现外部服务REST检查,确认用户授权的访问控制

目前默认启用Node和RBAC两个插件,可以通过kube-apiserver的–authorization-mode选项指定要启用的插件,多个值以逗号分割。

准入控制

准入控制器(admission controller)用于客户端请求在通过身份验证和权限检查之后,将对象数据保存到etcd数据库之前拦截请求,从而实现在资源的创建、修改和删除操作期间强制执行对象的语义验证等功能,读取资源信息的请求不会经过准入控制器检查。API Server内置了许多准入控制器,常用的包括以下几种:

  1. AlwaysPullImage:总是下载镜像,每次创建Pod都要下载镜像
  2. NamespaceLifecycle:拒绝在不存在的名称空间创建资源,而删除名称空间会删除名称空间下的所有资源
  3. LimitRanger:用于确保资源请求不会超出LimitRange的限制范围
  4. ServiceAccount:用于实现服务账户管控机制的自动化,实现创建Pod对象时自动为其附加相关的Service Account对象
  5. ResourceQuota:用于为名称空间设置资源配额,确保在名称空间中创建了任何资源对象时不会超出配额
  6. DefaultStorageClass:监控所有创建PVC对象的请求,保证那些没有附加任何专用StorageClass的请求会被设置一个默认值。如果没有设置默认StorageClass则此准入控制器不执行任何操作

可以通过kube-apiserver的–enable-admission-plugins指定要启用的准入控制插件,通过–disable-admission-plugins指定要禁用的准入控制插件

k8s中的RBAC

RBAC介绍

RBAC是一种权限管理模型,它把附加在“资源对象”上的“动作”称为“许可权限”,这些权限能够按需组合在一起构建出“角色“”,并通过为“用户账户或组账户”分配一到多个角色完成授权。这些能够发出操作用户在RBAC中也称为“主体”。如下图所示:
在这里插入图片描述
简单来说,RBAC就是一种访问控制模型,它以角色为中心界定了“谁”(subject)能够对哪个或哪类“对象”(object)执行哪些“操作”(verb)。动作的发出这是“主体”,在k8s上,可以是普通账户也可以是服务账户。“动作”用于表明要执行的具体操作,包括增删改查等,对API Server来说就是POST、GET、PUT、DELETE等请求方法。而“对象”则指管理操作能够施加的目标主体,对k8s来说主要是各类资源对象以及非资源型URL

Role与ClusterRole

k8s的RBAC授权插件将角色分为Role和ClusterRole两类,它们都是内置的资源类型,Role作用于名称空间级别,用于承载名称空间内的资源权限集合,而ClusterRole作用于集群级别,能够同时承载名称空间级别和集群级别资源权限集合。Role无法承载集群级别资源的权限,这类资源包括集群级别资源(例如node、pv等)和非资源类型的url(例如/healthz)

利用Role和ClusterRole进行授权时还需要借助RoleBinding和ClusterRoleBinding这两种资源,它们同样是内置的资源类型。RoleBinding用于将Role绑定到一个或一组用户上,它仅能作用于其所在的名称空间。RoleBinding可以引用同一名称空间中的Role,也可以引用集群级别的ClusterRole,但引用ClusterRole时 ClusterRole上的权限只能在RoleBinding所在名称空间生效。ClusterRoleBinding用于将ClusterRole绑定到用户或组,它作用于集群全局,且仅能引用ClusterRole。

Role和ClusterRole都是内置的资源类型,它们的资源规范基本一致,区别是Role需要指定名称空间,ClusterRole不需要,它们都没有spec字段,直接使用rules字段指定授权规则,规则的基本要素是动作(verb)和规则生效的目标资源。rules字段可嵌套使用的字段如下:

  • apiGroups: <[]string> #目标资源所属的API群组,可以用列表指定多个值,空值表示核心群组
  • resources: <[]string> #规则应用的目标资源类型,例如pods、services,*代表所有的资源类型
  • resourceNames: <[]string> #可选,用于指定规则生效的具体资源对象的名称
  • nonResourceURLs: <[]string> #用于定义有权访问的URL列表,它并非名称空间级别的资源因此只能应用于ClusterRole。该字段不能和resources和resourceNames同时使用
  • verbs: <[]string> #必选,指定此规则匹配的资源允许的操作列表,可选项有get、list、create、update、patch、watch、proxy、redirect、delete和deletecollection,*代表所有操作
RoleBinding和ClusterRoleBinding

RoleBinding负责在名称空间级别向普通账户、服务账户或组分配Role或ClusterRole,而ClusterRoleBinding只能在集群级别向账户或组分配ClusterRole。两者的配置规范基本一致,RoleBinding需要指定名称空间,它们都没有spec字段,直接使用subjects和roleRef字段,subjects用于指定要绑定的主体,roleRef用于指定要绑定的Role或ClusterRole。

subjects字段可嵌套使用的字段如下:

  • apiGroup:<string> #要引用的主体所属的API群组 ,对于ServiceAccount类的主体来说默认为"“,而User和Group类主体的默认值为"rbac.authorrization.k8s.io”
  • kind:<string> #要引用的主体所属的类别,可用值为User、Group和ServiceAccount
  • name:<string> #要引用的主体的名称
  • namespace:<string> #要引用的主体所属的名称空间,引用主体为ServiceAccount时指定

roleRef可嵌套使用的字段如下:

  • apiGroup:引用的Role或ClusterRole所属的API群组,必选字段
  • kind <string>:引用的资源类型,可选值Role或ClusterRole
  • name <string>:Role或ClusterRole的名称
内置ClusterRole

k8s内置了一些默认的ClusterRole,其中大部分以system开头,是预留给集群使用的。另一部分不以system开头是面向用户的需求而设计的,包括集群管理员cluster-admin,以及用于授予名称空间特定权限的admin、view和edit。它们各自的权限说明如下表所示:

默认ClusterRole说明
cluster-admin超级管理员,拥有操作所有资源的权限
admin名称空间管理员,拥有指定名称空间中所有资源的管理权限,包括Role和RoleBinding,但不包括名称空间本身和资源配置
edit允许读写访问一个名称空间中的大部分资源,但不允许查看或修改Role和RoleBinding
view允许读写一个名称空间内的大部分资源,但不允许查看或修改Role或RoleBinding,以及Secret资源

在多租户或多项目的环境下,用户应该获得名称空间级别大多数资源的管理(admin)、编辑(edit)和只读(view)权限,可以通过在名称空间中创建RoleBinding引用内置的ClusterRole完成快速授权

kubeconfig配置文件

kubeconfig配置文件保存一到多个k8s集群的配置信息,用于访问k8s集群时使用。简单来说,kubeconfig文件包含多个k8s集群的API Server信息和多个身份认证信息,然后指定了用户应该以什么身份访问哪个k8s集群。

如下图所示,一个kubeconfig文件主要包含4部分:

  • clusters字段:定义k8s集群的API Server地址,每个列表项表示一个k8s集群
  • usres字段:身份认证信息,每个列表项表示一个能认证到某个k8s集群的凭据
  • contexts字段:上下文信息,用于将访问凭据和集群关联起来,一个context表示应该以什么凭据访问哪个集群
  • current-context:当前使用的上下文,即执行kubectl时是在哪个k8s集群上执行
    在这里插入图片描述

kubeconfig是一个文本文件,可以使用kubectl config及其子命令来设置其内容。kubectl config可用的子命令如下:

  • view:查看kubeconfig文件内容
  • set-cluster:设定新的集群信息
  • set-context:设置新的上下文信息
  • set-credentials:设置新的认证凭据
  • use-context:设置要使用的上下文
  • delete-cluster:删除集群信息
  • delete-user:删除认证凭据
  • delete-context:删除上下文
  • get-clusters:获取所有的集群信息
  • get-users: 获取所有的认证凭据
  • get-contexts:获取所有的上下文

kubectl config命令的操作针对加载的单个kubeconfig文件进行,它根据优先级高低,依次搜索–kubeconfig指定的文件,KUBECONIFG环境变量指定的文件和默认的$HOME/.kube/config文件。

认证和授权案例

X509证书实现集群访问和授权

客户端请可以携带证书访问API Server用于认证,认证完成后证书的主体标识(Subject)会被识别为用户表示,其中的字段CN的值是用户名,字段O的值是用户所属的组。例如例如 /CN=ilinux/O=admin中,用户名是ilinux,它属于admin组。

在这种认证方式下,客户端的证书需要API Server信任的CA根证书签发,kube-apiserver的–client-ca-file用于指定信任的根证书,默认是集群自己的CA。
在这里插入图片描述

下面测试利用集群的CA签发一个客户端证书用于访问API Server。

先为客户端签发证书:

#生成私钥
(umask 077; openssl genrsa --out client-jack.key 2048)
#生成证书证书签发请求文件,CN设置为jack,O设置为developers
openssl req -new -key client-jack.key \
-out .certs/client-jack.csr \
-subj "/CN=jack/O=developers"
#使用k8s集群的CA签发证书
openssl x509 -req -days 365 \
-CA /etc/kubernetes/ssl/ca.pem \
-CAkey /etc/kubernetes/ssl/ca-key.pem -CAcreateserial \
-in client-jack.csr -out client-jack.crt

设置一个新的kubeconfig文件

#添加集群信息,保存到一个新的文件test-kubeconfig中
kubectl config set-cluster k8s-cluster1 \
--server https://192.168.122.188:6443 \
--embed-certs=true \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--kubeconfig ./test-kubeconfig
#添加访问凭据
kubectl config set-credentials jack \
--client-certificate client-ca/client-jack.crt \
--client-key client-ca/client-jack.key \
--embed-certs=true --kubeconfig ./test-kubeconfig
#添加context
kubectl config set-context jack@k8s-cluster1  \
--cluster k8s-cluster1 --user jack \
--kubeconfig test-kubeconfig
#设置当前使用的context
kubectl config use-context jack@k8s-cluster1 --kubeconfig test-kubeconfig

查看test-kubeconfig内容
在这里插入图片描述
测试访问集群, 如下图,已经可以访问集群,但是jack用户还未授权所以不能对资源进行任何操作。
在这里插入图片描述

创建ClusterRole和ClusterRoleBinding进行授权

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pv-admin
rules:
- apiGroups: [""]	#对pv拥有所有操作权限
  resources: ["persistentvolumes"]	
  verbs: ["*"]
- apiGroups: ["apps"]	#对deploy具有增删改查的权限
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pv-admin-for-jack
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: jack
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: pv-admin

然后通过jack用户访问集群,如下图,只能管理pv和deployment资源,符合ClusterRole的权限设定
在这里插入图片描述

ServiceAccount实现集群访问和授权

ServiceAccount主要用于Pod中的应用程序访问API Server时进行认证,每个Pod对象都可以附加一个同名称空间下的ServiceAccount,只能附加一个,可以通过pod.spec.serviceAccountName字段指定要使用的ServiceAccount对象,忽略此字段时会由ServiceAccount准入控制器自动附加当前名称空间下的默认ServiceAccount对象。

首先创建一个ServiceAccount对象

kubectl create sa my-sa

在这里插入图片描述

创建ServiceAcount对应的Secret

apiVersion: v1
kind: Secret
metadata:
  name: test
  annotations:
    kubernetes.io/service-account.name: test
type: kubernetes.io/service-account-token

在这里插入图片描述

获取ServiceAccount对应Secret中保存的Token

kubectl get secret/secret-for-my-sa -o jsonpath={.data.token} |base64 -d

在这里插入图片描述

设置kubeconfig文件

kubectl config set-credentials my-sa --token <token> --kubeconfig test-kubeconfig
kubectl config set-context my-sa@k8s-cluster1 --cluster k8s-cluster1 --user my-sa --kubeconfig test-kubeconfig

测试访问集群,如下图所示,已经可以通过Token访问API Server,但是由于没有对my-sa授权所以不能访问任何资源
在这里插入图片描述

创建Role和RoleBinding进行授权

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pods-reader
  namespace: default
rules:
- apiGroups: [""]	#核心API群组
  resources: ["pods", "services", "pods/log"]	#规则对pods、services和pods/log(pod的日志)资源生效
  verbs: ["get", "list", "watch"]	#仅能执行get、list和watch操作

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pods-reader-for-my-sa
  namespace: default
subjects:
- kind: ServiceAccount
  name: my-sa
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pods-reader

测试通过my-sa访问集群,如下图,只能查询default名称空间下的pod和service资源,符合Role的权限设定
在这里插入图片描述

上边的步骤将ServiceAccount的token直接保存在kubeconfig中用于访问API Server,正常情况下ServiceAccount主要用于Pod中的应用访问API Server时使用,Pod创建时会自动定义一个存储卷挂载在容器内/run/secrets/kubernetes.io/serviceaccount/目录下,如下图,主要包括3个文件:ca.crt、namespace和token。其中ca.crt是k8s集群的ca,可以用于访问API Server时校验API Server的证书;namspace是Pod所在的名称空间;token就是访问API Server的令牌,Pod中应用访问API Server时携带此token用于认证即可
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值