调用k8s API

调用k8s API,第1张

如上图所示,用户(User和Service Account)在调用API时会经过三个步骤:认证、鉴权和准入控制。

如上图步骤 1 所示,建立 TLS 后, HTTP 请求将进入认证(Authentication)步骤。 集群创建脚本或者集群管理员配置 API 服务器,使之运行一个或多个身份认证组件。

认证步骤输入的是整个 HTTP 请求,但是组件通常只检查头部和客户端证书

认证模块包含客户端证书、密码、普通令牌、引导令牌和 JSON Web 令牌(JWT,用于服务账户)。

可以指定多个认证模块,在这种情况下,服务器依次尝试每个验证模块,直到其中一个成功。

如果请求认证不通过,服务器将以 HTTP 状态码 401 拒绝该请求。 反之,该用户被认证为特定的 username ,并且该用户名可用于后续步骤以在其决策中使用。 部分验证器还提供用户的组成员身份,其他则不提供。

如上图的步骤 2 所示,将请求验证为来自特定的用户后,请求必须被鉴权。

请求必须包含请求者的用户名、请求的行为以及受该 *** 作影响的对象。 如果现有策略声明用户有权完成请求的 *** 作,那么该请求被鉴权通过。

Kubernetes 支持多种鉴权模块,例如 ABAC 模式、RBAC 模式和 Webhook 模式等。 管理员创建集群时,他们配置应在 API 服务器中使用的鉴权模块。 如果配置了多个鉴权模块,则 Kubernetes 会检查每个模块,任意一个模块鉴权该请求,请求即可继续; 如果所有模块拒绝了该请求,请求将会被拒绝(HTTP 状态码 403)。

准入控制模块是可以修改或拒绝请求的软件模块。 除鉴权模块可用的属性外,准入控制模块还可以访问正在创建或修改的对象的内容。

准入控制器对创建、修改、删除或(通过代理)连接对象的请求进行 *** 作。 准入控制器不会对仅读取对象的请求起作用 。 有多个准入控制器被配置时,服务器将依次调用它们。

这一 *** 作如上图的步骤 3 所示。

与身份认证和鉴权模块不同,如果任何准入控制器模块拒绝某请求,则该请求将立即被拒绝。

除了拒绝对象之外,准入控制器还可以为字段设置复杂的默认值。

请求通过所有准入控制器后,将使用检验例程检查对应的 API 对象,然后将其写入对象存储(如步骤 4 所示)。

所有 Kubernetes 集群都有两类用户:普通用户和由 Kubernetes 管理的服务账号。

Kubernetes 并不包含用来代表普通用户账号的对象 。 普通用户的信息无法通过 API 调用添加到集群中。

但是Kubernetes 仍然认为能够提供由集群的证书机构签名的合法证书的用户是通过身份认证的用户。基于这样的配置,Kubernetes 使用证书中的 'subject' 的通用名称(Common Name)字段(例如,"/CN=bob")来确定用户名。然后,基于角色访问控制(RBAC)子系统会确定用户是否有权针对 某资源执行特定的 *** 作。

与普通用户不同,服务账号是 Kubernetes API 所管理的用户。它们被绑定到特定的名字空间, 或者由 API 服务器自动创建,或者通过 API 调用创建。服务账号与一组以 Secret 保存的凭据相关,这些凭据会被挂载到 Pod 中,从而允许集群内的进程访问 Kubernetes API。

Kubernetes 使用身份认证插件利用客户端证书、持有者令牌(Bearer Token)、身份认证代理(Proxy) 或者 HTTP 基本认证机制来认证 API 请求的身份。HTTP 请求发给 API 服务器时, 插件会将以下属性关联到请求本身:

你可以同时启用多种身份认证方法,并且你通常会至少使用两种方法:

当集群中启用了多个身份认证模块时,第一个成功地对请求完成身份认证的模块会 直接做出评估决定。API 服务器并不保证身份认证模块的运行顺序。

要启动客户端证书身份认证,需要配置apiserver, 传入参数 --client-ca-file=SOMEFILE ,其中ca要与集群的ca一致。集群使用的ca可以通过以下命令查看

如果客户端的证书认证通过,则 subject 中的公共名称(Common Name)就被 作为请求的用户名。 自 Kubernetes 1.4 开始,客户端证书还可以通过证书的 organization 字段标明用户的组成员信息。 要包含用户的多个组成员信息,可以在证书种包含多个 organization 字段。

