Kubernetes 安全机制

Kubernetes 作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Server 是集群内部各个组件通信的中介,也是外部控制的入口。所以 Kubernetes 的安全机制基本就是围绕保护 API Server 来设计的。Kubernetes 使用了认证(Authentication)、鉴权(Authorization)、准入控制(AdmissionControl)三步来保证API Server的安全。

当用户或者pod访问apiserver的时候来镜像身份的识别,这就是认证。
在这里插入图片描述

Authentication 认证

HTTP Token 认证:通过一个 Token 来识别合法用户(或者理解为通过一个字符串识别合法用户)

HTTP Token 的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串 - Token 来表达客户的一种方式。Token 是一个很长的很复杂的字符串,每一个 Token 对应一个用户名存储在 API Server 能访问的文件中(这种存储方式不是存储在etcd上面,而是一个文件当中,安全性可想而知)。当客户端发起 API 调用请求时,需要在 HTTP Header 里放入 Token。

HTTP Base 认证:通过用户名+密码的方式认证

用户名+:+密码用 BASE64 算法进行编码后的字符串放在 HTTP Request 中的 Heather Authorization 域里发送给服务端,服务端收到后进行解码,获取用户名及密码。这样服务器就知道用户名密码,然后进行判定。

上面两种都不太安全,都是服务器去验证客户端的机会,但是客户端没有认证服务器。也就是服务器可以认证客户端是否是一个合理的合法的。但是客户端不知道这个服务是不是真的,万一是一个假的也不是不可能。上面的一种放在文件当中不安全,第二种用户名密码方式太费劲。

最严格的 HTTPS 证书认证:基于 CA 根证书签名的客户端身份认证方式

在整个K8s域当中签署一个CA根证书,所有节点的证书都是以这个根证书签发出来的子证书,并且实现的是https的双向认证。

https证书认证

在这里插入图片描述

需要认证的节点

在这里插入图片描述
对于认证来说白了就是用户或者pod访问apiserver的时候来进行身份的识别,集群的组件etcd controller manager等需要访问apiserver。那么也需要有双向认证的证书存在

两种类型

  • Kubenetes 组件对 API Server 的访问:kubectl、Controller Manager、Scheduler、kubelet、kube-proxy(CA证书认证)
  • Kubernetes 管理的 Pod 容器对API Server的访问:Pod(dashboard 也是以 Pod 形式运行,SA Service Account认证)

安全性说明

  • Controller Manager、Scheduler与API Server在同一台机器,所以直接使用APIServer的非安全端口访问,-insecure-bind-address=127.0.0.1 (加密的交互是一个消耗资源的过程,由于API Server和Controller Manager、Scheduler在同一台机器,所以访问本地的回环接口就可以访问API Server,没有一个双向的https证书的加密,这里没有必要使用https加密)
  • kubectl、kubelet、kube-proxy 访问 API Server 就都需要证书进行 HTTPS 双向认证(是远程访问的过程,这个就要https的双向认证了)

证书颁发

  • 手动签发:通过 k8s 集群的跟 ca 进行签发 HTTPS 证书
  • 自动签发:kubelet 首次访问 API Server 时,使用 token 做认证,通过后,Controller Manager 会为kubelet 生成一个证书,以后的访问都是用证书做认证了

kubeconfig

kubeconfig文件包含集群参数(CA证书、API Server地址),客户端参数(上面生成的证书和私钥),集群context信息(集群名称、用户名)。Kubenetes 组件通过启动时指定不同的kubeconfig文件可以切换到不同的集群

ServiceAccount

Pod中的容器访问API Server。因为Pod的创建、销毁是动态的,所以要为它手动生成证书就不可行了。Kubenetes使用了Service Account解决Pod 访问API Server的认证问题

(为什么不使用组件之间的双向认证呢,如果使用双向认证就会几百个证书,因为有几百个pod,并且pod会销毁,所以证书就相当于没用了,同时创建证书对集群会造成压力)

