# k8s API 访问控制
可以使用 kubectl、客户端库方式对 REST API 的访问,k8s 的普通账户和 Service 帐户都可以实现授权访问 API。API 的请求会经过多个阶段的访问控制才会被接受处理,其中包含认证、授权以及准入控制(Admission Control)等。如下图所示:
需要注意:认证授权过程只存在 HTTPS 形式的 API 中。也就是说,如果客户端使用 HTTP 连接到 kube-apiserver,是不会进行认证授权的。所以说,可以这么设置,在集群内部组件间通信使用 HTTP,集群外部就使用 HTTPS,这样既增加了安全性,也不至于太复杂。
# 认证
开启 TLS 时,所有的请求首先需要认证。k8s 支持多种认证机制,并支持同时开启多个认证插件(只要有一个认证通过即可)。如果认证成功,则用户的 username 会传入授权模块做进一步授权验证;对于认证失败的请求则返回 HTTP 401。
当 TLS 建立时,HTTP 请求会进行身份认证步骤,如图中步骤 1,集群管理器将 apiserver 配置为运行一个或多个认证器模块。
认证模块包含客户端证书,密码、Plain Tokens、Bootstrap Tokens、JWT Tokens(used for service accounts)。
我们可以指定多个认证模块,每个认证模块都会按顺序进行,直到其中一个成功。
(在 GCE 上,客户端证书、密码、Plain Tokens 和 JWT Tokens 都会启用。)
更多认证模块的使用方法可以参考 认证
# 授权
认证之后的请求是授权模块。如图中步骤 2。
请求必须包含请求者的用户名,请求的操作以及受该操作影响的对象,如果策略已经声明用户具有完成请求的权限,则该请求将被授权。
例如:设置如下 Bob 策略,那么会在 namespace projectCaribou 中读取 pods
{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "bob",
"namespace": "projectCaribou",
"resource": "pods",
"readonly": true
}
}
如果 Bob 发出以下请求,被允许读取 projectCaribou namespace 中的对象,请求被授权
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "projectCaribou",
"verb": "get",
"group": "unicorn.example.org",
"resource": "pods"
}
}
}
- 如果 Bob 向 projectCaribou namespace 中对象写入(create 或 update)请求,则会拒绝其授权。
- 如果 Bob 请求在不同的 namespace 中读取(get)对象,比如 projectFish,授权也将被拒绝。
k8s 授权要求使用公共常见得 REST 属性与云提供商的访问控制系统进行交互。为了避免访问控制系统与 k8s API 与外部 API 的冲突,所以必须使用 REST 格式。
k8s 支持多种授权模块,如 ABAC 模式、RBAC 模式和 Webhook 模式。当管理员创建集群时,他们将会配置在 API Server 中使用的授权模块。如果配置了多个授权模块,k8s 会检查每个模块,当通过其中任何模块授权请求,则授权成功,如果所有模块都拒绝了该请求,则授权失败(HTTP 403)。
了解 k8s 授权的更多信息,参靠授权概述。
# 准入控制(Admission Control)
准入控制(Admission Control)用来对请求做进一步的验证或添加默认参数,除了授权模块可用的属性外,准入控制模块还可以访问正在创建或更新对象内容。
也可以可以配置多个准入控制器,每个都会按顺序调用。
如图中步骤 3。
与认证和授权模块不同,任何接入控制器模块被遭拒时,请求会立即失败。
当请求通过了所有准入控制(Admission Control),就会使用相应 API 对象的验证功能,然后写入对象存储(如步骤 4 所示)
# API Server 端口和 IPs
之前讨论用于发送到 API Server 安全端口的请求(经典情况)。API Server 实际上可以在两个端口上服务:
默认情况下,k8s API Server 在 2 个端口上提供 HTTP:
Localhost Port:
- is intended for testing and bootstrap, and for other components of the master node (scheduler, controller-manager) to talk to the API - no TLS - default is port 8080, change with `--insecure-port` flag. - defaults IP is localhost, change with `--insecure-bind-address` flag. - request **bypasses** authentication and authorization modules. - request handled by admission control module(s). - protected by need to have host access
Secure Port:
- use whenever possible - uses TLS. Set cert with `--tls-cert-file` and key with `--tls-private-key-file` flag. - default is port 6443, change with `--secure-port` flag. - default IP is first non-localhost network interface, change with `--bind-address` flag. - request handled by authentication and authorization modules. - request handled by admission control module(s). - authentication and authorisation modules run.
在 Google Compute Engine(GCE)或其他云提供商使用 kube-up.sh 创建集群时
- API Server 提供 443 端口
- GCE 项目配置防火墙
- 允许 API 进行外部 HTTPS 访问