当 API server的命令行设置了 --token-auth-file=SOMEFILE 选项时,会从文件中读取持有者令牌。目前,令牌会长期有效,并且在 不重启 API server的情况下 无法更改令牌列表。

令牌文件是一个 CSV 文件,包含至少 3 个列:令牌、用户名和用户的 UID。 其余列被视为可选的组名。

服务账号(Service Account)是一种自动被启用的用户认证机制,使用经过签名的 持有者令牌来验证请求。

当服务账号创建后,k8s会自动生成对应的secret,存有可以用来认证的token。

上面的token就可以用来认证。

所有使用token进行认证的请求 ,都要加上 Authorization 的 HTTP请求头,其值格式为 Bearer TOKEN 。

例如:如果持有者令牌为 31ada4fd-adec-460c-809a-9e56ceb75269 ,则其 出现在 HTTP 头部时如下所示:

使用这种认证方式,apiserver将从请求头中获取用户信息,认证过程如图所示。

使用这种认证方式需要对apiserver进行如下配置:

例子:

假设apiserver配置如下

收到的请求头如下

会生成如下的用户信息用于鉴权

Role 总是用来在某个namespace内设置访问权限;在你创建 Role 时,你必须指定该 Role 所属的namespace。

与之相对,ClusterRole 则是一个集群作用域的资源。这两种资源的名字不同(Role 和 ClusterRole)是因为 Kubernetes 对象要么是namespace作用域的,要么是集群作用域的, 不可两者兼具。

ClusterRole 有若干用法。你可以用它来:

如果你希望在namespace内定义角色,应该使用 Role; 如果你希望定义集群范围的角色,应该使用 ClusterRole。

Role例子

ClusterRole例子

角色绑定(Role Binding)是将角色中定义的权限赋予一个或者一组用户。 它包含若干 主体 (用户、组或服务账户)的列表和对这些主体所获得的角色的引用。 RoleBinding 在指定的名字空间中执行授权,而 ClusterRoleBinding 在集群范围执行授权。

一个 RoleBinding 可以引用同一的名字空间中的任何 Role。 或者,一个 RoleBinding 可以引用某 ClusterRole 并将该 ClusterRole 绑定到 RoleBinding 所在的名字空间。 如果你希望将某 ClusterRole 绑定到集群中所有名字空间,你要使用 ClusterRoleBinding。

RoleBinding例子

ClusterRoleBinding例子

以上就是RBAC鉴权的一个概述,总结下就是Role定义了角色有哪些权限,RoleBinding则将角色和用户关联起来。这里的权限指的是对哪些资源有哪些 *** 作的权限,用户则包括了普通用户和服务账号。

更多的关于RBAC的描述可以看下 官网 ,包括了k8s内置的一些默认角色。

这里测试使用的k8s集群是通过kubeadm安装的,这种安装方式会将k8s中的组件如kube-apiserver、kube-scheduler等作为static pod的形式运行。因此可以通过 kubectl get pod 命令来查看对应组件的配置。

从上面的结果可以看到使用的ca是 /etc/kubernetes/pki/ca.crt ,接下来开始生成客户端的证书。

这样就生成了一个用户名为test的客户端证书,接下来用这个证书去调k8s的api。

这代表我们认证通过了,但是鉴权没有通过。接下来给test授权。

先创建一个角色(role.yaml),拥有kube-system namespace下读取pod的权限,使用命令 kubectl apply -f role.yaml 来让他生效。

接下来创建一个RoleBinding,将刚刚创建的角色绑定到test上,并使用命令 kubectl apply -f bind.yaml 来让他生效

生效后再次使用curl调用api,一切正常。

先创建一个kube-system下的服务账号,命令如下

查看有没有生效

可以看到名称为test的sa(service account)已经创建了。接下来查看他对应的secret来获得token。

使用token调用k8s的api

从结果可以确认认证通过了,现在给sa授权,修改bind.yaml,修改后内容如下

使用命令 kubectl apply -f bind.yaml 生效后,再次调用api,这时就不会返回403了。

之前查看apiserver的配置时,看到以下配置,说明apiserver是开启了代理认证的,并且指明了使用的ca。