Secret 与 SA 的关系

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 的开放标准((Rrc 7519】)该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(sso)场景。jwt的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声面明德患,该 token 也可直接被用于认证,也可被加密

默认情况下,每个 namespace 都会有一个 ServiceAccount,如果 Pod 在创建时没有指定 ServiceAccount,就会使用 Pod 所属的 namespace 的 ServiceAccount,默认挂载目录/run/secrets/kubernetes.io/serviceaccount

这个serviceaccount会生成一个token保存在secret里面,serviceaccount和secret是有关联的,用sercert保存token的 (Kubernetes 自身也有一些内置的 Secret,主要用来保存访问 APIServer 的 service account token)

在这里插入图片描述
对于整个k8s集群来说使用的是https认证,是一个双向认证的方式,如果是系统的组件想要访问k8s apiserver分为两种

  • 一种是在一台机器上,访问非安全端口
  • 另外一种是远程访问需要https认证
  • 如果是pod想要访问就要使用ServiceAccount

授权

当认证通过以后,并不意味着你有访问资源可能。因为需要鉴权,这样才有访问具体对象的权限。

[root@k8s-master1 ~]# cat /etc/kubernetes/manifests/kube-apiserver.yaml |grep auth
    - --authorization-mode=Node,RBAC
    - --enable-bootstrap-token-auth=true

上面认证过程,只是确认通信的双方都确认了对方是可信的,可以相互通信。而鉴权是确定请求方有哪些资源的权限(具体对资源有哪些资源的权限就需要鉴权)。API Server 目前支持以下几种授权策略(通过 API Server 的启动参数 “–authorization-mode” 设置)

  • AlwaysDeny:表示拒绝所有的请求,一般用于测试
  • AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略
  • ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制(老版本采用的方式,也就是定义属性的访问类型,如果用户拥有这个属性就能访问对应的资源。需要定义一长串的属性,并且ABAC修改完之后并不能生效,现在淘汰了)
  • Webbook:通过调用外部 REST 服务对用户进行授权(在集群外部对集群鉴权)
  • RBAC(Role-Based Access Control):基于角色的访问控制,现行默认规则(拥有角色就代表拥有访问资源某些权限)

现在使用RBAC,前面这几种不做讨论

RBAC 授权模式

RBAC(Role-Based Access Control)基于角色的访问控制,在 Kubernetes 1.5 中引入,现行版本成为默认标准。相对其它访问控制方式,拥有以下优势:

  • 对集群中的资源(pod deploy cpu…)和非资源(元信息如pod状态)均拥有完整的覆盖
  • 整个 RBAC 完全由几个 API 对象完成,同其它 API 对象一样,可以用 kubectl 或 API 进行操作
  • 可以在运行时进行调整,无需重启 API Server(ABAC修改需要重启API server生效)
RBAC 的 API 资源对象说明

RBAC 引入了 4 个新的顶级资源对象:Role(角色)、ClusterRole(集群角色)、RoleBinding(角色绑定)、ClusterRoleBinding(集群角色绑定),4 种对象类型均可以通过 kubectl 与 API 操作
在这里插入图片描述
需要注意的是 Kubenetes 并不会提供用户管理,那么 User、Group、ServiceAccount 指定的用户又是从哪里来的呢? Kubenetes 组(kubectl、kube-proxy)或是其他自定义的用户在向 CA 申请证书时,需要提供一个证书请求文件(在k8s里面没有创建用户的命令,用户的命令在定义CA证书的时候就已经提供了)
在这里插入图片描述
API Server会把客户端证书的CN字段作为User,把names.O字段作为Group

kubelet 使用 TLS Bootstaping 认证时,API Server 可以使用 Bootstrap Tokens 或者 Token authenticationfile 验证=token,无论哪一种,Kubenetes 都会为 token 绑定一个默认的 User 和 Group

Pod使用 ServiceAccount 认证时,service-account-token 中的 JWT 会保存 User 信息

有了用户信息,再创建一对角色/角色绑定(集群角色/集群角色绑定)资源对象,就可以完成权限绑定了

案例

创建一个Role和ServiceAccount并把他们绑定起来。ServiceAccount有get、list、watch的权限
vim mysa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: mysa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: mysa-role
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mysa-rolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: mysa-role
subjects:
- kind: ServiceAccount
  name: mysa
[root@k8s-master1 ~]# kubectl apply -f mysa.yaml 
serviceaccount/mysa created
role.rbac.authorization.k8s.io/mysa-role created
rolebinding.rbac.authorization.k8s.io/mysa-rolebinding created

查看sa,查看Secret,下面的token
在这里插入图片描述

Logo

开源、云原生的融合云平台

更多推荐