K8S集群安全之安全机制

1. 安全机制说明:

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

K8S集群安全之安全机制_第1张图片

2. Authentication(认证)

  • HTTP Token认证:通过一个Token来识别合法用户。

    • HTTP Token的认证是用一个很长的特殊编码方式的并且难以被模仿的字符串-Token来表达客户的一种方式。Token是一个很长的很复杂的字符串,每一个Token对应一个用户名存储在API Server能访问的文件中。当客户端发起API调用请求时,需要在HTTP Header里放入Token
  • HTTP Base认证:通过用户名+密码的方式认证

    • 用户名+密码用BASE64算法进行编码后的字符串放在HTTP Request中的Heather
    • Authorization域里发送给服务端,服务端收到后进行解码,获取用户名及密码
  • 最严格的HTTPS证书认证:基于CA根证书签名的客户端身份认证方式

2.1. Https证书认证:

K8S集群安全之安全机制_第2张图片

2.2. 需要认证的节点

K8S集群安全之安全机制_第3张图片

  • 两种类型:

    • 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生成一个证书,以后的访问都是用证书做认证了。

2.3. kubeconfig

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

2.4. Service Account

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

2.5. Secret与SA的关系

  • Kubernetes设计了一种资源对象叫做Secret,分为两类,一种是用于ServiceAccountservice-account-token,另一种是用于保存用户自定义保密信息的OpaqueServiceAccount中用到包含三个部分: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
  • 默认挂载目录:/run/secrets/kubernetes.io/serviceaccount/
    K8S集群安全之安全机制_第4张图片

3. Authorization(鉴权)

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

    • AlwaysDeny:表示拒绝所有的请求,一般用于测试
    • AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策路
    • ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制
    • Webbook:通过调用外部REST服务对用户进行授权
    • RBAC(Role-Based Access Control):基于角色的访问控制,现行默认规则

3.1. RBAC授权模式

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

    • 对集群中的资源和非资源均拥有完整的覆盖
    • 整个RBAC完全由几个API对象完成,同其它API对象一样,可以用kubectl或API进行操作
    • 可以在运行时进行调整,无需重启API Server

3.1.1. RBAC的API资源对象说明

  • RBAC引入了4个新的顶级资源对象:Role、ClusterRole、RoleBinding、 ClusterRoleBinding,4种对象类型均可以通过kubectl与API操作
    K8S集群安全之安全机制_第5张图片

  • 需要注意的是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 信息
  • 有了用户信息,再创建一对角色/角色绑定(集群角色/集群角色绑定)资源对象,就可以完成权限绑定了

3.2. Role(角色) and RoleBinding(角色绑定)

  • 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

3.3. ClusterRole(集群角色) and ClusterRoleBinding(集群角色绑定)

  • 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:确保请求的资源不会超过资源所在NamespaceLimitRange的限制。
    • ServiceAccount:实现了自动化添加ServiceAccount
    • ResourceQuota:确保请求的资源不会超过资源的ResourceQuota限制。

你可能感兴趣的:(kubernetes,安全,容器)