前言:K8S 提供了丰富的认证和授权机制,可以满足各种场景细粒度的访问控制。本文会介绍 k8s 中的用户认证、授权机制,并通过例子阐述 kubeconfig 的生成和原理,最后会列举常见的证书问题,如过期、吊销、租户控制等。本文属于科普 + 实践k8s认证,不涉及 apiserver 中代码实现。

两种用户

k8s中的客户端访问有两类用户:

普通用户(Human User),一般是集群外访问,如 kubectl 使用的证书

service account: 如集群内的 Pod

有什么区别呢?

k8s 不会对 user 进行管理,并不存储 user 信息,你也不能通过调用k8s api来增删查这个 user。你可以认为这个 user 指的就是公司内的人员,一般需要对接内部权限系统,user 的增删操作都是在 k8s 外部进行,k8s 只做认证不做管理。

k8s 会对serviceaccount 进行管理,他的作用是给集群内运行的 pod 提供一种认证的方式,如果你这个 pod 想调用apiserver操作一些资源如获取 node列表,就需要绑定一个serviceaccount账户给自己,并为这个serviceaccount赋予一定的权限,这样就做到了实体和权限的分离,也就是后面会提到的 rbac 授权。

作用范围:

User独立在 K8S 之外,也就是说User是可以作用于全局的,跨 namespace,并且需要在全局唯一

ServiceAccount是K8S的一种资源,是存在于某个namespace之中的,在不同namespace中可以同名,代表了不同的资源。

举例说明:

为 user 生成 kubeconfig

一个同事张三都想要一份集群的 kubeconfig 用来日常 kubectl 操作集群,但限定只能操作名为 test 的 namespace,公司有独立的权限系统,他的用户 ID 是唯一的,叫zhangsan。接下来手动为这个用户生成 kubeconfig

生成证书:

k8s api_k8s centos部署_k8s认证

得到:

zhangsan.pem

zhangsan-key.pem

接下来为 zhangsan 授权,首先生成一份角色:test-role, 权限为test 的命名空间下的所有资源的所有操作权限

k8s认证_k8s api_k8s centos部署

然后将这个角色role绑定到zhangsan这个 user 上,代表 zhangsan 拥有了这个 role 的权限

k8s centos部署_k8s api_k8s认证

为张三生成专属的 kubeconfig 文件,名为zhangsan.conf

获取 test 下所有的 pod

如果获取其他 namespace 下的pod,则报权限错误

k8s认证_k8s api_k8s centos部署

为 pod 创建 serviceaccount

以 metrics-server的 pod 为例,需要对 pod、node、ns 等资源进行 get list操作,因此权限配置为:

k8s centos部署_k8s api_k8s认证

pod 的 yaml 配置中声明serviceAccountName为metrics-server

k8s api_k8s centos部署_k8s认证

以上是 user用户使用 kubeconfig、pod 使用 serviceaccount 的示例,pod 使用serviceaccount是比较好理解的,但其实 kubeconfig 也可以直接用serviceaccount来生成,不一定非得用 user,只是大多数情况下,kubeconfig 的管理是和用户的声明周期一致的,即子用户可以申领一份自己的 kubeconfig,管理员可以随时吊销或者禁用子用户 kubeconfig 的效力。这个在后面的”多租户下的kubeconfig“中会提到。

三种机制

谈 k8s 的认证和访问控制,一般都会看到这张图:

k8s api_k8s centos部署_k8s认证

k8s 中所有的 api 请求都要通过一个 gateway 也就是 apiserver 组件来实现,是集群唯一的访问入口。既然是 gateway,最基础的功能就是 api 的认证 + 鉴权了。对应了图上的步骤1和2,而 k8s 中还提供了第 3 步的 admission Control(准入控制),可以更方便地拦截、校验资源请求。

三种机制:

1、认证:Authentication,即身份认证。检查用户是否为合法用户,如客户端证书、密码、bootstrap tookens和JWT tokens等方式。

2、鉴权:Authorization,即权限判断。判断该用户是否具有该操作的权限,k8s 中支持 Node、RBAC(Role-Based Access Control)、ABAC、webhook等机制,RBAC 为主流方式

3、准入控制:Admission Control。请求的最后一个步骤,一般用于拓展功能,如检查 pod 的resource是否配置,yaml配置的安全是否合规等。一般使用admission webhooks来实现

1-2-3 全部通过后api 请求会被处理,在 k8s 中也就意味着资源变更可以落库到 etcd。

K8S 中的认证

上面提到 k8s 并不存储 user,只知道一个 user 名称,因此 user 在访问api 时怎么做的认证?

kubernetes 支持很多种认证机制,包括:

