Kubernetes
作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Server
是集群内部各个组件通信的中介,也是外部控制的入口。所以Kubernetes
的安全机制基本就是围绕保护APIServer
来设计的。Kubernetes
使用了认证(Authentication
)、鉴权(Authorization
)、准入控制(Admission Control
)三步来保证API Server
的安全HTTP Token
认证:通过一个Token
来识别合法用户。
HTTP Token
的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串-Token
来表达客户的一种方式。Token
是一个很长的很复杂的字符串,每一个Token
对应一个用户名存储在API Server
能访问的文件中。当客户端发起API
调用请求时,需要在HTTP Header
里放入Token
。HTTP Base
认证:通过用户名+密码的方式认证
HTTP Request
中的Heather
Authorization
域里发送给服务端,服务端收到后进行解码,获取用户名及密码最严格的HTTPS证书认证:基于CA根证书签名的客户端身份认证方式
两种类型:
Kubenetes
组件对API Server
的访问:kubectl、.Controller Manager、Scheduler、kubelet、kube-proxy
Kubernetes
管理的Pod对容器的访问:Pod(dashborad
也是以Pod形试运行)安全性说明:
Controller Manager、Scheduler与API Server
在同一台机器,所以直接使用API Server
的非安全端口访问,--insecure-bind-address=127.0.0.1
kubectl、kubelet、kube-proxy
访问API Server
就都需要证书进行HTTPS双向认证证书颁发:
k8s
集群跟ca
进行签发HTTPS
证书kubelet
首次访问API Server
时,使用token
做认证,通过后,Controller Manager
会为kubelet
生成一个证书,以后的访问都是用证书做认证了。kubeconfig
文件包含集群参数(CA证书、API Server地址
),客户端参数(上面生成的证书和私钥),集群context
信息(集群名称、用户名)。Kubenetes
组件通过启动时指定不同的kubeconfig
文件可以切换到不同的集群API Server
。因为Pod的创建、销毁是动态的,所以要为它手动生成证书就不可行了。Kubenetes
使用了Service Account
解决Pod访问API Server
的认证问题Kubernetes
设计了一种资源对象叫做Secret
,分为两类,一种是用于ServiceAccount
的service-account-token
,另一种是用于保存用户自定义保密信息的Opaque
。ServiceAccount
中用到包含三个部分:Token、ca.crt、namespace
token
是使用 API Server
私钥签名的JWT
。用于访问API Server
时,Server
端认证。ca.crt
根证书,用于Client
端验证API Server
发送的证书。namespace
,标识这个service-account-token
的作用域名空间--Json web token (JWT)
,是为了在网络应用环境间传递声明而执行的一种基于 JSON的开放标准((RFC 7519],该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(sso)场景。JWI的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密
[root@master1 ~]# kubectl get secrets --all-namespaces
[root@master1 ~]# kubectl describe -n kube-system secrets default-token-tbv44
namespace
都会有一个ServiceAccount
,如果 Pod在创建时没有指定ServiceAccount
,就会使用 Pod所属的 namespace的 ServiceAccount
上面认证过程,只是确认通信的双方都确认了对方是可信的,可以相互通信。而鉴权是确定请求方有哪些资源的权限。API Server目前支持以下几种授权策路(通过API Server
的启动参数"--authorization-mode
"设置)
AlwaysDeny
:表示拒绝所有的请求,一般用于测试AlwaysAllow
:允许接收所有请求,如果集群不需要授权流程,则可以采用该策路ABAC(Attribute-Based Access Control)
:基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制Webbook
:通过调用外部REST服务对用户进行授权RBAC(Role-Based Access Control)
:基于角色的访问控制,现行默认规则RBAC(Role-Based Access Control)
基于角色的访问控制,在Kubernetes1.5
中引入,现行版本成为默认标准。相对其它访问控制方式,拥有以下优势:
RBAC
完全由几个API对象完成,同其它API对象一样,可以用kubectl或API进行操作API Serve
rRBAC引入了4个新的顶级资源对象:Role、ClusterRole、RoleBinding、 ClusterRoleBinding
,4种对象类型均可以通过kubectl与API操作
需要注意的是Kubenetes
并不会提供用户管理,那么User、Group、ServiceAccount
指定的用户又是从哪里来的呢?Kubenetes组件(kubectl、 kube-proxy)
或是其他自定义的用户在向CA申请证书时,需要提供个证书请求文件
{
"CN": "admin", #Common Name,也就是通用名称,代表证书的主题或主体名称。在这个示例中,CN被设置为"admin",表示证书将用于标识一个名为"admin"的实体
"hosts": [], #这是一个主机列表,用于指定该证书可以用于哪些主机。在这个示例中,主机列表是空的,表示该证书不限制特定的主机。
"key": { #这是密钥相关的参数。"algo"表示使用的密钥算法,这里设置为"sra"。"size"表示密钥的长度,这里设置为2048比特
"algo": "sra"
"size": 2048
},
"name": [ #这是证书的主题(Subject)信息。包含了一些组织和位置相关的信息
{
"C": "CN", #Country,表示国家/地区代码。在这个示例中,"CN"表示中国
"ST": "ShenZhen", # State,表示州或省的名称。在这个示例中,"ShenZhen"表示深圳
"L": "system:master", #Location,表示城市或城镇的名称。在这个示例中,"system:master"表示系统的主控节点
"OU": "System" #Organizational Unit,表示组织单位。在这个示例中,"System"表示系统相关的组织单位
}
]
}
API Server
会把客户端证书的 CN
字段作为User
,把 names.O
字段作为Group
kubelet
使用 TLS Bootstaping
认证时, API Server
可以使用 Bootstrap Tokens 或者 Token
authentication file
验证 =token
,无论哪一种, Kubenetes
都会为 token
绑定一个默认的 User 和 Group
Pod
使用 ServiceAccount
认证时, service-account-token
中的JWT
会保存 User
信息Role
(角色)是一种在特定命名空间(Namespace
)内定义权限的资源。它定义了一组权限,比如可以访问哪些API资源以及可以执行哪些操作。Role只能在单个命名空间内使用,不能跨命名空间使用。
RoleBinding
用于将角色(Role)绑定到特定的命名空间(Namespace
)中的用户或服务账户。它授予绑定的用户或服务账户在指定命名空间中执行特定操作的权限。例如,可以将一个角色绑定到一个用户,使该用户能够读取或更新特定命名空间中的资源。
Role和RoleBinding
的关系是一对多的,即一个Role可以被多个RoleBinding绑定,从而允许多个用户或用户组共享相同的权限。
需要注意的是,Role和RoleBinding
只在特定命名空间中生效。如果想要在整个集群中使用,则需要使用ClusterRole和ClusterRoleBinding
。
kind: Role #指定了对象的类型为Role
apiVersion: rbac.authorization.k8s.io/v1 #指定了所使用的Kubernetes API版本
metadata: #该部分包含了Role的元数据,如名称(name)等
name: leader-locking-nfs-client-provisioner #定义了Role的名称
namespace: nfs #定义Role所属的命名空间
rules: #定义了角色的权限规则,这里允许对endpoints资源进行操作
- apiGroups: [""] #资源所属的组,""表示核心API组
resources: ["pods"] #定义了可以访问的资源为pod
verbs: ["get", "list", "watch", "create", "update", "patch"] #定义了可以执行的操作,比如get、list、watch等
---
kind: RoleBinding #指定了对象的类型为RoleBinding
apiVersion: rbac.authorization.k8s.io/v1 #指定了所使用的Kubernetes API版本
metadata: #该部分包含了RoleBinding的元数据,如名称(name)等
name: leader-locking-nfs-client-provisioner #定义了RoleBinding的名称
namespace: nfs #角色绑定所属的命名空间,与之前的服务账户相同
subjects: #定义了角色绑定的主体,即与角色关联的服务账户
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: nfs
roleRef: #定义了与角色绑定关联的角色
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
ClusterRole
(集群角色)与Role类似,但是作用范围更广,可以在整个集群内使用。它定义了一组全局权限,可以访问集群中的所有命名空间以及集群级别的资源。ClusterRoleBinding
用于将集群角色(ClusterRole
)绑定到整个集群中的用户或服务账户
。它授予绑定的用户或服务账户在整个集群中执行特定操作的权限。与RoleBinding不同,ClusterRoleBinding的作用范围跨越整个集群,而不仅限于单个命名空间。例如,可以将一个集群角色绑定到一个服务账户,使该服务账户能够在整个集群中管理节点或访问特定的API。ClusterRole和ClusterRoleBinding
,管理员可以为集群中的不同用户、组或ServiceAccount
分配不同的权限。ClusterRole和ClusterRoleBinding
是集群级别的资源,因此对它们的更改会影响整个集群。在创建和配置ClusterRole和ClusterRoleBinding
时,请谨慎操作,并确保为用户或ServiceAccount
分配适当的权限。kind: ClusterRole #指定了对象的类型为ClusterRole
apiVersion: rbac.authorization.k8s.io/v1 #指定了所使用的Kubernetes API版本
metadata: #该部分包含了集群角色的元数据,如名称(name)等
name: nfs-client-provisioner-runner #定义集群角色的名称
rules: #定义了集群角色的权限规则
- apiGroups: [""] #资源所属的组,""表示核心API组
resources: ["persistentvolumes"] #定义了可以访问的资源为PV
verbs: ["get", "list", "watch", "create", "delete"] #定义了可以执行的操作,比如get、list、watch、create和delete
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding #指定了对象的类型ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1 #指定了所使用的Kubernetes API版本
metadata: #该部分包含了集群角色绑定的元数据,如名称(name)等
name: run-nfs-client-provisioner #定义了集群角色绑定的名称
subjects: #定义了角色绑定的主体,即与角色关联的服务账户
- kind: ServiceAccount #主体的类型,这里是ServiceAccount
name: nfs-client-provisioner #主体的名称,即之前定义的服务账户nfs-client-provisioner
namespace: nfs #主体所属的命名空间,与之前的服务账户相同
roleRef: #定义了与角色绑定关联的角色
kind: ClusterRole #角色的类型,这里是ClusterRole
name: nfs-client-provisioner-runner #角色的名称,即之前定义的集群角色nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io #角色所属的API组,这里是rbac.authorization.k8s.io
准入控制是API Server
的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至于API Server
的一些主要的功能都需要通过Admission Controllers
实现,比如ServiceAccount
官方文档上有一份针对不同版本的准入控制器推荐列表,其中最新的1.14的推荐列表是:
NamespaceLifecycle
,LimitRanger
,ServiceAccount
,DefaultStorageclass
,DefaultTolerationSeconds
,MutatingAdmissionWebhook
,ValidatingAdmissionWebhook
,ResourceQuota
列举几个插件的功能:
NamespaceLifecycle
:防止在不存在的namespace
上创建对象,防止删除系统预置namespace
,删除namespace
时,连带删除它的所有资源对象。LimitRanger
:确保请求的资源不会超过资源所在Namespace
的LimitRange
的限制。ServiceAccount
:实现了自动化添加ServiceAccount
。ResourceQuota
:确保请求的资源不会超过资源的ResourceQuota
限制。