接下来根据ca生成代理所使用的证书,注意这个ca一般与X509所使用的ca不一致。

并且使用这种方法调用api时,不同的用户只需更改对应的请求头即可,证书不用变更,而如果使用X509的方法,则不同的用户需要使用不同的证书。

调用api

这里由于使用的请求头表明了当前的用户是test,并且之前已经给test授权过了,所以没有返回403。

接下来更改用户名为jojo,再次调用api

返回结果如下

这里 是官方的API参考文档,说明了有哪些api以及对应的使用方式。

开始是一个master,两个node节点,后面再扩。

使用centos7系统,前面文章已经安装过etcd。

wget https://dl.k8s.io/v1.21.10/kubernetes-server-linux-amd64.tar.gz

tar -zxf kubernetes-server-linux-amd64.tar.gz

cd kubernetes/server/bin/

cp kube-apiserver kubectl kube-controller-manager kube-scheduler /usr/local/bin

scp kubelet kube-proxy FNSHB109:/usr/local/bin

scp kubelet kube-proxy node1:/usr/local/bin

scp kubelet kube-proxy node2:/usr/local/bin

mkdir -p /etc/kubernetes

mkdir -p /etc/kubernetes/ssl

mkdir -p /var/log/kubernetes

一个应用程序访问https API(自签证书),有两种方式,证书添加IP可信任(写在证书的json的host文件里面)和携带CA证书。ca证书在etcd那篇文章里面已经配置过,这里直接配置kube-apiserver-csr.json请求文件,再利用ca证书和私钥,形成kube-apiserver证书。

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-apiserver-csr.json | cfssljson -bare kube-apiserver

随机生成序列号,并定义token.csv

kubelet 采用 TLS Bootstrapping 机制,自动完成到 kube-apiserver 的注册,在 node 节点量较大或者后期自动扩容时非常有用。

Master apiserver 启用 TLS 认证后,node 节点 kubelet 组件想要加入集群,必须使用CA签发的有效证书才能与 apiserver 通信,当 node 节点很多时,签署证书是一件很繁琐的事情。因此 Kubernetes 引入了 TLS bootstraping 机制来自动颁发客户端证书,kubelet 会以一个低权限用户自动向 apiserver 申请证书,kubelet 的证书由 apiserver 动态签署。

kubelet 首次启动通过加载 bootstrap.kubeconfig 中的用户 Token 和 apiserver CA 证书发起首次 CSR 请求,这个 Token 被预先内置在 apiserver 节点的 token.csv 中,其身份为 kubelet-bootstrap 用户和 system:kubelet-bootstrap 用户组;想要首次 CSR 请求能成功(即不会被 apiserver 401 拒绝),则需要先创建一个 ClusterRoleBinding,将 kubelet-bootstrap 用户和 system:node-bootstrapper 内置 ClusterRole 绑定(通过 kubectl get clusterroles 可查询),使其能够发起 CSR 认证请求。

TLS bootstrapping 时的证书实际是由 kube-controller-manager 组件来签署的,也就是说证书有效期是 kube-controller-manager 组件控制的;kube-controller-manager 组件提供了一个 --experimental-cluster-signing-duration 参数来设置签署的证书有效时间;默认为 8760h0m0s,将其改为 87600h0m0s,即 10 年后再进行 TLS bootstrapping 签署证书即可。

也就是说 kubelet 首次访问 API Server 时,是使用 token 做认证,通过后,Controller Manager 会为 kubelet 生成一个证书,以后的访问都是用证书做认证了。

cd /root/k8sbinary/TLS/k8s

cp /root/k8sbinary/TLS/k8s/token.csv /etc/kubernetes/ssl

cp /root/k8sbinary/TLS/k8s/ca*.pem /etc/kubernetes/ssl

cp /root/k8sbinary/TLS/k8s/kube-api*.pem /etc/kubernetes/ssl

scp ca*.pem node1:/etc/kubernetes/ssl

scp ca*.pem node2:/etc/kubernetes/ssl

scp /root/k8sbinary/TLS/k8s/token.csv node1:/etc/kubernetes/ssl

scp /root/k8sbinary/TLS/k8s/token.csv node1:/etc/kubernetes/ssl

systemctl daemon-reload

systemctl enable kube-apiserver

systemctl start kube-apiserver

systemctl status kube-apiserver


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/bake/11866269.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存