前面提到的 user 生成 kubeconfig就是X509 client certs方式, 而 metric-server 就是Service Account Tokens方式。

X509 client certs

即客户端证书认证,X509 是一种数字证书的格式标准,是 kubernetes 中默认开启使用最多的一种,也是最安全的一种,api-server 启动时会指定 ca 证书以及 ca 私钥,只要是通过同一个 ca 签发的客户端 x509 证书,则认为是可信的客户端,kubeadm 安装集群时就是基于证书的认证方式。

客户端证书认证叫作 TLS 双向认证,也就是服务器、客户端互相验证证书的正确性,在都正确的情况下协调通信加密方案。apiserver 、controller-manager、scheduler、kubelet 等组件之间的交互,一般也是基于X509的客户端认证方式,目前最常用的 X509 证书制作工具有 openssl、cfssl ,上面生成 kubeconfig 时用到就是 cfssl 工具签发的证书。

还是举个例子,在手动部署 k8s 集群时需要做的证书操作,如果你已经熟悉这个过程或者用了 kubeadm 等部署工具,可以跳过这一段。

1、基础证书生成

ca-config.json

k8s api_k8s centos部署_k8s认证

创建用来生成 CA 文件的 JSON 配置文件,这个文件后面会被各种组件使用,包括了证书过期时间的配置,expiry字段

k8s api_k8s认证_k8s centos部署

ca-csr.json

创建用来生成 CA 证书签名请求(CSR)的 JSON 配置文件

k8s centos部署_k8s认证_k8s api

生成基础 ca 证书

创建自签名 CA 证书:这里只需要ca-csr.json文件,执行后会生成三个文件:

ca.csr:证书签名请求,一般用于提供给证书颁发机构,自签的就不需要了

ca.pem:证书,公共证书

ca-key.pem:CA密钥

2、生成 apiserver 证书

apiserver-csr.json

k8s api_k8s认证_k8s centos部署

hosts列表不仅包含了三台 master 机器的ip,还包括了 对应的负载均衡的 ip和外网 ip(如果有的话),以及 kubernetes 的 svc IP:172.18.0.1

这个 ip 是 svc ip range 中的第一个 ip,如果没有这个 ip,集群内的 pod 将无法通过 serviceaccount 的形式访问 apiserver 并鉴权,会报证书错误。

创建apiserver 的 CA 证书:这里需要4 个文件

执行后会生成三个文件:

** 使用证书**

Service Account Tokens

也就是 service account 使用的认证方式。

你会发现x509的认证方式比较复杂,需要做很多证书,如果我在集群中部署了一个 pod,比如一些 operator,想访问apiserver获取集群的一些信息,甚至对集群的资源进行改动,这种认证属于 k8s 管理范畴,因此 k8s 定义了一种资源serviceaccounts来定义一个 pod 应该拥有什么权限。

serviceaccounts 是面向 namespace 的,每个 namespace 创建的时候,kubernetes 会自动在这个 namespace 下面创建一个默认的 serviceaccounts,并且这个 serviceaccounts 只能访问该 namespace 的资源。serviceaccounts 和 pod、service、deployment 一样是 kubernetes 集群中的一种资源,用户可以创建自己的serviceaccounts。

service account 主要包含了三个内容:namespace、token 和 ca

每个 service account 都对应一个 secret,这三个信息就存放在这个 secret 里,以 base64 编码。service account 通过 mount 的方式保存在 pod 的文件系统中,其三者都是保存在 /var/run/secrets/kubernetes.io/serviceaccount/目录下。

kubeconfig 的生成与含义

k8s centos部署_k8s api_k8s认证

kubeconfig 是用来访问 k8s 集群的凭证,生成 kubeconfig 的步骤很简单但参数很多,这里以生成 admin 的 kubeconfig 为例,解释各参数的含义。

生成最高权限的 kubeconfig。

一般情况下集群创建之后,会先生成一份最高权限的 kubeconfig,即管理员角色,可以操作集群的所有资源,并为其他用户创建或删除权限,可以称之为 admin 证书,生成方式是:

admin-csr.json

k8s centos部署_k8s认证_k8s api

admin 证书

生成 admin.conf,即最高权限的 kubeconfig

集群参数

本段设置了所需要访问的集群的信息。

使用 set-cluster 设置了需要访问的集群,如上为 kubernetes 这只是个名称,实际为 –server 指向的 apiserver 所在的集群。

–certificate-authority 设置了该集群的公钥

–embed-certs 为 true 表示将 –certificate-authority 证书写入到 kubeconfig 中

–server 则表示该集群的 apiserver 地址

用户参数

本段主要设置用户的相关信息,主要是用户证书。

用户名: zhangsan

证书: /etc/kubernetes/ssl/zhangsan.pem

