[TOC]
我们知道,当客户端通过安全端口访问apiserver的API时,都需要携带一个身份凭证,能让apiserver认证为某个User、Group或者ServiceAccount。kubelet也要访问apiserver的API,所以它也需要携带一个身份凭证。
我们列举一些kubelet需要访问的API:第一次向apiserver注册(`POST /api/v1/nodes`)、定期向apiserver更新自身节点的状态(`PUT /api/v1/nodes/{nodeName}`)、获取pod列表以知道哪些pod是调度到自身节点上(`GET /api/v1/pods`)等等。我们发现,有一些API比如获取pod列表`GET /api/v1/pods`是每个kubelet都要能访问的,而有一些API比如更改节点状态`PUT /api/v1/nodes/{nodeName}`应该只能被该节点本身访问。
所以k8s做了这样的设计,每一个kubelet访问API时。其携带的身份凭证必须被apiserver识别成某个User`system:node:{nodeName}`以及Group`system:nodes`。授权服务器会给User`system:node:{nodeName}`授权使它有权限访问`PUT /api/v1/nodes/{nodeName}`,以及给Group`system:nodes`授权使其能够访问`GET /api/v1/pods`。
至于kubelet的身份凭证如何得到,以及如何被apiserver认证我们先不管,我们先来说一下授权。授权模式有很多种,常见的有ABAC以及RBAC。假设我们使用RBAC,那么我们给Group`system:nodes`授权时,必须创建一个类似于如下的ClusterRole以及一个ClusterRoleBinding使该Group能够访问`GET /api/v1/pods`:
```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:node
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get"]
```
```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:node
subjects:
- kind: Group
name: system:nodes
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: system:node
apiGroup: rbac.authorization.k8s.io
```
当每有一个Node注册成功后,我们必须在集群中为该Node创建一个ClusterRole和ClusterRoleBinding,以使该Node只能访问`PUT /api/v1/nodes/{nodeName}`。如果集群Node很多的时候,手动创建这么多的ClusterRole和ClusterRoleBinding是不是很麻烦?是的,非常麻烦。那么k8s可不可以自动地为Group`system:nodes`以及每个Node`system:node:{nodeName}`创建ClusterRole与ClusterRoleBinding呢?答案是:每个版本,k8s做了不同的事情。
在1.6版本中,如果使用RBAC授权模式,那么`system:node`这个ClusterRole会自动地绑定到Group`system:nodes`。但是每个Node所需要的ClusterRole与ClusterRoleBinding不会自动创建。
在1.7版本中,k8s想,既然我们要基于RBAC给每个Node创建ClusterRole与ClusterRoleBinding,那么我们就把这个功能抽出来,设计一个叫Node Authorizor的授权器,如果API请求携带的身份凭证被认证为User`system:node:<nodeName>`以及Group`system:nodes`,那么就由Node Authorizor对这次请求进行授权,而不再由RBAC Authorizor进行授权。Node Authorizor会自动地赋予Group`system:nodes`访问`GET /api/v1/pods`的权限,以及赋予User`system:node:<nodeName>`访问`PUT /api/v1/nodes/{nodeName}`的权限,不像RBAC那样还要创建一个ClusterRole与ClusterRoleBinding。
要开启Node Authorizor,需要配置apiserver的启动参数`--authoriztion-mode=Node,···`和`--enable-admission-plugins=···,NodeRestriction,···`。不过需要注意的是,由于Node Authorizor的权限规则是写死的,不像RBAC那样可以手动配置;所以不同的k8s版本,Node Authorzior对每个Node能访问的接口可能会有一样的规则。
OK,现在Node授权的问题解决了,那么接下来应该要讲讲认证的问题了。
我们在前面的文章中介绍了三种常见的认证方式:用户名密码认证、token认证、客户端证书认证。我们直接给出答案:k8s的Node使用的是客户端证书认证。
在客户端证书认证机制中,apiserver会用参数`--client-ca-file`指定的CA证书来验证API请求携带的签名证书,所以kubelet携带的签名证书应该是由CA证书对应的CA密钥签名的。k8s集群的管理员可以在添加一个新的节点的时候,手动为新节点生成一对密钥,然后再手动使用CA密钥进行签名,最后拿这个签名证书去启动kubelet。
有没有觉得这种人工去生成密钥对以及签名很麻烦?是的,非常麻烦。刚开始安装集群的时候,可以使用脚本批量处理。但是如果到了以后,集群需要添加新的节点时,这个时候管理员只能手动地去生成密钥、签名,然后配置好kubelet。那么有没有办法可以简化这些操作呢?答案是,有的。请看下一节《TLS bootstrapping》
- 常用命令
- 安装
- 安装Kubeadm
- 安装单Master集群
- 安装高可用集群(手动分发证书)
- 安装高可用集群(自动分发证书)
- 启动参数解析
- certificate-key
- ETCD相关参数
- Kubernetes端口汇总
- 安装IPv4-IPv6双栈集群
- 下载二进制文件
- 使用Kata容器
- 快速安装shell脚本
- 存储
- 实践
- Ceph-RBD实践
- CephFS实践
- 对象存储
- 阿里云CSI
- CSI
- 安全
- 认证与授权
- 认证
- 认证-实践
- 授权
- ServiceAccount
- NodeAuthorizor
- TLS bootstrapping
- Kubelet的认证
- 准入控制
- 准入控制示例
- Pod安全上下文
- Selinux-Seccomp-Capabilities
- 给容器配置安全上下文
- PodSecurityPolicy
- K8S-1.8手动开启认证与授权
- Helm
- Helm命令
- Chart
- 快速入门
- 内置对象
- 模板函数与管道
- 模板函数列表
- 流程控制
- Chart依赖
- Repository
- 开源的Chart包
- CRD
- CRD入门
- 工作负载
- Pod
- Pod的重启策略
- Container
- 探针
- 工作负载的状态
- 有状态服务
- 网络插件
- Multus
- Calico+Flannel
- 容器网络限速
- 自研网络插件
- 设计文档
- Cilium
- 安装Cilium
- Calico
- Calico-FAQ
- IPAM
- Whereabouts
- 控制平面与Pod网络分开
- 重新编译
- 编译kubeadm
- 编译kubeadm-1.23
- 资源预留
- 资源预留简介
- imagefs与nodefs
- 资源预留 vs 驱逐 vs OOM
- 负载均衡
- 灰度与蓝绿
- Ingress的TLS
- 多个NginxIngressController实例
- Service的会话亲和
- CNI实践
- CNI规范
- 使用cnitool模拟调用
- CNI快速入门
- 性能测试
- 性能测试简介
- 制作kubemark镜像
- 使用clusterloader2进行性能测试
- 编译clusterloader2二进制文件
- 搭建性能测试环境
- 运行density测试
- 运行load测试
- 参数调优
- Measurement
- TestMetrics
- EtcdMetrics
- SLOMeasurement
- PrometheusMeasurement
- APIResponsivenessPrometheus
- PodStartupLatency
- FAQ
- 调度
- 亲和性与反亲和性
- GPU
- HPA
- 命名规范
- 可信云认证
- 磁盘限速
- Virtual-kubelet
- VK思路整理
- Kubebuilder
- FAQ
- 阿里云日志服务SLS