私钥: /etc/kubernetes/ssl/zhangsan-key.pem

这一步操作是指客户端的证书首先要经过集群 CA 的签署,否则不会被集群认可,认证就失败。

此处使用的是 客户端 x509 认证方式,也可以使用token认证,如kubelet的 TLS Boostrap机制下的bootstrapping 使用的就是 token 认证方式

上下文参数

集群参数和用户参数可以同时设置多对,而上下文参数就是集群参数和用户参数关联起来。

上面的上下文名称为 kubenetes,集群为 kubenetes(apiserver 地址对应的集群),用户为zhangsan,表示使用 zhangsan 的用户凭证来访问

kubenetes 集群

最后使用 kubectl config use-context kubernetes 来使用名为 kubenetes 的环境项来作为配置。

如果配置了多个环境项,可以通过切换不同的环境项名字来访问到不同的集群环境。

kubeconfig 的认证过程

正向生成 kubeconfig 我们已经做完了,apiserver 认证请求时,如何解析 kubeconfig 文件的内容呢?

我们可以看下 kubeconfig 的内容:

除了 context,里面有三个证书字段,都是 base64 编码后的内容

certificate-authority-data: server 端的证书,用于验证 apiserver 的合法性

client-certificate-data: 客户端证书

client-key-data: 客户端私钥

可以提取出来 certificate-authority-data 的内容放到一个文件cert.txt,然后base64解码

ertificate-authority-data:

得到的内容其实就是 ca.pem 即服务端证书,apiserver 的证书也是基于ca.pem签发,因为 TLS 是双向认证,apiserver 在认证 kubectl请求时,kubectl 也需要验证 apiserver 的证书,防止中间人攻击,验证的字段就是certificate-authority-data

client-certificate:

因为 k8s 没有 user 这种资源,因此在使用 kubeconfig 访问时,身份信息就“隐藏”在client-certificate的数据中,我们来查看一下。

将 kubeconfig 中的client-certificate-data的内容放在一个文件 client.txt 中,然后解码:

查看证书内容:

输出内容可以看到Subject: organization=system:masters, common_name=kubernetes-admin

apiserver 验证、解析请求,得到 system:masters 的http上下文信息,并传给后续的authorizers来做权限校验。

O 和 CN 的含义

“O”:Organization, apiserver接到请求后从证书中提取该字段作为请求用户所属的组 (Group)

“CN”:Common Name,apiserver从证书中提取该字段作为请求的用户名 (User Name)

在admin-csr.json中, admin使用了system:masters作为组 (Group)

k8s 预定义了 RoleBinding:cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用 k8s 相关 API 的权限,权限极高。

即:

k8s 核心组件的默认权限

admin权限:system:masters组,clusterrole 和 rolebinding 都叫 cluster-admin

kubelet: system:nodes组,clusterrole 和 rolebinding 都叫system:nodes,下同

kube-proxy: system:kube-proxy组

scheduler: system:kube-scheduler组

controller-manager: system:kube-controller-manager组

对应关系如图所示

k8s centos部署_k8s api_k8s认证

即 k8s 所有自身组件使用的权限都是基于内置的 clusterrole,生成出来的 kubeconfig 被各组件进程使用,权限都是默认已有 role,如果希望自己创建 role ,就要使用 rbac 授权了

至此k8s认证,我们应该知道了kubeconfig 的生成流程、验证方式,以及为什么采用了 admin.conf 作为kubeconfig,kubectl就能拥有最高权限。下面是一幅示意图

k8s认证_k8s centos部署_k8s api

K8S 中的授权

无论是 user的x509认证 还是 service account的 token认证,认证完后,都要到达第 2 步:授权,

K8S 目前支持了如下四种授权机制:

用的最多的就是 RBAC,即基于角色做权限控制。

Node

仅 v1.7 版本以上支持 Node 授权,配合 NodeRestriction 准入控制来限制 kubelet,使其仅可访问 node、endpoint、pod、service 以及 secret、configmap、pv、pvc 等相关的资源,在 apiserver 中使用以下配置来开启

node 的鉴权机制:

RBAC

RBAC(Role-Based Access Control)是 kubernetes 中基于角色的访问控制,通过自定义角色并将角色和特定的 user,group,serviceaccounts 关联起来达到权限控制的目的。

RBAC 中有三个比较重要的概念:

k8s认证_k8s api_k8s centos部署

RBAC 其实就是通过创建角色(Role),通过 RoleBinding 将被作用者(subject)和角色(Role)进行绑定。下图是 RBAC 中的几种绑定关系:

k8s认证_k8s api_k8s centos部署

示例:

role:

k8s认证_k8s centos部署_k8s api

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: wxii2p22